Backport MultiCraft Engine changes
This commit is contained in:
parent
6227f9c72c
commit
2aa0400bd2
182
.github/workflows/build.yml
vendored
182
.github/workflows/build.yml
vendored
@ -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"
|
||||
@ -221,8 +221,8 @@ jobs:
|
||||
name: VS 2019 ${{ matrix.config.arch }}-${{ matrix.type }}
|
||||
runs-on: windows-2019
|
||||
env:
|
||||
VCPKG_VERSION: c7ab9d3110813979a873b2dbac630a9ab79850dc
|
||||
# 2020.04
|
||||
VCPKG_VERSION: 0bf3923f9fab4001c00f0f429682a0853b5749e0
|
||||
# 2020.11
|
||||
vcpkg_packages: irrlicht zlib curl[winssl] openal-soft libvorbis libogg sqlite3 freetype luajit
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@ -248,7 +248,7 @@ jobs:
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Restore from cache and run vcpkg
|
||||
uses: lukka/run-vcpkg@v2
|
||||
uses: lukka/run-vcpkg@v5
|
||||
with:
|
||||
vcpkgArguments: ${{env.vcpkg_packages}}
|
||||
vcpkgDirectory: '${{ github.workspace }}\vcpkg'
|
||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -55,6 +55,8 @@ build/.cmake/
|
||||
/clientmods/*
|
||||
!/clientmods/preview/
|
||||
/client/mod_storage/
|
||||
/builtin/mainmenu/hosting/
|
||||
/textures/base/pack/hosting/
|
||||
|
||||
## Configuration/log files
|
||||
multicraft.conf
|
||||
|
@ -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")
|
||||
|
@ -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" \
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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<ModChannelMgr> m_modchannel_mgr;
|
||||
|
||||
u16 m_round_screen;
|
||||
f32 m_hud_scaling;
|
||||
};
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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] = {
|
||||
|
@ -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 <list>
|
||||
#include <map>
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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<u32> ¤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
|
||||
|
@ -65,7 +65,7 @@ void GameUI::init()
|
||||
// Object infos are shown in this
|
||||
m_guitext_info = gui::StaticText::add(guienv, L"",
|
||||
core::rect<s32>(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"<Status>",
|
||||
@ -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<s32>(5, 5, screensize.X,
|
||||
5 + g_fontengine->getTextHeight()));
|
||||
}
|
||||
m_guitext->setRelativePosition(core::rect<s32>(
|
||||
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<s32>(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();
|
||||
|
||||
|
@ -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<u32> 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 <=
|
||||
|
@ -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 */
|
||||
|
@ -65,6 +65,7 @@ public:
|
||||
TOGGLE_PROFILER,
|
||||
CAMERA_MODE,
|
||||
INCREASE_VIEWING_RANGE,
|
||||
INCREASE_VIEWING_RANGE2,
|
||||
DECREASE_VIEWING_RANGE,
|
||||
RANGESELECT,
|
||||
ZOOM,
|
||||
|
@ -19,7 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
|
||||
#include "localplayer.h"
|
||||
#include <cmath>
|
||||
#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)
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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) {
|
||||
|
@ -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<s32>(0, 0, screensize.X * 4, screensize.Y * 4),
|
||||
irr::core::rect<s32>(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<u32> &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<u32> 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<s32>(img_pos.X, img_pos.Y,
|
||||
img_pos.X + imgW,
|
||||
img_pos.Y + imgH),
|
||||
core::rect<s32>(0, 0, img_size.Width,
|
||||
img_size.Height),
|
||||
0, 0, true);
|
||||
draw2DImageFilterScaled(
|
||||
driver, progress_img_bg,
|
||||
core::rect<s32>(img_pos.X, img_pos.Y, img_pos.X + imgW, img_pos.Y + imgH),
|
||||
core::rect<s32>(0, 0, img_size.Width, img_size.Height),
|
||||
0, 0, true);
|
||||
|
||||
// rects for drawing a color progress bar
|
||||
const static core::rect<s32> rects[] = {
|
||||
core::rect<s32>( 4, 24, 5, 40),
|
||||
core::rect<s32>( 5, 21, 6, 43),
|
||||
core::rect<s32>( 6, 19, 7, 45),
|
||||
core::rect<s32>( 7, 17, 8, 47),
|
||||
core::rect<s32>( 8, 15, 9, 49),
|
||||
core::rect<s32>( 9, 14, 10, 50),
|
||||
core::rect<s32>( 10, 13, 11, 51),
|
||||
core::rect<s32>( 11, 12, 12, 52),
|
||||
core::rect<s32>( 12, 11, 13, 53),
|
||||
core::rect<s32>( 13, 10, 14, 54),
|
||||
core::rect<s32>( 14, 9, 15, 55),
|
||||
core::rect<s32>( 15, 8, 17, 56),
|
||||
core::rect<s32>( 17, 7, 19, 57),
|
||||
core::rect<s32>( 19, 6, 21, 58),
|
||||
core::rect<s32>( 21, 5, 24, 59),
|
||||
core::rect<s32>( 24, 4, 488, 60),
|
||||
core::rect<s32>(488, 5, 491, 59),
|
||||
core::rect<s32>(491, 6, 493, 58),
|
||||
core::rect<s32>(493, 7, 495, 57),
|
||||
core::rect<s32>(495, 8, 497, 56),
|
||||
core::rect<s32>(497, 9, 498, 55),
|
||||
core::rect<s32>(498, 10, 499, 54),
|
||||
core::rect<s32>(499, 11, 500, 53),
|
||||
core::rect<s32>(500, 12, 501, 52),
|
||||
core::rect<s32>(501, 13, 502, 51),
|
||||
core::rect<s32>(502, 14, 503, 50),
|
||||
core::rect<s32>(503, 15, 504, 49),
|
||||
core::rect<s32>(504, 17, 505, 47),
|
||||
core::rect<s32>(505, 19, 506, 45),
|
||||
core::rect<s32>(506, 21, 507, 43),
|
||||
core::rect<s32>(507, 24, 508, 40)
|
||||
};
|
||||
|
||||
for (const auto & i : rects) {
|
||||
const s32 clipx = (percent * imgW) / 100;
|
||||
core::rect<s32> 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<s32>(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__
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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 ""
|
||||
|
@ -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)
|
||||
|
@ -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"));
|
||||
|
||||
|
@ -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 <AppKit/AppKit.h>
|
||||
#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
|
||||
}
|
||||
|
@ -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";
|
||||
|
@ -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 <UIKit/UIKit.h>
|
||||
#else
|
||||
#import <AppKit/AppKit.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if USE_GETTEXT && defined(_MSC_VER)
|
||||
#include <windows.h>
|
||||
@ -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, "");
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -30,6 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "log.h"
|
||||
#include "gettext.h"
|
||||
#include <string>
|
||||
#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
|
||||
|
@ -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<s32>(
|
||||
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
|
||||
|
@ -51,7 +51,7 @@ public:
|
||||
bool processInput();
|
||||
|
||||
bool OnEvent(const SEvent &event);
|
||||
#ifdef __ANDROID__
|
||||
#if defined(__ANDROID__) || defined(__IOS__)
|
||||
bool getAndroidUIInput();
|
||||
#endif
|
||||
|
||||
|
@ -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<u32> ¤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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -218,6 +218,9 @@ private:
|
||||
/** scripting interface */
|
||||
MainMenuScripting *m_script = nullptr;
|
||||
|
||||
/** irrlicht device */
|
||||
IrrlichtDevice *m_device = nullptr;
|
||||
|
||||
/** script basefolder */
|
||||
std::string m_scriptdir = "";
|
||||
|
||||
|
@ -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<std::string> 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<std::string> v_pos = split(parts[0],',');
|
||||
std::vector<std::string> 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<s32> rect = core::rect<s32>(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<s32> 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>&
|
||||
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<std::string>&
|
||||
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<IGUIElement *>::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;
|
||||
|
@ -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<s32> rect;
|
||||
gui::ECURSOR_ICON fcursor_icon;
|
||||
};
|
||||
@ -259,7 +261,7 @@ public:
|
||||
GUITable* getTable(const std::string &tablename);
|
||||
std::vector<std::string>* getDropDownValues(const std::string &name);
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#if defined(__ANDROID__) || defined(__IOS__)
|
||||
bool getAndroidUIInput();
|
||||
#endif
|
||||
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include <algorithm>
|
||||
|
||||
#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<s32>(
|
||||
screensize.X / 2 - 835 * s / 2,
|
||||
screensize.Y / 2 - 430 * s / 2,
|
||||
|
@ -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<s32>(
|
||||
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
|
||||
|
@ -46,7 +46,7 @@ public:
|
||||
bool processInput();
|
||||
|
||||
bool OnEvent(const SEvent &event);
|
||||
#ifdef __ANDROID__
|
||||
#if defined(__ANDROID__) || defined(__IOS__)
|
||||
bool getAndroidUIInput();
|
||||
#endif
|
||||
|
||||
|
@ -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<s32> 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<s32>(
|
||||
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<s32> source_rect(
|
||||
core::position2d<s32>(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<s32> 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<s32> 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<s32> 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;
|
||||
}
|
||||
|
||||
|
@ -201,6 +201,8 @@ protected:
|
||||
gui::IGUIFont *m_font = nullptr;
|
||||
GUIScrollBar *m_scrollbar = nullptr;
|
||||
|
||||
float scale;
|
||||
|
||||
// Allocated strings and images
|
||||
std::vector<core::stringw> m_strings;
|
||||
std::vector<video::ITexture*> m_images;
|
||||
|
@ -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<s32>(
|
||||
screensize.X / 2 - 380 * s / 2,
|
||||
screensize.Y / 2 - 200 * s / 2,
|
||||
|
@ -32,13 +32,13 @@ GUIModalMenu::GUIModalMenu(gui::IGUIEnvironment *env, gui::IGUIElement *parent,
|
||||
IMenuManager *menumgr) :
|
||||
IGUIElement(gui::EGUIET_ELEMENT, env, parent, id,
|
||||
core::rect<s32>(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
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -198,6 +198,9 @@ public:
|
||||
void hide();
|
||||
void show();
|
||||
|
||||
// handle all buttons
|
||||
void handleReleaseAll();
|
||||
|
||||
private:
|
||||
IrrlichtDevice *m_device;
|
||||
IGUIEnvironment *m_guienv;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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 <IGUIFont.h>
|
||||
#include <IVideoDriver.h>
|
||||
@ -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_
|
||||
|
@ -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_
|
||||
|
@ -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++) {
|
||||
|
29
src/log.cpp
29
src/log.cpp
@ -35,6 +35,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include <cerrno>
|
||||
#include <cstring>
|
||||
|
||||
#ifdef __IOS__
|
||||
#import <Foundation/Foundation.h>
|
||||
#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
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
17
src/main.cpp
17
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);
|
||||
|
20
src/map.cpp
20
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 <deque>
|
||||
#include <queue>
|
||||
@ -195,8 +197,10 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n,
|
||||
std::map<v3s16, MapBlock*> &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<v3s16, MapBlock*> &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<v3s16, MapBlock*> &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()
|
||||
|
@ -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:
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -127,6 +127,11 @@ bool UDPSocket::init(bool ipv6, bool noExceptions)
|
||||
reinterpret_cast<char *>(&value), sizeof(value));
|
||||
}
|
||||
|
||||
#ifdef __IOS__
|
||||
int value = 1;
|
||||
setsockopt(m_handle, SOL_SOCKET, SO_NOSIGPIPE, &value, sizeof(value));
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,7 @@ struct ObjectProperties
|
||||
std::string mesh = "";
|
||||
v3f visual_size = v3f(1, 1, 1);
|
||||
std::vector<std::string> textures;
|
||||
std::string damage_texture_modifier = "^[brighten";
|
||||
std::string damage_texture_modifier = "^[colorize:#FF000085";
|
||||
std::vector<video::SColor> colors;
|
||||
v2s16 spritediv = v2s16(1, 1);
|
||||
v2s16 initial_sprite_basepos;
|
||||
|
@ -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
|
||||
////
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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<session_t> 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<RollbackAction> &actions,
|
||||
std::list<std::string> *log)
|
||||
{
|
||||
@ -3599,6 +3614,7 @@ bool Server::rollbackRevertActions(const std::list<RollbackAction> &actions,
|
||||
// Call it done if less than half failed
|
||||
return num_failed <= num_tried/2;
|
||||
}
|
||||
#endif
|
||||
|
||||
// IGameDef interface
|
||||
// Under envlock
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)"<<std::endl;
|
||||
bool large_amount = (block->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: "
|
||||
<<block->m_static_objects.m_stored.size()<<" in "
|
||||
<<PP(block->getPos())
|
||||
<<"; removing all of them."<<std::endl;
|
||||
@ -2078,9 +2085,10 @@ bool ServerEnvironment::saveStaticToBlock(
|
||||
PlayerDatabase *ServerEnvironment::openPlayerDatabase(const std::string &name,
|
||||
const std::string &savedir, const Settings &conf)
|
||||
{
|
||||
|
||||
#if USE_SQLITE
|
||||
if (name == "sqlite3")
|
||||
return new PlayerDatabaseSQLite3(savedir);
|
||||
#endif
|
||||
|
||||
if (name == "dummy")
|
||||
return new Database_Dummy();
|
||||
@ -2101,7 +2109,7 @@ PlayerDatabase *ServerEnvironment::openPlayerDatabase(const std::string &name,
|
||||
if (name == "files")
|
||||
return new PlayerDatabaseFiles(savedir + DIR_DELIM + "players");
|
||||
|
||||
throw BaseException(std::string("Database backend ") + name + " not supported.");
|
||||
throw ModError(std::string("Database backend ") + name + " not supported.");
|
||||
}
|
||||
|
||||
bool ServerEnvironment::migratePlayersDatabase(const GameParams &game_params,
|
||||
@ -2194,8 +2202,10 @@ bool ServerEnvironment::migratePlayersDatabase(const GameParams &game_params,
|
||||
AuthDatabase *ServerEnvironment::openAuthDatabase(
|
||||
const std::string &name, const std::string &savedir, const Settings &conf)
|
||||
{
|
||||
#if USE_SQLITE
|
||||
if (name == "sqlite3")
|
||||
return new AuthDatabaseSQLite3(savedir);
|
||||
#endif
|
||||
|
||||
#if USE_POSTGRESQL
|
||||
if (name == "postgresql") {
|
||||
@ -2213,7 +2223,7 @@ AuthDatabase *ServerEnvironment::openAuthDatabase(
|
||||
return new AuthDatabaseLevelDB(savedir);
|
||||
#endif
|
||||
|
||||
throw BaseException(std::string("Database backend ") + name + " not supported.");
|
||||
throw ModError(std::string("Database backend ") + name + " not supported.");
|
||||
}
|
||||
|
||||
bool ServerEnvironment::migrateAuthDatabase(
|
||||
|
@ -73,8 +73,14 @@ std::vector<ServerListSpec> 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
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include <istream>
|
||||
#include "util/container.h"
|
||||
#include "util/numeric.h"
|
||||
#ifndef ANDROID
|
||||
#if !defined(__ANDROID__) && !defined(__APPLE__)
|
||||
#include "cmake_config.h"
|
||||
#endif
|
||||
#if USE_SPATIAL
|
||||
|
@ -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;
|
||||
|
BIN
textures/base/pack/crack_anylength_touch.png
Normal file
BIN
textures/base/pack/crack_anylength_touch.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 806 B |
Binary file not shown.
Before Width: | Height: | Size: 413 B After Width: | Height: | Size: 272 B |
Binary file not shown.
Before Width: | Height: | Size: 354 B After Width: | Height: | Size: 294 B |
@ -4,5 +4,6 @@ mkdir cmakebuild
|
||||
cd cmakebuild
|
||||
cmake -DCMAKE_BUILD_TYPE=Debug \
|
||||
-DRUN_IN_PLACE=TRUE -DENABLE_GETTEXT=TRUE \
|
||||
-DBUILD_UNITTESTS=TRUE \
|
||||
-DBUILD_SERVER=TRUE ${CMAKE_FLAGS} ..
|
||||
make -j2
|
||||
|
Loading…
x
Reference in New Issue
Block a user