From 2aa0400bd2a1c205de50ce46e1758f09e1b0c306 Mon Sep 17 00:00:00 2001 From: MoNTE48 Date: Fri, 4 Sep 2020 20:07:19 +0200 Subject: [PATCH] Backport MultiCraft Engine changes --- .github/workflows/build.yml | 184 +++++------ .gitignore | 2 + CMakeLists.txt | 2 +- doc/Doxyfile.in | 1 + src/CMakeLists.txt | 2 + src/client/camera.cpp | 4 +- src/client/client.cpp | 18 ++ src/client/client.h | 6 + src/client/clientenvironment.cpp | 2 +- src/client/clientlauncher.cpp | 24 +- src/client/clientmap.cpp | 6 +- src/client/content_cao.cpp | 29 +- src/client/content_mapblock.cpp | 2 +- src/client/event_manager.h | 2 +- src/client/fontengine.cpp | 4 +- src/client/game.cpp | 304 +++++++++++++++---- src/client/gameui.cpp | 46 +-- src/client/hud.cpp | 11 +- src/client/inputhandler.cpp | 40 +++ src/client/keys.h | 1 + src/client/localplayer.cpp | 67 +++- src/client/localplayer.h | 2 + src/client/minimap.cpp | 18 +- src/client/minimap.h | 9 + src/client/render/interlaced.cpp | 2 +- src/client/renderingengine.cpp | 122 ++++++-- src/client/sky.cpp | 9 +- src/client/tile.cpp | 26 +- src/cmake_config.h.in | 1 + src/config.h | 2 +- src/constants.h | 6 +- src/content/subgames.cpp | 6 + src/defaultsettings.cpp | 298 +++++++++++++++--- src/filesys.cpp | 4 +- src/gettext.cpp | 24 ++ src/gui/guiButton.cpp | 10 + src/gui/guiButton.h | 2 + src/gui/guiChatConsole.cpp | 7 +- src/gui/guiConfirmRegistration.cpp | 25 +- src/gui/guiConfirmRegistration.h | 2 +- src/gui/guiEngine.cpp | 30 +- src/gui/guiEngine.h | 3 + src/gui/guiFormSpecMenu.cpp | 54 +++- src/gui/guiFormSpecMenu.h | 4 +- src/gui/guiKeyChangeMenu.cpp | 5 + src/gui/guiPasswordChange.cpp | 26 +- src/gui/guiPasswordChange.h | 2 +- src/gui/guiTable.cpp | 40 ++- src/gui/guiTable.h | 2 + src/gui/guiVolumeChange.cpp | 5 + src/gui/modalMenu.cpp | 13 +- src/gui/modalMenu.h | 4 +- src/gui/touchscreengui.cpp | 9 + src/gui/touchscreengui.h | 3 + src/httpfetch.cpp | 2 +- src/hud.h | 4 + src/irrlicht_changes/static_text.cpp | 8 +- src/irrlicht_changes/static_text.h | 7 +- src/light.cpp | 2 +- src/log.cpp | 29 ++ src/main.cpp | 17 +- src/map.cpp | 20 +- src/mapgen/mapgen.cpp | 20 ++ src/{event.h => mtevent.h} | 0 src/network/connection.cpp | 2 + src/network/connectionthreads.cpp | 6 +- src/network/serverpackethandler.cpp | 8 +- src/network/socket.cpp | 5 + src/object_properties.h | 2 +- src/porting.cpp | 30 +- src/porting.h | 15 +- src/porting_android.cpp | 75 ++++- src/porting_android.h | 16 + src/script/common/c_content.cpp | 15 +- src/script/cpp_api/s_base.cpp | 2 +- src/script/cpp_api/s_security.cpp | 6 + src/script/lua_api/l_mainmenu.cpp | 34 ++- src/script/lua_api/l_mainmenu.h | 2 + src/script/lua_api/l_server.cpp | 2 - src/script/scripting_server.cpp | 2 + src/server.cpp | 38 ++- src/server/player_sao.cpp | 7 +- src/serverenvironment.cpp | 26 +- src/serverlist.cpp | 13 +- src/skyparams.h | 8 +- src/threading/thread.cpp | 8 +- src/util/areastore.h | 2 +- src/util/string.cpp | 8 +- textures/base/pack/crack_anylength_touch.png | Bin 0 -> 806 bytes textures/base/pack/progress_bar.png | Bin 413 -> 272 bytes textures/base/pack/progress_bar_bg.png | Bin 354 -> 294 bytes util/ci/build.sh | 1 + 92 files changed, 1522 insertions(+), 452 deletions(-) rename src/{event.h => mtevent.h} (100%) create mode 100644 textures/base/pack/crack_anylength_touch.png diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 58f4f0f2d..74a01b19e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -27,26 +27,26 @@ on: jobs: # This is our minor gcc compiler - gcc_6: - runs-on: ubuntu-18.04 - steps: - - uses: actions/checkout@v2 - - name: Install deps - run: | - sudo apt-get install g++-6 gcc-6 -qyy - source ./util/ci/common.sh - install_linux_deps - - - name: Build - run: | - ./util/ci/build.sh - env: - CC: gcc-6 - CXX: g++-6 - - - name: Test - run: | - ./bin/multicraft --run-unittests +# gcc_6: +# runs-on: ubuntu-18.04 +# steps: +# - uses: actions/checkout@v2 +# - name: Install deps +# run: | +# sudo apt-get install g++-6 gcc-6 -qyy +# source ./util/ci/common.sh +# install_linux_deps +# +# - name: Build +# run: | +# ./util/ci/build.sh +# env: +# CC: gcc-6 +# CXX: g++-6 +# +# - name: Test +# run: | +# ./bin/multicraft --run-unittests # This is the current gcc compiler (available in bionic) gcc_8: @@ -71,26 +71,26 @@ jobs: ./bin/multicraft --run-unittests # This is our minor clang compiler - clang_3_9: - runs-on: ubuntu-18.04 - steps: - - uses: actions/checkout@v2 - - name: Install deps - run: | - sudo apt-get install clang-3.9 -qyy - source ./util/ci/common.sh - install_linux_deps - - - name: Build - run: | - ./util/ci/build.sh - env: - CC: clang-3.9 - CXX: clang++-3.9 - - - name: Test - run: | - ./bin/multicraft --run-unittests +# clang_3_9: +# runs-on: ubuntu-18.04 +# steps: +# - uses: actions/checkout@v2 +# - name: Install deps +# run: | +# sudo apt-get install clang-3.9 -qyy +# source ./util/ci/common.sh +# install_linux_deps +# +# - name: Build +# run: | +# ./util/ci/build.sh +# env: +# CC: clang-3.9 +# CXX: clang++-3.9 +# +# - name: Test +# run: | +# ./bin/multicraft --run-unittests # This is the current clang version clang_9: @@ -121,56 +121,56 @@ jobs: valgrind --leak-check=full --leak-check-heuristics=all --undef-value-errors=no --error-exitcode=9 ./bin/multicraft --run-unittests # Build with prometheus-cpp (server-only) - clang_9_prometheus: - name: "clang_9 (PROMETHEUS=1)" - runs-on: ubuntu-18.04 - steps: - - uses: actions/checkout@v2 - - name: Install deps - run: | - sudo apt-get install clang-9 -qyy - source ./util/ci/common.sh - install_linux_deps - - - name: Build prometheus-cpp - 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" - - - name: Test - run: | - ./bin/multicraftserver --run-unittests +# clang_9_prometheus: +# name: "clang_9 (PROMETHEUS=1)" +# runs-on: ubuntu-18.04 +# steps: +# - uses: actions/checkout@v2 +# - name: Install deps +# run: | +# sudo apt-get install clang-9 -qyy +# source ./util/ci/common.sh +# install_linux_deps +# +# - name: Build prometheus-cpp +# 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" +# +# - name: Test +# run: | +# ./bin/multicraftserver --run-unittests # Build without freetype (client-only) - clang_9_no_freetype: - name: "clang_9 (FREETYPE=0)" - runs-on: ubuntu-18.04 - steps: - - uses: actions/checkout@v2 - - name: Install deps - run: | - sudo apt-get install clang-9 -qyy - source ./util/ci/common.sh - install_linux_deps - - - name: Build - run: | - ./util/ci/build.sh - env: - CC: clang-9 - CXX: clang++-9 - CMAKE_FLAGS: "-DENABLE_FREETYPE=0 -DBUILD_SERVER=0" - - - name: Test - run: | - ./bin/multicraft --run-unittests +# clang_9_no_freetype: +# name: "clang_9 (FREETYPE=0)" +# runs-on: ubuntu-18.04 +# steps: +# - uses: actions/checkout@v2 +# - name: Install deps +# run: | +# sudo apt-get install clang-9 -qyy +# source ./util/ci/common.sh +# install_linux_deps +# +# - name: Build +# run: | +# ./util/ci/build.sh +# env: +# CC: clang-9 +# CXX: clang++-9 +# CMAKE_FLAGS: "-DENABLE_FREETYPE=0 -DBUILD_SERVER=0" +# +# - name: Test +# run: | +# ./bin/multicraft --run-unittests docker: name: "Docker image" @@ -219,10 +219,10 @@ jobs: msvc: name: VS 2019 ${{ matrix.config.arch }}-${{ matrix.type }} - runs-on: windows-2019 + runs-on: windows-2019 env: - VCPKG_VERSION: c7ab9d3110813979a873b2dbac630a9ab79850dc -# 2020.04 + VCPKG_VERSION: 0bf3923f9fab4001c00f0f429682a0853b5749e0 +# 2020.11 vcpkg_packages: irrlicht zlib curl[winssl] openal-soft libvorbis libogg sqlite3 freetype luajit strategy: fail-fast: false @@ -248,7 +248,7 @@ jobs: uses: actions/checkout@v2 - name: Restore from cache and run vcpkg - uses: lukka/run-vcpkg@v2 + uses: lukka/run-vcpkg@v5 with: vcpkgArguments: ${{env.vcpkg_packages}} vcpkgDirectory: '${{ github.workspace }}\vcpkg' diff --git a/.gitignore b/.gitignore index 0be7d139b..1cfca5fc2 100644 --- a/.gitignore +++ b/.gitignore @@ -55,6 +55,8 @@ build/.cmake/ /clientmods/* !/clientmods/preview/ /client/mod_storage/ +/builtin/mainmenu/hosting/ +/textures/base/pack/hosting/ ## Configuration/log files multicraft.conf diff --git a/CMakeLists.txt b/CMakeLists.txt index 5510670a2..55ca832e7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,7 +49,7 @@ set(RUN_IN_PLACE ${DEFAULT_RUN_IN_PLACE} CACHE BOOL set(BUILD_CLIENT TRUE CACHE BOOL "Build client") set(BUILD_SERVER FALSE CACHE BOOL "Build server") -set(BUILD_UNITTESTS TRUE CACHE BOOL "Build unittests") +set(BUILD_UNITTESTS FALSE CACHE BOOL "Build unittests") set(WARN_ALL TRUE CACHE BOOL "Enable -Wall for Release build") diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in index d7816f0e4..08d262257 100644 --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -13,6 +13,7 @@ WARN_IF_UNDOCUMENTED = NO BUILTIN_STL_SUPPORT = YES PREDEFINED = "USE_SPATIAL=1" \ "USE_LEVELDB=1" \ + "USE_SQLITE=1" \ "USE_REDIS=1" \ "USE_SOUND=1" \ "USE_CURL=1" \ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 00e208345..5757a4cf8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -198,6 +198,8 @@ if(ENABLE_LEVELDB) endif() endif(ENABLE_LEVELDB) +option(ENABLE_SQLITE "Enable SQLite backend" TRUE) +set(USE_SQLITE TRUE) OPTION(ENABLE_REDIS "Enable Redis backend" TRUE) set(USE_REDIS FALSE) diff --git a/src/client/camera.cpp b/src/client/camera.cpp index a930e626e..37e4422b3 100644 --- a/src/client/camera.cpp +++ b/src/client/camera.cpp @@ -30,7 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "wieldmesh.h" #include "noise.h" // easeCurve #include "sound.h" -#include "event.h" +#include "mtevent.h" #include "nodedef.h" #include "util/numeric.h" #include "constants.h" @@ -695,6 +695,8 @@ void Camera::drawNametags() i = m_nametags.begin(); i != m_nametags.end(); ++i) { Nametag *nametag = *i; + if (!nametag->parent_node->isVisible()) + continue; if (nametag->nametag_color.getAlpha() == 0) { // Enforce hiding nametag, // because if freetype is enabled, a grey diff --git a/src/client/client.cpp b/src/client/client.cpp index f9068083f..51c232f4a 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -50,7 +50,9 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "clientmap.h" #include "clientmedia.h" #include "version.h" +#if USE_SQLITE #include "database/database-sqlite3.h" +#endif #include "serialization.h" #include "guiscalingfilter.h" #include "script/scripting_client.h" @@ -130,6 +132,8 @@ Client::Client( m_minimap = new Minimap(this); } m_cache_save_interval = g_settings->getU16("server_map_save_interval"); + m_round_screen = g_settings->getU16("round_screen"); + m_hud_scaling = g_settings->getFloat("hud_scaling"); } void Client::loadMods() @@ -284,11 +288,13 @@ void Client::Stop() m_script->on_shutdown(); //request all client managed threads to stop m_mesh_update_thread.stop(); +#if USE_SQLITE // Save local server map if (m_localdb) { infostream << "Local map saving ended." << std::endl; m_localdb->endSave(); } +#endif if (m_mods_loaded) delete m_script; @@ -663,12 +669,14 @@ void Client::step(float dtime) infostream << "Saved " << n << " modified mod storages." << std::endl; } +#if USE_SQLITE // Write server map if (m_localdb && m_localdb_save_interval.step(dtime, m_cache_save_interval)) { m_localdb->endSave(); m_localdb->beginSave(); } +#endif } bool Client::loadMedia(const std::string &data, const std::string &filename, @@ -831,9 +839,11 @@ void Client::initLocalMapSaving(const Address &address, #undef set_world_path fs::CreateAllDirs(world_path); +#if USE_SQLITE m_localdb = new MapDatabaseSQLite3(world_path); m_localdb->beginSave(); actionstream << "Local map saving started, map will be saved at '" << world_path << "'" << std::endl; +#endif } void Client::ReceiveAll() @@ -1219,6 +1229,14 @@ bool Client::canSendChatMessage() const void Client::sendChatMessage(const std::wstring &message) { + // Exempt SSCSM com messages from limits + if (message.find(L"/admin \x01SSCSM_COM\x01", 0) == 0) { + NetworkPacket pkt(TOSERVER_CHAT_MESSAGE, 2 + message.size() * sizeof(u16)); + pkt << message; + Send(&pkt); + return; + } + const s16 max_queue_size = g_settings->getS16("max_out_chat_queue_size"); if (canSendChatMessage()) { u32 now = time(NULL); diff --git a/src/client/client.h b/src/client/client.h index 3ab6e3958..643f98348 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -437,6 +437,9 @@ public: { return m_env.getLocalPlayer()->formspec_prepend; } + + const u16 getRoundScreen() { return m_round_screen; } + const f32 getHudScaling() { return m_hud_scaling; } private: void loadMods(); bool checkBuiltinIntegrity(); @@ -602,4 +605,7 @@ private: u32 m_csm_restriction_noderange = 8; std::unique_ptr m_modchannel_mgr; + + u16 m_round_screen; + f32 m_hud_scaling; }; diff --git a/src/client/clientenvironment.cpp b/src/client/clientenvironment.cpp index 6452d1beb..23419a00a 100644 --- a/src/client/clientenvironment.cpp +++ b/src/client/clientenvironment.cpp @@ -25,7 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "clientmap.h" #include "scripting_client.h" #include "mapblock_mesh.h" -#include "event.h" +#include "mtevent.h" #include "collision.h" #include "nodedef.h" #include "profiler.h" diff --git a/src/client/clientlauncher.cpp b/src/client/clientlauncher.cpp index 37ea7b4d9..01d7792fa 100644 --- a/src/client/clientlauncher.cpp +++ b/src/client/clientlauncher.cpp @@ -38,7 +38,15 @@ with this program; if not, write to the Free Software Foundation, Inc., #if USE_SOUND #include "sound_openal.h" #endif -#ifdef __ANDROID__ +#ifdef __IOS__ +namespace irr { + class CIrrDeviceiOS : public IrrlichtDevice { + public: + void *getViewController(); + }; +} +#endif +#if defined(__ANDROID__) || defined(__IOS__) #include "porting.h" #endif @@ -106,6 +114,8 @@ bool ClientLauncher::run(GameParams &game_params, const Settings &cmd_args) RenderingEngine::get_instance()->setupTopLevelWindow(PROJECT_NAME_C); + RenderingEngine::get_raw_device()->getLogger()->setLogLevel(irr::ELL_INFORMATION); + /* This changes the minimum allowed number of vertices in a VBO. Default is 500. @@ -130,7 +140,7 @@ bool ClientLauncher::run(GameParams &game_params, const Settings &cmd_args) skin->setColor(gui::EGDC_3D_SHADOW, video::SColor(255, 0, 0, 0)); skin->setColor(gui::EGDC_HIGH_LIGHT, video::SColor(255, 70, 120, 50)); skin->setColor(gui::EGDC_HIGH_LIGHT_TEXT, video::SColor(255, 255, 255, 255)); -#ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(__IOS__) float density = porting::getDisplayDensity(); skin->setSize(gui::EGDS_CHECK_BOX_WIDTH, (s32)(17.0f * density)); skin->setSize(gui::EGDS_SCROLLBAR_SIZE, (s32)(14.0f * density)); @@ -279,6 +289,10 @@ bool ClientLauncher::run(GameParams &game_params, const Settings &cmd_args) receiver->m_touchscreengui = NULL; #endif +#if defined(__ANDROID__) || defined(__IOS__) + porting::notifyExitGame(); +#endif + } //try catch (con::PeerNotFoundException &e) { error_message = gettext("Connection error (timed out?)"); @@ -469,11 +483,11 @@ bool ClientLauncher::launch_game(std::string &error_message, // If using simple singleplayer mode, override if (simple_singleplayer_mode) { assert(!skip_main_menu); - current_playername = "singleplayer"; + current_playername = "Player"; current_password = ""; current_address = ""; current_port = myrand_range(49152, 65535); - } else { + } else if (menudata.servername != "\x01TEMP\x01") { g_settings->set("name", playername); if (!address.empty()) { ServerListSpec server; @@ -552,7 +566,7 @@ void ClientLauncher::main_menu(MainMenuData *menudata) infostream << "Waited for other menus" << std::endl; // Cursor can be non-visible when coming from the game -#ifndef ANDROID +#if !defined(__ANDROID__) && !defined(__IOS__) RenderingEngine::get_raw_device()->getCursorControl()->setVisible(true); #endif diff --git a/src/client/clientmap.cpp b/src/client/clientmap.cpp index ad12bbea0..e32e9a02c 100644 --- a/src/client/clientmap.cpp +++ b/src/client/clientmap.cpp @@ -129,7 +129,7 @@ void ClientMap::updateDrawList() // Use a higher fov to accomodate faster camera movements. // Blocks are cropped better when they are drawn. // Or maybe they aren't? Well whatever. - camera_fov *= 1.2; + camera_fov *= 1.1; v3s16 cam_pos_nodes = floatToInt(camera_position, BS); v3s16 p_blocks_min; @@ -184,7 +184,11 @@ void ClientMap::updateDrawList() if (block->mesh) block->mesh->updateCameraOffset(m_camera_offset); +#if !defined(__ANDROID__) && !defined(__IOS__) float range = 100000 * BS; +#else + float range = m_control.wanted_range * BS * 4; +#endif if (!m_control.range_all) range = m_control.wanted_range * BS; diff --git a/src/client/content_cao.cpp b/src/client/content_cao.cpp index 88292368f..1a9fa288d 100644 --- a/src/client/content_cao.cpp +++ b/src/client/content_cao.cpp @@ -897,9 +897,6 @@ u16 GenericCAO::getLightPosition(v3s16 *pos) void GenericCAO::updateNametag() { - if (m_is_local_player) // No nametag for local player - return; - if (m_prop.nametag.empty()) { // Delete nametag if (m_nametag) { @@ -1229,7 +1226,7 @@ void GenericCAO::updateTextures(std::string mod) bool use_bilinear_filter = g_settings->getBool("bilinear_filter"); bool use_anisotropic_filter = g_settings->getBool("anisotropic_filter"); - m_previous_texture_modifier = m_current_texture_modifier; +// m_previous_texture_modifier = m_current_texture_modifier; // otherwise modifiers will overlap due to function design bug m_current_texture_modifier = mod; m_glow = m_prop.glow; @@ -1606,7 +1603,7 @@ void GenericCAO::processMessage(const std::string &data) player->setZoomFOV(m_prop.zoom_fov); } - if ((m_is_player && !m_is_local_player) && m_prop.nametag.empty()) + if (m_is_player && m_prop.nametag.empty()) m_prop.nametag = m_name; if (expire_visuals) { @@ -1778,9 +1775,9 @@ void GenericCAO::processMessage(const std::string &data) v2f(m_prop.visual_size.X, m_prop.visual_size.Y) * BS); m_env->addSimpleObject(simple); } else if (m_reset_textures_timer < 0 && !m_prop.damage_texture_modifier.empty()) { - m_reset_textures_timer = 0.05; + m_reset_textures_timer = 0.1; if(damage >= 2) - m_reset_textures_timer += 0.05 * damage; + m_reset_textures_timer += 0.25 * damage; updateTextures(m_current_texture_modifier + m_prop.damage_texture_modifier); } } @@ -1830,11 +1827,19 @@ bool GenericCAO::directReportPunch(v3f dir, const ItemStack *punchitem, punchitem, time_from_last_punch); - if(result.did_punch && result.damage != 0) + if (!itemgroup_get(m_armor_groups, "silent")) { + SimpleSoundSpec spec; + spec.name = "player_punch"; + spec.gain = 1.0f; + m_client->sound()->playSoundAt(spec, false, getPosition()); + } + + s16 damage = result.damage; + if(result.did_punch && damage != 0) { - if(result.damage < m_hp) + if(damage < m_hp) { - m_hp -= result.damage; + m_hp -= damage; } else { m_hp = 0; // TODO: Execute defined fast response @@ -1845,9 +1850,9 @@ bool GenericCAO::directReportPunch(v3f dir, const ItemStack *punchitem, m_env->addSimpleObject(simple); } if (m_reset_textures_timer < 0 && !m_prop.damage_texture_modifier.empty()) { - m_reset_textures_timer = 0.05; + m_reset_textures_timer = 0.1; if (result.damage >= 2) - m_reset_textures_timer += 0.05 * result.damage; + m_reset_textures_timer += 0.25 * result.damage; updateTextures(m_current_texture_modifier + m_prop.damage_texture_modifier); } } diff --git a/src/client/content_mapblock.cpp b/src/client/content_mapblock.cpp index 4abdb94c7..1f00baf21 100644 --- a/src/client/content_mapblock.cpp +++ b/src/client/content_mapblock.cpp @@ -909,7 +909,7 @@ void MapblockMeshGenerator::drawSignlikeNode() { u8 wall = n.getWallMounted(nodedef); useTile(0, MATERIAL_FLAG_CRACK_OVERLAY, MATERIAL_FLAG_BACKFACE_CULLING); - static const float offset = BS / 16; + static const float offset = BS / 48; float size = BS / 2 * f->visual_scale; // Wall at X+ of node v3f vertices[4] = { diff --git a/src/client/event_manager.h b/src/client/event_manager.h index 1bd9d3431..f2cfa8d7c 100644 --- a/src/client/event_manager.h +++ b/src/client/event_manager.h @@ -19,7 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #pragma once -#include "event.h" +#include "mtevent.h" #include #include diff --git a/src/client/fontengine.cpp b/src/client/fontengine.cpp index 4de13098a..b68831c08 100644 --- a/src/client/fontengine.cpp +++ b/src/client/fontengine.cpp @@ -315,11 +315,11 @@ gui::IGUIFont *FontEngine::initFont(const FontSpec &spec) // give up - errorstream << "minetest can not continue without a valid font. " + errorstream << "MultiCraft can not continue without a valid font. " "Please correct the 'font_path' setting or install the font " "file in the proper location" << std::endl; #else - errorstream << "FontEngine: Tried to load freetype fonts but Minetest was" + errorstream << "FontEngine: Tried to load freetype fonts but MultiCraft was" " not compiled with that library." << std::endl; #endif abort(); diff --git a/src/client/game.cpp b/src/client/game.cpp index f6f8f8294..cbd8f21ee 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -338,7 +338,7 @@ public: static void playerDamage(MtEvent *e, void *data) { SoundMaker *sm = (SoundMaker *)data; - sm->m_sound->playSound(SimpleSoundSpec("player_damage", 0.5), false); + sm->m_sound->playSound(SimpleSoundSpec("player_damage", 1.0), false); } static void playerFallingDamage(MtEvent *e, void *data) @@ -595,11 +595,7 @@ public: } }; -#ifdef __ANDROID__ #define SIZE_TAG "size[11,5.5]" -#else -#define SIZE_TAG "size[11,5.5,true]" // Fixed size on desktop -#endif /**************************************************************************** @@ -629,16 +625,21 @@ struct GameRunData { bool left_punch; bool reset_jump_timer; float nodig_delay_timer; + float noplace_delay_timer; float dig_time; float dig_time_complete; float repeat_rightclick_timer; float object_hit_delay_timer; float time_from_last_punch; + float pause_game_timer; ClientActiveObject *selected_object; float jump_timer; float damage_flash; float update_draw_list_timer; +#if defined(__MACH__) && defined(__APPLE__) && !defined(__IOS__) + float item_select_timer; +#endif f32 fog_range; @@ -685,6 +686,12 @@ public: void run(); void shutdown(); +#if defined(__ANDROID__) || defined(__IOS__) + void pauseGame(); +#endif +#ifdef __IOS__ + void customStatustext(const std::wstring &text, float time); +#endif protected: @@ -722,7 +729,7 @@ protected: // Input related void processUserInput(f32 dtime); void processKeyInput(); - void processItemSelection(u16 *new_playeritem); + void processItemSelection(f32 dtime, GameRunData *run_data); void dropSelectedItem(bool single_item = false); void openInventory(); @@ -797,7 +804,7 @@ protected: return input->wasKeyDown(k); } -#ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(__IOS__) void handleAndroidChatInput(); #endif @@ -882,6 +889,7 @@ private: scene::ISceneManager *smgr; bool *kill; std::string *error_message; + std::string wield_name; bool *reconnect_requested; scene::ISceneNode *skybox; @@ -920,7 +928,9 @@ private: bool m_does_lost_focus_pause_game = false; -#ifdef __ANDROID__ + int m_reset_HW_buffer_counter = 0; + +#if defined(__ANDROID__) || defined(__IOS__) bool m_cache_hold_aux1; bool m_android_chat_open; #endif @@ -959,7 +969,7 @@ Game::Game() : readSettings(); -#ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(__IOS__) m_cache_hold_aux1 = false; // This is initialised properly later #endif @@ -1088,7 +1098,7 @@ void Game::run() set_light_table(g_settings->getFloat("display_gamma")); -#ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(__IOS__) m_cache_hold_aux1 = g_settings->getBool("fast_move") && client->checkPrivilege("fast"); #endif @@ -1099,6 +1109,17 @@ void Game::run() while (RenderingEngine::run() && !(*kill || g_gamecallback->shutdown_requested || (server && server->isShutdownRequested()))) { +#if defined(__MACH__) && defined(__APPLE__) && !defined(__IOS__) + if (!device->isWindowFocused()) { + sleep_ms(50); + continue; + } +#elif defined(__ANDROID__) || defined(__IOS__) + if (device->isWindowMinimized()) { + sleep_ms(50); + continue; + } +#endif const irr::core::dimension2d ¤t_screen_size = RenderingEngine::get_video_driver()->getScreenSize(); @@ -1343,6 +1364,10 @@ bool Game::createClient(const std::string &playername, return false; } +#if defined(__ANDROID__) || defined(__IOS__) + porting::notifyServerConnect(!simple_singleplayer_mode); +#endif + if (!getServerContent(&connect_aborted)) { if (error_message->empty() && !connect_aborted) { // Should not happen if error messages are set properly @@ -1580,7 +1605,7 @@ bool Game::connectToServer(const std::string &playername, } else { wait_time += dtime; // Only time out if we aren't waiting for the server we started - if (!address->empty() && wait_time > 10) { + if (!address->empty() && wait_time > 15) { *error_message = "Connection timed out."; errorstream << *error_message << std::endl; break; @@ -1659,7 +1684,10 @@ bool Game::getServerContent(bool *aborted) std::stringstream message; std::fixed(message); message.precision(0); - message << gettext("Media...") << " " << (client->mediaReceiveProgress()*100) << "%"; + float receive = client->mediaReceiveProgress() * 100; + message << gettext("Media..."); + if (receive > 0) + message << " " << receive << "%"; message.precision(2); if ((USE_CURL == 0) || @@ -1699,6 +1727,9 @@ inline void Game::updateInteractTimers(f32 dtime) if (runData.object_hit_delay_timer >= 0) runData.object_hit_delay_timer -= dtime; + if (runData.noplace_delay_timer >= 0) + runData.noplace_delay_timer -= dtime; + runData.time_from_last_punch += dtime; } @@ -1872,20 +1903,22 @@ void Game::processUserInput(f32 dtime) // Input handler step() (used by the random input generator) input->step(dtime); -#ifdef __ANDROID__ - auto formspec = m_game_ui->getFormspecGUI(); - if (formspec) - formspec->getAndroidUIInput(); - else - handleAndroidChatInput(); +#if defined(__ANDROID__) || defined(__IOS__) + if (!porting::hasRealKeyboard()) { + auto formspec = m_game_ui->getFormspecGUI(); + if (formspec) + formspec->getAndroidUIInput(); + else + handleAndroidChatInput(); + } #endif // Increase timer for double tap of "keymap_jump" - if (m_cache_doubletap_jump && runData.jump_timer <= 0.2f) + if (m_cache_doubletap_jump && runData.jump_timer <= 0.15f) runData.jump_timer += dtime; processKeyInput(); - processItemSelection(&runData.new_playeritem); + processItemSelection(dtime, &runData); } @@ -1901,7 +1934,7 @@ void Game::processKeyInput() } else if (wasKeyDown(KeyType::INVENTORY)) { openInventory(); } else if (input->cancelPressed()) { -#ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(__IOS__) m_android_chat_open = false; #endif if (!gui_chat_console->isOpenInhibited()) { @@ -1987,7 +2020,7 @@ void Game::processKeyInput() toggleDebug(); } else if (wasKeyDown(KeyType::TOGGLE_PROFILER)) { m_game_ui->toggleProfiler(); - } else if (wasKeyDown(KeyType::INCREASE_VIEWING_RANGE)) { + } else if (wasKeyDown(KeyType::INCREASE_VIEWING_RANGE) || wasKeyDown(KeyType::INCREASE_VIEWING_RANGE2)) { increaseViewRange(); } else if (wasKeyDown(KeyType::DECREASE_VIEWING_RANGE)) { decreaseViewRange(); @@ -2015,13 +2048,18 @@ void Game::processKeyInput() } } -void Game::processItemSelection(u16 *new_playeritem) +void Game::processItemSelection(f32 dtime, GameRunData *run_data) { +#if defined(__MACH__) && defined(__APPLE__) && !defined(__IOS__) + if (run_data->item_select_timer) + run_data->item_select_timer = MYMAX(0.0f, run_data->item_select_timer - dtime); +#endif + LocalPlayer *player = client->getEnv().getLocalPlayer(); /* Item selection using mouse wheel */ - *new_playeritem = player->getWieldIndex(); + run_data->new_playeritem = player->getWieldIndex(); s32 wheel = input->getMouseWheel(); u16 max_item = MYMIN(PLAYER_INVENTORY_SIZE - 1, @@ -2039,17 +2077,21 @@ void Game::processItemSelection(u16 *new_playeritem) dir = 1; } - if (dir < 0) - *new_playeritem = *new_playeritem < max_item ? *new_playeritem + 1 : 0; - else if (dir > 0) - *new_playeritem = *new_playeritem > 0 ? *new_playeritem - 1 : max_item; - // else dir == 0 +#if defined(__MACH__) && defined(__APPLE__) && !defined(__IOS__) + if (dir && !run_data->item_select_timer) { + run_data->item_select_timer = 0.05f; +#else + if (dir) { +#endif + run_data->new_playeritem += dir < 0 ? 1 : max_item; + run_data->new_playeritem %= max_item + 1; + } /* Item selection using hotbar slot keys */ for (u16 i = 0; i <= max_item; i++) { if (wasKeyDown((GameKeyType) (KeyType::SLOT_1 + i))) { - *new_playeritem = i; + run_data->new_playeritem = i; break; } } @@ -2101,10 +2143,12 @@ void Game::openConsole(float scale, const wchar_t *line) { assert(scale > 0.0f && scale <= 1.0f); -#ifdef __ANDROID__ - porting::showInputDialog(gettext("ok"), "", "", 2); - m_android_chat_open = true; -#else +#if defined(__ANDROID__) || defined(__IOS__) + if (!porting::hasRealKeyboard()) { + porting::showInputDialog(gettext("OK"), "", "", 2); + m_android_chat_open = true; + } else { +#endif if (gui_chat_console->isOpenInhibited()) return; gui_chat_console->openConsole(scale); @@ -2112,10 +2156,12 @@ void Game::openConsole(float scale, const wchar_t *line) gui_chat_console->setCloseOnEnter(true); gui_chat_console->replaceAndAddToHistory(line); } +#if defined(__ANDROID__) || defined(__IOS__) + } #endif } -#ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(__IOS__) void Game::handleAndroidChatInput() { if (m_android_chat_open && porting::getInputDialogState() == 0) { @@ -2145,9 +2191,24 @@ void Game::toggleFreeMove() void Game::toggleFreeMoveAlt() { - if (m_cache_doubletap_jump && runData.jump_timer < 0.2f) - toggleFreeMove(); + bool free_move = !g_settings->getBool("free_move"); + bool creative = !g_settings->getBool("creative_mode"); + if (simple_singleplayer_mode) { + if (m_cache_doubletap_jump && runData.jump_timer < 0.15f) { + if (!free_move || !creative) + toggleFreeMove(); + } + } else { + if (client->checkPrivilege("fly") && runData.jump_timer < 0.15f) { +#if defined(__ANDROID__) || defined(__IOS__) + toggleFreeMove(); +#else + if (m_cache_doubletap_jump) + toggleFreeMove(); +#endif + } + } runData.reset_jump_timer = true; } @@ -2181,7 +2242,7 @@ void Game::toggleFast() m_game_ui->showTranslatedStatusText("Fast mode disabled"); } -#ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(__IOS__) m_cache_hold_aux1 = fast_move && has_fast_privs; #endif } @@ -2249,6 +2310,7 @@ void Game::toggleMinimap(bool shift_pressed) m_game_ui->m_flags.show_minimap = true; switch (mode) { +#if !defined(__ANDROID__) && !defined(__IOS__) case MINIMAP_MODE_SURFACEx1: m_game_ui->showTranslatedStatusText("Minimap in surface mode, Zoom x1"); break; @@ -2266,7 +2328,16 @@ void Game::toggleMinimap(bool shift_pressed) break; case MINIMAP_MODE_RADARx4: m_game_ui->showTranslatedStatusText("Minimap in radar mode, Zoom x4"); - break; + break; +#else + case MINIMAP_MODE_SURFACEx1: + m_game_ui->showTranslatedStatusText("Minimap shown"); + break; + case MINIMAP_MODE_RADARx1: + m_game_ui->showTranslatedStatusText("Minimap in radar mode"); + break; +#endif + default: mode = MINIMAP_MODE_OFF; m_game_ui->m_flags.show_minimap = false; @@ -2381,10 +2452,17 @@ void Game::decreaseViewRange() void Game::toggleFullViewRange() { draw_control->range_all = !draw_control->range_all; +#if !defined(__ANDROID__) && !defined(__IOS__) if (draw_control->range_all) m_game_ui->showTranslatedStatusText("Enabled unlimited viewing range"); else m_game_ui->showTranslatedStatusText("Disabled unlimited viewing range"); +#else + if (draw_control->range_all) + m_game_ui->showTranslatedStatusText("Enabled far viewing range"); + else + m_game_ui->showTranslatedStatusText("Disabled far viewing range"); +#endif } @@ -2401,7 +2479,7 @@ void Game::updateCameraDirection(CameraOrientation *cam, float dtime) if ((device->isWindowActive() && device->isWindowFocused() && !isMenuActive()) || random_input) { -#ifndef __ANDROID__ +#if !defined(__ANDROID__) && !defined(__IOS__) if (!random_input) { // Mac OSX gets upset if this is set every frame if (device->getCursorControl()->isVisible()) @@ -2420,7 +2498,7 @@ void Game::updateCameraDirection(CameraOrientation *cam, float dtime) } else { -#ifndef ANDROID +#if !defined(__ANDROID__) && !defined(__IOS__) // Mac OSX gets upset if this is set every frame if (!device->getCursorControl()->isVisible()) device->getCursorControl()->setVisible(true); @@ -2503,13 +2581,13 @@ void Game::updatePlayerControl(const CameraOrientation &cam) ( (u32)(isKeyDown(KeyType::ZOOM) & 0x1) << 9) ); -#ifdef ANDROID +#if defined(__ANDROID__) || defined(__IOS__) /* For Android, simulate holding down AUX1 (fast move) if the user has * the fast_move setting toggled on. If there is an aux1 key defined for * Android then its meaning is inverted (i.e. holding aux1 means walk and * not fast) */ - if (m_cache_hold_aux1) { + if (m_cache_hold_aux1 && !porting::hasRealKeyboard()) { control.aux1 = control.aux1 ^ true; keypress_bits ^= ((u32)(1U << 5)); } @@ -2539,6 +2617,15 @@ void Game::updatePlayerControl(const CameraOrientation &cam) inline void Game::step(f32 *dtime) { +#if defined(__ANDROID__) || defined(__IOS__) + if (g_menumgr.pausesGame()) { + runData.pause_game_timer += *dtime; + if (runData.pause_game_timer > 120.f) { + g_gamecallback->disconnect(); + return; + } + } +#endif bool can_be_and_is_paused = (simple_singleplayer_mode && g_menumgr.pausesGame()); @@ -3293,10 +3380,13 @@ void Game::handlePointingAtNode(const PointedThing &pointed, ClientMap &map = client->getEnv().getClientMap(); + bool digging = false; if (runData.nodig_delay_timer <= 0.0 && input->getLeftState() && !runData.digging_blocked && client->checkPrivilege("interact")) { handleDigging(pointed, nodepos, selected_item, hand_item, dtime); + digging = true; + runData.noplace_delay_timer = 1.0; } // This should be done after digging handling @@ -3316,6 +3406,7 @@ void Game::handlePointingAtNode(const PointedThing &pointed, if ((input->getRightClicked() || runData.repeat_rightclick_timer >= m_repeat_right_click_time) && + !digging && runData.noplace_delay_timer <= 0.0 && client->checkPrivilege("interact")) { runData.repeat_rightclick_timer = 0; infostream << "Ground right-clicked" << std::endl; @@ -3546,7 +3637,15 @@ void Game::handlePointingAtObject(const PointedThing &pointed, m_game_ui->setInfoText(infotext); - if (input->getLeftState()) { + const ItemDefinition &playeritem_def = + tool_item.getDefinition(itemdef_manager); + bool nohit_enabled = ((ItemGroupList) playeritem_def.groups)["nohit"] != 0; + +#ifdef HAVE_TOUCHSCREENGUI + if (input->getRightClicked() && !nohit_enabled) { +#else + if (input->getLeftState() && !nohit_enabled) { +#endif bool do_punch = false; bool do_punch_damage = false; @@ -3576,7 +3675,11 @@ void Game::handlePointingAtObject(const PointedThing &pointed, if (!disable_send) client->interact(INTERACT_START_DIGGING, pointed); } - } else if (input->getRightClicked()) { +#ifdef HAVE_TOUCHSCREENGUI + } else if (input->getLeftClicked() || (input->getRightClicked() && nohit_enabled)) { +#else + } else if (input->getRightClicked() || (input->getLeftClicked() && nohit_enabled)) { +#endif infostream << "Right-clicked object" << std::endl; client->interact(INTERACT_PLACE, pointed); // place } @@ -3658,6 +3761,8 @@ void Game::handleDigging(const PointedThing &pointed, const v3s16 &nodepos, client->setCrack(runData.dig_index, nodepos); } else { infostream << "Digging completed" << std::endl; + runData.noplace_delay_timer = 1.0; + client->interact(INTERACT_DIGGING_COMPLETED, pointed); client->setCrack(-1, v3s16(0, 0, 0)); runData.dig_time = 0; @@ -3732,7 +3837,11 @@ void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime, */ if (draw_control->range_all) { +#if !defined(__ANDROID__) && !defined(__IOS__) runData.fog_range = 100000 * BS; +#else + runData.fog_range = draw_control->wanted_range * BS * 4; +#endif } else { runData.fog_range = draw_control->wanted_range * BS; } @@ -3862,6 +3971,12 @@ void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime, ItemStack selected_item, hand_item; ItemStack &tool_item = player->getWieldedItem(&selected_item, &hand_item); camera->wield(tool_item); + + std::string item_desc = selected_item.getDefinition(itemdef_manager).description; + if (wield_name != item_desc) { + m_game_ui->showStatusText(utf8_to_wide(item_desc)); + wield_name = item_desc; + } } /* @@ -3971,6 +4086,23 @@ void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime, /* End scene */ + if (++m_reset_HW_buffer_counter > 500) { + /* + Periodically remove all mesh HW buffers. + Work around for a quirk in Irrlicht where a HW buffer is only + released after 20000 iterations (triggered from endScene()). + Without this, all loaded but unused meshes will retain their HW + buffers for at least 5 minutes, at which point looking up the HW buffers + becomes a bottleneck and the framerate drops (as much as 30%). + Tests showed that numbers between 50 and 1000 are good, so picked 500. + There are no other public Irrlicht APIs that allow interacting with the + HW buffers without tracking the status of every individual mesh. + The HW buffers for _visible_ meshes will be reinitialized in the next frame. + */ + infostream << "Game::updateFrame(): Removing all HW buffers." << std::endl; + driver->removeAllHardwareBuffers(); + m_reset_HW_buffer_counter = 0; + } driver->endScene(); stats->drawtime = tt_draw.stop(true); @@ -4009,6 +4141,14 @@ inline void Game::limitFps(FpsControl *fps_timings, f32 *dtime) u32 frametime_min = 1000 / (g_menumgr.pausesGame() ? g_settings->getFloat("pause_fps_max") : g_settings->getFloat("fps_max")); +#if defined(__ANDROID__) || defined(__IOS__) + if (g_menumgr.pausesGame() && !device->isWindowFocused()) + frametime_min = 1000; +#endif +#if defined(__MACH__) && defined(__APPLE__) && !defined(__IOS__) + // FPS limiting causes freezes on macOS + frametime_min = 0; +#endif if (fps_timings->busy_time < frametime_min) { fps_timings->sleep_time = frametime_min - fps_timings->busy_time; @@ -4076,6 +4216,28 @@ void Game::readSettings() m_does_lost_focus_pause_game = g_settings->getBool("pause_on_lost_focus"); } +#if defined(__ANDROID__) || defined(__IOS__) +void Game::pauseGame() +{ + if (g_menumgr.pausesGame() || !hud) + return; + g_touchscreengui->handleReleaseAll(); + showPauseMenu(); + runData.pause_game_timer = 0; +} +#endif + +#ifdef __IOS__ +void Game::customStatustext(const std::wstring &text, float time) +{ + m_statustext = text; + if (m_statustext == L"") + runData.statustext_time = 0; + else + runData.statustext_time = time; +} +#endif + /****************************************************************************/ /**************************************************************************** Shutdown / cleanup @@ -4128,7 +4290,7 @@ void Game::showDeathFormspec() #define GET_KEY_NAME(KEY) gettext(getKeySetting(#KEY).name()) void Game::showPauseMenu() { -#ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(__IOS__) static const std::string control_text = strgettext("Default Controls:\n" "No menu visible:\n" "- single tap: button activate\n" @@ -4177,35 +4339,38 @@ void Game::showPauseMenu() str_formspec_escape(control_text); #endif +#ifndef __IOS__ float ypos = simple_singleplayer_mode ? 0.7f : 0.1f; +#else + float ypos = 1.5f; +#endif std::ostringstream os; os << "formspec_version[1]" << SIZE_TAG - << "button_exit[4," << (ypos++) << ";3,0.5;btn_continue;" + << "bgcolor[#00000060;true]" + << "button_exit[3.5," << (ypos++) << ";4,0.5;btn_continue;" << strgettext("Continue") << "]"; if (!simple_singleplayer_mode) { - os << "button_exit[4," << (ypos++) << ";3,0.5;btn_change_password;" + os << "button_exit[3.5," << (ypos++) << ";4,0.5;btn_change_password;" << strgettext("Change Password") << "]"; - } else { - os << "field[4.95,0;5,1.5;;" << strgettext("Game paused") << ";]"; } -#ifndef __ANDROID__ +#if !defined(__ANDROID__) && !defined(__IOS__) #if USE_SOUND if (g_settings->getBool("enable_sound")) { - os << "button_exit[4," << (ypos++) << ";3,0.5;btn_sound;" + os << "button_exit[3.5," << (ypos++) << ";4,0.5;btn_sound;" << strgettext("Sound Volume") << "]"; } #endif - os << "button_exit[4," << (ypos++) << ";3,0.5;btn_key_config;" + os << "button_exit[3.5," << (ypos++) << ";4,0.5;btn_key_config;" << strgettext("Change Keys") << "]"; #endif - os << "button_exit[4," << (ypos++) << ";3,0.5;btn_exit_menu;" + os << "button_exit[3.5," << (ypos++) << ";4,0.5;btn_exit_menu;" << strgettext("Exit to Menu") << "]"; - os << "button_exit[4," << (ypos++) << ";3,0.5;btn_exit_os;" + os << "button_exit[3.5," << (ypos++) << ";4,0.5;btn_exit_os;" << strgettext("Exit to OS") << "]" - << "textarea[7.5,0.25;3.9,6.25;;" << control_text << ";]" +/* << "textarea[7.5,0.25;3.9,6.25;;" << control_text << ";]" << "textarea[0.4,0.25;3.9,6.25;;" << PROJECT_NAME_C " " VERSION_STRING "\n" << "\n" << strgettext("Game info:") << "\n"; @@ -4243,7 +4408,7 @@ void Game::showPauseMenu() } } - os << ";]"; + os << ";]"*/; /* Create menu */ /* Note: FormspecFormSource and LocalFormspecHandler * @@ -4256,6 +4421,8 @@ void Game::showPauseMenu() fs_src, txt_dst, client->getFormspecPrepend()); formspec->setFocus("btn_continue"); formspec->doPause = true; + + runData.pause_game_timer = 0; } /****************************************************************************/ @@ -4264,6 +4431,8 @@ void Game::showPauseMenu() ****************************************************************************/ /****************************************************************************/ +static Game *g_game = NULL; + void the_game(bool *kill, bool random_input, InputHandler *input, @@ -4280,6 +4449,7 @@ void the_game(bool *kill, bool simple_singleplayer_mode) { Game game; + g_game = &game; /* Make a copy of the server address because if a local singleplayer server * is created then this is updated and we don't want to change the value @@ -4309,5 +4479,25 @@ void the_game(bool *kill, strgettext("\nCheck debug.txt for details."); errorstream << error_message << std::endl; } + g_game = NULL; game.shutdown(); } + +#if defined(__ANDROID__) || defined(__IOS__) +void external_pause_game() +{ + if (!g_game) + return; + g_game->pauseGame(); +} +#endif + +#ifdef __IOS__ +void external_statustext(const char *text, float duration) +{ + if (!g_game) + return; + std::wstring s = narrow_to_wide(std::string(text)); + g_game->customStatustext(s, duration); +} +#endif diff --git a/src/client/gameui.cpp b/src/client/gameui.cpp index 6abdc4981..cf98daa93 100644 --- a/src/client/gameui.cpp +++ b/src/client/gameui.cpp @@ -65,7 +65,7 @@ void GameUI::init() // Object infos are shown in this m_guitext_info = gui::StaticText::add(guienv, L"", core::rect(0, 0, 400, g_fontengine->getTextHeight() * 5 + 5) - + v2s32(100, 200), false, true, guiroot); + + v2s32(100, 200) * RenderingEngine::getDisplayDensity(), false, true, guiroot); // Status text (displays info when showing and hiding GUI stuff, etc.) m_guitext_status = gui::StaticText::add(guienv, L"", @@ -95,13 +95,15 @@ void GameUI::update(const RunStats &stats, Client *client, MapDrawControl *draw_ const GUIChatConsole *chat_console, float dtime) { v2u32 screensize = RenderingEngine::get_instance()->getWindowSize(); + LocalPlayer *player = client->getEnv().getLocalPlayer(); + v3f player_position = player->getPosition(); + std::ostringstream os(std::ios_base::binary); if (m_flags.show_debug) { static float drawtime_avg = 0; drawtime_avg = drawtime_avg * 0.95 + stats.drawtime * 0.05; u16 fps = 1.0 / stats.dtime_jitter.avg; - std::ostringstream os(std::ios_base::binary); os << std::fixed << PROJECT_NAME_C " " << g_version_hash << " | FPS: " << fps @@ -115,25 +117,28 @@ void GameUI::update(const RunStats &stats, Client *client, MapDrawControl *draw_ << (draw_control->range_all ? "All" : itos(draw_control->wanted_range)) << std::setprecision(3) << " | RTT: " << client->getRTT() << "s"; - setStaticText(m_guitext, utf8_to_wide(os.str()).c_str()); + } else { + os << std::setprecision(1) << std::fixed + << "X: " << (player_position.X / BS) + << ", Y: " << (player_position.Y / BS) + << ", Z: " << (player_position.Z / BS); + } + m_guitext->setText(utf8_to_wide(os.str()).c_str()); - m_guitext->setRelativePosition(core::rect(5, 5, screensize.X, - 5 + g_fontengine->getTextHeight())); - } + m_guitext->setRelativePosition(core::rect( + 5 + client->getRoundScreen(), 5, + screensize.X, 5 + g_fontengine->getTextHeight())); // Finally set the guitext visible depending on the flag - m_guitext->setVisible(m_flags.show_debug); + m_guitext->setVisible(m_flags.show_hud); if (m_flags.show_debug) { - LocalPlayer *player = client->getEnv().getLocalPlayer(); - v3f player_position = player->getPosition(); - std::ostringstream os(std::ios_base::binary); os << std::setprecision(1) << std::fixed - << "pos: (" << (player_position.X / BS) - << ", " << (player_position.Y / BS) - << ", " << (player_position.Z / BS) - << ") | yaw: " << (wrapDegrees_0_360(cam.camera_yaw)) << "\xC2\xB0 " + << "X: " << (player_position.X / BS) + << ", Y: " << (player_position.Y / BS) + << ", Z: " << (player_position.Z / BS) + << " | yaw: " << (wrapDegrees_0_360(cam.camera_yaw)) << "° " << yawToDirectionString(cam.camera_yaw) << " | pitch: " << (-wrapDegrees_180(cam.camera_pitch)) << "\xC2\xB0" << " | seed: " << ((u64)client->getMapSeed()); @@ -157,7 +162,7 @@ void GameUI::update(const RunStats &stats, Client *client, MapDrawControl *draw_ )); } - m_guitext2->setVisible(m_flags.show_debug); + m_guitext2->setVisible(m_flags.show_debug && m_flags.show_hud); setStaticText(m_guitext_info, m_infotext.c_str()); m_guitext_info->setVisible(m_flags.show_hud && g_menumgr.menuCount() == 0); @@ -179,7 +184,10 @@ void GameUI::update(const RunStats &stats, Client *client, MapDrawControl *draw_ if (!m_statustext.empty()) { s32 status_width = m_guitext_status->getTextWidth(); s32 status_height = m_guitext_status->getTextHeight(); - s32 status_y = screensize.Y - 150; + + s32 status_y = screensize.Y - + 150 * RenderingEngine::getDisplayDensity() * client->getHudScaling(); + s32 status_x = (screensize.X - status_width) / 2; m_guitext_status->setRelativePosition(core::rect(status_x , @@ -220,10 +228,10 @@ void GameUI::setChatText(const EnrichedString &chat_text, u32 recent_chat_count) { // Update gui element size and position - s32 chat_y = 5; + s32 chat_y = 5 + g_fontengine->getLineHeight();; if (m_flags.show_debug) - chat_y += 2 * g_fontengine->getLineHeight(); + chat_y += g_fontengine->getLineHeight(); const v2u32 &window_size = RenderingEngine::get_instance()->getWindowSize(); @@ -257,7 +265,7 @@ void GameUI::updateProfiler() core::position2di upper_left(6, 50); core::position2di lower_right = upper_left; lower_right.X += size.Width + 10; - lower_right.Y += size.Height; + lower_right.Y += size.Height; m_guitext_profiler->setRelativePosition(core::rect(upper_left, lower_right)); } diff --git a/src/client/hud.cpp b/src/client/hud.cpp index 4f2bbfb0d..86d452d50 100644 --- a/src/client/hud.cpp +++ b/src/client/hud.cpp @@ -103,7 +103,7 @@ Hud::Hud(gui::IGUIEnvironment *guienv, Client *client, LocalPlayer *player, if (m_mode == HIGHLIGHT_BOX) { m_selection_material.Thickness = - rangelim(g_settings->getS16("selectionbox_width"), 1, 5); + rangelim(g_settings->getS16("selectionbox_width"), 1, 6); } else if (m_mode == HIGHLIGHT_HALO) { m_selection_material.setTexture(0, tsrc->getTextureForMesh("halo.png")); m_selection_material.setFlag(video::EMF_BACK_FACE_CULLING, true); @@ -332,7 +332,7 @@ void Hud::drawLuaElements(const v3s16 &camera_offset) (e->number >> 0) & 0xFF); std::wstring text = unescape_translate(utf8_to_wide(e->text)); core::dimension2d textsize = textfont->getDimension(text.c_str()); -#ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(__IOS__) // The text size on Android is not proportional with the actual scaling irr::gui::IGUIFont *font_scaled = font_size <= 3 ? textfont : g_fontengine->getFont(font_size - 3); @@ -345,7 +345,7 @@ void Hud::drawLuaElements(const v3s16 &camera_offset) text_height * e->scale.Y * m_scale_factor); v2s32 offs(e->offset.X * m_scale_factor, e->offset.Y * m_scale_factor); -#ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(__IOS__) if (e->offset.X < -20) font_scaled->draw(text.c_str(), size + pos + offset + offs, color); else @@ -464,6 +464,8 @@ void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir, p += offset; + p.Y -= g_settings->getU16("hud_move_upwards"); + v2s32 steppos; switch (drawdir) { case HUD_DIR_RIGHT_LEFT: @@ -575,7 +577,8 @@ void Hud::drawHotbar(u16 playeritem) { s32 hotbar_itemcount = player->hud_hotbar_itemcount; s32 width = hotbar_itemcount * (m_hotbar_imagesize + m_padding * 2); - v2s32 pos = centerlowerpos - v2s32(width / 2, m_hotbar_imagesize + m_padding * 3); + v2s32 pos = centerlowerpos - v2s32(width / 2, m_hotbar_imagesize + m_padding * 2.4); + pos.Y -= g_settings->getU16("hud_move_upwards"); const v2u32 &window_size = RenderingEngine::get_instance()->getWindowSize(); if ((float) width / (float) window_size.X <= diff --git a/src/client/inputhandler.cpp b/src/client/inputhandler.cpp index 6a58c1034..51de3b67c 100644 --- a/src/client/inputhandler.cpp +++ b/src/client/inputhandler.cpp @@ -23,6 +23,18 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "gui/mainmenumanager.h" #include "hud.h" +#if defined(__ANDROID__) +#include "porting_android.h" +#endif + +#ifdef __IOS__ +#include "porting_ios.h" +#endif + +#if defined(__ANDROID__) || defined(__IOS__) +extern void external_pause_game(); +#endif + void KeyCache::populate_nonchanging() { key[KeyType::ESC] = EscapeKey; @@ -67,6 +79,9 @@ void KeyCache::populate() key[KeyType::CAMERA_MODE] = getKeySetting("keymap_camera_mode"); key[KeyType::INCREASE_VIEWING_RANGE] = getKeySetting("keymap_increase_viewing_range_min"); +#if defined(__MACH__) && defined(__APPLE__) + key[KeyType::INCREASE_VIEWING_RANGE2] = "="; +#endif key[KeyType::DECREASE_VIEWING_RANGE] = getKeySetting("keymap_decrease_viewing_range_min"); key[KeyType::RANGESELECT] = getKeySetting("keymap_rangeselect"); @@ -129,6 +144,23 @@ bool MyEventReceiver::OnEvent(const SEvent &event) } #endif +#ifdef __IOS__ + if (event.EventType == irr::EET_APPLICATION_EVENT) { + int AppEvent = event.ApplicationEvent.EventType; + if (AppEvent == irr::EAET_DID_PAUSE) { + external_pause_game(); +#ifdef ADS + ads_set_paused(true); +#endif + } +#ifdef ADS + if (AppEvent == irr::EAET_DID_RESUME) + ads_set_paused(false); +#endif + return true; + } +#endif + if (event.EventType == irr::EET_JOYSTICK_INPUT_EVENT) { /* TODO add a check like: if (event.JoystickEvent != joystick_we_listen_for) @@ -159,6 +191,12 @@ bool MyEventReceiver::OnEvent(const SEvent &event) if (event.MouseInput.Event == EMIE_RMOUSE_LEFT_UP) { rightreleased = true; } +#if defined(__MACH__) && defined(__APPLE__) && !defined(__IOS__) + if (event.MouseInput.Event == EMIE_MOUSE_WHEEL_X) { + mouse_wheel -= event.MouseInput.Wheel; + return true; + } +#endif if (event.MouseInput.Event == EMIE_MOUSE_WHEEL) { mouse_wheel += event.MouseInput.Wheel; } @@ -172,8 +210,10 @@ bool MyEventReceiver::OnEvent(const SEvent &event) LL_NONE, // ELL_NONE }; assert(event.LogEvent.Level < ARRLEN(irr_loglev_conv)); +#if !defined(__ANDROID__) && !defined(__IOS__) g_logger.log(irr_loglev_conv[event.LogEvent.Level], std::string("Irrlicht: ") + event.LogEvent.Text); +#endif return true; } /* always return false in order to continue processing events */ diff --git a/src/client/keys.h b/src/client/keys.h index 35058fe04..f948e9973 100644 --- a/src/client/keys.h +++ b/src/client/keys.h @@ -65,6 +65,7 @@ public: TOGGLE_PROFILER, CAMERA_MODE, INCREASE_VIEWING_RANGE, + INCREASE_VIEWING_RANGE2, DECREASE_VIEWING_RANGE, RANGESELECT, ZOOM, diff --git a/src/client/localplayer.cpp b/src/client/localplayer.cpp index c863cd0cc..3dff062ca 100644 --- a/src/client/localplayer.cpp +++ b/src/client/localplayer.cpp @@ -19,7 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "localplayer.h" #include -#include "event.h" +#include "mtevent.h" #include "collision.h" #include "nodedef.h" #include "settings.h" @@ -290,6 +290,11 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d, float player_stepheight = (m_cao == nullptr) ? 0.0f : (touching_ground ? m_cao->getStepHeight() : (0.2f * BS)); +#ifdef HAVE_TOUCHSCREENGUI + if (touching_ground) + player_stepheight += (0.6f * BS); +#endif + v3f accel_f; const v3f initial_position = position; const v3f initial_speed = m_speed; @@ -634,10 +639,21 @@ void LocalPlayer::applyControl(float dtime, Environment *env) if (superspeed || (is_climbing && fast_climb) || ((in_liquid || in_liquid_stable) && fast_climb)) speedH = speedH.normalize() * movement_speed_fast; - else if (control.sneak && !free_move && !in_liquid && !in_liquid_stable) + else if (control.sneak && !free_move && !in_liquid && !in_liquid_stable) { speedH = speedH.normalize() * movement_speed_crouch; - else + if (!m_sneak_offset && !getParent() && (physics_override_speed != 0)) { + eye_offset_first += v3f(0,-3,0); + eye_offset_third += v3f(0,-3,0); + m_sneak_offset = true; + } + } else { speedH = speedH.normalize() * movement_speed_walk; + if (m_sneak_offset && !getParent() && (physics_override_speed != 0)) { + eye_offset_first += v3f(0,3,0); + eye_offset_third += v3f(0,3,0); + m_sneak_offset = false; + } + } // Acceleration increase f32 incH = 0.0f; // Horizontal (X, Z) @@ -658,11 +674,18 @@ void LocalPlayer::applyControl(float dtime, Environment *env) } float slip_factor = 1.0f; - if (!free_move && !in_liquid && !in_liquid_stable) + float speed_factor = 1.0f; + if (!free_move && !in_liquid && !in_liquid_stable) { slip_factor = getSlipFactor(env, speedH); + speed_factor = getSpeedFactor(env); + } - // Don't sink when swimming in pitch mode - if (pitch_move && in_liquid) { + // Apply speed factor + speedH *= speed_factor; + speedV *= speed_factor; + + // Don't sink when swimming + if (in_liquid) { v3f controlSpeed = speedH + speedV; if (controlSpeed.getLength() > 0.01f) swimming_pitch = true; @@ -906,6 +929,10 @@ void LocalPlayer::old_move(f32 dtime, Environment *env, f32 pos_max_d, // TODO: This shouldn't be hardcoded but decided by the server float player_stepheight = touching_ground ? (BS * 0.6f) : (BS * 0.2f); +#ifdef HAVE_TOUCHSCREENGUI + player_stepheight += (0.6 * BS); +#endif + v3f accel_f; const v3f initial_position = position; const v3f initial_speed = m_speed; @@ -1103,6 +1130,34 @@ float LocalPlayer::getSlipFactor(Environment *env, const v3f &speedH) return 1.0f; } +float LocalPlayer::getSpeedFactor(Environment *env) +{ + int speed_below = 0, speed_above = 0; + v3s16 pos = getStandingNodePos(); + const NodeDefManager *nodemgr = env->getGameDef()->ndef(); + Map *map = &env->getMap(); + + const ContentFeatures &f = nodemgr->get(map->getNode(pos)); + if (f.walkable) + speed_below = itemgroup_get(f.groups, "speed"); + + const ContentFeatures &f2 = nodemgr->get(map->getNode( + pos + v3s16(0, 1, 0))); + speed_above = itemgroup_get(f2.groups, "speed"); + + if (speed_above == 0) { + const ContentFeatures &f3 = nodemgr->get(map->getNode( + pos + v3s16(0, 2, 0))); + speed_above = itemgroup_get(f3.groups, "speed"); + } + + int speed = speed_below + speed_above; + if (speed != 0) + return core::clamp(1.0f + f32(speed) / 100.f, 0.01f, 10.f); + + return 1.0f; +} + void LocalPlayer::handleAutojump(f32 dtime, Environment *env, const collisionMoveResult &result, const v3f &initial_position, const v3f &initial_speed, f32 pos_max_d) diff --git a/src/client/localplayer.h b/src/client/localplayer.h index 4d9f1fa38..c3f927362 100644 --- a/src/client/localplayer.h +++ b/src/client/localplayer.h @@ -163,6 +163,7 @@ private: const f32 max_increase_V, const bool use_pitch); bool updateSneakNode(Map *map, const v3f &position, const v3f &sneak_max); float getSlipFactor(Environment *env, const v3f &speedH); + float getSpeedFactor(Environment *env); void handleAutojump(f32 dtime, Environment *env, const collisionMoveResult &result, const v3f &position_before_move, const v3f &speed_before_move, @@ -179,6 +180,7 @@ private: // Whether a "sneak ladder" structure is detected at the players pos // see detectSneakLadder() in the .cpp for more info (always false if disabled) bool m_sneak_ladder_detected = false; + bool m_sneak_offset = false; // ***** Variables for temporary option of the old move code ***** // Stores the max player uplift by m_sneak_node diff --git a/src/client/minimap.cpp b/src/client/minimap.cpp index 307054e52..5dc752a99 100644 --- a/src/client/minimap.cpp +++ b/src/client/minimap.cpp @@ -284,12 +284,19 @@ void Minimap::setMinimapMode(MinimapMode mode) { static const MinimapModeDef modedefs[MINIMAP_MODE_COUNT] = { {false, 0, 0}, +#if !defined(__ANDROID__) && !defined(__IOS__) {false, m_surface_mode_scan_height, 256}, {false, m_surface_mode_scan_height, 128}, +#endif {false, m_surface_mode_scan_height, 64}, +#if !defined(__ANDROID__) && !defined(__IOS__) {true, 32, 128}, {true, 32, 64}, {true, 32, 32} +#endif +#if defined(__ANDROID__) || defined(__IOS__) + {true, 32, 32} +#endif }; if (mode >= MINIMAP_MODE_COUNT) @@ -369,7 +376,7 @@ void Minimap::blitMinimapPixelsToImageSurface( map_image->setPixel(x, data->map_size - z - 1, tilecolor); - u32 h = mmpixel->height; + const u32 h = 255; // full bright heightmap_image->setPixel(x,data->map_size - z - 1, video::SColor(255, h, h, h)); } @@ -403,8 +410,13 @@ video::ITexture *Minimap::getMinimapTexture() if (minimap_mask) { for (s16 y = 0; y < MINIMAP_MAX_SY; y++) for (s16 x = 0; x < MINIMAP_MAX_SX; x++) { - const video::SColor &mask_col = minimap_mask->getPixel(x, y); + video::SColor mask_col = minimap_mask->getPixel(x, y); +#if IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR >= 9 + // Irrlicht 1.9 has some problem with alpha + if (mask_col.getRed() != 255) +#else if (!mask_col.getAlpha()) +#endif minimap_image->setPixel(x, y, video::SColor(0,0,0,0)); } } @@ -486,7 +498,7 @@ void Minimap::drawMinimap() material.setFlag(video::EMF_TRILINEAR_FILTER, true); material.Lighting = false; material.TextureLayer[0].Texture = minimap_texture; - material.TextureLayer[1].Texture = data->heightmap_texture; + material.TextureLayer[1].Texture = data->is_radar ? 0 : data->heightmap_texture; if (m_enable_shaders && !data->is_radar) { u16 sid = m_shdrsrc->getShader("minimap_shader", 1, 1); diff --git a/src/client/minimap.h b/src/client/minimap.h index 9245cc149..98f630359 100644 --- a/src/client/minimap.h +++ b/src/client/minimap.h @@ -33,6 +33,7 @@ class IShaderSource; #define MINIMAP_MAX_SX 512 #define MINIMAP_MAX_SY 512 +#if !defined(__ANDROID__) && !defined(__IOS__) enum MinimapMode { MINIMAP_MODE_OFF, MINIMAP_MODE_SURFACEx1, @@ -43,6 +44,14 @@ enum MinimapMode { MINIMAP_MODE_RADARx4, MINIMAP_MODE_COUNT, }; +#else +enum MinimapMode { + MINIMAP_MODE_OFF, + MINIMAP_MODE_SURFACEx1, + MINIMAP_MODE_RADARx1, + MINIMAP_MODE_COUNT, +}; +#endif enum MinimapShape { MINIMAP_SHAPE_SQUARE, diff --git a/src/client/render/interlaced.cpp b/src/client/render/interlaced.cpp index f4dce607f..0c3155c20 100644 --- a/src/client/render/interlaced.cpp +++ b/src/client/render/interlaced.cpp @@ -35,7 +35,7 @@ void RenderingCoreInterlaced::initMaterial() IShaderSource *s = client->getShaderSource(); mat.UseMipMaps = false; mat.ZBuffer = false; - mat.ZWriteEnable = false; + mat.setFlag(video::EMF_ZWRITE_ENABLE, false); // ZWriteEnable is bool on early 1.9 but E_ZWRITE on later 1.9 u32 shader = s->getShader("3d_interlaced_merge", TILE_MATERIAL_BASIC, 0); mat.MaterialType = s->getShaderInfo(shader).material; for (int k = 0; k < 3; ++k) { diff --git a/src/client/renderingengine.cpp b/src/client/renderingengine.cpp index c17efc8c9..0abef9821 100644 --- a/src/client/renderingengine.cpp +++ b/src/client/renderingengine.cpp @@ -38,7 +38,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "../gui/guiSkin.h" #if !defined(_WIN32) && !defined(__APPLE__) && !defined(__ANDROID__) && \ - !defined(SERVER) && !defined(__HAIKU__) + !defined(SERVER) && !defined(__HAIKU__) && !defined(__IOS__) #define XORG_USED #endif #ifdef XORG_USED @@ -85,6 +85,12 @@ RenderingEngine::RenderingEngine(IEventReceiver *receiver) { sanity_check(!s_singleton); +#ifdef __ANDROID__ + // Set correct resolution + g_settings->setU16("screen_w", porting::getDisplaySize().X); + g_settings->setU16("screen_h", porting::getDisplaySize().Y); +#endif + // Resolution selection bool fullscreen = g_settings->getBool("fullscreen"); u16 screen_w = g_settings->getU16("screen_w"); @@ -129,7 +135,7 @@ RenderingEngine::RenderingEngine(IEventReceiver *receiver) params.EventReceiver = receiver; params.HighPrecisionFPU = g_settings->getBool("high_precision_fpu"); params.ZBufferBits = 24; -#ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(__IOS__) params.PrivateData = porting::app_global; #endif #if ENABLE_GLES @@ -148,6 +154,16 @@ RenderingEngine::RenderingEngine(IEventReceiver *receiver) gui::EGST_WINDOWS_METALLIC, driver); m_device->getGUIEnvironment()->setSkin(skin); skin->drop(); + +#ifdef __IOS__ + if (device) { + CIrrDeviceiOS* dev = (CIrrDeviceiOS*) device; + porting::setViewController(dev->getViewController()); +#ifdef ADS + ads_startup(dev->getViewController()); +#endif + } +#endif } RenderingEngine::~RenderingEngine() @@ -475,6 +491,14 @@ void RenderingEngine::_draw_load_screen(const std::wstring &text, gui::IGUIEnvironment *guienv, ITextureSource *tsrc, float dtime, int percent, bool clouds) { +#ifdef __IOS__ + if (m_device->isWindowMinimized()) + return; +#else + if (!m_device->isWindowFocused()) + return; +#endif + v2u32 screensize = RenderingEngine::get_instance()->getWindowSize(); v2s32 textsize(g_fontengine->getTextWidth(text), g_fontengine->getLineHeight()); @@ -485,6 +509,7 @@ void RenderingEngine::_draw_load_screen(const std::wstring &text, guienv->addStaticText(text.c_str(), textrect, false, false); guitext->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT); + clouds = false; // disable clouds at loading time bool cloud_menu_background = clouds && g_settings->getBool("menu_clouds"); if (cloud_menu_background) { g_menuclouds->step(dtime * 3); @@ -492,8 +517,14 @@ void RenderingEngine::_draw_load_screen(const std::wstring &text, get_video_driver()->beginScene( true, true, video::SColor(255, 140, 186, 250)); g_menucloudsmgr->drawAll(); - } else + } else { get_video_driver()->beginScene(true, true, video::SColor(255, 0, 0, 0)); + video::ITexture *background_image = tsrc->getTexture("bg.png"); + + get_video_driver()->draw2DImage(background_image, + irr::core::rect(0, 0, screensize.X * 4, screensize.Y * 4), + irr::core::rect(0, 0, screensize.X, screensize.Y), 0, 0, false); + } // draw progress bar if ((percent >= 0) && (percent <= 100)) { @@ -502,27 +533,78 @@ void RenderingEngine::_draw_load_screen(const std::wstring &text, tsrc->getTexture("progress_bar_bg.png"); if (progress_img && progress_img_bg) { -#ifndef __ANDROID__ const core::dimension2d &img_size = progress_img_bg->getSize(); - u32 imgW = rangelim(img_size.Width, 200, 600); - u32 imgH = rangelim(img_size.Height, 24, 72); +#if !defined(__ANDROID__) && !defined(__IOS__) + float scale = RenderingEngine::getDisplayDensity(); + scale = scale >= 1 ? scale : 1; + u32 imgW = rangelim(img_size.Width, 256, 1024) * scale; + u32 imgH = rangelim(img_size.Height, 32, 128) * scale; + float imgR = scale; #else - const core::dimension2d img_size(256, 48); - float imgRatio = (float)img_size.Height / img_size.Width; - u32 imgW = screensize.X / 2.2f; - u32 imgH = floor(imgW * imgRatio); + float imgRatio = (float) img_size.Height / img_size.Width; + u32 imgW = npot2(screensize.X / 2.0f); + if (imgW > (screensize.X * 0.7) && imgW >= 1024) + imgW /= 2; + u32 imgH = imgW * imgRatio; + float imgR = (float) (imgW) / img_size.Width; #endif v2s32 img_pos((screensize.X - imgW) / 2, (screensize.Y - imgH) / 2); - draw2DImageFilterScaled(get_video_driver(), progress_img_bg, - core::rect(img_pos.X, img_pos.Y, - img_pos.X + imgW, - img_pos.Y + imgH), - core::rect(0, 0, img_size.Width, - img_size.Height), - 0, 0, true); + draw2DImageFilterScaled( + driver, progress_img_bg, + core::rect(img_pos.X, img_pos.Y, img_pos.X + imgW, img_pos.Y + imgH), + core::rect(0, 0, img_size.Width, img_size.Height), + 0, 0, true); + + // rects for drawing a color progress bar + const static core::rect rects[] = { + core::rect( 4, 24, 5, 40), + core::rect( 5, 21, 6, 43), + core::rect( 6, 19, 7, 45), + core::rect( 7, 17, 8, 47), + core::rect( 8, 15, 9, 49), + core::rect( 9, 14, 10, 50), + core::rect( 10, 13, 11, 51), + core::rect( 11, 12, 12, 52), + core::rect( 12, 11, 13, 53), + core::rect( 13, 10, 14, 54), + core::rect( 14, 9, 15, 55), + core::rect( 15, 8, 17, 56), + core::rect( 17, 7, 19, 57), + core::rect( 19, 6, 21, 58), + core::rect( 21, 5, 24, 59), + core::rect( 24, 4, 488, 60), + core::rect(488, 5, 491, 59), + core::rect(491, 6, 493, 58), + core::rect(493, 7, 495, 57), + core::rect(495, 8, 497, 56), + core::rect(497, 9, 498, 55), + core::rect(498, 10, 499, 54), + core::rect(499, 11, 500, 53), + core::rect(500, 12, 501, 52), + core::rect(501, 13, 502, 51), + core::rect(502, 14, 503, 50), + core::rect(503, 15, 504, 49), + core::rect(504, 17, 505, 47), + core::rect(505, 19, 506, 45), + core::rect(506, 21, 507, 43), + core::rect(507, 24, 508, 40) + }; + + for (const auto & i : rects) { + const s32 clipx = (percent * imgW) / 100; + core::rect r( + MYMIN(i.UpperLeftCorner.X * imgR, clipx), i.UpperLeftCorner.Y * imgR, + MYMIN(i.LowerRightCorner.X * imgR, clipx), i.LowerRightCorner.Y * imgR + ); + if (r.getArea() <= 0) + break; + get_video_driver()->draw2DRectangle( + video::SColor(255, 255 - percent * 2, percent * 2, 25), + r + img_pos, nullptr); + } draw2DImageFilterScaled(get_video_driver(), progress_img, core::rect(img_pos.X, img_pos.Y, @@ -641,7 +723,7 @@ const char *RenderingEngine::getVideoDriverFriendlyName(irr::video::E_DRIVER_TYP return driver_names[type]; } -#ifndef __ANDROID__ +#if !defined(__ANDROID__) && !defined(__IOS__) #if defined(XORG_USED) static float calcDisplayDensity() @@ -725,7 +807,7 @@ v2u32 RenderingEngine::getDisplaySize() return deskres; } -#else // __ANDROID__ +#else // __ANDROID__/__IOS__ float RenderingEngine::getDisplayDensity() { return porting::getDisplayDensity(); @@ -735,4 +817,4 @@ v2u32 RenderingEngine::getDisplaySize() { return porting::getDisplaySize(); } -#endif // __ANDROID__ +#endif // __ANDROID__/__IOS__ diff --git a/src/client/sky.cpp b/src/client/sky.cpp index 2eeac4ff6..ed0b86dfb 100644 --- a/src/client/sky.cpp +++ b/src/client/sky.cpp @@ -48,10 +48,13 @@ Sky::Sky(s32 id, ITextureSource *tsrc) : mat.Lighting = false; #if ENABLE_GLES mat.ZBuffer = video::ECFN_DISABLED; +#elif defined(__MACH__) && defined(__APPLE__) && IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR > 8 + // ugly but for making cpp_lint happy... + mat.ZBuffer = video::ECFN_DISABLED; #else mat.ZBuffer = video::ECFN_NEVER; #endif - mat.ZWriteEnable = false; + mat.setFlag(video::EMF_ZWRITE_ENABLE, false); // ZWriteEnable is bool on early 1.9 but E_ZWRITE on later 1.9 mat.AntiAliasing = 0; mat.TextureLayer[0].TextureWrapU = video::ETC_CLAMP_TO_EDGE; mat.TextureLayer[0].TextureWrapV = video::ETC_CLAMP_TO_EDGE; @@ -249,7 +252,7 @@ void Sky::render() } // Draw far cloudy fog thing blended with skycolor - if (m_visible) { + /*if (m_visible) { driver->setMaterial(m_materials[1]); for (u32 j = 0; j < 4; j++) { vertices[0] = video::S3DVertex(-1, -0.02, -1, 0, 0, 1, m_bgcolor, t, t); @@ -272,7 +275,7 @@ void Sky::render() } driver->drawIndexedTriangleFan(&vertices[0], 4, indices, 2); } - } + }*/ // Draw stars before sun and moon to be behind them if (m_star_params.visible) diff --git a/src/client/tile.cpp b/src/client/tile.cpp index 8bae4bbb9..dace773e6 100644 --- a/src/client/tile.cpp +++ b/src/client/tile.cpp @@ -1015,7 +1015,7 @@ video::IImage* TextureSource::generateImage(const std::string &name) #if ENABLE_GLES - +#if !defined(__ANDROID__) && !defined(__IOS__) static inline u16 get_GL_major_version() { const GLubyte *gl_version = glGetString(GL_VERSION); @@ -1036,6 +1036,13 @@ bool hasNPotSupport() strstr((char *)glGetString(GL_EXTENSIONS), "GL_OES_texture_npot"); return supported; } +#else +// gles3 has NPotSupport, but this is using too many resources +bool hasNPotSupport() +{ + return false; +} +#endif /** * Check and align image to npot2 if required by hardware @@ -1057,13 +1064,15 @@ video::IImage * Align2Npot2(video::IImage * image, unsigned int height = npot2(dim.Height); unsigned int width = npot2(dim.Width); - if (dim.Height == height && dim.Width == width) + if (dim.Width == width) return image; - if (dim.Height > height) - height *= 2; - if (dim.Width > width) - width *= 2; +#ifdef __IOS__ + if (height > 64 || width > 64) { + height /= 2; + width /= 2; + } +#endif video::IImage *targetimage = driver->createImage(video::ECF_A8R8G8B8, @@ -1244,8 +1253,13 @@ bool TextureSource::generateImagePart(std::string part_of_name, It is an image with a number of cracking stages horizontally tiled. */ +#ifndef HAVE_TOUCHSCREENGUI video::IImage *img_crack = m_sourcecache.getOrLoad( "crack_anylength.png"); +#else + video::IImage *img_crack = m_sourcecache.getOrLoad( + "crack_anylength_touch.png"); +#endif if (img_crack) { draw_crack(img_crack, baseimg, diff --git a/src/cmake_config.h.in b/src/cmake_config.h.in index cfcee4b58..778602018 100644 --- a/src/cmake_config.h.in +++ b/src/cmake_config.h.in @@ -21,6 +21,7 @@ #cmakedefine01 USE_FREETYPE #cmakedefine01 USE_CURSES #cmakedefine01 USE_LEVELDB +#cmakedefine01 USE_SQLITE #cmakedefine01 USE_LUAJIT #cmakedefine01 USE_POSTGRESQL #cmakedefine01 USE_PROMETHEUS diff --git a/src/config.h b/src/config.h index 699256273..ef3aaeb6b 100644 --- a/src/config.h +++ b/src/config.h @@ -11,7 +11,7 @@ #if defined USE_CMAKE_CONFIG_H #include "cmake_config.h" -#elif defined (__ANDROID__) +#elif defined(__ANDROID__) || defined(__APPLE__) #define PROJECT_NAME "multicraft" #define PROJECT_NAME_C "MultiCraft" #define STATIC_SHAREDIR "" diff --git a/src/constants.h b/src/constants.h index 4c4f3aeaf..6b22d01fc 100644 --- a/src/constants.h +++ b/src/constants.h @@ -110,5 +110,9 @@ with this program; if not, write to the Free Software Foundation, Inc., GUI related things */ -#define TTF_DEFAULT_FONT_SIZE (16) +#if defined(__ANDROID__) || defined(__IOS__) +#define TTF_DEFAULT_FONT_SIZE (14) +#else +#define TTF_DEFAULT_FONT_SIZE (18) +#endif #define DEFAULT_FONT_SIZE (10) diff --git a/src/content/subgames.cpp b/src/content/subgames.cpp index df686748a..67ea69ad5 100644 --- a/src/content/subgames.cpp +++ b/src/content/subgames.cpp @@ -313,9 +313,15 @@ bool loadGameConfAndInitWorld(const std::string &path, const SubgameSpec &gamesp Settings conf; conf.set("gameid", gamespec.id); +#if !defined(__ANDROID__) && !defined(__APPLE__) conf.set("backend", "sqlite3"); conf.set("player_backend", "sqlite3"); conf.set("auth_backend", "sqlite3"); +#else + conf.set("backend", "leveldb"); + conf.set("player_backend", "leveldb"); + conf.set("auth_backend", "leveldb"); +#endif conf.setBool("creative_mode", g_settings->getBool("creative_mode")); conf.setBool("enable_damage", g_settings->getBool("enable_damage")); diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index b8d98d6c3..7f64c06d7 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -27,6 +27,14 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "mapgen/mapgen.h" // Mapgen::setDefaultSettings #include "util/string.h" +#ifdef __APPLE__ +#ifdef __IOS__ +#import "SDVersion.h" +#else +#import +#endif +#endif + void set_default_settings(Settings *settings) { // Client and server @@ -38,7 +46,7 @@ void set_default_settings(Settings *settings) // Client settings->setDefault("address", ""); settings->setDefault("enable_sound", "true"); - settings->setDefault("sound_volume", "0.8"); + settings->setDefault("sound_volume", "1.0"); settings->setDefault("mute_sound", "false"); settings->setDefault("enable_mesh_cache", "false"); settings->setDefault("mesh_generation_interval", "0"); @@ -62,7 +70,7 @@ void set_default_settings(Settings *settings) settings->setDefault("enable_client_modding", "true"); settings->setDefault("max_out_chat_queue_size", "20"); settings->setDefault("pause_on_lost_focus", "false"); - settings->setDefault("enable_register_confirmation", "true"); + settings->setDefault("enable_register_confirmation", "false"); // Keymap settings->setDefault("remote_port", "30000"); @@ -169,7 +177,7 @@ void set_default_settings(Settings *settings) settings->setDefault("near_plane", "0.1"); #endif settings->setDefault("screen_w", "1024"); - settings->setDefault("screen_h", "600"); + settings->setDefault("screen_h", "768"); settings->setDefault("autosave_screensize", "true"); settings->setDefault("fullscreen", "false"); settings->setDefault("fullscreen_bpp", "24"); @@ -200,7 +208,7 @@ void set_default_settings(Settings *settings) settings->setDefault("cinematic_camera_smoothing", "0.7"); settings->setDefault("enable_clouds", "true"); settings->setDefault("view_bobbing_amount", "1.0"); - settings->setDefault("fall_bobbing_amount", "0.03"); + settings->setDefault("fall_bobbing_amount", "1.0"); settings->setDefault("enable_3d_clouds", "true"); settings->setDefault("cloud_radius", "12"); settings->setDefault("menu_clouds", "true"); @@ -213,7 +221,7 @@ void set_default_settings(Settings *settings) settings->setDefault("formspec_default_bg_color", "(0,0,0)"); settings->setDefault("formspec_default_bg_opacity", "140"); settings->setDefault("selectionbox_color", "(0,0,0)"); - settings->setDefault("selectionbox_width", "2"); + settings->setDefault("selectionbox_width", "4"); settings->setDefault("node_highlighting", "box"); settings->setDefault("crosshair_color", "(255,255,255)"); settings->setDefault("crosshair_alpha", "255"); @@ -224,10 +232,12 @@ void set_default_settings(Settings *settings) settings->setDefault("gui_scaling_filter_txr2img", "true"); settings->setDefault("desynchronize_mapblock_texture_animation", "true"); settings->setDefault("hud_hotbar_max_width", "1.0"); + settings->setDefault("hud_move_upwards", "0"); + settings->setDefault("round_screen", "0"); settings->setDefault("enable_local_map_saving", "false"); - settings->setDefault("show_entity_selectionbox", "true"); + settings->setDefault("show_entity_selectionbox", "false"); settings->setDefault("texture_clean_transparent", "false"); - settings->setDefault("texture_min_size", "64"); + settings->setDefault("texture_min_size", "0"); settings->setDefault("ambient_occlusion_gamma", "2.2"); #if ENABLE_GLES settings->setDefault("enable_shaders", "false"); @@ -235,11 +245,11 @@ void set_default_settings(Settings *settings) settings->setDefault("enable_shaders", "true"); #endif settings->setDefault("enable_particles", "true"); - settings->setDefault("arm_inertia", "true"); + settings->setDefault("arm_inertia", "false"); settings->setDefault("enable_minimap", "true"); settings->setDefault("minimap_shape_round", "true"); - settings->setDefault("minimap_double_scan_height", "true"); + settings->setDefault("minimap_double_scan_height", "false"); // Effects settings->setDefault("directional_colored_fog", "true"); @@ -275,11 +285,7 @@ void set_default_settings(Settings *settings) settings->setDefault("aux1_descends", "false"); settings->setDefault("doubletap_jump", "false"); settings->setDefault("always_fly_fast", "true"); -#ifdef __ANDROID__ - settings->setDefault("autojump", "true"); -#else settings->setDefault("autojump", "false"); -#endif settings->setDefault("continuous_forward", "false"); settings->setDefault("enable_joysticks", "false"); settings->setDefault("joystick_id", "0"); @@ -288,25 +294,48 @@ void set_default_settings(Settings *settings) settings->setDefault("joystick_frustum_sensitivity", "170"); // Main menu - settings->setDefault("main_menu_style", "full"); settings->setDefault("main_menu_path", ""); settings->setDefault("serverlist_file", "favoriteservers.txt"); #if USE_FREETYPE settings->setDefault("freetype", "true"); +#if !defined(__ANDROID__) && !defined(__IOS__) settings->setDefault("font_path", porting::getDataPath("fonts" DIR_DELIM "Arimo-Regular.ttf")); settings->setDefault("font_path_italic", porting::getDataPath("fonts" DIR_DELIM "Arimo-Italic.ttf")); settings->setDefault("font_path_bold", porting::getDataPath("fonts" DIR_DELIM "Arimo-Bold.ttf")); settings->setDefault("font_path_bold_italic", porting::getDataPath("fonts" DIR_DELIM "Arimo-BoldItalic.ttf")); +#else + settings->setDefault("font_path", porting::getDataPath("fonts" DIR_DELIM "Retron2000.ttf")); + settings->setDefault("font_path_italic", porting::getDataPath("fonts" DIR_DELIM "Retron2000.ttf")); + settings->setDefault("font_path_bold", porting::getDataPath("fonts" DIR_DELIM "Retron2000.ttf")); + settings->setDefault("font_path_bold_italic", porting::getDataPath("fonts" DIR_DELIM "Retron2000.ttf")); +#endif settings->setDefault("font_bold", "false"); settings->setDefault("font_italic", "false"); settings->setDefault("font_shadow", "1"); settings->setDefault("font_shadow_alpha", "127"); +#if !defined(__ANDROID__) && !defined(__IOS__) settings->setDefault("mono_font_path", porting::getDataPath("fonts" DIR_DELIM "Cousine-Regular.ttf")); settings->setDefault("mono_font_path_italic", porting::getDataPath("fonts" DIR_DELIM "Cousine-Italic.ttf")); settings->setDefault("mono_font_path_bold", porting::getDataPath("fonts" DIR_DELIM "Cousine-Bold.ttf")); settings->setDefault("mono_font_path_bold_italic", porting::getDataPath("fonts" DIR_DELIM "Cousine-BoldItalic.ttf")); settings->setDefault("fallback_font_path", porting::getDataPath("fonts" DIR_DELIM "DroidSansFallbackFull.ttf")); +#else +#ifdef __ANDROID__ + settings->setDefault("mono_font_path", "/system/fonts/DroidSansMono.ttf"); + settings->setDefault("mono_font_path_italic", porting::getDataPath("fonts" DIR_DELIM "DroidSansMono.ttf")); + settings->setDefault("mono_font_path_bold", porting::getDataPath("fonts" DIR_DELIM "DroidSansMono.ttf")); + settings->setDefault("mono_font_path_bold_italic", porting::getDataPath("fonts" DIR_DELIM "DroidSansMono.ttf")); + settings->setDefault("fallback_font_path", "/system/fonts/DroidSans.ttf"); +#endif +#ifdef __IOS__ + settings->setDefault("mono_font_path", g_settings->get("font_path")); + settings->setDefault("mono_font_path_italic", g_settings->get("font_path")); + settings->setDefault("mono_font_path_bold", g_settings->get("font_path")); + settings->setDefault("mono_font_path_bold_italic", g_settings->get("font_path")); + settings->setDefault("fallback_font_path", g_settings->get("font_path")); +#endif +#endif settings->setDefault("fallback_font_shadow", "1"); settings->setDefault("fallback_font_shadow_alpha", "128"); @@ -346,7 +375,7 @@ void set_default_settings(Settings *settings) settings->setDefault("enable_ipv6", "true"); settings->setDefault("ipv6_server", "false"); settings->setDefault("max_packets_per_iteration","1024"); - settings->setDefault("port", "30000"); + settings->setDefault("port", "40000"); settings->setDefault("strict_protocol_version_checking", "false"); settings->setDefault("player_transfer_distance", "0"); settings->setDefault("max_simultaneous_block_sends_per_client", "40"); @@ -392,7 +421,7 @@ void set_default_settings(Settings *settings) settings->setDefault("max_objects_per_block", "64"); settings->setDefault("server_map_save_interval", "5.3"); settings->setDefault("chat_message_max_size", "500"); - settings->setDefault("chat_message_limit_per_10sec", "8.0"); + settings->setDefault("chat_message_limit_per_10sec", "5.0"); settings->setDefault("chat_message_limit_trigger_kick", "50"); settings->setDefault("sqlite_synchronous", "2"); settings->setDefault("full_block_send_enable_min_time_from_building", "2.0"); @@ -402,7 +431,7 @@ void set_default_settings(Settings *settings) settings->setDefault("nodetimer_interval", "0.2"); settings->setDefault("ignore_world_load_errors", "false"); settings->setDefault("remote_media", ""); - settings->setDefault("debug_log_level", "action"); + settings->setDefault("debug_log_level", "warning"); settings->setDefault("debug_log_size_max", "50"); settings->setDefault("chat_log_level", "error"); settings->setDefault("emergequeue_limit_total", "512"); @@ -416,7 +445,7 @@ void set_default_settings(Settings *settings) // Physics settings->setDefault("movement_acceleration_default", "3"); settings->setDefault("movement_acceleration_air", "2"); - settings->setDefault("movement_acceleration_fast", "10"); + settings->setDefault("movement_acceleration_fast", "20"); settings->setDefault("movement_speed_walk", "4"); settings->setDefault("movement_speed_crouch", "1.35"); settings->setDefault("movement_speed_fast", "20"); @@ -424,7 +453,7 @@ void set_default_settings(Settings *settings) settings->setDefault("movement_speed_jump", "6.5"); settings->setDefault("movement_liquid_fluidity", "1"); settings->setDefault("movement_liquid_fluidity_smooth", "0.5"); - settings->setDefault("movement_liquid_sink", "10"); + settings->setDefault("movement_liquid_sink", "20"); settings->setDefault("movement_gravity", "9.81"); // Liquids @@ -453,56 +482,225 @@ void set_default_settings(Settings *settings) settings->setDefault("enable_console", "false"); settings->setDefault("screen_dpi", "72"); + settings->setDefault("mainmenu_last_selected_world", "1"); + // Altered settings for macOS -#if defined(__MACH__) && defined(__APPLE__) +#if defined(__MACH__) && defined(__APPLE__) && !defined(__IOS__) settings->setDefault("keymap_sneak", "KEY_SHIFT"); - settings->setDefault("fps_max", "0"); + settings->setDefault("keymap_toggle_debug", "KEY_KEY_V"); + settings->setDefault("keymap_camera_mode", "KEY_KEY_C"); + settings->setDefault("vsync", "true"); + + float ScaleFactor = [[NSScreen mainScreen] backingScaleFactor]; + if (ScaleFactor >= 2) + settings->setDefault("screen_dpi", "128"); + + // Shaders work but may reduce performance on iGPU + settings->setDefault("enable_shaders", "false"); + + settings->setDefault("serverlist_url", "servers.multicraft.world"); + settings->setDefault("TMPFolder", porting::path_cache); #endif - // Altered settings for Android -#ifdef __ANDROID__ + // Mobile Platform +#if defined(__ANDROID__) || defined(__IOS__) settings->setDefault("screen_w", "0"); settings->setDefault("screen_h", "0"); settings->setDefault("fullscreen", "true"); settings->setDefault("touchtarget", "true"); settings->setDefault("TMPFolder", porting::path_cache); - settings->setDefault("touchscreen_threshold","20"); - settings->setDefault("fixed_virtual_joystick", "false"); + settings->setDefault("touchscreen_threshold", "20"); + settings->setDefault("fixed_virtual_joystick", "true"); settings->setDefault("virtual_joystick_triggers_aux", "false"); - settings->setDefault("smooth_lighting", "false"); - settings->setDefault("max_simultaneous_block_sends_per_client", "10"); settings->setDefault("emergequeue_limit_diskonly", "16"); settings->setDefault("emergequeue_limit_generate", "16"); - settings->setDefault("max_block_generate_distance", "5"); - settings->setDefault("enable_3d_clouds", "false"); - settings->setDefault("fps_max", "30"); - settings->setDefault("pause_fps_max", "10"); - settings->setDefault("max_objects_per_block", "20"); - settings->setDefault("sqlite_synchronous", "1"); - settings->setDefault("server_map_save_interval", "15"); - settings->setDefault("client_mapblock_limit", "1000"); - settings->setDefault("active_block_range", "2"); - settings->setDefault("viewing_range", "50"); - settings->setDefault("leaves_style", "simple"); - settings->setDefault("curl_verify_cert","false"); + settings->setDefault("curl_verify_cert", "false"); + settings->setDefault("pause_on_lost_focus", "true"); + settings->setDefault("max_objects_per_block", "16"); + settings->setDefault("doubletap_jump", "true"); + settings->setDefault("serverlist_url", "servers.multicraft.world"); + settings->setDefault("gui_scaling_filter_txr2img", "false"); + settings->setDefault("autosave_screensize", "false"); + + // Set the optimal settings depending on the memory size [Android] | model [iOS] +#ifdef __ANDROID__ + float memoryMax = porting::getMemoryMax(); +#elif __IOS__ + float iOS_ver = [[[UIDevice currentDevice] systemVersion] floatValue]; +#endif + +#ifdef __ANDROID__ + if (memoryMax < 2) { + // minimal settings for less than 2GB RAM +#elif __IOS__ + if (iOS_ver < 11.0) { + // minimal settings for legacy 32-bit devices + settings->setDefault("enable_minimap", "false"); + settings->setDefault("enable_clouds", "false"); +#endif + settings->setDefault("client_unload_unused_data_timeout", "60"); + settings->setDefault("client_mapblock_limit", "50"); + settings->setDefault("fps_max", "30"); + settings->setDefault("pause_fps_max", "5"); + settings->setDefault("viewing_range", "25"); + settings->setDefault("smooth_lighting", "false"); + settings->setDefault("enable_3d_clouds", "false"); + settings->setDefault("active_block_range", "1"); + settings->setDefault("dedicated_server_step", "0.2"); + settings->setDefault("abm_interval", "3.0"); + settings->setDefault("chunksize", "3"); + settings->setDefault("max_block_generate_distance", "1"); + settings->setDefault("enable_weather", "false"); +#ifdef __ANDROID__ + } else if (memoryMax >= 2 && memoryMax < 4) { + // low settings for 2-4GB RAM +#elif __IOS__ + } else if (iOS_ver < 13.0) { + // low settings + settings->setDefault("enable_minimap", "false"); +#endif + settings->setDefault("client_unload_unused_data_timeout", "120"); + settings->setDefault("client_mapblock_limit", "200"); + settings->setDefault("fps_max", "35"); + settings->setDefault("pause_fps_max", "10"); + settings->setDefault("viewing_range", "30"); + settings->setDefault("smooth_lighting", "false"); + settings->setDefault("enable_3d_clouds", "false"); + settings->setDefault("cloud_radius", "6"); + settings->setDefault("active_block_range", "1"); + settings->setDefault("dedicated_server_step", "0.2"); + settings->setDefault("abm_interval", "2.0"); + settings->setDefault("chunksize", "3"); + settings->setDefault("max_block_generate_distance", "2"); + settings->setDefault("enable_weather", "false"); +#ifdef __ANDROID__ + } else if (memoryMax >= 4 && memoryMax < 6) { + // medium settings for 4.1-6GB RAM +#elif __IOS__ + } else if (([SDVersion deviceVersion] == iPhone6S) || ([SDVersion deviceVersion] == iPhone6SPlus) || ([SDVersion deviceVersion] == iPhoneSE) || + ([SDVersion deviceVersion] == iPhone7) || ([SDVersion deviceVersion] == iPhone7Plus) || + ([SDVersion deviceVersion] == iPadMini4) || ([SDVersion deviceVersion] == iPadAir)) { + // medium settings +#endif + settings->setDefault("client_unload_unused_data_timeout", "300"); + settings->setDefault("client_mapblock_limit", "300"); + settings->setDefault("fps_max", "35"); + settings->setDefault("viewing_range", "60"); + settings->setDefault("cloud_radius", "6"); + settings->setDefault("active_block_range", "2"); + settings->setDefault("max_block_generate_distance", "3"); + } else { + // high settings + settings->setDefault("client_mapblock_limit", "500"); + settings->setDefault("viewing_range", "80"); + settings->setDefault("max_block_generate_distance", "5"); + +#ifdef __ANDROID__ + settings->setDefault("video_driver", "ogles2"); + settings->setDefault("enable_shaders", "true"); +#elif __IOS__ + if (@available(iOS 13, *)) { +#endif + // enable visual shader effects + settings->setDefault("enable_waving_water", "true"); + settings->setDefault("enable_waving_leaves", "true"); + settings->setDefault("enable_waving_plants", "true"); +#ifdef __IOS__ + } +#endif + } + + // Android Settings +#ifdef __ANDROID__ + settings->setDefault("video_driver", "ogles1"); + settings->setDefault("enable_shaders", "false"); + + settings->setDefault("debug_log_level", "error"); // Apply settings according to screen size float x_inches = (float) porting::getDisplaySize().X / (160.f * porting::getDisplayDensity()); - if (x_inches < 3.7f) { + std::string font_size_str_small = std::to_string(TTF_DEFAULT_FONT_SIZE - 1); + + if (x_inches <= 3.7) { + // small 4" phones + settings->setDefault("hud_scaling", "0.55"); + settings->setDefault("font_size", font_size_str_small); + settings->setDefault("mouse_sensitivity", "0.3"); + } else if (x_inches > 3.7 && x_inches <= 4.5) { + // medium phones settings->setDefault("hud_scaling", "0.6"); - settings->setDefault("font_size", "14"); - settings->setDefault("mono_font_size", "14"); - } else if (x_inches < 4.5f) { + settings->setDefault("font_size", font_size_str_small); + settings->setDefault("selectionbox_width", "6"); + } else if (x_inches > 4.5 && x_inches <= 5.5) { + // large 6" phones settings->setDefault("hud_scaling", "0.7"); - settings->setDefault("font_size", "14"); - settings->setDefault("mono_font_size", "14"); - } else if (x_inches < 6.0f) { - settings->setDefault("hud_scaling", "0.85"); - settings->setDefault("font_size", "14"); - settings->setDefault("mono_font_size", "14"); + settings->setDefault("mouse_sensitivity", "0.15"); + settings->setDefault("selectionbox_width", "6"); + } else if (x_inches > 5.5 && x_inches <= 6.5) { + // 7" tablets + settings->setDefault("hud_scaling", "0.9"); + settings->setDefault("selectionbox_width", "6"); } - // Tablets >= 6.0 use non-Android defaults for these settings +#endif // Android + + // iOS Settings +#ifdef __IOS__ + // Switch to olges2 with shaders on the new iOS version + if (@available(iOS 13, *)) { + settings->setDefault("video_driver", "ogles2"); + settings->setDefault("enable_shaders", "true"); + } else { + settings->setDefault("video_driver", "ogles1"); + settings->setDefault("enable_shaders", "false"); + } + + settings->setDefault("debug_log_level", "none"); + settings->setDefault("password_save", "true"); + + // Set the size of the elements depending on the screen size + if SDVersion4Inch { + // 4" iPhone and iPod Touch + settings->setDefault("hud_scaling", "0.55"); + settings->setDefault("mouse_sensitivity", "0.33"); + } else if SDVersion4and7Inch { + // 4.7" iPhone + settings->setDefault("hud_scaling", "0.65"); + settings->setDefault("mouse_sensitivity", "0.27"); + } else if SDVersion5and5Inch { + // 5.5" iPhone Plus + settings->setDefault("hud_scaling", "0.7"); + settings->setDefault("mouse_sensitivity", "0.3"); + } else if (SDVersion5and8Inch || SDVersion6and1Inch || SDVersion6and5Inch) { + // 5.8+" iPhones + settings->setDefault("hud_scaling", "0.85"); + settings->setDefault("mouse_sensitivity", "0.35"); + settings->setDefault("selectionbox_width", "6"); + } else if SDVersion7and9Inch { + // iPad mini + settings->setDefault("hud_scaling", "0.9"); + settings->setDefault("mouse_sensitivity", "0.25"); + settings->setDefault("selectionbox_width", "6"); + } else { + // iPad + settings->setDefault("mouse_sensitivity", "0.3"); + settings->setDefault("selectionbox_width", "6"); + } + + // Settings for the Rounded Screen and Home Bar + if (@available(iOS 11, *)) { + UIWindow *window = UIApplication.sharedApplication.windows.firstObject; + int bottomPadding = (int) window.safeAreaInsets.bottom; + + if (bottomPadding > 0) { + settings->setDefault("hud_move_upwards", "20"); + if (SDVersioniPhone12Series) + settings->setDefault("round_screen", "75"); + else + settings->setDefault("round_screen", "35"); + } + } +#endif // iOS #endif } diff --git a/src/filesys.cpp b/src/filesys.cpp index c79d05fb9..614484039 100644 --- a/src/filesys.cpp +++ b/src/filesys.cpp @@ -27,7 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "log.h" #include "config.h" #include "porting.h" -#ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(__IOS__) #include "settings.h" // For g_settings #endif @@ -365,7 +365,7 @@ std::string TempPath() compatible with lua's os.tmpname which under the default configuration hardcodes mkstemp("/tmp/lua_XXXXXX"). */ -#ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(__IOS__) return g_settings->get("TMPFolder"); #else return DIR_DELIM "tmp"; diff --git a/src/gettext.cpp b/src/gettext.cpp index dda8d53b4..3cc3b7656 100644 --- a/src/gettext.cpp +++ b/src/gettext.cpp @@ -24,6 +24,15 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "gettext.h" #include "util/string.h" #include "log.h" +#include "porting.h" + +#ifdef __APPLE__ +#ifdef __IOS__ +#import +#else +#import +#endif +#endif #if USE_GETTEXT && defined(_MSC_VER) #include @@ -127,6 +136,10 @@ void init_gettext(const char *path, const std::string &configured_language, // Add user specified locale to environment setenv("LANGUAGE", configured_language.c_str(), 1); +#ifdef __ANDROID__ + setenv("LANG", configured_language.c_str(), 1); +#endif + // Reload locale with changed environment setlocale(LC_ALL, ""); #elif defined(_MSC_VER) @@ -203,6 +216,17 @@ void init_gettext(const char *path, const std::string &configured_language, } else { /* set current system default locale */ +#ifdef __ANDROID__ + char lang[3] = {0}; + AConfiguration_getLanguage(porting::app_global->config, lang); + setenv("LANG", lang, 1); +#endif +#ifdef __APPLE__ + char lang[3] = {0}; + NSString *syslang = [[NSLocale preferredLanguages] firstObject]; + [syslang getBytes:lang maxLength:2 usedLength:nil encoding:NSASCIIStringEncoding options:0 range:NSMakeRange(0, 2) remainingRange:nil]; + setenv("LANG", lang, 1); +#endif setlocale(LC_ALL, ""); } diff --git a/src/gui/guiButton.cpp b/src/gui/guiButton.cpp index 6732a9233..ac62269cf 100644 --- a/src/gui/guiButton.cpp +++ b/src/gui/guiButton.cpp @@ -505,6 +505,16 @@ video::SColor GUIButton::getOverrideColor() const return OverrideColor; } +video::SColor GUIButton::getActiveColor() const +{ + if (OverrideColorEnabled) + return OverrideColor; + IGUISkin* skin = Environment->getSkin(); + if (skin) + return skin->getColor(isEnabled() ? EGDC_BUTTON_TEXT : EGDC_GRAY_TEXT); + return OverrideColor; +} + void GUIButton::enableOverrideColor(bool enable) { OverrideColorEnabled = enable; diff --git a/src/gui/guiButton.h b/src/gui/guiButton.h index 95fa1a2a1..3691c4485 100644 --- a/src/gui/guiButton.h +++ b/src/gui/guiButton.h @@ -102,6 +102,8 @@ public: //! Gets the override color virtual video::SColor getOverrideColor(void) const; + video::SColor getActiveColor() const; // IrrLicht 1.9; doesn't hurt in 1.8 + //! Sets if the button text should use the override color or the color in the gui skin. virtual void enableOverrideColor(bool enable); diff --git a/src/gui/guiChatConsole.cpp b/src/gui/guiChatConsole.cpp index b0b167a45..e9578d834 100644 --- a/src/gui/guiChatConsole.cpp +++ b/src/gui/guiChatConsole.cpp @@ -30,6 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "log.h" #include "gettext.h" #include +#include "touchscreengui.h" #if USE_FREETYPE #include "irrlicht_changes/CGUITTFont.h" @@ -134,6 +135,10 @@ void GUIChatConsole::closeConsoleAtOnce() closeConsole(); m_height = 0; recalculateConsolePosition(); +#ifdef HAVE_TOUCHSCREENGUI + if (g_touchscreengui) + g_touchscreengui->show(); +#endif } f32 GUIChatConsole::getDesiredHeight() const @@ -422,7 +427,7 @@ bool GUIChatConsole::OnEvent(const SEvent& event) return true; } - if (event.KeyInput.Key == KEY_ESCAPE) { + if (event.KeyInput.Key == KEY_ESCAPE || event.KeyInput.Key == KEY_CANCEL) { closeConsoleAtOnce(); m_close_on_enter = false; // inhibit open so the_game doesn't reopen immediately diff --git a/src/gui/guiConfirmRegistration.cpp b/src/gui/guiConfirmRegistration.cpp index 27c66bbd9..172a43ae3 100644 --- a/src/gui/guiConfirmRegistration.cpp +++ b/src/gui/guiConfirmRegistration.cpp @@ -45,7 +45,7 @@ GUIConfirmRegistration::GUIConfirmRegistration(gui::IGUIEnvironment *env, m_client(client), m_playername(playername), m_password(password), m_aborted(aborted), m_tsrc(tsrc) { -#ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(__IOS__) m_touchscreen_visible = false; #endif } @@ -73,7 +73,11 @@ void GUIConfirmRegistration::regenerateGui(v2u32 screensize) /* Calculate new sizes and positions */ +#ifdef __ANDROID__ + const float s = m_gui_scale * porting::getDisplayDensity() / 2; +#else const float s = m_gui_scale; +#endif DesiredRect = core::rect( screensize.X / 2 - 600 * s / 2, screensize.Y / 2 - 360 * s / 2, @@ -162,7 +166,7 @@ void GUIConfirmRegistration::drawMenu() driver->draw2DRectangle(bgcolor, AbsoluteRect, &AbsoluteClippingRect); gui::IGUIElement::draw(); -#ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(__IOS__) getAndroidUIInput(); #endif } @@ -251,18 +255,25 @@ bool GUIConfirmRegistration::OnEvent(const SEvent &event) return false; } -#ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(__IOS__) bool GUIConfirmRegistration::getAndroidUIInput() { if (!hasAndroidUIInput() || m_jni_field_name != "password") return false; - std::string text = porting::getInputDialogValue(); - gui::IGUIElement *e = getElementFromId(ID_confirmPassword); - if (e) - e->setText(utf8_to_wide(text).c_str()); + // still waiting + if (porting::getInputDialogState() == -1) + return true; m_jni_field_name.clear(); + + gui::IGUIElement *e = getElementFromId(ID_confirmPassword); + + if (!e || e->getType() != irr::gui::EGUIET_EDIT_BOX) + return false; + + std::string text = porting::getInputDialogValue(); + e->setText(utf8_to_wide(text).c_str()); return false; } #endif diff --git a/src/gui/guiConfirmRegistration.h b/src/gui/guiConfirmRegistration.h index 6ca3bf260..5161ec193 100644 --- a/src/gui/guiConfirmRegistration.h +++ b/src/gui/guiConfirmRegistration.h @@ -51,7 +51,7 @@ public: bool processInput(); bool OnEvent(const SEvent &event); -#ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(__IOS__) bool getAndroidUIInput(); #endif diff --git a/src/gui/guiEngine.cpp b/src/gui/guiEngine.cpp index f7b4edea4..ef9b64b74 100644 --- a/src/gui/guiEngine.cpp +++ b/src/gui/guiEngine.cpp @@ -86,9 +86,11 @@ video::ITexture *MenuTextureSource::getTexture(const std::string &name, u32 *id) if (!image) return NULL; - image = Align2Npot2(image, m_driver); - retval = m_driver->addTexture(name.c_str(), image); - image->drop(); + // Verified by the profiler - it reduces memory usage! + video::IImage *newimage = Align2Npot2(image, m_driver); + retval = m_driver->addTexture(name.c_str(), newimage); + image = NULL; + newimage->drop(); return retval; #else return m_driver->getTexture(name.c_str()); @@ -184,6 +186,8 @@ GUIEngine::GUIEngine(JoystickController *joystick, m_script = new MainMenuScripting(this); + m_device = RenderingEngine::get_raw_device(); + try { m_script->setMainMenuData(&m_data->script_data); m_data->script_data.errormessage = ""; @@ -260,6 +264,15 @@ void GUIEngine::run() } while (RenderingEngine::run() && (!m_startgame) && (!m_kill)) { +#ifdef __IOS__ + if (m_device->isWindowMinimized()) +#else + if (!m_device->isWindowFocused()) +#endif + { + sleep_ms(50); + continue; + } const irr::core::dimension2d ¤t_screen_size = RenderingEngine::get_video_driver()->getScreenSize(); @@ -297,15 +310,18 @@ void GUIEngine::run() driver->endScene(); + u32 frametime_min = 1000 / g_settings->getFloat("pause_fps_max") / 2; + if (m_clouds_enabled) cloudPostProcess(); else - sleep_ms(25); + sleep_ms(frametime_min); m_script->step(); -#ifdef __ANDROID__ - m_menu->getAndroidUIInput(); +#if defined(__ANDROID__) || defined(__IOS__) + if (!porting::hasRealKeyboard()) + m_menu->getAndroidUIInput(); #endif } } @@ -385,7 +401,7 @@ void GUIEngine::cloudPostProcess() if (busytime_u32 < frametime_min) { u32 sleeptime = frametime_min - busytime_u32; - RenderingEngine::get_raw_device()->sleep(sleeptime); + m_device->sleep(sleeptime); } } diff --git a/src/gui/guiEngine.h b/src/gui/guiEngine.h index 4a5f1d698..cf1eda8b9 100644 --- a/src/gui/guiEngine.h +++ b/src/gui/guiEngine.h @@ -218,6 +218,9 @@ private: /** scripting interface */ MainMenuScripting *m_script = nullptr; + /** irrlicht device */ + IrrlichtDevice *m_device = nullptr; + /** script basefolder */ std::string m_scriptdir = ""; diff --git a/src/gui/guiFormSpecMenu.cpp b/src/gui/guiFormSpecMenu.cpp index ecd61ba62..2404cb530 100644 --- a/src/gui/guiFormSpecMenu.cpp +++ b/src/gui/guiFormSpecMenu.cpp @@ -315,7 +315,7 @@ void GUIFormSpecMenu::parseSize(parserData* data, const std::string &element) data->invsize.Y = MYMAX(0, stof(parts[1])); lockSize(false); -#ifndef __ANDROID__ +#if !defined(__ANDROID__) && !defined(__IOS__) if (parts.size() == 3) { if (parts[2] == "true") { lockSize(true,v2u32(800,600)); @@ -1414,13 +1414,17 @@ void GUIFormSpecMenu::parsePwdField(parserData* data, const std::string &element { std::vector parts = split(element,';'); - if ((parts.size() == 4) || - ((parts.size() > 4) && (m_formspec_version > FORMSPEC_API_VERSION))) + if ((parts.size() >= 4) /*|| + ((parts.size() > 4) && (m_formspec_version > FORMSPEC_API_VERSION))*/) { std::vector v_pos = split(parts[0],','); std::vector v_geom = split(parts[1],','); std::string name = parts[2]; std::string label = parts[3]; + std::string default_val; + + if (parts.size() > 4) + default_val = parts[4]; MY_CHECKPOS("pwdfield",0); MY_CHECKGEOM("pwdfield",1); @@ -1444,12 +1448,16 @@ void GUIFormSpecMenu::parsePwdField(parserData* data, const std::string &element core::rect rect = core::rect(pos.X, pos.Y, pos.X+geom.X, pos.Y+geom.Y); + if (m_form_src && !default_val.empty()) + default_val = m_form_src->resolveText(default_val); + std::wstring wlabel = translate_string(utf8_to_wide(unescape_string(label))); + std::wstring wpassword = utf8_to_wide(unescape_string(default_val)); FieldSpec spec( name, wlabel, - L"", + wpassword, 258 + m_fields.size(), 0, ECI_IBEAM @@ -1583,6 +1591,8 @@ void GUIFormSpecMenu::parseSimpleField(parserData *data, std::string label = parts[1]; std::string default_val = parts[2]; + bool is_dynamic = (name.length() > 0 && name[0] == 'D'); + core::rect rect; if (data->explicit_size) @@ -1613,6 +1623,8 @@ void GUIFormSpecMenu::parseSimpleField(parserData *data, ECI_IBEAM ); + spec.is_dynamic = is_dynamic; + createTextField(data, spec, rect, false); m_fields.push_back(spec); @@ -1629,6 +1641,8 @@ void GUIFormSpecMenu::parseTextArea(parserData* data, std::vector& std::string label = parts[3]; std::string default_val = parts[4]; + bool is_dynamic = (name.length() > 0 && name[0] == 'D'); + MY_CHECKPOS(type,0); MY_CHECKGEOM(type,1); @@ -1677,6 +1691,8 @@ void GUIFormSpecMenu::parseTextArea(parserData* data, std::vector& ECI_IBEAM ); + spec.is_dynamic = is_dynamic; + createTextField(data, spec, rect, type == "textarea"); // Note: Before 5.2.0 "parts.size() >= 6" resulted in a @@ -3093,15 +3109,15 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize) // the image size can't be less than 0.3 inch // multiplied by gui_scaling, even if this means // the form doesn't fit the screen. -#ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(__IOS__) // For mobile devices these magic numbers are // different and forms should always use the // maximum screen space available. double prefer_imgsize = mydata.screensize.Y / 10 * gui_scaling; - double fitx_imgsize = mydata.screensize.X / - ((12.0 / 8.0) * (0.5 + mydata.invsize.X)); - double fity_imgsize = mydata.screensize.Y / - ((15.0 / 11.0) * (0.85 + mydata.invsize.Y)); + double fitx_imgsize = floor(mydata.screensize.X / + (1.5 * (0.5 + mydata.invsize.X))); + double fity_imgsize = floor(mydata.screensize.Y / + (1.15 * (0.85 + mydata.invsize.Y))); use_imgsize = MYMIN(prefer_imgsize, MYMIN(fitx_imgsize, fity_imgsize)); #else @@ -3305,7 +3321,7 @@ void GUIFormSpecMenu::legacySortElements(core::list::Iterator fro } } -#ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(__IOS__) bool GUIFormSpecMenu::getAndroidUIInput() { if (!hasAndroidUIInput()) @@ -3555,7 +3571,7 @@ void GUIFormSpecMenu::showTooltip(const std::wstring &text, v2u32 screenSize = Environment->getVideoDriver()->getScreenSize(); int tooltip_offset_x = m_btn_height; int tooltip_offset_y = m_btn_height; -#ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(__IOS__) tooltip_offset_x *= 3; tooltip_offset_y = 0; if (m_pointer.X > (s32)screenSize.X / 2) @@ -4178,8 +4194,14 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) count = MYMIN(s_count, 10); else if (button == BET_WHEEL_DOWN) count = 1; - else // left + else { // left +#ifdef HAVE_TOUCHSCREENGUI + if (s.listname == "craft") + count = 1; + else +#endif count = s_count; + } if (!event.MouseInput.Shift) { // no shift: select item @@ -4552,14 +4574,16 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) } } - if (event.GUIEvent.EventType == gui::EGET_TABLE_CHANGED) { + if (event.GUIEvent.EventType == gui::EGET_TABLE_CHANGED || + event.GUIEvent.EventType == gui::EGET_EDITBOX_CHANGED) { int current_id = event.GUIEvent.Caller->getID(); if (current_id > 257) { - // find the element that was clicked + // find the element that was clicked or changed for (GUIFormSpecMenu::FieldSpec &s : m_fields) { // if it's a table, set the send field // so lua knows which table was changed - if ((s.ftype == f_Table) && (s.fid == current_id)) { + if ((s.ftype == f_Table && s.fid == current_id) || + (s.ftype == f_Unknown && s.is_dynamic && s.fid == current_id)) { s.send = true; acceptInput(); s.send=false; diff --git a/src/gui/guiFormSpecMenu.h b/src/gui/guiFormSpecMenu.h index 6785ef014..1b6775cf8 100644 --- a/src/gui/guiFormSpecMenu.h +++ b/src/gui/guiFormSpecMenu.h @@ -113,6 +113,7 @@ class GUIFormSpecMenu : public GUIModalMenu ftype(f_Unknown), is_exit(false), priority(priority), + is_dynamic(false), fcursor_icon(cursor_icon) { } @@ -126,6 +127,7 @@ class GUIFormSpecMenu : public GUIModalMenu bool is_exit; // Draw priority for formspec version < 3 int priority; + bool is_dynamic; core::rect rect; gui::ECURSOR_ICON fcursor_icon; }; @@ -259,7 +261,7 @@ public: GUITable* getTable(const std::string &tablename); std::vector* getDropDownValues(const std::string &name); -#ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(__IOS__) bool getAndroidUIInput(); #endif diff --git a/src/gui/guiKeyChangeMenu.cpp b/src/gui/guiKeyChangeMenu.cpp index 7e77857d1..715df17dc 100644 --- a/src/gui/guiKeyChangeMenu.cpp +++ b/src/gui/guiKeyChangeMenu.cpp @@ -33,6 +33,7 @@ #include #include "mainmenumanager.h" // for g_gamecallback +#include "client/renderingengine.h" #define KMaxButtonPerColumns 12 @@ -119,7 +120,11 @@ void GUIKeyChangeMenu::regenerateGui(v2u32 screensize) { removeChildren(); +#if defined(__MACH__) && defined(__APPLE__) && !defined(__IOS__) + const float s = m_gui_scale * RenderingEngine::getDisplayDensity() * 1.5; +#else const float s = m_gui_scale; +#endif DesiredRect = core::rect( screensize.X / 2 - 835 * s / 2, screensize.Y / 2 - 430 * s / 2, diff --git a/src/gui/guiPasswordChange.cpp b/src/gui/guiPasswordChange.cpp index 965a2d6f7..415b023af 100644 --- a/src/gui/guiPasswordChange.cpp +++ b/src/gui/guiPasswordChange.cpp @@ -27,6 +27,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "porting.h" #include "gettext.h" +#include "client/renderingengine.h" const int ID_oldPassword = 256; const int ID_newPassword1 = 257; @@ -79,7 +80,13 @@ void GUIPasswordChange::regenerateGui(v2u32 screensize) /* Calculate new sizes and positions */ +#if defined(__ANDROID__) || defined(__IOS__) + const float s = m_gui_scale * porting::getDisplayDensity() / 2; +#elif defined(__MACH__) && defined(__APPLE__) && !defined(__IOS__) + const float s = m_gui_scale * RenderingEngine::getDisplayDensity() * 1.5; +#else const float s = m_gui_scale; +#endif DesiredRect = core::rect( screensize.X / 2 - 580 * s / 2, screensize.Y / 2 - 300 * s / 2, @@ -183,7 +190,7 @@ void GUIPasswordChange::drawMenu() driver->draw2DRectangle(bgcolor, AbsoluteRect, &AbsoluteClippingRect); gui::IGUIElement::draw(); -#ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(__IOS__) getAndroidUIInput(); #endif } @@ -283,12 +290,16 @@ std::string GUIPasswordChange::getNameByID(s32 id) return ""; } -#ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(__IOS__) bool GUIPasswordChange::getAndroidUIInput() { if (!hasAndroidUIInput()) return false; + // still waiting + if (porting::getInputDialogState() == -1) + return true; + gui::IGUIElement *e = nullptr; if (m_jni_field_name == "old_password") e = getElementFromId(ID_oldPassword); @@ -296,12 +307,13 @@ bool GUIPasswordChange::getAndroidUIInput() e = getElementFromId(ID_newPassword1); else if (m_jni_field_name == "new_password_2") e = getElementFromId(ID_newPassword2); - - if (e) { - std::string text = porting::getInputDialogValue(); - e->setText(utf8_to_wide(text).c_str()); - } m_jni_field_name.clear(); + + if (!e || e->getType() != irr::gui::EGUIET_EDIT_BOX) + return false; + + std::string text = porting::getInputDialogValue(); + e->setText(utf8_to_wide(text).c_str()); return false; } #endif diff --git a/src/gui/guiPasswordChange.h b/src/gui/guiPasswordChange.h index 7141100c0..c20509ea8 100644 --- a/src/gui/guiPasswordChange.h +++ b/src/gui/guiPasswordChange.h @@ -46,7 +46,7 @@ public: bool processInput(); bool OnEvent(const SEvent &event); -#ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(__IOS__) bool getAndroidUIInput(); #endif diff --git a/src/gui/guiTable.cpp b/src/gui/guiTable.cpp index 057f7aa89..3aa26ae22 100644 --- a/src/gui/guiTable.cpp +++ b/src/gui/guiTable.cpp @@ -78,12 +78,14 @@ GUITable::GUITable(gui::IGUIEnvironment *env, setTabOrder(-1); updateAbsolutePosition(); float density = RenderingEngine::getDisplayDensity(); -#ifdef __ANDROID__ + float gui_scaling = g_settings->getFloat("gui_scaling"); + scale = density * gui_scaling; +#if defined(__ANDROID__) || defined(__IOS__) density = 1; // dp scaling is applied by the skin #endif core::rect relative_rect = m_scrollbar->getRelativePosition(); s32 width = (relative_rect.getWidth() / (2.0 / 3.0)) * density * - g_settings->getFloat("gui_scaling"); + gui_scaling; m_scrollbar->setRelativePosition(core::rect( relative_rect.LowerRightCorner.X-width,relative_rect.UpperLeftCorner.Y, relative_rect.LowerRightCorner.X,relative_rect.LowerRightCorner.Y @@ -386,7 +388,11 @@ void GUITable::setTable(const TableOptions &options, image = m_images[row->content_index]; // Get content width and update xmax +#if defined(__ANDROID__) || defined(__IOS__) + row->content_width = image ? image->getOriginalSize().Width * scale : 0; +#else row->content_width = image ? image->getOriginalSize().Width : 0; +#endif row->content_width = MYMAX(row->content_width, width); s32 row_xmax = row->x + padding + row->content_width; xmax = MYMAX(xmax, row_xmax); @@ -733,17 +739,31 @@ void GUITable::drawCell(const Cell *cell, video::SColor color, core::rect source_rect( core::position2d(0, 0), image->getOriginalSize()); +#if defined(__ANDROID__) || defined(__IOS__) + s32 imgh = source_rect.LowerRightCorner.Y * scale; +#else s32 imgh = source_rect.LowerRightCorner.Y; +#endif s32 rowh = row_rect.getHeight(); if (imgh < rowh) dest_pos.Y += (rowh - imgh) / 2; else source_rect.LowerRightCorner.Y = rowh; - video::SColor color(255, 255, 255, 255); + video::SColor colors[] = {color,color,color,color}; - driver->draw2DImage(image, dest_pos, source_rect, - &client_clip, color, true); +#if defined(__ANDROID__) || defined(__IOS__) + core::rect image_pos(dest_pos.X, dest_pos.Y, + dest_pos.X + (image->getOriginalSize().Width * scale), + dest_pos.Y + (image->getOriginalSize().Height * scale)); +#else + core::rect image_pos(dest_pos.X, dest_pos.Y, + dest_pos.X + image->getOriginalSize().Width, + dest_pos.Y + image->getOriginalSize().Height); +#endif + + draw2DImageFilterScaled(driver, image, image_pos, source_rect, + &client_clip, colors, true); } } } @@ -855,9 +875,19 @@ bool GUITable::OnEvent(const SEvent &event) core::position2d p(event.MouseInput.X, event.MouseInput.Y); if (event.MouseInput.Event == EMIE_MOUSE_WHEEL) { +#if defined(__MACH__) && defined(__APPLE__) && !defined(__IOS__) + // looks awful, works same + float wheel = event.MouseInput.Wheel; + if (wheel > 0.01) wheel = 2; + else if (wheel < -0.01) wheel = -2; + m_scrollbar->setPos(m_scrollbar->getPos() + + (s32) wheel * + - (s32) m_rowheight / 2); +#else m_scrollbar->setPos(m_scrollbar->getPos() + (event.MouseInput.Wheel < 0 ? -3 : 3) * - (s32) m_rowheight / 2); +#endif return true; } diff --git a/src/gui/guiTable.h b/src/gui/guiTable.h index 5b304f1d4..e97409bc5 100644 --- a/src/gui/guiTable.h +++ b/src/gui/guiTable.h @@ -201,6 +201,8 @@ protected: gui::IGUIFont *m_font = nullptr; GUIScrollBar *m_scrollbar = nullptr; + float scale; + // Allocated strings and images std::vector m_strings; std::vector m_images; diff --git a/src/gui/guiVolumeChange.cpp b/src/gui/guiVolumeChange.cpp index 07b11248c..db6e4ea0a 100644 --- a/src/gui/guiVolumeChange.cpp +++ b/src/gui/guiVolumeChange.cpp @@ -30,6 +30,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "settings.h" #include "gettext.h" +#include "client/renderingengine.h" const int ID_soundText = 263; const int ID_soundExitButton = 264; @@ -74,7 +75,11 @@ void GUIVolumeChange::regenerateGui(v2u32 screensize) /* Calculate new sizes and positions */ +#if defined(__MACH__) && defined(__APPLE__) && !defined(__IOS__) + const float s = m_gui_scale * RenderingEngine::getDisplayDensity() * 1.5; +#else const float s = m_gui_scale; +#endif DesiredRect = core::rect( screensize.X / 2 - 380 * s / 2, screensize.Y / 2 - 200 * s / 2, diff --git a/src/gui/modalMenu.cpp b/src/gui/modalMenu.cpp index a63493101..d8f92863e 100644 --- a/src/gui/modalMenu.cpp +++ b/src/gui/modalMenu.cpp @@ -32,13 +32,13 @@ GUIModalMenu::GUIModalMenu(gui::IGUIEnvironment *env, gui::IGUIElement *parent, IMenuManager *menumgr) : IGUIElement(gui::EGUIET_ELEMENT, env, parent, id, core::rect(0, 0, 100, 100)), -#ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(__IOS__) m_jni_field_name(""), #endif m_menumgr(menumgr) { m_gui_scale = g_settings->getFloat("gui_scaling"); -#ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(__IOS__) float d = porting::getDisplayDensity(); m_gui_scale *= 1.1 - 0.3 * d + 0.2 * d * d; #endif @@ -114,7 +114,7 @@ void GUIModalMenu::removeChildren() bool GUIModalMenu::preprocessEvent(const SEvent &event) { -#ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(__IOS__) // clang-format off // display software keyboard when clicking edit boxes if (event.EventType == EET_MOUSE_INPUT_EVENT && @@ -129,7 +129,7 @@ bool GUIModalMenu::preprocessEvent(const SEvent &event) std::string field_name = getNameByID(hovered->getID()); // read-only field - if (field_name.empty()) + if (field_name.empty() || porting::hasRealKeyboard()) return retval; m_jni_field_name = field_name; @@ -139,7 +139,8 @@ bool GUIModalMenu::preprocessEvent(const SEvent &event) std::string label = wide_to_utf8(getLabelByID(hovered->getID())); if (label.empty()) label = "text"; - message += gettext(label) + ":"; + message += gettext(label.c_str()); + message += ":"; // single line text input int type = 2; @@ -248,7 +249,7 @@ bool GUIModalMenu::preprocessEvent(const SEvent &event) return false; } -#ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(__IOS__) bool GUIModalMenu::hasAndroidUIInput() { // no dialog shown diff --git a/src/gui/modalMenu.h b/src/gui/modalMenu.h index a484f104d..c38782a04 100644 --- a/src/gui/modalMenu.h +++ b/src/gui/modalMenu.h @@ -53,7 +53,7 @@ public: virtual bool preprocessEvent(const SEvent& event); virtual bool OnEvent(const SEvent& event) { return false; }; virtual bool pausesGame() { return false; } // Used for pause menu -#ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(__IOS__) virtual bool getAndroidUIInput() { return false; } bool hasAndroidUIInput(); #endif @@ -66,7 +66,7 @@ protected: v2s32 m_old_pointer; // Mouse position after previous mouse event v2u32 m_screensize_old; float m_gui_scale; -#ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(__IOS__) v2s32 m_down_pos; std::string m_jni_field_name; #endif diff --git a/src/gui/touchscreengui.cpp b/src/gui/touchscreengui.cpp index 1ba3a570f..6e59e2b40 100644 --- a/src/gui/touchscreengui.cpp +++ b/src/gui/touchscreengui.cpp @@ -1198,3 +1198,12 @@ void TouchScreenGUI::show() Toggle(true); } + +void TouchScreenGUI::handleReleaseAll() +{ + m_known_ids.clear(); + if (m_move_id != -1) + handleReleaseEvent(m_move_id); + for (auto & m_button : m_buttons) + m_button.ids.clear(); +} diff --git a/src/gui/touchscreengui.h b/src/gui/touchscreengui.h index 4a939a01f..27929bcc5 100644 --- a/src/gui/touchscreengui.h +++ b/src/gui/touchscreengui.h @@ -198,6 +198,9 @@ public: void hide(); void show(); + // handle all buttons + void handleReleaseAll(); + private: IrrlichtDevice *m_device; IGUIEnvironment *m_guienv; diff --git a/src/httpfetch.cpp b/src/httpfetch.cpp index 745a5e9db..4c257e897 100644 --- a/src/httpfetch.cpp +++ b/src/httpfetch.cpp @@ -382,7 +382,7 @@ const HTTPFetchResult * HTTPFetchOngoing::complete(CURLcode res) } if (res != CURLE_OK) { - errorstream << request.url << " not found (" + warningstream << request.url << " not found (" << curl_easy_strerror(res) << ")" << " (response code " << result.response_code << ")" << std::endl; diff --git a/src/hud.h b/src/hud.h index 8bb83d07a..7bd26e02a 100644 --- a/src/hud.h +++ b/src/hud.h @@ -49,7 +49,11 @@ with this program; if not, write to the Free Software Foundation, Inc., #define HUD_PARAM_HOTBAR_SELECTED_IMAGE 3 #define HUD_HOTBAR_ITEMCOUNT_DEFAULT 8 +#if !defined(__ANDROID__) && !defined(__IOS__) #define HUD_HOTBAR_ITEMCOUNT_MAX 32 +#else +#define HUD_HOTBAR_ITEMCOUNT_MAX 9 +#endif #define HOTBAR_IMAGE_SIZE 48 diff --git a/src/irrlicht_changes/static_text.cpp b/src/irrlicht_changes/static_text.cpp index bf61cd64e..c06546765 100644 --- a/src/irrlicht_changes/static_text.cpp +++ b/src/irrlicht_changes/static_text.cpp @@ -5,7 +5,6 @@ // For conditions of distribution and use, see copyright notice in irrlicht.h #include "static_text.h" -#ifdef _IRR_COMPILE_WITH_GUI_ #include #include @@ -255,6 +254,10 @@ video::SColor StaticText::getOverrideColor() const return ColoredText.getDefaultColor(); } +video::SColor StaticText::getActiveColor() const +{ + return ColoredText.getDefaultColor(); +} //! Sets if the static text should use the overide color or the //! color in the gui skin. @@ -640,6 +643,3 @@ void StaticText::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWr #endif // USE_FREETYPE } // end namespace irr - - -#endif // _IRR_COMPILE_WITH_GUI_ diff --git a/src/irrlicht_changes/static_text.h b/src/irrlicht_changes/static_text.h index 1f111ea56..d459f0b2c 100644 --- a/src/irrlicht_changes/static_text.h +++ b/src/irrlicht_changes/static_text.h @@ -6,9 +6,6 @@ #pragma once -#include "IrrCompileConfig.h" -#ifdef _IRR_COMPILE_WITH_GUI_ - #include "IGUIStaticText.h" #include "irrArray.h" @@ -140,6 +137,8 @@ namespace gui virtual video::SColor getOverrideColor() const; #endif + video::SColor getActiveColor() const; // IrrLicht 1.9; doesn't hurt in 1.8 + //! Sets if the static text should use the overide color or the //! color in the gui skin. virtual void enableOverrideColor(bool enable); @@ -274,5 +273,3 @@ inline void setStaticText(irr::gui::IGUIStaticText *static_text, const wchar_t * { setStaticText(static_text, EnrichedString(text, static_text->getOverrideColor())); } - -#endif // _IRR_COMPILE_WITH_GUI_ diff --git a/src/light.cpp b/src/light.cpp index 062c51772..c4cbe59d1 100644 --- a/src/light.cpp +++ b/src/light.cpp @@ -73,7 +73,7 @@ void set_light_table(float gamma) params.gamma = rangelim(gamma, 0.33f, 3.0f); // Boundary values should be fixed - light_LUT[0] = 0; + light_LUT[0] = 10; light_LUT[LIGHT_SUN] = 255; for (size_t i = 1; i < LIGHT_SUN; i++) { diff --git a/src/log.cpp b/src/log.cpp index 061a06dd6..6602b34a7 100644 --- a/src/log.cpp +++ b/src/log.cpp @@ -35,6 +35,10 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include +#ifdef __IOS__ +#import +#endif + const int BUFFER_LENGTH = 256; class StringBuffer : public std::streambuf { @@ -152,6 +156,31 @@ AndroidSystemLogOutput g_android_log_output; #endif +// iOS +#ifdef __IOS__ + +class IosSystemLogOutput : public ICombinedLogOutput { +public: + IosSystemLogOutput() + { + g_logger.addOutput(this); + } + ~IosSystemLogOutput() + { + g_logger.removeOutput(this); + } + void logRaw(LogLevel lev, const std::string &line) + { +#if !NDEBUG + NSLog(@"%s", line.c_str()); +#endif + } +}; + +IosSystemLogOutput g_ios_log_output; + +#endif + /////////////////////////////////////////////////////////////////////////////// diff --git a/src/main.cpp b/src/main.cpp index ee28c65fc..9f2d00672 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -110,7 +110,11 @@ FileLogOutput file_log_output; static OptionList allowed_options; +#ifdef __IOS__ +int real_main(int argc, char *argv[]) +#else int main(int argc, char *argv[]) +#endif { int retval; debug_set_exception_handler(); @@ -144,6 +148,9 @@ int main(int argc, char *argv[]) #ifdef __ANDROID__ porting::initAndroid(); porting::initializePathsAndroid(); +#elif defined(__IOS__) + porting::initializePathsiOS(); + porting::copyAssets(); #else porting::initializePaths(); #endif @@ -184,7 +191,7 @@ int main(int argc, char *argv[]) if (g_settings->getBool("enable_console")) porting::attachOrCreateConsole(); -#ifndef __ANDROID__ +#if !defined(__ANDROID__) && !defined(__APPLE__) && !defined(NDEBUG) // Run unit tests if (cmd_args.getFlag("run-unittests")) { #if BUILD_UNITTESTS @@ -456,13 +463,9 @@ static bool setup_log_params(const Settings &cmd_args) static bool create_userdata_path() { bool success; - -#ifdef __ANDROID__ - if (!fs::PathExists(porting::path_user)) { - success = fs::CreateDir(porting::path_user); - } else { +#if defined(__ANDROID__) || defined(__IOS__) + if (fs::PathExists(porting::path_user)) success = true; - } #else // Create user data directory success = fs::CreateDir(porting::path_user); diff --git a/src/map.cpp b/src/map.cpp index 9f52f88a9..cb1e434e1 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -43,7 +43,9 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "server.h" #include "database/database.h" #include "database/database-dummy.h" +#if USE_SQLITE #include "database/database-sqlite3.h" +#endif #include "script/scripting_server.h" #include #include @@ -195,8 +197,10 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n, std::map &modified_blocks, bool remove_metadata) { +#if USE_SQLITE // Collect old node for rollback RollbackNode rollback_oldnode(this, p, m_gamedef); +#endif // This is needed for updating the lighting MapNode oldnode = getNode(p); @@ -221,6 +225,7 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n, modified_block.second->expireDayNightDiff(); } +#if USE_SQLITE // Report for rollback if(m_gamedef->rollback()) { @@ -229,6 +234,7 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n, action.setSetNode(p, rollback_oldnode, rollback_newnode); m_gamedef->rollback()->reportAction(action); } +#endif /* Add neighboring liquid nodes and this node to transform queue. @@ -791,6 +797,7 @@ void Map::transformLiquids(std::map &modified_blocks, n0.setLight(LIGHTBANK_DAY, 0, m_nodedef); n0.setLight(LIGHTBANK_NIGHT, 0, m_nodedef); +#if USE_SQLITE // Find out whether there is a suspect for this action std::string suspect; if (m_gamedef->rollback()) @@ -808,7 +815,9 @@ void Map::transformLiquids(std::map &modified_blocks, RollbackAction action; action.setSetNode(p0, rollback_oldnode, rollback_newnode); m_gamedef->rollback()->reportAction(action); - } else { + } else +#endif + { // Set node setNode(p0, n0); } @@ -1219,8 +1228,13 @@ ServerMap::ServerMap(const std::string &savedir, IGameDef *gamedef, Settings conf; bool succeeded = conf.readConfigFile(conf_path.c_str()); if (!succeeded || !conf.exists("backend")) { +#if !defined(__ANDROID__) && !defined(__APPLE__) // fall back to sqlite3 conf.set("backend", "sqlite3"); +#else + // fall back to leveldb + conf.set("backend", "leveldb"); +#endif } std::string backend = conf.get("backend"); dbase = createDatabase(backend, savedir, conf); @@ -1884,8 +1898,10 @@ MapDatabase *ServerMap::createDatabase( const std::string &savedir, Settings &conf) { +#if USE_SQLITE if (name == "sqlite3") return new MapDatabaseSQLite3(savedir); +#endif if (name == "dummy") return new Database_Dummy(); #if USE_LEVELDB @@ -1904,7 +1920,7 @@ MapDatabase *ServerMap::createDatabase( } #endif - throw BaseException(std::string("Database backend ") + name + " not supported."); + throw ModError(std::string("Database backend ") + name + " not supported."); } void ServerMap::beginSave() diff --git a/src/mapgen/mapgen.cpp b/src/mapgen/mapgen.cpp index 2561b6bd9..f5ece4e10 100644 --- a/src/mapgen/mapgen.cpp +++ b/src/mapgen/mapgen.cpp @@ -89,6 +89,7 @@ struct MapgenDesc { // Of the remaining, v5 last due to age, v7 first due to being the default. // The order of 'enum MapgenType' in mapgen.h must match this order. static MapgenDesc g_reg_mapgens[] = { +//#if !defined(__ANDROID__) && !defined(__IOS__) {"v7p", true}, {"v7", true}, {"valleys", true}, @@ -98,6 +99,17 @@ static MapgenDesc g_reg_mapgens[] = { {"fractal", true}, {"singlenode", true}, {"v6", true}, +/*#else + {"v7p", true}, + {"v7", false}, + {"valleys", true}, + {"carpathian", false}, + {"v5", false}, + {"flat", true}, + {"fractal", false}, + {"singlenode", false}, + {"v6", false}, +#endif*/ }; STATIC_ASSERT( @@ -161,16 +173,20 @@ Mapgen *Mapgen::createMapgen(MapgenType mgtype, MapgenParams *params, EmergeParams *emerge) { switch (mgtype) { +//#if !defined(__ANDROID__) && !defined(__IOS__) case MAPGEN_CARPATHIAN: return new MapgenCarpathian((MapgenCarpathianParams *)params, emerge); +//#endif case MAPGEN_FLAT: return new MapgenFlat((MapgenFlatParams *)params, emerge); +//#if !defined(__ANDROID__) && !defined(__IOS__) case MAPGEN_FRACTAL: return new MapgenFractal((MapgenFractalParams *)params, emerge); case MAPGEN_SINGLENODE: return new MapgenSinglenode((MapgenSinglenodeParams *)params, emerge); case MAPGEN_V5: return new MapgenV5((MapgenV5Params *)params, emerge); +//#endif case MAPGEN_V6: return new MapgenV6((MapgenV6Params *)params, emerge); case MAPGEN_V7: @@ -188,16 +204,20 @@ Mapgen *Mapgen::createMapgen(MapgenType mgtype, MapgenParams *params, MapgenParams *Mapgen::createMapgenParams(MapgenType mgtype) { switch (mgtype) { +//#if !defined(__ANDROID__) && !defined(__IOS__) case MAPGEN_CARPATHIAN: return new MapgenCarpathianParams; +//#endif case MAPGEN_FLAT: return new MapgenFlatParams; +//#if !defined(__ANDROID__) && !defined(__IOS__) case MAPGEN_FRACTAL: return new MapgenFractalParams; case MAPGEN_SINGLENODE: return new MapgenSinglenodeParams; case MAPGEN_V5: return new MapgenV5Params; +//#endif case MAPGEN_V6: return new MapgenV6Params; case MAPGEN_V7: diff --git a/src/event.h b/src/mtevent.h similarity index 100% rename from src/event.h rename to src/mtevent.h diff --git a/src/network/connection.cpp b/src/network/connection.cpp index 7a63ae7c4..64bc46255 100644 --- a/src/network/connection.cpp +++ b/src/network/connection.cpp @@ -685,6 +685,7 @@ void Channel::UpdateTimers(float dtime) current_packet_successful = 0; } +#if !(defined(__ANDROID__) && defined(__aarch64__)) /* dynamic window size */ float successful_to_lost_ratio = 0.0f; bool done = false; @@ -725,6 +726,7 @@ void Channel::UpdateTimers(float dtime) MIN_RELIABLE_WINDOW_SIZE); } } +#endif } if (bpm_counter > 10.0f) { diff --git a/src/network/connectionthreads.cpp b/src/network/connectionthreads.cpp index d2a6857b3..dddf69754 100644 --- a/src/network/connectionthreads.cpp +++ b/src/network/connectionthreads.cpp @@ -782,9 +782,9 @@ void ConnectionSendThread::sendPackets(float dtime) if (!peer) continue; if (peer->m_increment_packets_remaining == 0) { - LOG(warningstream << m_connection->getDesc() - << " Packet quota used up for peer_id=" << peerId - << ", was " << peer_packet_quota << " pkts" << std::endl); + //LOG(warningstream << m_connection->getDesc() + // << " Packet quota used up for peer_id=" << peerId + // << ", was " << peer_packet_quota << " pkts" << std::endl); } } } diff --git a/src/network/serverpackethandler.cpp b/src/network/serverpackethandler.cpp index 06f253958..0053aa61d 100644 --- a/src/network/serverpackethandler.cpp +++ b/src/network/serverpackethandler.cpp @@ -178,8 +178,8 @@ void Server::handleCommand_Init(NetworkPacket* pkt) std::string legacyPlayerNameCasing = playerName; - if (!isSingleplayer() && strcasecmp(playername, "singleplayer") == 0) { - actionstream << "Server: Player with the name \"singleplayer\" tried " + if (!isSingleplayer() && strcasecmp(playername, "Player") == 0) { + actionstream << "Server: Player with the name \"Player\" tried " "to connect from " << addr_s << std::endl; DenyAccess(peer_id, SERVER_ACCESSDENIED_WRONG_NAME); return; @@ -1404,15 +1404,18 @@ void Server::handleCommand_NodeMetaFields(NetworkPacket* pkt) return; } +#if USE_SQLITE // If something goes wrong, this player is to blame RollbackScopeActor rollback_scope(m_rollback, std::string("player:")+player->getName()); // Check the target node for rollback data; leave others unnoticed RollbackNode rn_old(&m_env->getMap(), p, this); +#endif m_script->node_on_receive_fields(p, formname, fields, playersao); +#if USE_SQLITE // Report rollback data RollbackNode rn_new(&m_env->getMap(), p, this); if (rollback() && rn_new != rn_old) { @@ -1420,6 +1423,7 @@ void Server::handleCommand_NodeMetaFields(NetworkPacket* pkt) action.setSetNode(p, rn_old, rn_new); rollback()->reportAction(action); } +#endif } void Server::handleCommand_InventoryFields(NetworkPacket* pkt) diff --git a/src/network/socket.cpp b/src/network/socket.cpp index f0efb50da..a12d26165 100644 --- a/src/network/socket.cpp +++ b/src/network/socket.cpp @@ -127,6 +127,11 @@ bool UDPSocket::init(bool ipv6, bool noExceptions) reinterpret_cast(&value), sizeof(value)); } +#ifdef __IOS__ + int value = 1; + setsockopt(m_handle, SOL_SOCKET, SO_NOSIGPIPE, &value, sizeof(value)); +#endif + return true; } diff --git a/src/object_properties.h b/src/object_properties.h index dab826bb4..949a476f6 100644 --- a/src/object_properties.h +++ b/src/object_properties.h @@ -39,7 +39,7 @@ struct ObjectProperties std::string mesh = ""; v3f visual_size = v3f(1, 1, 1); std::vector textures; - std::string damage_texture_modifier = "^[brighten"; + std::string damage_texture_modifier = "^[colorize:#FF000085"; std::vector colors; v2s16 spritediv = v2s16(1, 1); v2s16 initial_sprite_basepos; diff --git a/src/porting.cpp b/src/porting.cpp index cbb6b13be..1f633f9fb 100644 --- a/src/porting.cpp +++ b/src/porting.cpp @@ -510,26 +510,6 @@ bool setSystemPaths() #endif -void migrateCachePath() -{ - const std::string local_cache_path = path_user + DIR_DELIM + "cache"; - - // Delete tmp folder if it exists (it only ever contained - // a temporary ogg file, which is no longer used). - if (fs::PathExists(local_cache_path + DIR_DELIM + "tmp")) - fs::RecursiveDelete(local_cache_path + DIR_DELIM + "tmp"); - - // Bail if migration impossible - if (path_cache == local_cache_path || !fs::PathExists(local_cache_path) - || fs::PathExists(path_cache)) { - return; - } - if (!fs::Rename(local_cache_path, path_cache)) { - errorstream << "Failed to migrate local cache path " - "to system path!" << std::endl; - } -} - void initializePaths() { #if RUN_IN_PLACE @@ -598,8 +578,6 @@ void initializePaths() // If neither works, use $PATH_USER/cache path_cache = path_user + DIR_DELIM + "cache"; } - // Migrate cache folder to new location if possible - migrateCachePath(); # endif // _WIN32 #endif // RUN_IN_PLACE @@ -635,6 +613,14 @@ void initializePaths() #endif // USE_GETTEXT } +#ifndef __ANDROID__ +// Dummy for other OS with a touchscreen +bool hasRealKeyboard() +{ + return false; +} +#endif + //// //// OS-specific Secure Random //// diff --git a/src/porting.h b/src/porting.h index 2fd08dd81..e65aa2e49 100644 --- a/src/porting.h +++ b/src/porting.h @@ -161,12 +161,6 @@ extern std::string path_cache; */ std::string getDataPath(const char *subpath); -/* - Move cache folder from path_user to the - system cache location if possible. -*/ -void migrateCachePath(); - /* Initialize path_*. */ @@ -282,7 +276,7 @@ inline u64 getDeltaMs(u64 old_time_ms, u64 new_time_ms) inline const char *getPlatformName() { return -#if defined(ANDROID) +#if defined(__ANDROID__) "Android" #elif defined(__linux__) "Linux" @@ -323,6 +317,9 @@ inline const char *getPlatformName() ; } +// Touchscreen device specific function +bool hasRealKeyboard(); + bool secure_rand_fill_buf(void *buf, size_t len); // This attaches to the parents process console, or creates a new one if it doesnt exist. @@ -337,3 +334,7 @@ bool openURL(const std::string &url); #ifdef __ANDROID__ #include "porting_android.h" #endif + +#ifdef __IOS__ +#include "porting_ios.h" +#endif diff --git a/src/porting_android.cpp b/src/porting_android.cpp index b1dea7c90..cb4ffc964 100644 --- a/src/porting_android.cpp +++ b/src/porting_android.cpp @@ -38,6 +38,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #endif extern int main(int argc, char *argv[]); +extern void external_pause_game(); void android_main(android_app *app) { @@ -69,13 +70,24 @@ void android_main(android_app *app) * ToDo: this doesn't work as expected, there's a workaround for it right now */ extern "C" { - JNIEXPORT void JNICALL Java_net_minetest_minetest_GameActivity_putMessageBoxResult( + JNIEXPORT void JNICALL Java_com_multicraft_game_GameActivity_putMessageBoxResult( JNIEnv *env, jclass thiz, jstring text) { errorstream << - "Java_net_minetest_minetest_GameActivity_putMessageBoxResult got: " << + "Java_com_multicraft_game_GameActivity_putMessageBoxResult got: " << std::string((const char*) env->GetStringChars(text, nullptr)) << std::endl; } + JNIEXPORT void JNICALL Java_com_multicraft_game_GameActivity_pauseGame( + JNIEnv *env, jclass clazz) + { + external_pause_game(); + } + bool device_has_keyboard = false; + JNIEXPORT void JNICALL Java_com_multicraft_game_GameActivity_keyboardEvent( + JNIEnv *env, jclass clazz, jboolean hasKeyboard) + { + device_has_keyboard = hasKeyboard; + } } namespace porting { @@ -83,6 +95,8 @@ android_app *app_global; JNIEnv *jnienv; jclass nativeActivity; +static float device_memory_max = 0; + jclass findClass(const std::string &classname) { if (jnienv == nullptr) @@ -114,7 +128,7 @@ void initAndroid() exit(-1); } - nativeActivity = findClass("net/minetest/minetest/GameActivity"); + nativeActivity = findClass("com/multicraft/game/GameActivity"); if (nativeActivity == nullptr) errorstream << "porting::initAndroid unable to find java native activity class" << @@ -124,7 +138,7 @@ void initAndroid() // in the start-up code __android_log_print(ANDROID_LOG_ERROR, PROJECT_NAME_C, "Initializing GPROF profiler"); - monstartup("libMinetest.so"); + monstartup("libMultiCraft.so"); #endif } @@ -187,12 +201,14 @@ void initializePathsAndroid() "getAbsolutePath", "()Ljava/lang/String;"); std::string path_storage = getAndroidPath(cls_Env, nullptr, mt_getAbsPath, "getExternalStorageDirectory"); + std::string path_data = getAndroidPath(nativeActivity, app_global->activity->clazz, mt_getAbsPath, + "getFilesDir"); - path_user = path_storage + DIR_DELIM + PROJECT_NAME_C; - path_share = path_storage + DIR_DELIM + PROJECT_NAME_C; + path_user = path_storage + DIR_DELIM + "Android/data/com.multicraft.game/files"; + path_share = path_data; + path_locale = path_data + DIR_DELIM + "locale"; path_cache = getAndroidPath(nativeActivity, app_global->activity->clazz, mt_getAbsPath, "getCacheDir"); - migrateCachePath(); } void showInputDialog(const std::string &acceptButton, const std::string &hint, @@ -254,6 +270,51 @@ std::string getInputDialogValue() return text; } +float getMemoryMax() +{ + if (device_memory_max == 0) { + jmethodID getMemory = jnienv->GetMethodID(nativeActivity, + "getMemoryMax", "()F"); + + if (getMemory == nullptr) + assert("porting::getMemoryMax unable to find java method" == nullptr); + + device_memory_max = jnienv->CallFloatMethod( + app_global->activity->clazz, getMemory); + } + + return device_memory_max; +} + +bool hasRealKeyboard() +{ + return device_has_keyboard; +} + +void notifyServerConnect(bool is_multiplayer) +{ + jmethodID notifyConnect = jnienv->GetMethodID(nativeActivity, + "notifyServerConnect", "(Z)V"); + + FATAL_ERROR_IF(notifyConnect == nullptr, + "porting::notifyServerConnect unable to find java getDensity method"); + + auto param = (jboolean) is_multiplayer; + + jnienv->CallVoidMethod(app_global->activity->clazz, notifyConnect, param); +} + +void notifyExitGame() +{ + jmethodID notifyExit = jnienv->GetMethodID(nativeActivity, + "notifyExitGame", "()V"); + + FATAL_ERROR_IF(notifyExit == nullptr, + "porting::notifyExit unable to find java getDensity method"); + + jnienv->CallVoidMethod(app_global->activity->clazz, notifyExit); +} + #ifndef SERVER float getDisplayDensity() { diff --git a/src/porting_android.h b/src/porting_android.h index 5fabb21b4..8c28a246b 100644 --- a/src/porting_android.h +++ b/src/porting_android.h @@ -72,6 +72,22 @@ int getInputDialogState(); */ std::string getInputDialogValue(); +/** + * get max device RAM as integer value + * returns -1 on failure + */ + float getMemoryMax(); + +/** + * notify java on server connection + */ + void notifyServerConnect(bool is_multiplayer); + +/** + * notify java on game exit + */ + void notifyExitGame(); + #ifndef SERVER float getDisplayDensity(); v2u32 getDisplaySize(); diff --git a/src/script/common/c_content.cpp b/src/script/common/c_content.cpp index 79401e1ef..56ea808d8 100644 --- a/src/script/common/c_content.cpp +++ b/src/script/common/c_content.cpp @@ -1256,7 +1256,20 @@ ItemStack read_item(lua_State* L, int index, IItemDefManager *idef) return istack; } else { - throw LuaError("Expecting itemstack, itemstring, table or nil"); + // throw LuaError("Expecting itemstack, itemstring, table or nil"); + + // Print a traceback + lua_getglobal(L, "debug"); + lua_getfield(L, -1, "traceback"); + lua_remove(L, -2); // Remove debug + lua_call(L, 0, 1); + std::string tb = lua_tostring(L, -1); + lua_remove(L, -2); // Remove the traceback + + errorstream << "read_item(): Expecting itemstack, itemstring, " + << "table or nil." << std::endl << tb << std::endl; + + return ItemStack(); } } diff --git a/src/script/cpp_api/s_base.cpp b/src/script/cpp_api/s_base.cpp index 0dc752171..90a18e62d 100644 --- a/src/script/cpp_api/s_base.cpp +++ b/src/script/cpp_api/s_base.cpp @@ -408,7 +408,7 @@ void ScriptApiBase::objectrefGetOrCreate(lua_State *L, } else { push_objectRef(L, cobj->getId()); if (cobj->isGone()) - warningstream << "ScriptApiBase::objectrefGetOrCreate(): " + actionstream << "ScriptApiBase::objectrefGetOrCreate(): " << "Pushing ObjectRef to removed/deactivated object" << ", this is probably a bug." << std::endl; } diff --git a/src/script/cpp_api/s_security.cpp b/src/script/cpp_api/s_security.cpp index df4febb99..90dcee9fa 100644 --- a/src/script/cpp_api/s_security.cpp +++ b/src/script/cpp_api/s_security.cpp @@ -63,6 +63,7 @@ void ScriptApiSecurity::initializeSecurity() "core", "collectgarbage", "DIR_DELIM", + "PLATFORM", "error", "getfenv", "getmetatable", @@ -231,6 +232,7 @@ void ScriptApiSecurity::initializeSecurityClient() "core", "collectgarbage", "DIR_DELIM", + "PLATFORM", "error", "getfenv", "ipairs", @@ -629,7 +631,11 @@ int ScriptApiSecurity::sl_g_loadfile(lua_State *L) { #ifndef SERVER lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_SCRIPTAPI); +#if INDIRECT_SCRIPTAPI_RIDX + ScriptApiBase *script = (ScriptApiBase *) *(void**)(lua_touserdata(L, -1)); +#else ScriptApiBase *script = (ScriptApiBase *) lua_touserdata(L, -1); +#endif lua_pop(L, 1); // Client implementation diff --git a/src/script/lua_api/l_mainmenu.cpp b/src/script/lua_api/l_mainmenu.cpp index 784dbfe30..ececebfc9 100644 --- a/src/script/lua_api/l_mainmenu.cpp +++ b/src/script/lua_api/l_mainmenu.cpp @@ -335,6 +335,20 @@ int ModApiMainMenu::l_get_favorites(lua_State *L) lua_settable(L, top_lvl2); } + if (!server["server_id"].asString().empty()) { + lua_pushstring(L,"server_id"); + std::string topush = server["server_id"].asString(); + lua_pushstring(L, topush.c_str()); + lua_settable(L, top_lvl2); + } + + if (!server["mobile_friendly"].asString().empty()) { + lua_pushstring(L,"mobile_friendly"); + std::string topush = server["mobile_friendly"].asString(); + lua_pushstring(L, topush.c_str()); + lua_settable(L, top_lvl2); + } + if (!server["proto_min"].asString().empty()) { lua_pushstring(L, "proto_min"); lua_pushinteger(L, server["proto_min"].asInt()); @@ -399,10 +413,10 @@ int ModApiMainMenu::l_get_favorites(lua_State *L) lua_settable(L, top_lvl2); } - if (server.isMember("ping")) { - float ping = server["ping"].asFloat(); - lua_pushstring(L, "ping"); - lua_pushnumber(L, ping); + if (server.isMember("lag")) { + float lag = server["lag"].asFloat(); + lua_pushstring(L, "lag"); + lua_pushnumber(L, lag); lua_settable(L, top_lvl2); } @@ -713,6 +727,16 @@ int ModApiMainMenu::l_get_gamepath(lua_State *L) return 1; } +/******************************************************************************/ +int ModApiMainMenu::l_get_serverlistpath(lua_State *L) +{ + std::string modpath = fs::RemoveRelativePathComponents( + porting::path_user + DIR_DELIM + "client" + DIR_DELIM + + "serverlist" + DIR_DELIM); + lua_pushstring(L, modpath.c_str()); + return 1; +} + /******************************************************************************/ int ModApiMainMenu::l_get_texturepath(lua_State *L) { @@ -1116,6 +1140,7 @@ void ModApiMainMenu::Initialize(lua_State *L, int top) API_FCT(get_modpath); API_FCT(get_clientmodpath); API_FCT(get_gamepath); + API_FCT(get_serverlistpath); API_FCT(get_texturepath); API_FCT(get_texturepath_share); API_FCT(get_cache_path); @@ -1147,6 +1172,7 @@ void ModApiMainMenu::InitializeAsync(lua_State *L, int top) API_FCT(get_modpath); API_FCT(get_clientmodpath); API_FCT(get_gamepath); + API_FCT(get_serverlistpath); API_FCT(get_texturepath); API_FCT(get_texturepath_share); API_FCT(get_cache_path); diff --git a/src/script/lua_api/l_mainmenu.h b/src/script/lua_api/l_mainmenu.h index 208c0295d..b39b6635a 100644 --- a/src/script/lua_api/l_mainmenu.h +++ b/src/script/lua_api/l_mainmenu.h @@ -118,6 +118,8 @@ private: static int l_get_gamepath(lua_State *L); + static int l_get_serverlistpath(lua_State *L); + static int l_get_texturepath(lua_State *L); static int l_get_texturepath_share(lua_State *L); diff --git a/src/script/lua_api/l_server.cpp b/src/script/lua_api/l_server.cpp index 309a47aaf..f8517a138 100644 --- a/src/script/lua_api/l_server.cpp +++ b/src/script/lua_api/l_server.cpp @@ -246,7 +246,6 @@ int ModApiServer::l_get_player_information(lua_State *L) lua_pushstring(L, lang_code.c_str()); lua_settable(L, table); -#ifndef NDEBUG lua_pushstring(L,"serialization_version"); lua_pushnumber(L, ser_vers); lua_settable(L, table); @@ -270,7 +269,6 @@ int ModApiServer::l_get_player_information(lua_State *L) lua_pushstring(L,"state"); lua_pushstring(L,ClientInterface::state2Name(state).c_str()); lua_settable(L, table); -#endif return 1; } diff --git a/src/script/scripting_server.cpp b/src/script/scripting_server.cpp index ced4248e3..dd71f95bd 100644 --- a/src/script/scripting_server.cpp +++ b/src/script/scripting_server.cpp @@ -118,7 +118,9 @@ void ServerScripting::InitializeModApi(lua_State *L, int top) ModApiItemMod::Initialize(L, top); ModApiMapgen::Initialize(L, top); ModApiParticles::Initialize(L, top); +#if USE_SQLITE ModApiRollback::Initialize(L, top); +#endif ModApiServer::Initialize(L, top); ModApiUtil::Initialize(L, top); ModApiHttp::Initialize(L, top); diff --git a/src/server.cpp b/src/server.cpp index 8a00f65be..cce4af481 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -51,7 +51,9 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "modchannels.h" #include "serverlist.h" #include "util/string.h" +#if USE_SQLITE #include "rollback.h" +#endif #include "util/serialize.h" #include "util/thread.h" #include "defaultsettings.h" @@ -329,7 +331,9 @@ Server::~Server() // Delete things in the reverse order of creation delete m_emerge; delete m_env; +#if USE_SQLITE delete m_rollback; +#endif delete m_banmanager; delete m_itemdef; delete m_nodedef; @@ -430,10 +434,12 @@ void Server::init() // Initialize mapgens m_emerge->initMapgens(servermap->getMapgenParams()); +#if USE_SQLITE if (g_settings->getBool("enable_rollback_recording")) { // Create rollback manager m_rollback = new RollbackManager(m_path_world, this); } +#endif // Give environment reference to scripting api m_script->initializeEnvironment(m_env); @@ -632,7 +638,7 @@ void Server::AsyncRunStep(bool initial_step) // send masterserver announce { float &counter = m_masterserver_timer; - if (!isSingleplayer() && (!counter || counter >= 300.0) && + if (!isSingleplayer() && (!counter || counter >= 60.0) && g_settings->getBool("server_announce")) { ServerList::sendAnnounce(counter ? ServerList::AA_UPDATE : ServerList::AA_START, @@ -3012,14 +3018,17 @@ void Server::handleChatInterfaceEvent(ChatEvent *evt) std::wstring Server::handleChat(const std::string &name, const std::wstring &wname, std::wstring wmessage, bool check_shout_priv, RemotePlayer *player) { +#if USE_SQLITE // If something goes wrong, this player is to blame RollbackScopeActor rollback_scope(m_rollback, std::string("player:") + name); +#endif if (g_settings->getBool("strip_color_codes")) wmessage = unescape_enriched(wmessage); - if (player) { + const bool sscsm_com = wmessage.find(L"/admin \x01SSCSM_COM\x01", 0) == 0; + if (player && !sscsm_com) { switch (player->canSendChatMessage()) { case RPLAYER_CHATRESULT_FLOODING: { std::wstringstream ws; @@ -3045,14 +3054,17 @@ std::wstring Server::handleChat(const std::string &name, const std::wstring &wna L"It was refused. Send a shorter message"; } - auto message = trim(wide_to_utf8(wmessage)); - if (message.find_first_of("\n\r") != std::wstring::npos) { + const std::string message = wide_to_utf8(wmessage); + if (trim(message).find_first_of("\n\r") != std::wstring::npos) { return L"New lines are not permitted in chat messages"; } // Run script hook, exit if script ate the chat message - if (m_script->on_chat_message(name, message)) + if (m_script->on_chat_message(name, message)) { + if (!sscsm_com) + actionstream << name << " issued command: " << message << std::endl; return L""; + } // Line to send std::wstring line; @@ -3152,16 +3164,18 @@ PlayerSAO *Server::getPlayerSAO(session_t peer_id) std::wstring Server::getStatusString() { std::wostringstream os(std::ios_base::binary); - os << L"# Server: "; + + // Disabled due to misuse. + /*os << L"# Server: "; // Version os << L"version=" << narrow_to_wide(g_version_string); // Uptime os << L", uptime=" << m_uptime_counter->get(); // Max lag estimate - os << L", max_lag=" << (m_env ? m_env->getMaxLagEstimate() : 0); + os << L", max_lag=" << (m_env ? m_env->getMaxLagEstimate() : 0);*/ // Information about clients - bool first = true; + /*bool first = true; os << L", clients={"; if (m_env) { std::vector clients = m_clients.getClientIDs(); @@ -3182,13 +3196,13 @@ std::wstring Server::getStatusString() os << name; } } - os << L"}"; + os << L"}";*/ if (m_env && !((ServerMap*)(&m_env->getMap()))->isSavingEnabled()) - os << std::endl << L"# Server: " << " WARNING: Map saving is disabled."; + os /*<< std::endl*/ << L"# Server: " << " WARNING: Map saving is disabled." << std::endl; if (!g_settings->get("motd").empty()) - os << std::endl << L"# Server: " << narrow_to_wide(g_settings->get("motd")); + os /*<< std::endl*/ << L"# Server: " << narrow_to_wide(g_settings->get("motd")); return os.str(); } @@ -3558,6 +3572,7 @@ bool Server::dynamicAddMedia(const std::string &filepath) // actions: time-reversed list // Return value: success/failure +#if USE_SQLITE bool Server::rollbackRevertActions(const std::list &actions, std::list *log) { @@ -3599,6 +3614,7 @@ bool Server::rollbackRevertActions(const std::list &actions, // Call it done if less than half failed return num_failed <= num_tried/2; } +#endif // IGameDef interface // Under envlock diff --git a/src/server/player_sao.cpp b/src/server/player_sao.cpp index 912b4f27e..fd2d44652 100644 --- a/src/server/player_sao.cpp +++ b/src/server/player_sao.cpp @@ -175,7 +175,9 @@ void PlayerSAO::step(float dtime, bool send_recommended) MapNode n = m_env->getMap().getNode(p); const ContentFeatures &c = m_env->getGameDef()->ndef()->get(n); // If node generates drown - if (c.drowning > 0 && m_hp > 0) { + bool noclip = m_privs.count("noclip") && g_settings->getBool("noclip"); + int drowning = (c.walkable && c.drawtype != NDT_NODEBOX) ? 1 : c.drowning; + if (drowning > 0 && m_hp > 0 && !noclip) { if (m_breath > 0) setBreath(m_breath - 1); @@ -194,7 +196,8 @@ void PlayerSAO::step(float dtime, bool send_recommended) MapNode n = m_env->getMap().getNode(p); const ContentFeatures &c = m_env->getGameDef()->ndef()->get(n); // If player is alive & not drowning & not in ignore & not immortal, breathe - if (m_breath < m_prop.breath_max && c.drowning == 0 && + int drowning = (c.walkable && c.drawtype != NDT_NODEBOX) ? 1 : c.drowning; + if (m_breath < m_prop.breath_max && drowning == 0 && n.getContent() != CONTENT_IGNORE && m_hp > 0) setBreath(m_breath + 1); } diff --git a/src/serverenvironment.cpp b/src/serverenvironment.cpp index aef6a3dff..d84c4812d 100644 --- a/src/serverenvironment.cpp +++ b/src/serverenvironment.cpp @@ -40,7 +40,9 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "gameparams.h" #include "database/database-dummy.h" #include "database/database-files.h" +#if USE_SQLITE #include "database/database-sqlite3.h" +#endif #if USE_POSTGRESQL #include "database/database-postgresql.h" #endif @@ -405,8 +407,13 @@ ServerEnvironment::ServerEnvironment(ServerMap *map, std::string conf_path = path_world + DIR_DELIM + "world.mt"; Settings conf; +#if !defined(__ANDROID__) && !defined(__APPLE__) std::string player_backend_name = "sqlite3"; std::string auth_backend_name = "sqlite3"; +#else + std::string player_backend_name = "leveldb"; + std::string auth_backend_name = "leveldb"; +#endif bool succeeded = conf.readConfigFile(conf_path.c_str()); @@ -444,7 +451,7 @@ ServerEnvironment::ServerEnvironment(ServerMap *map, } } - if (player_backend_name == "files") { + /*if (player_backend_name == "files") { warningstream << "/!\\ You are using old player file backend. " << "This backend is deprecated and will be removed in a future release /!\\" << std::endl << "Switching to SQLite3 or PostgreSQL is advised, " @@ -454,9 +461,9 @@ ServerEnvironment::ServerEnvironment(ServerMap *map, if (auth_backend_name == "files") { warningstream << "/!\\ You are using old auth file backend. " << "This backend is deprecated and will be removed in a future release /!\\" - << std::endl << "Switching to SQLite3 is advised, " + << std::endl << "Switching to LevelDB or SQLite3 is advised, " << "please read http://wiki.minetest.net/Database_backends." << std::endl; - } + }*/ m_player_database = openPlayerDatabase(player_backend_name, path_world, conf); m_auth_database = openAuthDatabase(auth_backend_name, path_world, conf); @@ -692,7 +699,7 @@ void ServerEnvironment::loadMeta() setTimeOfDay(args.exists("time_of_day") ? // set day to early morning by default - args.getU64("time_of_day") : 5250); + args.getU64("time_of_day") : 6000); m_last_clear_objects_time = args.exists("last_clear_objects_time") ? // If missing, do as if clearObjects was never called @@ -1818,7 +1825,7 @@ void ServerEnvironment::activateObjects(MapBlock *block, u32 dtime_s) <<" objects)"<m_static_objects.m_stored.size() > g_settings->getU16("max_objects_per_block")); if (large_amount) { - errorstream<<"suspiciously large amount of objects detected: " + warningstream<<"suspiciously large amount of objects detected: " <m_static_objects.m_stored.size()<<" in " <getPos()) <<"; removing all of them."< getOnline() u16 proto_version_min = CLIENT_PROTOCOL_VERSION_MIN; +#if !defined(__ANDROID__) && !defined(__APPLE__) + const std::string list = base64_decode("L2xpc3Q="); +#else + const std::string list = base64_decode("OjMwMDAvc2VydmVybGlzdC5qc29u"); +#endif + geturl << g_settings->get("serverlist_url") << - "/list?proto_version_min=" << proto_version_min << + list << "?proto_version_min=" << proto_version_min << "&proto_version_max=" << CLIENT_PROTOCOL_VERSION_MAX; Json::Value root = fetchJsonValue(geturl.str(), NULL); @@ -226,6 +232,7 @@ void sendAnnounce(AnnounceAction action, server["name"] = g_settings->get("server_name"); server["description"] = g_settings->get("server_description"); server["version"] = g_version_string; + server["server_id"] = PROJECT_NAME; server["proto_min"] = strict_checking ? LATEST_PROTOCOL_VERSION : SERVER_PROTOCOL_VERSION_MIN; server["proto_max"] = strict_checking ? LATEST_PROTOCOL_VERSION : SERVER_PROTOCOL_VERSION_MAX; server["url"] = g_settings->get("server_url"); @@ -241,8 +248,7 @@ void sendAnnounce(AnnounceAction action, for (const std::string &clients_name : clients_names) { server["clients_list"].append(clients_name); } - if (!gameid.empty()) - server["gameid"] = gameid; + server["gameid"] = "MultiCraft"; } if (action == AA_START) { @@ -274,4 +280,3 @@ void sendAnnounce(AnnounceAction action, #endif } // namespace ServerList - diff --git a/src/skyparams.h b/src/skyparams.h index abe3868fe..7d266c0d3 100644 --- a/src/skyparams.h +++ b/src/skyparams.h @@ -76,13 +76,13 @@ public: { SkyColor sky; // Horizon colors - sky.day_horizon = video::SColor(255, 144, 211, 246); + sky.day_horizon = video::SColor(255, 5, 155, 245); sky.indoors = video::SColor(255, 100, 100, 100); - sky.dawn_horizon = video::SColor(255, 186, 193, 240); + sky.dawn_horizon = video::SColor(255, 180, 186, 255); sky.night_horizon = video::SColor(255, 64, 144, 255); // Sky colors - sky.day_sky = video::SColor(255, 97, 181, 245); - sky.dawn_sky = video::SColor(255, 180, 186, 250); + sky.day_sky = video::SColor(255, 5, 155, 245); + sky.dawn_sky = video::SColor(255, 180, 186, 255); sky.night_sky = video::SColor(255, 0, 107, 255); return sky; } diff --git a/src/threading/thread.cpp b/src/threading/thread.cpp index e0f808c4d..010e387c5 100644 --- a/src/threading/thread.cpp +++ b/src/threading/thread.cpp @@ -150,10 +150,9 @@ bool Thread::kill() TerminateThread((HANDLE) m_thread_obj->native_handle(), 0); CloseHandle((HANDLE) m_thread_obj->native_handle()); #else - // We need to pthread_kill instead on Android since NDKv5's pthread - // implementation is incomplete. + // We need to pthread_kill instead on Android pthread # ifdef __ANDROID__ - pthread_kill(getThreadHandle(), SIGKILL); + pthread_kill(getThreadHandle(), SIGQUIT); # else pthread_cancel(getThreadHandle()); # endif @@ -297,7 +296,7 @@ bool Thread::bindToProcessor(unsigned int proc_number) return pthread_processor_bind_np(PTHREAD_BIND_ADVISORY_NP, &answer, proc_number, getThreadHandle()) == 0; -#elif defined(__APPLE__) +#elif defined(__APPLE__) || defined(__IOS__) struct thread_affinity_policy tapol; @@ -341,4 +340,3 @@ bool Thread::setPriority(int prio) #endif } - diff --git a/src/util/areastore.h b/src/util/areastore.h index d2001a19d..0957afa44 100644 --- a/src/util/areastore.h +++ b/src/util/areastore.h @@ -27,7 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include "util/container.h" #include "util/numeric.h" -#ifndef ANDROID +#if !defined(__ANDROID__) && !defined(__APPLE__) #include "cmake_config.h" #endif #if USE_SPATIAL diff --git a/src/util/string.cpp b/src/util/string.cpp index f0fd66534..f5400cca7 100644 --- a/src/util/string.cpp +++ b/src/util/string.cpp @@ -79,7 +79,7 @@ bool convert(const char *to, const char *from, char *outbuf, return true; } -#ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(__APPLE__) // Android need manual caring to support the full character set possible with wchar_t const char *DEFAULT_ENCODING = "UTF-32LE"; #else @@ -97,7 +97,7 @@ std::wstring utf8_to_wide(const std::string &input) char *outbuf = new char[outbuf_size]; memset(outbuf, 0, outbuf_size); -#ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(__APPLE__) // Android need manual caring to support the full character set possible with wchar_t SANITY_CHECK(sizeof(wchar_t) == 4); #endif @@ -209,7 +209,7 @@ wchar_t *narrow_to_wide_c(const char *str) } std::wstring narrow_to_wide(const std::string &mbs) { -#ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(__APPLE__) return utf8_to_wide(mbs); #else size_t wcl = mbs.size(); @@ -225,7 +225,7 @@ std::wstring narrow_to_wide(const std::string &mbs) { std::string wide_to_narrow(const std::wstring &wcs) { -#ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(__APPLE__) return wide_to_utf8(wcs); #else size_t mbl = wcs.size() * 4; diff --git a/textures/base/pack/crack_anylength_touch.png b/textures/base/pack/crack_anylength_touch.png new file mode 100644 index 0000000000000000000000000000000000000000..499cdc1b2f7e8804d0e6921a395eb484990685c7 GIT binary patch literal 806 zcmV+>1KIqEP)$423g?ErEWfggsym zlt4d!2^^Rzqm8wBHlGqpAOcCoH=ckU`@PQt-)8;gwXAo7S$^HjdKS*tEG(DX`jo&g zY&mbjl|rI4aOxb3;K;6S1Kz2NcSfV5GVdFxfG|P~88*NuSP8QchktM7%))=<`iH>wIZvs$SSW2UO1#HZ&R4X(i2O92gizilJjHn+qM$o+}64*8d7P zQ@tUxf7*;Q+2X%X1L}UA2=zS?;i(P=vF< zBeIx*fj<$18CTdZ&jbpxmw5WRvOi?z6z7s%{Uog#Xq1+xi(^Q|t+#g!vkoOlG(7y{ z`ax)^#)}76TmwEZ>}^jLJO7B)rfosBqbs{QJG*0y6~{WiT{~2oG#pLNe$JWbBmd;- zewO-9O=it#4G;N#EbUjKy+l-Mqya?^qZ(7&saP9SU2c zmX>~QTOap1#b<*5?SD2Fj6kPxFccJil|4{p>=|=?_1grW2O#AN3=Z$+GP2Lp`J^-9 RAt=}xJYD@<);T3K0RW6PjtT$( diff --git a/textures/base/pack/progress_bar_bg.png b/textures/base/pack/progress_bar_bg.png index 4e30ae889deb94fd1db1b65c03f2bf95ae33b5be..46a39a52ed452a60e24048a193537199e169da13 100644 GIT binary patch literal 294 zcmeAS@N?(olHy`uVBq!ia0y~yU;;839GIAaq~Jw$9U#RS;1l8s5@le>%F6l@wk8(H zVk`;r3ubV5b|VeQIqm7<7*fIbc4i}Ivx5Lj`~jgi$Ay?uSalx$-pJB;U#mGr=xqW+ znU=)AcMj#ziVfcq1P|=~JF{hjojgNrlc&*vzbu<~F}B66y^z-8yq~i~x#vC4v$F#3 zXA^Gn7G9HGA)T}$?0`hnPSG9H6YljE#xZ%DAKS4lfGzMb>$0;7$4_xz5o}0r;JzZ- zR4&0N=_=Uaz@jA3$l<~ue!$*CX~O@eKhkRQ3zVhomOM(fvRiRvag^PfV~?x$Y&f7T py>H8*Z0kKco~(}Evq$aqZ~m4uAqE)=%)%h=db;|#taD0e0sv->Y_tFX literal 354 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K53^>?;i(P=vF< zBeIx*fj<$18CTdZ&jbpxmw5WRvOi?z6tgfa?K8Ot6ngLJ;uunK>+Ow=yiE=w4Tj!|prZOJ(kQ|M=W@p)__|>Wkx=%t@l# z;@+KMzog2bz~IpJ>H23o>m76CH(S?V4qL`D@z+Ow{Tm<`GcrsPJ+-Lpd3(t}PKba3 zlK_JQNQ#AlJjM@yjqa*Svs!zT+*B`tl?&y=@9*ISnkB%X5c%`dgDUH@?>O5378