From 14ef2b445adcec770defe1abf83af9d22ccf39d8 Mon Sep 17 00:00:00 2001 From: Ekdohibs Date: Tue, 31 May 2016 17:30:11 +0200 Subject: Add colored text (not only colored chat). Add documentation, move files to a proper place and avoid memory leaks. Make it work with most kind of texts, and allow backgrounds too. --- src/defaultsettings.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/defaultsettings.cpp') diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index e8b652c17..632ec0df9 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -202,6 +202,8 @@ void set_default_settings(Settings *settings) settings->setDefault("server_name", ""); settings->setDefault("server_description", ""); + settings->setDefault("disable_escape_sequences", "false"); + #if USE_FREETYPE settings->setDefault("freetype", "true"); settings->setDefault("font_path", porting::getDataPath("fonts" DIR_DELIM "liberationsans.ttf")); -- cgit v1.2.3 From 2060fd9cbe587d7e8ffe0cecdd67925f13a56c05 Mon Sep 17 00:00:00 2001 From: est31 Date: Fri, 27 May 2016 08:35:07 +0200 Subject: Initial Gamepad support Adds initial ingame gamepad support to minetest. Full Formspec support is not implemented yet and can be added by a later change. --- builtin/settingtypes.txt | 11 +++ src/client/CMakeLists.txt | 1 + src/client/clientlauncher.cpp | 20 ++++- src/client/inputhandler.h | 13 +++ src/client/joystick_controller.cpp | 179 +++++++++++++++++++++++++++++++++++++ src/client/joystick_controller.h | 163 +++++++++++++++++++++++++++++++++ src/client/keys.h | 6 ++ src/content_cao.cpp | 4 +- src/defaultsettings.cpp | 3 + src/game.cpp | 165 ++++++++++++++++++++++------------ src/game.h | 3 + src/guiEngine.cpp | 2 + src/guiEngine.h | 3 +- src/guiFormSpecMenu.cpp | 42 +++++++-- src/guiFormSpecMenu.h | 13 ++- src/localplayer.cpp | 17 ++-- src/player.h | 10 ++- 17 files changed, 576 insertions(+), 79 deletions(-) create mode 100644 src/client/joystick_controller.cpp create mode 100644 src/client/joystick_controller.h (limited to 'src/defaultsettings.cpp') diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index 538a04f33..b53e35a85 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -104,6 +104,17 @@ random_input (Random input) bool false # Continuous forward movement (only used for testing). continuous_forward (Continuous forward) bool false +# Enable Joysticks +enable_joysticks (Enable Joysticks) bool true + +# The time in seconds it takes between repeated events +# when holding down a joystick button combination. +repeat_joystick_button_time (Joystick button repetition invterval) float 0.17 + +# The sensitivity of the joystick axes for moving the +# ingame view frustum around. +joystick_frustum_sensitivity (Joystick frustum sensitivity) float 170 + # Key for moving the player forward. # See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3 keymap_forward (Forward key) key KEY_KEY_W diff --git a/src/client/CMakeLists.txt b/src/client/CMakeLists.txt index a1ec37fe3..5faa186a7 100644 --- a/src/client/CMakeLists.txt +++ b/src/client/CMakeLists.txt @@ -1,6 +1,7 @@ set(client_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/clientlauncher.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tile.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/joystick_controller.cpp PARENT_SCOPE ) diff --git a/src/client/clientlauncher.cpp b/src/client/clientlauncher.cpp index 404a16310..ee8662ed6 100644 --- a/src/client/clientlauncher.cpp +++ b/src/client/clientlauncher.cpp @@ -32,6 +32,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "guiEngine.h" #include "player.h" #include "fontengine.h" +#include "joystick_controller.h" #include "clientlauncher.h" /* mainmenumanager.h @@ -499,7 +500,8 @@ void ClientLauncher::main_menu(MainMenuData *menudata) #endif /* show main menu */ - GUIEngine mymenu(device, guiroot, &g_menumgr, smgr, menudata, *kill); + GUIEngine mymenu(device, &input->joystick, guiroot, + &g_menumgr, smgr, menudata, *kill); smgr->clear(); /* leave scene manager in a clean state */ } @@ -558,6 +560,22 @@ bool ClientLauncher::create_engine_device() device = createDeviceEx(params); if (device) { + if (g_settings->getBool("enable_joysticks")) { + irr::core::array infos; + std::vector joystick_infos; + // Make sure this is called maximum once per + // irrlicht device, otherwise it will give you + // multiple events for the same joystick. + if (device->activateJoysticks(infos)) { + infostream << "Joystick support enabled" << std::endl; + joystick_infos.reserve(infos.size()); + for (u32 i = 0; i < infos.size(); i++) { + joystick_infos.push_back(infos[i]); + } + } else { + errorstream << "Could not activate joystick support." << std::endl; + } + } porting::initIrrlicht(device); } diff --git a/src/client/inputhandler.h b/src/client/inputhandler.h index 73e507fdc..824b0da2e 100644 --- a/src/client/inputhandler.h +++ b/src/client/inputhandler.h @@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #define INPUT_HANDLER_H #include "irrlichttypes_extrabloated.h" +#include "joystick_controller.h" class MyEventReceiver : public IEventReceiver { @@ -62,6 +63,14 @@ public: return true; } #endif + + if (event.EventType == irr::EET_JOYSTICK_INPUT_EVENT) { + /* TODO add a check like: + if (event.JoystickEvent != joystick_we_listen_for) + return false; + */ + return joystick->handleEvent(event.JoystickEvent); + } // handle mouse events if (event.EventType == irr::EET_MOUSE_INPUT_EVENT) { if (noMenuActive() == false) { @@ -172,6 +181,8 @@ public: s32 mouse_wheel; + JoystickController *joystick; + #ifdef HAVE_TOUCHSCREENGUI TouchScreenGUI* m_touchscreengui; #endif @@ -202,6 +213,7 @@ public: m_receiver(receiver), m_mousepos(0,0) { + m_receiver->joystick = &joystick; } virtual bool isKeyDown(const KeyPress &keyCode) { @@ -288,6 +300,7 @@ public: void clear() { + joystick.clear(); m_receiver->clearInput(); } private: diff --git a/src/client/joystick_controller.cpp b/src/client/joystick_controller.cpp new file mode 100644 index 000000000..ef8d18ab0 --- /dev/null +++ b/src/client/joystick_controller.cpp @@ -0,0 +1,179 @@ +/* +Minetest +Copyright (C) 2016 est31, + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "joystick_controller.h" +#include "irrlichttypes_extrabloated.h" +#include "keys.h" +#include "settings.h" +#include "gettime.h" + +bool JoystickButtonCmb::isTriggered(const irr::SEvent::SJoystickEvent &ev) const +{ + u32 buttons = ev.ButtonStates; + + buttons &= filter_mask; + return buttons == compare_mask; +} + +bool JoystickAxisCmb::isTriggered(const irr::SEvent::SJoystickEvent &ev) const +{ + s16 ax_val = ev.Axis[axis_to_compare]; + + return (ax_val * direction < 0) && (thresh * direction > ax_val * direction); +} + +// spares many characters +#define JLO_B_PB(A, B, C) jlo.button_keys.push_back(JoystickButtonCmb(A, B, C)) +#define JLO_A_PB(A, B, C, D) jlo.axis_keys.push_back(JoystickAxisCmb(A, B, C, D)) + +static JoystickLayout create_default_layout() +{ + JoystickLayout jlo; + + jlo.axes_dead_border = 1024; + + const JoystickAxisLayout axes[JA_COUNT] = { + {0, 1}, // JA_SIDEWARD_MOVE + {1, 1}, // JA_FORWARD_MOVE + {3, 1}, // JA_FRUSTUM_HORIZONTAL + {4, 1}, // JA_FRUSTUM_VERTICAL + }; + memcpy(jlo.axes, axes, sizeof(jlo.axes)); + + u32 sb = 1 << 7; // START button mask + u32 fb = 1 << 3; // FOUR button mask + u32 bm = sb | fb; // Mask for Both Modifiers + + // The back button means "ESC". + JLO_B_PB(KeyType::ESC, 1 << 6, 1 << 6); + + // The start button counts as modifier as well as use key. + // JLO_B_PB(KeyType::USE, sb, sb)); + + // Accessible without start modifier button pressed + // regardless whether four is pressed or not + JLO_B_PB(KeyType::SNEAK, sb | 1 << 2, 1 << 2); + + // Accessible without four modifier button pressed + // regardless whether start is pressed or not + JLO_B_PB(KeyType::MOUSE_L, fb | 1 << 4, 1 << 4); + JLO_B_PB(KeyType::MOUSE_R, fb | 1 << 5, 1 << 5); + + // Accessible without any modifier pressed + JLO_B_PB(KeyType::JUMP, bm | 1 << 0, 1 << 0); + JLO_B_PB(KeyType::SPECIAL1, bm | 1 << 1, 1 << 1); + + // Accessible with start button not pressed, but four pressed + // TODO find usage for button 0 + JLO_B_PB(KeyType::DROP, bm | 1 << 1, fb | 1 << 1); + JLO_B_PB(KeyType::SCROLL_UP, bm | 1 << 4, fb | 1 << 4); + JLO_B_PB(KeyType::SCROLL_DOWN,bm | 1 << 5, fb | 1 << 5); + + // Accessible with start button and four pressed + // TODO find usage for buttons 0, 1 and 4, 5 + + // Now about the buttons simulated by the axes + + // Movement buttons, important for vessels + JLO_A_PB(KeyType::FORWARD, 1, 1, 1024); + JLO_A_PB(KeyType::BACKWARD, 1, -1, 1024); + JLO_A_PB(KeyType::LEFT, 0, 1, 1024); + JLO_A_PB(KeyType::RIGHT, 0, -1, 1024); + + // Scroll buttons + JLO_A_PB(KeyType::SCROLL_UP, 2, -1, 1024); + JLO_A_PB(KeyType::SCROLL_DOWN, 5, -1, 1024); + + return jlo; +} + +static const JoystickLayout default_layout = create_default_layout(); + +JoystickController::JoystickController() +{ + m_layout = &default_layout; + doubling_dtime = g_settings->getFloat("repeat_joystick_button_time"); + + for (size_t i = 0; i < KeyType::INTERNAL_ENUM_COUNT; i++) { + m_past_pressed_time[i] = 0; + } + clear(); +} + +bool JoystickController::handleEvent(const irr::SEvent::SJoystickEvent &ev) +{ + m_internal_time = getTimeMs() / 1000.f; + + std::bitset keys_pressed; + + // First generate a list of keys pressed + + for (size_t i = 0; i < m_layout->button_keys.size(); i++) { + if (m_layout->button_keys[i].isTriggered(ev)) { + keys_pressed.set(m_layout->button_keys[i].key); + } + } + + for (size_t i = 0; i < m_layout->axis_keys.size(); i++) { + if (m_layout->axis_keys[i].isTriggered(ev)) { + keys_pressed.set(m_layout->axis_keys[i].key); + } + } + + // Then update the values + + for (size_t i = 0; i < KeyType::INTERNAL_ENUM_COUNT; i++) { + if (keys_pressed[i]) { + if (!m_past_pressed_keys[i] && + m_past_pressed_time[i] < m_internal_time - doubling_dtime) { + m_past_pressed_keys[i] = true; + m_past_pressed_time[i] = m_internal_time; + } + } else if (m_pressed_keys[i]) { + m_past_released_keys[i] = true; + } + + m_pressed_keys[i] = keys_pressed[i]; + } + + for (size_t i = 0; i < JA_COUNT; i++) { + const JoystickAxisLayout &ax_la = m_layout->axes[i]; + m_axes_vals[i] = ax_la.invert * ev.Axis[ax_la.axis_id]; + } + + + return true; +} + +void JoystickController::clear() +{ + m_pressed_keys.reset(); + m_past_pressed_keys.reset(); + m_past_released_keys.reset(); + memset(m_axes_vals, 0, sizeof(m_axes_vals)); +} + +s16 JoystickController::getAxisWithoutDead(JoystickAxis axis) +{ + s16 v = m_axes_vals[axis]; + if (((v > 0) && (v < m_layout->axes_dead_border)) || + ((v < 0) && (v > -m_layout->axes_dead_border))) + return 0; + return v; +} diff --git a/src/client/joystick_controller.h b/src/client/joystick_controller.h new file mode 100644 index 000000000..ed0ee4068 --- /dev/null +++ b/src/client/joystick_controller.h @@ -0,0 +1,163 @@ +/* +Minetest +Copyright (C) 2016 est31, + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#ifndef JOYSTICK_HEADER +#define JOYSTICK_HEADER + +#include "irrlichttypes_extrabloated.h" +#include "keys.h" +#include +#include + +enum JoystickAxis { + JA_SIDEWARD_MOVE, + JA_FORWARD_MOVE, + + JA_FRUSTUM_HORIZONTAL, + JA_FRUSTUM_VERTICAL, + + // To know the count of enum values + JA_COUNT, +}; + +struct JoystickAxisLayout { + u16 axis_id; + // -1 if to invert, 1 if to keep it. + int invert; +}; + + +struct JoystickCombination { + + virtual bool isTriggered(const irr::SEvent::SJoystickEvent &ev) const=0; + + GameKeyType key; +}; + +struct JoystickButtonCmb : public JoystickCombination { + + JoystickButtonCmb() {} + JoystickButtonCmb(GameKeyType key, u32 filter_mask, u32 compare_mask) : + filter_mask(filter_mask), + compare_mask(compare_mask) + { + this->key = key; + } + + virtual bool isTriggered(const irr::SEvent::SJoystickEvent &ev) const; + + u32 filter_mask; + u32 compare_mask; +}; + +struct JoystickAxisCmb : public JoystickCombination { + + JoystickAxisCmb() {} + JoystickAxisCmb(GameKeyType key, u16 axis_to_compare, int direction, s16 thresh) : + axis_to_compare(axis_to_compare), + direction(direction), + thresh(thresh) + { + this->key = key; + } + + virtual bool isTriggered(const irr::SEvent::SJoystickEvent &ev) const; + + u16 axis_to_compare; + + // if -1, thresh must be smaller than the axis value in order to trigger + // if 1, thresh must be bigger than the axis value in order to trigger + int direction; + s16 thresh; +}; + +struct JoystickLayout { + std::vector button_keys; + std::vector axis_keys; + JoystickAxisLayout axes[JA_COUNT]; + s16 axes_dead_border; +}; + +class JoystickController { + +public: + JoystickController(); + bool handleEvent(const irr::SEvent::SJoystickEvent &ev); + void clear(); + + bool wasKeyDown(GameKeyType b) + { + bool r = m_past_pressed_keys[b]; + m_past_pressed_keys[b] = false; + return r; + } + bool getWasKeyDown(GameKeyType b) + { + return m_past_pressed_keys[b]; + } + void clearWasKeyDown(GameKeyType b) + { + m_past_pressed_keys[b] = false; + } + + bool wasKeyReleased(GameKeyType b) + { + bool r = m_past_released_keys[b]; + m_past_released_keys[b] = false; + return r; + } + bool getWasKeyReleased(GameKeyType b) + { + return m_past_pressed_keys[b]; + } + void clearWasKeyReleased(GameKeyType b) + { + m_past_pressed_keys[b] = false; + } + + bool isKeyDown(GameKeyType b) + { + return m_pressed_keys[b]; + } + + s16 getAxis(JoystickAxis axis) + { + return m_axes_vals[axis]; + } + + s16 getAxisWithoutDead(JoystickAxis axis); + + f32 doubling_dtime; + +private: + const JoystickLayout *m_layout; + + s16 m_axes_vals[JA_COUNT]; + + std::bitset m_pressed_keys; + + f32 m_internal_time; + + f32 m_past_pressed_time[KeyType::INTERNAL_ENUM_COUNT]; + + std::bitset m_past_pressed_keys; + std::bitset m_past_released_keys; +}; + +#endif diff --git a/src/client/keys.h b/src/client/keys.h index 08b1c4123..0921bc166 100644 --- a/src/client/keys.h +++ b/src/client/keys.h @@ -67,6 +67,12 @@ public: DEBUG_STACKS, + // joystick specific keys + MOUSE_L, + MOUSE_R, + SCROLL_UP, + SCROLL_DOWN, + // Fake keycode for array size and internal checks INTERNAL_ENUM_COUNT diff --git a/src/content_cao.cpp b/src/content_cao.cpp index 35ab1c508..eeb85c8a6 100644 --- a/src/content_cao.cpp +++ b/src/content_cao.cpp @@ -1056,7 +1056,9 @@ void GenericCAO::step(float dtime, ClientEnvironment *env) PlayerControl controls = player->getPlayerControl(); bool walking = false; - if(controls.up || controls.down || controls.left || controls.right) + if (controls.up || controls.down || controls.left || controls.right || + controls.forw_move_joystick_axis != 0.f || + controls.sidew_move_joystick_axis != 0.f) walking = true; f32 new_speed = player->local_animation_speed; diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 632ec0df9..43a7a7c00 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -116,6 +116,9 @@ void set_default_settings(Settings *settings) settings->setDefault("free_move", "false"); settings->setDefault("noclip", "false"); settings->setDefault("continuous_forward", "false"); + settings->setDefault("enable_joysticks", "true"); + settings->setDefault("repeat_joystick_button_time", "0.17"); + settings->setDefault("joystick_frustum_sensitivity", "170"); settings->setDefault("cinematic", "false"); settings->setDefault("camera_smoothing", "0"); settings->setDefault("cinematic_camera_smoothing", "0.7"); diff --git a/src/game.cpp b/src/game.cpp index ac1c0fe6b..ba77d299a 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "client.h" #include "client/tile.h" // For TextureSource #include "client/keys.h" +#include "client/joystick_controller.h" #include "clientmap.h" #include "clouds.h" #include "config.h" @@ -1108,12 +1109,14 @@ bool nodePlacementPrediction(Client &client, static inline void create_formspec_menu(GUIFormSpecMenu **cur_formspec, InventoryManager *invmgr, IGameDef *gamedef, IWritableTextureSource *tsrc, IrrlichtDevice *device, + JoystickController *joystick, IFormSource *fs_src, TextDest *txt_dest, Client *client) { if (*cur_formspec == 0) { - *cur_formspec = new GUIFormSpecMenu(device, guiroot, -1, &g_menumgr, - invmgr, gamedef, tsrc, fs_src, txt_dest, client); + *cur_formspec = new GUIFormSpecMenu(device, joystick, + guiroot, -1, &g_menumgr, invmgr, gamedef, tsrc, + fs_src, txt_dest, client); (*cur_formspec)->doPause = false; /* @@ -1138,7 +1141,8 @@ static inline void create_formspec_menu(GUIFormSpecMenu **cur_formspec, static void show_deathscreen(GUIFormSpecMenu **cur_formspec, InventoryManager *invmgr, IGameDef *gamedef, - IWritableTextureSource *tsrc, IrrlichtDevice *device, Client *client) + IWritableTextureSource *tsrc, IrrlichtDevice *device, + JoystickController *joystick, Client *client) { std::string formspec = std::string(FORMSPEC_VERSION_STRING) + @@ -1154,14 +1158,15 @@ static void show_deathscreen(GUIFormSpecMenu **cur_formspec, FormspecFormSource *fs_src = new FormspecFormSource(formspec); LocalFormspecHandler *txt_dst = new LocalFormspecHandler("MT_DEATH_SCREEN", client); - create_formspec_menu(cur_formspec, invmgr, gamedef, tsrc, device, fs_src, txt_dst, NULL); + create_formspec_menu(cur_formspec, invmgr, gamedef, tsrc, device, + joystick, fs_src, txt_dst, NULL); } /******************************************************************************/ static void show_pause_menu(GUIFormSpecMenu **cur_formspec, InventoryManager *invmgr, IGameDef *gamedef, IWritableTextureSource *tsrc, IrrlichtDevice *device, - bool singleplayermode) + JoystickController *joystick, bool singleplayermode) { #ifdef __ANDROID__ std::string control_text = strgettext("Default Controls:\n" @@ -1226,7 +1231,8 @@ static void show_pause_menu(GUIFormSpecMenu **cur_formspec, FormspecFormSource *fs_src = new FormspecFormSource(os.str()); LocalFormspecHandler *txt_dst = new LocalFormspecHandler("MT_PAUSE_MENU"); - create_formspec_menu(cur_formspec, invmgr, gamedef, tsrc, device, fs_src, txt_dst, NULL); + create_formspec_menu(cur_formspec, invmgr, gamedef, tsrc, device, + joystick, fs_src, txt_dst, NULL); std::string con("btn_continue"); (*cur_formspec)->setFocus(con); (*cur_formspec)->doPause = true; @@ -1574,9 +1580,10 @@ protected: void decreaseViewRange(float *statustext_time); void toggleFullViewRange(float *statustext_time); - void updateCameraDirection(CameraOrientation *cam, VolatileRunFlags *flags); + void updateCameraDirection(CameraOrientation *cam, VolatileRunFlags *flags, + float dtime); void updateCameraOrientation(CameraOrientation *cam, - const VolatileRunFlags &flags); + const VolatileRunFlags &flags, float dtime); void updatePlayerControl(const CameraOrientation &cam); void step(f32 *dtime); void processClientEvents(CameraOrientation *cam, float *damage_flash); @@ -1611,34 +1618,39 @@ protected: static void settingChangedCallback(const std::string &setting_name, void *data); void readSettings(); - bool getLeftClicked() + inline bool getLeftClicked() { - return input->getLeftClicked(); + return input->getLeftClicked() || + input->joystick.getWasKeyDown(KeyType::MOUSE_L); } - bool getRightClicked() + inline bool getRightClicked() { - return input->getRightClicked(); + return input->getRightClicked() || + input->joystick.getWasKeyDown(KeyType::MOUSE_R); } - bool isLeftPressed() + inline bool isLeftPressed() { - return input->getLeftState(); + return input->getLeftState() || + input->joystick.isKeyDown(KeyType::MOUSE_L); } - bool isRightPressed() + inline bool isRightPressed() { - return input->getRightState(); + return input->getRightState() || + input->joystick.isKeyDown(KeyType::MOUSE_R); } - bool getLeftReleased() + inline bool getLeftReleased() { - return input->getLeftReleased(); + return input->getLeftReleased() || + input->joystick.wasKeyReleased(KeyType::MOUSE_L); } - bool isKeyDown(GameKeyType k) + inline bool isKeyDown(GameKeyType k) { - return input->isKeyDown(keycache.key[k]); + return input->isKeyDown(keycache.key[k]) || input->joystick.isKeyDown(k); } - bool wasKeyDown(GameKeyType k) + inline bool wasKeyDown(GameKeyType k) { - return input->wasKeyDown(keycache.key[k]); + return input->wasKeyDown(keycache.key[k]) || input->joystick.wasKeyDown(k); } #ifdef __ANDROID__ @@ -1724,9 +1736,11 @@ private: */ bool m_cache_doubletap_jump; bool m_cache_enable_clouds; + bool m_cache_enable_joysticks; bool m_cache_enable_particles; bool m_cache_enable_fog; f32 m_cache_mouse_sensitivity; + f32 m_cache_joystick_frustum_sensitivity; f32 m_repeat_right_click_time; #ifdef __ANDROID__ @@ -1762,12 +1776,16 @@ Game::Game() : &settingChangedCallback, this); g_settings->registerChangedCallback("enable_clouds", &settingChangedCallback, this); + g_settings->registerChangedCallback("doubletap_joysticks", + &settingChangedCallback, this); g_settings->registerChangedCallback("enable_particles", &settingChangedCallback, this); g_settings->registerChangedCallback("enable_fog", &settingChangedCallback, this); g_settings->registerChangedCallback("mouse_sensitivity", &settingChangedCallback, this); + g_settings->registerChangedCallback("joystick_frustum_sensitivity", + &settingChangedCallback, this); g_settings->registerChangedCallback("repeat_rightclick_time", &settingChangedCallback, this); @@ -1930,7 +1948,7 @@ void Game::run() updateProfilers(runData, stats, draw_times, dtime); processUserInput(&flags, &runData, dtime); // Update camera before player movement to avoid camera lag of one frame - updateCameraDirection(&cam_view_target, &flags); + updateCameraDirection(&cam_view_target, &flags, dtime); float cam_smoothing = 0; if (g_settings->getBool("cinematic")) cam_smoothing = 1 - g_settings->getFloat("cinematic_camera_smoothing"); @@ -2727,7 +2745,8 @@ void Game::processKeyInput(VolatileRunFlags *flags, } else if (wasKeyDown(KeyType::ESC) || input->wasKeyDown(CancelKey)) { if (!gui_chat_console->isOpenInhibited()) { show_pause_menu(¤t_formspec, client, gamedef, - texture_src, device, simple_singleplayer_mode); + texture_src, device, &input->joystick, + simple_singleplayer_mode); } } else if (wasKeyDown(KeyType::CHAT)) { openConsole(0.2, L""); @@ -2813,12 +2832,21 @@ void Game::processItemSelection(u16 *new_playeritem) u16 max_item = MYMIN(PLAYER_INVENTORY_SIZE - 1, player->hud_hotbar_itemcount - 1); - if (wheel < 0) + s32 dir = wheel; + + if (input->joystick.wasKeyDown(KeyType::SCROLL_DOWN)) { + dir = -1; + } + + if (input->joystick.wasKeyDown(KeyType::SCROLL_UP)) { + dir = 1; + } + + if (dir < 0) *new_playeritem = *new_playeritem < max_item ? *new_playeritem + 1 : 0; - else if (wheel > 0) + else if (dir > 0) *new_playeritem = *new_playeritem > 0 ? *new_playeritem - 1 : max_item; - // else wheel == 0 - + // else dir == 0 /* Item selection using keyboard */ @@ -2868,7 +2896,7 @@ void Game::openInventory() TextDest *txt_dst = new TextDestPlayerInventory(client); create_formspec_menu(¤t_formspec, client, gamedef, texture_src, - device, fs_src, txt_dst, client); + device, &input->joystick, fs_src, txt_dst, client); InventoryLocation inventoryloc; inventoryloc.setCurrentPlayer(); @@ -3154,7 +3182,7 @@ void Game::toggleFullViewRange(float *statustext_time) void Game::updateCameraDirection(CameraOrientation *cam, - VolatileRunFlags *flags) + VolatileRunFlags *flags, float dtime) { if ((device->isWindowActive() && noMenuActive()) || random_input) { @@ -3169,7 +3197,7 @@ void Game::updateCameraDirection(CameraOrientation *cam, if (flags->first_loop_after_window_activation) flags->first_loop_after_window_activation = false; else - updateCameraOrientation(cam, *flags); + updateCameraOrientation(cam, *flags, dtime); input->setMousePos((driver->getScreenSize().Width / 2), (driver->getScreenSize().Height / 2)); @@ -3187,9 +3215,8 @@ void Game::updateCameraDirection(CameraOrientation *cam, } } - void Game::updateCameraOrientation(CameraOrientation *cam, - const VolatileRunFlags &flags) + const VolatileRunFlags &flags, float dtime) { #ifdef HAVE_TOUCHSCREENGUI if (g_touchscreengui) { @@ -3197,6 +3224,7 @@ void Game::updateCameraOrientation(CameraOrientation *cam, cam->camera_pitch = g_touchscreengui->getPitch(); } else { #endif + s32 dx = input->getMousePos().X - (driver->getScreenSize().Width / 2); s32 dy = input->getMousePos().Y - (driver->getScreenSize().Height / 2); @@ -3212,6 +3240,14 @@ void Game::updateCameraOrientation(CameraOrientation *cam, } #endif + if (m_cache_enable_joysticks) { + f32 c = m_cache_joystick_frustum_sensitivity * (1.f / 32767.f) * dtime; + cam->camera_yaw -= input->joystick.getAxisWithoutDead(JA_FRUSTUM_HORIZONTAL) * + c; + cam->camera_pitch += input->joystick.getAxisWithoutDead(JA_FRUSTUM_VERTICAL) * + c; + } + cam->camera_pitch = rangelim(cam->camera_pitch, -89.5, 89.5); } @@ -3220,30 +3256,36 @@ void Game::updatePlayerControl(const CameraOrientation &cam) { //TimeTaker tt("update player control", NULL, PRECISION_NANO); + // DO NOT use the isKeyDown method for the forward, backward, left, right + // buttons, as the code that uses the controls needs to be able to + // distinguish between the two in order to know when to use joysticks. + PlayerControl control( input->isKeyDown(keycache.key[KeyType::FORWARD]), input->isKeyDown(keycache.key[KeyType::BACKWARD]), input->isKeyDown(keycache.key[KeyType::LEFT]), input->isKeyDown(keycache.key[KeyType::RIGHT]), - input->isKeyDown(keycache.key[KeyType::JUMP]), - input->isKeyDown(keycache.key[KeyType::SPECIAL1]), - input->isKeyDown(keycache.key[KeyType::SNEAK]), - input->getLeftState(), - input->getRightState(), + isKeyDown(KeyType::JUMP), + isKeyDown(KeyType::SPECIAL1), + isKeyDown(KeyType::SNEAK), + isLeftPressed(), + isRightPressed(), cam.camera_pitch, - cam.camera_yaw + cam.camera_yaw, + input->joystick.getAxisWithoutDead(JA_SIDEWARD_MOVE), + input->joystick.getAxisWithoutDead(JA_FORWARD_MOVE) ); u32 keypress_bits = - ( (u32)(input->isKeyDown(keycache.key[KeyType::FORWARD]) & 0x1) << 0) | - ( (u32)(input->isKeyDown(keycache.key[KeyType::BACKWARD]) & 0x1) << 1) | - ( (u32)(input->isKeyDown(keycache.key[KeyType::LEFT]) & 0x1) << 2) | - ( (u32)(input->isKeyDown(keycache.key[KeyType::RIGHT]) & 0x1) << 3) | - ( (u32)(input->isKeyDown(keycache.key[KeyType::JUMP]) & 0x1) << 4) | - ( (u32)(input->isKeyDown(keycache.key[KeyType::SPECIAL1]) & 0x1) << 5) | - ( (u32)(input->isKeyDown(keycache.key[KeyType::SNEAK]) & 0x1) << 6) | - ( (u32)(input->getLeftState() & 0x1) << 7) | - ( (u32)(input->getRightState() & 0x1) << 8 + ( (u32)(isKeyDown(KeyType::FORWARD) & 0x1) << 0) | + ( (u32)(isKeyDown(KeyType::BACKWARD) & 0x1) << 1) | + ( (u32)(isKeyDown(KeyType::LEFT) & 0x1) << 2) | + ( (u32)(isKeyDown(KeyType::RIGHT) & 0x1) << 3) | + ( (u32)(isKeyDown(KeyType::JUMP) & 0x1) << 4) | + ( (u32)(isKeyDown(KeyType::SPECIAL1) & 0x1) << 5) | + ( (u32)(isKeyDown(KeyType::SNEAK) & 0x1) << 6) | + ( (u32)(isLeftPressed() & 0x1) << 7) | + ( (u32)(isRightPressed() & 0x1) << 8 ); #ifdef ANDROID @@ -3312,7 +3354,7 @@ void Game::processClientEvents(CameraOrientation *cam, float *damage_flash) cam->camera_pitch = event.player_force_move.pitch; } else if (event.type == CE_DEATHSCREEN) { show_deathscreen(¤t_formspec, client, gamedef, texture_src, - device, client); + device, &input->joystick, client); chat_backend->addMessage(L"", L"You died."); @@ -3328,7 +3370,8 @@ void Game::processClientEvents(CameraOrientation *cam, float *damage_flash) new TextDestPlayerInventory(client, *(event.show_formspec.formname)); create_formspec_menu(¤t_formspec, client, gamedef, - texture_src, device, fs_src, txt_dst, client); + texture_src, device, &input->joystick, + fs_src, txt_dst, client); delete(event.show_formspec.formspec); delete(event.show_formspec.formname); @@ -3723,8 +3766,14 @@ void Game::processPlayerInteraction(GameRunData *runData, input->resetLeftClicked(); input->resetRightClicked(); + input->joystick.clearWasKeyDown(KeyType::MOUSE_L); + input->joystick.clearWasKeyDown(KeyType::MOUSE_R); + input->resetLeftReleased(); input->resetRightReleased(); + + input->joystick.clearWasKeyReleased(KeyType::MOUSE_L); + input->joystick.clearWasKeyReleased(KeyType::MOUSE_R); } @@ -3785,7 +3834,7 @@ void Game::handlePointingAtNode(GameRunData *runData, TextDest *txt_dst = new TextDestNodeMetadata(nodepos, client); create_formspec_menu(¤t_formspec, client, gamedef, - texture_src, device, fs_src, txt_dst, client); + texture_src, device, &input->joystick, fs_src, txt_dst, client); current_formspec->setFormSpec(meta->getString("formspec"), inventoryloc); } else { @@ -4468,12 +4517,14 @@ void Game::settingChangedCallback(const std::string &setting_name, void *data) void Game::readSettings() { - m_cache_doubletap_jump = g_settings->getBool("doubletap_jump"); - m_cache_enable_clouds = g_settings->getBool("enable_clouds"); - m_cache_enable_particles = g_settings->getBool("enable_particles"); - m_cache_enable_fog = g_settings->getBool("enable_fog"); - m_cache_mouse_sensitivity = g_settings->getFloat("mouse_sensitivity"); - m_repeat_right_click_time = g_settings->getFloat("repeat_rightclick_time"); + m_cache_doubletap_jump = g_settings->getBool("doubletap_jump"); + m_cache_enable_clouds = g_settings->getBool("enable_clouds"); + m_cache_enable_joysticks = g_settings->getBool("enable_joysticks"); + m_cache_enable_particles = g_settings->getBool("enable_particles"); + m_cache_enable_fog = g_settings->getBool("enable_fog"); + m_cache_mouse_sensitivity = g_settings->getFloat("mouse_sensitivity"); + m_cache_joystick_frustum_sensitivity = g_settings->getFloat("joystick_frustum_sensitivity"); + m_repeat_right_click_time = g_settings->getFloat("repeat_rightclick_time"); m_cache_mouse_sensitivity = rangelim(m_cache_mouse_sensitivity, 0.001, 100.0); } diff --git a/src/game.h b/src/game.h index d8c2f78fc..df32e3397 100644 --- a/src/game.h +++ b/src/game.h @@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "irrlichttypes_extrabloated.h" #include #include "client/keys.h" +#include "client/joystick_controller.h" #include "keycode.h" #include @@ -135,6 +136,8 @@ public: virtual void step(float dtime) {} virtual void clear() {} + + JoystickController joystick; }; class ChatBackend; /* to avoid having to include chat.h */ diff --git a/src/guiEngine.cpp b/src/guiEngine.cpp index 96de7a4f7..b9d796ccb 100644 --- a/src/guiEngine.cpp +++ b/src/guiEngine.cpp @@ -131,6 +131,7 @@ void MenuMusicFetcher::fetchSounds(const std::string &name, /** GUIEngine */ /******************************************************************************/ GUIEngine::GUIEngine( irr::IrrlichtDevice* dev, + JoystickController *joystick, gui::IGUIElement* parent, IMenuManager *menumgr, scene::ISceneManager* smgr, @@ -189,6 +190,7 @@ GUIEngine::GUIEngine( irr::IrrlichtDevice* dev, /* Create menu */ m_menu = new GUIFormSpecMenu(m_device, + joystick, m_parent, -1, m_menumanager, diff --git a/src/guiEngine.h b/src/guiEngine.h index fa98a21e4..a59436953 100644 --- a/src/guiEngine.h +++ b/src/guiEngine.h @@ -149,7 +149,8 @@ public: * @param smgr scene manager to add scene elements to * @param data struct to transfer data to main game handling */ - GUIEngine( irr::IrrlichtDevice* dev, + GUIEngine(irr::IrrlichtDevice* dev, + JoystickController *joystick, gui::IGUIElement* parent, IMenuManager *menumgr, scene::ISceneManager* smgr, diff --git a/src/guiFormSpecMenu.cpp b/src/guiFormSpecMenu.cpp index cf01dc38c..a9cbb6254 100644 --- a/src/guiFormSpecMenu.cpp +++ b/src/guiFormSpecMenu.cpp @@ -79,6 +79,7 @@ static unsigned int font_line_height(gui::IGUIFont *font) } GUIFormSpecMenu::GUIFormSpecMenu(irr::IrrlichtDevice* dev, + JoystickController *joystick, gui::IGUIElement* parent, s32 id, IMenuManager *menumgr, InventoryManager *invmgr, IGameDef *gamedef, ISimpleTextureSource *tsrc, IFormSource* fsrc, TextDest* tdst, @@ -102,6 +103,7 @@ GUIFormSpecMenu::GUIFormSpecMenu(irr::IrrlichtDevice* dev, m_text_dst(tdst), m_formspec_version(0), m_focused_element(""), + m_joystick(joystick), m_font(NULL), m_remap_dbl_click(remap_dbl_click) #ifdef __ANDROID__ @@ -2459,7 +2461,7 @@ void GUIFormSpecMenu::drawMenu() Draw static text elements */ for (u32 i = 0; i < m_static_texts.size(); i++) { - const StaticTextSpec &spec = m_static_texts[i]; + const StaticTextSpec &spec = m_static_texts[i]; core::rect rect = spec.rect; if (spec.parent_button && spec.parent_button->isPressed()) { #if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8) @@ -3024,6 +3026,25 @@ bool GUIFormSpecMenu::preprocessEvent(const SEvent& event) } #endif + if (event.EventType == irr::EET_JOYSTICK_INPUT_EVENT) { + /* TODO add a check like: + if (event.JoystickEvent != joystick_we_listen_for) + return false; + */ + bool handled = m_joystick->handleEvent(event.JoystickEvent); + if (handled) { + if (m_joystick->wasKeyDown(KeyType::ESC)) { + tryClose(); + } else if (m_joystick->wasKeyDown(KeyType::JUMP)) { + if (m_allowclose) { + acceptInput(quit_mode_accept); + quitMenu(); + } + } + } + return handled; + } + return false; } @@ -3085,19 +3106,24 @@ bool GUIFormSpecMenu::DoubleClickDetection(const SEvent event) return false; } +void GUIFormSpecMenu::tryClose() +{ + if (m_allowclose) { + doPause = false; + acceptInput(quit_mode_cancel); + quitMenu(); + } else { + m_text_dst->gotText(L"MenuQuit"); + } +} + bool GUIFormSpecMenu::OnEvent(const SEvent& event) { if (event.EventType==EET_KEY_INPUT_EVENT) { KeyPress kp(event.KeyInput); if (event.KeyInput.PressedDown && ( (kp == EscapeKey) || (kp == getKeySetting("keymap_inventory")) || (kp == CancelKey))) { - if (m_allowclose) { - doPause = false; - acceptInput(quit_mode_cancel); - quitMenu(); - } else { - m_text_dst->gotText(L"MenuQuit"); - } + tryClose(); return true; } else if (m_client != NULL && event.KeyInput.PressedDown && (kp == getKeySetting("keymap_screenshot"))) { diff --git a/src/guiFormSpecMenu.h b/src/guiFormSpecMenu.h index 4122b1f56..2fb55070d 100644 --- a/src/guiFormSpecMenu.h +++ b/src/guiFormSpecMenu.h @@ -29,6 +29,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "modalMenu.h" #include "guiTable.h" #include "network/networkprotocol.h" +#include "client/joystick_controller.h" #include "util/string.h" #include "util/enriched_string.h" @@ -278,6 +279,7 @@ class GUIFormSpecMenu : public GUIModalMenu public: GUIFormSpecMenu(irr::IrrlichtDevice* dev, + JoystickController *joystick, gui::IGUIElement* parent, s32 id, IMenuManager *menumgr, InventoryManager *invmgr, @@ -433,10 +435,11 @@ protected: video::SColor m_default_tooltip_color; private: - IFormSource *m_form_src; - TextDest *m_text_dst; - unsigned int m_formspec_version; - std::string m_focused_element; + IFormSource *m_form_src; + TextDest *m_text_dst; + unsigned int m_formspec_version; + std::string m_focused_element; + JoystickController *m_joystick; typedef struct { bool explicit_size; @@ -494,6 +497,8 @@ private: bool parseSizeDirect(parserData* data, std::string element); void parseScrollBar(parserData* data, std::string element); + void tryClose(); + /** * check if event is part of a double click * @param event event to evaluate diff --git a/src/localplayer.cpp b/src/localplayer.cpp index 507f31980..732ca8acf 100644 --- a/src/localplayer.cpp +++ b/src/localplayer.cpp @@ -528,18 +528,23 @@ void LocalPlayer::applyControl(float dtime) speedH += move_direction; } } - if(control.down) - { + if (control.down) { speedH -= move_direction; } - if(control.left) - { + if (!control.up && !control.down) { + speedH -= move_direction * + (control.forw_move_joystick_axis / 32767.f); + } + if (control.left) { speedH += move_direction.crossProduct(v3f(0,1,0)); } - if(control.right) - { + if (control.right) { speedH += move_direction.crossProduct(v3f(0,-1,0)); } + if (!control.left && !control.right) { + speedH -= move_direction.crossProduct(v3f(0,1,0)) * + (control.sidew_move_joystick_axis / 32767.f); + } if(control.jump) { if (free_move) { diff --git a/src/player.h b/src/player.h index b317cda4f..6687ca86e 100644 --- a/src/player.h +++ b/src/player.h @@ -46,6 +46,8 @@ struct PlayerControl RMB = false; pitch = 0; yaw = 0; + sidew_move_joystick_axis = .0f; + forw_move_joystick_axis = .0f; } PlayerControl( bool a_up, @@ -58,7 +60,9 @@ struct PlayerControl bool a_LMB, bool a_RMB, float a_pitch, - float a_yaw + float a_yaw, + float a_sidew_move_joystick_axis, + float a_forw_move_joystick_axis ) { up = a_up; @@ -72,6 +76,8 @@ struct PlayerControl RMB = a_RMB; pitch = a_pitch; yaw = a_yaw; + sidew_move_joystick_axis = a_sidew_move_joystick_axis; + forw_move_joystick_axis = a_forw_move_joystick_axis; } bool up; bool down; @@ -84,6 +90,8 @@ struct PlayerControl bool RMB; float pitch; float yaw; + float sidew_move_joystick_axis; + float forw_move_joystick_axis; }; class Map; -- cgit v1.2.3 From f64914708092958f735337b3a14a33ca402b7893 Mon Sep 17 00:00:00 2001 From: est31 Date: Mon, 4 Jul 2016 20:49:13 +0200 Subject: Disable joysticks per default for now It seems that various different devices register as Joysticks on linux, and their presence has caused lots of confusion amongst minetest users. Therefore, disable the joystick feature. Closes #4261 Closes #4221 --- builtin/settingtypes.txt | 2 +- src/defaultsettings.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/defaultsettings.cpp') diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index c751f34f2..3f256ec43 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -105,7 +105,7 @@ random_input (Random input) bool false continuous_forward (Continuous forward) bool false # Enable Joysticks -enable_joysticks (Enable Joysticks) bool true +enable_joysticks (Enable Joysticks) bool false # The time in seconds it takes between repeated events # when holding down a joystick button combination. diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 43a7a7c00..8ee26ecff 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -116,7 +116,7 @@ void set_default_settings(Settings *settings) settings->setDefault("free_move", "false"); settings->setDefault("noclip", "false"); settings->setDefault("continuous_forward", "false"); - settings->setDefault("enable_joysticks", "true"); + settings->setDefault("enable_joysticks", "false"); settings->setDefault("repeat_joystick_button_time", "0.17"); settings->setDefault("joystick_frustum_sensitivity", "170"); settings->setDefault("cinematic", "false"); -- cgit v1.2.3 From 538af97d8d0d0a3c50a7092c029d8585079144c4 Mon Sep 17 00:00:00 2001 From: rubenwardy Date: Mon, 4 Jul 2016 18:01:58 +0100 Subject: Remove cinematic toggle on F8 Also update cinematic mode's description to include mouse --- builtin/settingtypes.txt | 4 ++-- minetest.conf.example | 5 ++--- src/defaultsettings.cpp | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) (limited to 'src/defaultsettings.cpp') diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index 3f256ec43..0b9d29a33 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -70,7 +70,7 @@ fast_move (Fast movement) bool false # This requires the "noclip" privilege on the server. noclip (Noclip) bool false -# Smooths camera when moving and looking around. +# Smooths camera when looking around. Also called look or mouse smoothing. # Useful for recording videos. cinematic (Cinematic mode) bool false @@ -178,7 +178,7 @@ keymap_noclip (Noclip key) key KEY_KEY_H # Key for toggling cinematic mode. # See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3 -keymap_cinematic (Cinematic mode key) key KEY_F8 +keymap_cinematic (Cinematic mode key) key # Key for toggling display of minimap. # See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3 diff --git a/minetest.conf.example b/minetest.conf.example index 35675dfe3..bc0d4c527 100644 --- a/minetest.conf.example +++ b/minetest.conf.example @@ -38,7 +38,7 @@ # type: bool # noclip = false -# Smooths camera when moving and looking around. +# Smooths camera when looking around. Also called look or mouse smoothing. # Useful for recording videos. # type: bool # cinematic = false @@ -162,7 +162,7 @@ # Key for toggling cinematic mode. # See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3 # type: key -# keymap_cinematic = KEY_F8 +# keymap_cinematic = # Key for toggling display of minimap. # See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3 @@ -1527,4 +1527,3 @@ # type: string # modstore_details_url = https://forum.minetest.net/mmdb/mod/*/ - diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 8ee26ecff..3220b915a 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -50,7 +50,7 @@ void set_default_settings(Settings *settings) settings->setDefault("keymap_freemove", "KEY_KEY_K"); settings->setDefault("keymap_fastmove", "KEY_KEY_J"); settings->setDefault("keymap_noclip", "KEY_KEY_H"); - settings->setDefault("keymap_cinematic", "KEY_F8"); + settings->setDefault("keymap_cinematic", ""); settings->setDefault("keymap_screenshot", "KEY_F12"); settings->setDefault("keymap_toggle_hud", "KEY_F1"); settings->setDefault("keymap_toggle_chat", "KEY_F2"); -- cgit v1.2.3 From 2c31b79235dd83de753fce5890c5797e149048b8 Mon Sep 17 00:00:00 2001 From: "Esteban I. Ruiz Moreno" Date: Sun, 31 Mar 2013 00:30:32 -0300 Subject: Add zoom, tweakable with zoom_fov, default key: Z (like optifine) --- src/camera.cpp | 10 ++++++++-- src/camera.h | 1 + src/client/keys.h | 1 + src/defaultsettings.cpp | 2 ++ src/game.cpp | 2 ++ src/guiKeyChangeMenu.cpp | 2 ++ src/player.h | 4 ++++ 7 files changed, 20 insertions(+), 2 deletions(-) (limited to 'src/defaultsettings.cpp') diff --git a/src/camera.cpp b/src/camera.cpp index 6893b8cbf..e1d6dd910 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -103,6 +103,7 @@ Camera::Camera(scene::ISceneManager* smgr, MapDrawControl& draw_control, m_cache_fall_bobbing_amount = g_settings->getFloat("fall_bobbing_amount"); m_cache_view_bobbing_amount = g_settings->getFloat("view_bobbing_amount"); m_cache_fov = g_settings->getFloat("fov"); + m_cache_zoom_fov = g_settings->getFloat("zoom_fov"); m_cache_view_bobbing = g_settings->getBool("view_bobbing"); m_nametags.clear(); } @@ -387,8 +388,13 @@ void Camera::update(LocalPlayer* player, f32 frametime, f32 busytime, if (m_camera_mode == CAMERA_MODE_THIRD_FRONT) m_camera_position = my_cp; - // Get FOV setting - f32 fov_degrees = m_cache_fov; + // Get FOV + f32 fov_degrees; + if (player->getPlayerControl().zoom) { + fov_degrees = m_cache_zoom_fov; + } else { + fov_degrees = m_cache_fov; + } fov_degrees = MYMAX(fov_degrees, 10.0); fov_degrees = MYMIN(fov_degrees, 170.0); diff --git a/src/camera.h b/src/camera.h index ce46c3190..cb0e9686d 100644 --- a/src/camera.h +++ b/src/camera.h @@ -231,6 +231,7 @@ private: f32 m_cache_fall_bobbing_amount; f32 m_cache_view_bobbing_amount; f32 m_cache_fov; + f32 m_cache_zoom_fov; bool m_cache_view_bobbing; std::list m_nametags; diff --git a/src/client/keys.h b/src/client/keys.h index 0921bc166..6467c443e 100644 --- a/src/client/keys.h +++ b/src/client/keys.h @@ -59,6 +59,7 @@ public: INCREASE_VIEWING_RANGE, DECREASE_VIEWING_RANGE, RANGESELECT, + ZOOM, QUICKTUNE_NEXT, QUICKTUNE_PREV, diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 3220b915a..42b232afc 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -40,6 +40,7 @@ void set_default_settings(Settings *settings) settings->setDefault("keymap_jump", "KEY_SPACE"); settings->setDefault("keymap_sneak", "KEY_LSHIFT"); settings->setDefault("keymap_drop", "KEY_KEY_Q"); + settings->setDefault("keymap_zoom", "KEY_KEY_Z"); settings->setDefault("keymap_inventory", "KEY_KEY_I"); settings->setDefault("keymap_special1", "KEY_KEY_E"); settings->setDefault("keymap_chat", "KEY_KEY_T"); @@ -74,6 +75,7 @@ void set_default_settings(Settings *settings) settings->setDefault("always_fly_fast", "true"); settings->setDefault("directional_colored_fog", "true"); settings->setDefault("tooltip_show_delay", "400"); + settings->setDefault("zoom_fov", "15"); // Some (temporary) keys for debugging settings->setDefault("keymap_print_debug_stacks", "KEY_KEY_P"); diff --git a/src/game.cpp b/src/game.cpp index 9b9f3a75f..1a036d03a 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -1371,6 +1371,7 @@ void KeyCache::populate() = getKeySetting("keymap_decrease_viewing_range_min"); key[KeyType::RANGESELECT] = getKeySetting("keymap_rangeselect"); + key[KeyType::ZOOM] = getKeySetting("keymap_zoom"); key[KeyType::QUICKTUNE_NEXT] = getKeySetting("keymap_quicktune_next"); key[KeyType::QUICKTUNE_PREV] = getKeySetting("keymap_quicktune_prev"); @@ -3270,6 +3271,7 @@ void Game::updatePlayerControl(const CameraOrientation &cam) isKeyDown(KeyType::JUMP), isKeyDown(KeyType::SPECIAL1), isKeyDown(KeyType::SNEAK), + isKeyDown(KeyType::ZOOM), isLeftPressed(), isRightPressed(), cam.camera_pitch, diff --git a/src/guiKeyChangeMenu.cpp b/src/guiKeyChangeMenu.cpp index 785e921f7..07137d1bc 100644 --- a/src/guiKeyChangeMenu.cpp +++ b/src/guiKeyChangeMenu.cpp @@ -59,6 +59,7 @@ enum GUI_ID_KEY_INVENTORY_BUTTON, GUI_ID_KEY_DUMP_BUTTON, GUI_ID_KEY_RANGE_BUTTON, + GUI_ID_KEY_ZOOM_BUTTON, // other GUI_ID_CB_AUX1_DESCENDS, GUI_ID_CB_DOUBLETAP_JUMP, @@ -414,5 +415,6 @@ void GUIKeyChangeMenu::init_keys() this->add_key(GUI_ID_KEY_NOCLIP_BUTTON, wgettext("Toggle noclip"), "keymap_noclip"); this->add_key(GUI_ID_KEY_RANGE_BUTTON, wgettext("Range select"), "keymap_rangeselect"); this->add_key(GUI_ID_KEY_DUMP_BUTTON, wgettext("Print stacks"), "keymap_print_debug_stacks"); + this->add_key(GUI_ID_KEY_ZOOM_BUTTON, wgettext("Zoom"), "keymap_zoom"); } diff --git a/src/player.h b/src/player.h index e6fcf388a..eab00bb04 100644 --- a/src/player.h +++ b/src/player.h @@ -49,6 +49,7 @@ struct PlayerControl sidew_move_joystick_axis = .0f; forw_move_joystick_axis = .0f; } + PlayerControl( bool a_up, bool a_down, @@ -57,6 +58,7 @@ struct PlayerControl bool a_jump, bool a_aux1, bool a_sneak, + bool a_zoom, bool a_LMB, bool a_RMB, float a_pitch, @@ -72,6 +74,7 @@ struct PlayerControl jump = a_jump; aux1 = a_aux1; sneak = a_sneak; + zoom = a_zoom; LMB = a_LMB; RMB = a_RMB; pitch = a_pitch; @@ -86,6 +89,7 @@ struct PlayerControl bool jump; bool aux1; bool sneak; + bool zoom; bool LMB; bool RMB; float pitch; -- cgit v1.2.3 From d767f025cb0d5cca29c1f2147d2a0931a088b717 Mon Sep 17 00:00:00 2001 From: est31 Date: Mon, 22 Aug 2016 04:27:44 +0200 Subject: Client: disable pre v25 init sending by default Disable the ability to connect to old servers by default to improve password security. If people still want to connect to old (0.4.12 and earlier) servers, they can flip the send_pre_v25_init setting. Add the ability to detect if we've tried to connect to a server which only supports the pre v25 init protocol, and show an apropriate error message. Most times the error will already be catched at the serverlist level, the detection mechanism only acts as last resort, because the "Connection timed out" error message that would be shown otherwise would be very confusing. Automatic "fixing" of this condition is not desired, as it would allow for downgrade attacks. As already 161 of the 167 servers on the serverlist support the new srp based auth protocol (> 96%), the breakage should be minimal. Follow up of commit af30183124d40a969040d7de4b3a487feec466e4 "Add option to not send pre v25 init packet" Also change the pessimistic assumption of masterlist server versions to optimistic, in order to avoid buggy behaviour (favourites not in the serverlist would be denied to connect to, etc). --- builtin/mainmenu/common.lua | 10 +++++++--- builtin/settingtypes.txt | 2 +- minetest.conf.example | 4 ++-- src/client.h | 3 +++ src/defaultsettings.cpp | 2 +- src/game.cpp | 21 ++++++++++++++++++++- 6 files changed, 34 insertions(+), 8 deletions(-) (limited to 'src/defaultsettings.cpp') diff --git a/builtin/mainmenu/common.lua b/builtin/mainmenu/common.lua index 1fd89ff77..da3667828 100644 --- a/builtin/mainmenu/common.lua +++ b/builtin/mainmenu/common.lua @@ -248,14 +248,18 @@ end -------------------------------------------------------------------------------- function is_server_protocol_compat(server_proto_min, server_proto_max) - return min_supp_proto <= (server_proto_max or 24) and max_supp_proto >= (server_proto_min or 13) + if (not server_proto_min) or (not server_proto_max) then + -- There is no info. Assume the best and act as if we would be compatible. + return true + end + return min_supp_proto <= server_proto_max and max_supp_proto >= server_proto_min end -------------------------------------------------------------------------------- function is_server_protocol_compat_or_error(server_proto_min, server_proto_max) if not is_server_protocol_compat(server_proto_min, server_proto_max) then local server_prot_ver_info, client_prot_ver_info - local s_p_min = server_proto_min or 13 - local s_p_max = server_proto_max or 24 + local s_p_min = server_proto_min + local s_p_max = server_proto_max if s_p_min ~= s_p_max then server_prot_ver_info = fgettext_ne("Server supports protocol versions between $1 and $2. ", diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index 864485cce..4d354a7ef 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -247,7 +247,7 @@ remote_port (Remote port) int 30000 1 65535 # Enable if you want to connect to 0.4.12 servers and before. # Servers starting with 0.4.13 will work, 0.4.12-dev servers may work. # Disabling this option will protect your password better. -send_pre_v25_init (Support older servers) bool true +send_pre_v25_init (Support older servers) bool false # Save the map received by the client on disk. enable_local_map_saving (Saving map received from server) bool false diff --git a/minetest.conf.example b/minetest.conf.example index 03a917a39..48c54c320 100644 --- a/minetest.conf.example +++ b/minetest.conf.example @@ -261,7 +261,7 @@ # Servers starting with 0.4.13 will work, 0.4.12-dev servers may work. # Disabling this option will protect your password better. # type: bool -# send_pre_v25_init = true +# send_pre_v25_init = false # Save the map received by the client on disk. # type: bool @@ -1485,7 +1485,7 @@ # profiler.default_report_format = txt # The file path relative to your worldpath in which profiles will be saved to. -# +# # type: string # profiler.report_path = "" diff --git a/src/client.h b/src/client.h index a7eb22ad9..b479062a0 100644 --- a/src/client.h +++ b/src/client.h @@ -499,6 +499,9 @@ public: u8 getProtoVersion() { return m_proto_ver; } + bool connectedToServer() + { return m_con.Connected(); } + float mediaReceiveProgress(); void afterContentReceived(IrrlichtDevice *device); diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 42b232afc..7c6f7ef3d 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -190,7 +190,7 @@ void set_default_settings(Settings *settings) settings->setDefault("minimap_shape_round", "true"); settings->setDefault("minimap_double_scan_height", "true"); - settings->setDefault("send_pre_v25_init", "true"); + settings->setDefault("send_pre_v25_init", "false"); settings->setDefault("curl_timeout", "5000"); settings->setDefault("curl_parallel_limit", "8"); diff --git a/src/game.cpp b/src/game.cpp index 1a036d03a..5a3b10879 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -2403,7 +2403,26 @@ bool Game::connectToServer(const std::string &playername, wait_time += dtime; // Only time out if we aren't waiting for the server we started if ((*address != "") && (wait_time > 10)) { - *error_message = "Connection timed out."; + bool sent_old_init = g_settings->getFlag("send_pre_v25_init"); + // If no pre v25 init was sent, and no answer was received, + // but the low level connection could be established + // (meaning that we have a peer id), then we probably wanted + // to connect to a legacy server. In this case, tell the user + // to enable the option to be able to connect. + if (!sent_old_init && + (client->getProtoVersion() == 0) && + client->connectedToServer()) { + *error_message = "Connection failure: init packet not " + "recognized by server.\n" + "Most likely the server uses an old protocol version ( Network -> Support older Servers'\n" + "entry in the advanced settings menu."; + } else { + *error_message = "Connection timed out."; + } errorstream << *error_message << std::endl; break; } -- cgit v1.2.3 From 679c8de63ffb7119f2b99b00883bc959f5917da4 Mon Sep 17 00:00:00 2001 From: James Stevenson Date: Thu, 15 Sep 2016 11:53:17 -0400 Subject: Increase default font size by 1 --- builtin/settingtypes.txt | 4 ++-- minetest.conf.example | 4 ++-- src/constants.h | 2 +- src/defaultsettings.cpp | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src/defaultsettings.cpp') diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index 4622a7217..15fab0f30 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -561,13 +561,13 @@ freetype (Freetype fonts) bool true # Path to TrueTypeFont or bitmap. font_path (Font path) path fonts/liberationsans.ttf -font_size (Font size) int 15 +font_size (Font size) int 16 # Font shadow offset, if 0 then shadow will not be drawn. font_shadow (Font shadow) int 1 # Font shadow alpha (opaqueness, between 0 and 255). -font_shadow_alpha (Font shadow alpha) int 128 0 255 +font_shadow_alpha (Font shadow alpha) int 127 0 255 mono_font_path (Monospace font path) path fonts/liberationmono.ttf diff --git a/minetest.conf.example b/minetest.conf.example index 3d9b77306..bedc8c579 100644 --- a/minetest.conf.example +++ b/minetest.conf.example @@ -655,7 +655,7 @@ # font_path = fonts/liberationsans.ttf # type: int -# font_size = 15 +# font_size = 16 # Font shadow offset, if 0 then shadow will not be drawn. # type: int @@ -663,7 +663,7 @@ # Font shadow alpha (opaqueness, between 0 and 255). # type: int min: 0 max: 255 -# font_shadow_alpha = 128 +# font_shadow_alpha = 127 # type: path # mono_font_path = fonts/liberationmono.ttf diff --git a/src/constants.h b/src/constants.h index b606fc4fa..55ae9daf3 100644 --- a/src/constants.h +++ b/src/constants.h @@ -112,7 +112,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #if defined(_WIN32) #define TTF_DEFAULT_FONT_SIZE (18) #else - #define TTF_DEFAULT_FONT_SIZE (15) + #define TTF_DEFAULT_FONT_SIZE (16) #endif #define DEFAULT_FONT_SIZE (10) diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 7c6f7ef3d..4520bac2f 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -213,7 +213,7 @@ void set_default_settings(Settings *settings) settings->setDefault("freetype", "true"); settings->setDefault("font_path", porting::getDataPath("fonts" DIR_DELIM "liberationsans.ttf")); settings->setDefault("font_shadow", "1"); - settings->setDefault("font_shadow_alpha", "128"); + settings->setDefault("font_shadow_alpha", "127"); settings->setDefault("mono_font_path", porting::getDataPath("fonts" DIR_DELIM "liberationmono.ttf")); settings->setDefault("fallback_font_path", porting::getDataPath("fonts" DIR_DELIM "DroidSansFallbackFull.ttf")); -- cgit v1.2.3 From d4c76258e37337ea585cf24d8e05b50a30fa307d Mon Sep 17 00:00:00 2001 From: Loic Blot Date: Tue, 4 Oct 2016 18:17:12 +0200 Subject: Chat: new settings to prevent spam Added the following chat coreside features * Chat messages length limit * Message rate limiting * Message rate kicking Note: * handleChat now takes RemotePlayer pointer instead of u16 to remove useless lookups --- builtin/settingtypes.txt | 9 ++++++ minetest.conf.example | 14 +++++++++- src/defaultsettings.cpp | 3 ++ src/network/serverpackethandler.cpp | 10 +++---- src/player.cpp | 56 ++++++++++++++++++++++++++++++++++++- src/player.h | 16 ++++++++++- src/server.cpp | 25 +++++++++++++++-- src/server.h | 3 +- 8 files changed, 125 insertions(+), 11 deletions(-) (limited to 'src/defaultsettings.cpp') diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index 15fab0f30..95cc826a0 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -774,6 +774,15 @@ time_speed (Time speed) int 72 # Interval of saving important changes in the world, stated in seconds. server_map_save_interval (Map save interval) float 5.3 +# Set the maximum character length of a chat message sent by clients. +# chat_message_max_size int 500 + +# Limit a single player to send X messages per 10 seconds. +# chat_message_limit_per_10sec float 10.0 + +# Kick player if send more than X messages per 10 seconds. +# chat_message_limit_trigger_kick int 50 + [**Physics] movement_acceleration_default (Default acceleration) float 3 diff --git a/minetest.conf.example b/minetest.conf.example index 9c8015625..b1b202786 100644 --- a/minetest.conf.example +++ b/minetest.conf.example @@ -933,6 +933,18 @@ # type: float # server_map_save_interval = 5.3 +# Set the maximum character length of a chat message sent by clients. (0 to disable) +# type: integer +# chat_message_max_size = 500 + +# Limit a single player to send X messages per 10 seconds. (0 to disable) +# type: float +# chat_message_limit_per_10sec = 8.0 + +# Kick player if send more than X messages per 10 seconds. (0 to disable) +# type: integer +# chat_message_limit_trigger_kick = 50 + ### Physics # type: float @@ -1523,7 +1535,7 @@ # profiler.default_report_format = txt # The file path relative to your worldpath in which profiles will be saved to. -# +# # type: string # profiler.report_path = "" diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 4520bac2f..00c233a42 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -285,6 +285,9 @@ void set_default_settings(Settings *settings) settings->setDefault("server_unload_unused_data_timeout", "29"); settings->setDefault("max_objects_per_block", "49"); 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_trigger_kick", "50"); settings->setDefault("sqlite_synchronous", "2"); settings->setDefault("full_block_send_enable_min_time_from_building", "2.0"); settings->setDefault("dedicated_server_step", "0.1"); diff --git a/src/network/serverpackethandler.cpp b/src/network/serverpackethandler.cpp index 1bcb78a8a..a8bfd9068 100644 --- a/src/network/serverpackethandler.cpp +++ b/src/network/serverpackethandler.cpp @@ -1065,7 +1065,7 @@ void Server::handleCommand_ChatMessage(NetworkPacket* pkt) std::wstring wname = narrow_to_wide(name); std::wstring answer_to_sender = handleChat(name, wname, message, - true, pkt->getPeerId()); + true, dynamic_cast(player)); if (!answer_to_sender.empty()) { // Send the answer to sender SendChatMessage(pkt->getPeerId(), answer_to_sender); @@ -1656,16 +1656,16 @@ void Server::handleCommand_Interact(NetworkPacket* pkt) } } // action == 4 - + /* 5: rightclick air */ else if (action == 5) { ItemStack item = playersao->getWieldedItem(); - - actionstream << player->getName() << " activates " + + actionstream << player->getName() << " activates " << item.name << std::endl; - + if (m_script->item_OnSecondaryUse( item, playersao)) { if( playersao->setWieldedItem(item)) { diff --git a/src/player.cpp b/src/player.cpp index 5949712a5..fd72d63b6 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -227,10 +227,25 @@ void Player::clearHud() } } +// static config cache for remoteplayer +bool RemotePlayer::m_setting_cache_loaded = false; +float RemotePlayer::m_setting_chat_message_limit_per_10sec = 0.0f; +u16 RemotePlayer::m_setting_chat_message_limit_trigger_kick = 0; + RemotePlayer::RemotePlayer(IGameDef *gamedef, const char *name): Player(gamedef, name), - m_sao(NULL) + m_sao(NULL), + m_last_chat_message_sent(time(NULL)), + m_chat_message_allowance(5.0f), + m_message_rate_overhead(0) { + if (!RemotePlayer::m_setting_cache_loaded) { + RemotePlayer::m_setting_chat_message_limit_per_10sec = + g_settings->getFloat("chat_message_limit_per_10sec"); + RemotePlayer::m_setting_chat_message_limit_trigger_kick = + g_settings->getU16("chat_message_limit_trigger_kick"); + RemotePlayer::m_setting_cache_loaded = true; + } movement_acceleration_default = g_settings->getFloat("movement_acceleration_default") * BS; movement_acceleration_air = g_settings->getFloat("movement_acceleration_air") * BS; movement_acceleration_fast = g_settings->getFloat("movement_acceleration_fast") * BS; @@ -304,3 +319,42 @@ void RemotePlayer::setPosition(const v3f &position) m_sao->setBasePosition(position); } +const RemotePlayerChatResult RemotePlayer::canSendChatMessage() +{ + // Rate limit messages + u32 now = time(NULL); + float time_passed = now - m_last_chat_message_sent; + m_last_chat_message_sent = now; + + // If this feature is disabled + if (m_setting_chat_message_limit_per_10sec <= 0.0) { + return RPLAYER_CHATRESULT_OK; + } + + m_chat_message_allowance += time_passed * (m_setting_chat_message_limit_per_10sec / 8.0f); + if (m_chat_message_allowance > m_setting_chat_message_limit_per_10sec) { + m_chat_message_allowance = m_setting_chat_message_limit_per_10sec; + } + + if (m_chat_message_allowance < 1.0f) { + infostream << "Player " << m_name + << " chat limited due to excessive message amount." << std::endl; + + // Kick player if flooding is too intensive + m_message_rate_overhead++; + if (m_message_rate_overhead > RemotePlayer::m_setting_chat_message_limit_trigger_kick) { + return RPLAYER_CHATRESULT_KICK; + } + + return RPLAYER_CHATRESULT_FLOODING; + } + + // Reinit message overhead + if (m_message_rate_overhead > 0) { + m_message_rate_overhead = 0; + } + + m_chat_message_allowance -= 1.0f; + return RPLAYER_CHATRESULT_OK; +} + diff --git a/src/player.h b/src/player.h index eab00bb04..f38effa9d 100644 --- a/src/player.h +++ b/src/player.h @@ -439,7 +439,11 @@ private: Mutex m_mutex; }; - +enum RemotePlayerChatResult { + RPLAYER_CHATRESULT_OK, + RPLAYER_CHATRESULT_FLOODING, + RPLAYER_CHATRESULT_KICK, +}; /* Player on the server */ @@ -457,8 +461,18 @@ public: { m_sao = sao; } void setPosition(const v3f &position); + const RemotePlayerChatResult canSendChatMessage(); + private: PlayerSAO *m_sao; + + static bool m_setting_cache_loaded; + static float m_setting_chat_message_limit_per_10sec; + static u16 m_setting_chat_message_limit_trigger_kick; + + u32 m_last_chat_message_sent; + float m_chat_message_allowance; + u16 m_message_rate_overhead; }; #endif diff --git a/src/server.cpp b/src/server.cpp index fb241f179..c615aee13 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -358,6 +358,7 @@ Server::Server( add_legacy_abms(m_env, m_nodedef); m_liquid_transform_every = g_settings->getFloat("liquid_update"); + m_max_chatmessage_length = g_settings->getU16("chat_message_max_size"); } Server::~Server() @@ -2734,8 +2735,7 @@ void Server::handleChatInterfaceEvent(ChatEvent *evt) } std::wstring Server::handleChat(const std::string &name, const std::wstring &wname, - const std::wstring &wmessage, bool check_shout_priv, - u16 peer_id_to_avoid_sending) + const std::wstring &wmessage, bool check_shout_priv, RemotePlayer *player) { // If something goes wrong, this player is to blame RollbackScopeActor rollback_scope(m_rollback, @@ -2753,6 +2753,26 @@ std::wstring Server::handleChat(const std::string &name, const std::wstring &wna if (ate) return L""; + switch (player->canSendChatMessage()) { + case RPLAYER_CHATRESULT_FLOODING: { + std::wstringstream ws; + ws << L"You cannot send more messages. You are limited to " + << g_settings->getFloat("chat_message_limit_per_10sec") + << " messages per 10 seconds."; + return ws.str(); + } + case RPLAYER_CHATRESULT_KICK: + DenyAccess_Legacy(player->peer_id, L"You have been kicked due to message flooding."); + return L""; + case RPLAYER_CHATRESULT_OK: break; + default: FATAL_ERROR("Unhandled chat filtering result found."); + } + + if (m_max_chatmessage_length > 0 && wmessage.length() > m_max_chatmessage_length) { + return L"Your message exceed the maximum chat message limit set on the server. " + "It was refused. Send a shorter message"; + } + // Commands are implemented in Lua, so only catch invalid // commands that were not "eaten" and send an error back if (wmessage[0] == L'/') { @@ -2787,6 +2807,7 @@ std::wstring Server::handleChat(const std::string &name, const std::wstring &wna std::vector clients = m_clients.getClientIDs(); + u16 peer_id_to_avoid_sending = (player ? player->peer_id : PEER_ID_INEXISTENT); for (u16 i = 0; i < clients.size(); i++) { u16 cid = clients[i]; if (cid != peer_id_to_avoid_sending) diff --git a/src/server.h b/src/server.h index 7ee15a463..3ad894b38 100644 --- a/src/server.h +++ b/src/server.h @@ -487,7 +487,7 @@ private: std::wstring handleChat(const std::string &name, const std::wstring &wname, const std::wstring &wmessage, bool check_shout_priv = false, - u16 peer_id_to_avoid_sending = PEER_ID_INEXISTENT); + RemotePlayer *player = NULL); void handleAdminChat(const ChatEventChat *evt); v3f findSpawnPos(); @@ -522,6 +522,7 @@ private: // If true, do not allow multiple players and hide some multiplayer // functionality bool m_simple_singleplayer_mode; + u16 m_max_chatmessage_length; // Thread can set; step() will throw as ServerError MutexedVariable m_async_fatal_error; -- cgit v1.2.3 From 2ff054d0419535a9422a957d50491ed119d6eb73 Mon Sep 17 00:00:00 2001 From: ShadowNinja Date: Sun, 9 Oct 2016 14:36:22 -0400 Subject: Enable mod security by default --- builtin/settingtypes.txt | 2 +- minetest.conf.example | 2 +- src/defaultsettings.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/defaultsettings.cpp') diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index 0a6c21a46..9b5f386e0 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -1161,7 +1161,7 @@ mgvalleys_np_inter_valley_slope (Valley Slope) noise_params 0.5, 0.5, (128, 128, [*Security] # Prevent mods from doing insecure things like running shell commands. -secure.enable_security (Enable mod security) bool false +secure.enable_security (Enable mod security) bool true # Comma-separated list of trusted mods that are allowed to access insecure # functions even when mod security is on (via request_insecure_environment()). diff --git a/minetest.conf.example b/minetest.conf.example index 465e1d069..e24d3a384 100644 --- a/minetest.conf.example +++ b/minetest.conf.example @@ -1507,7 +1507,7 @@ # Prevent mods from doing insecure things like running shell commands. # type: bool -# secure.enable_security = false +# secure.enable_security = true # Comma-separated list of trusted mods that are allowed to access insecure # functions even when mod security is on (via request_insecure_environment()). diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 00c233a42..522aa8481 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -301,7 +301,7 @@ void set_default_settings(Settings *settings) settings->setDefault("emergequeue_limit_diskonly", "32"); settings->setDefault("emergequeue_limit_generate", "32"); settings->setDefault("num_emerge_threads", "1"); - settings->setDefault("secure.enable_security", "false"); + settings->setDefault("secure.enable_security", "true"); settings->setDefault("secure.trusted_mods", ""); settings->setDefault("secure.http_mods", ""); -- cgit v1.2.3 From 63a3bb229a9ff288ab01e3e80c8477da5e84ee1e Mon Sep 17 00:00:00 2001 From: paramat Date: Wed, 19 Oct 2016 01:37:12 +0100 Subject: Changes to static object storage limit and error message Move static object storage force-delete message from errorstream to warningstream. Increase 'max objects per block' setting to 64. Add missing spaces in warning code. --- builtin/settingtypes.txt | 2 +- minetest.conf.example | 2 +- src/defaultsettings.cpp | 2 +- src/environment.cpp | 14 +++++++------- 4 files changed, 10 insertions(+), 10 deletions(-) (limited to 'src/defaultsettings.cpp') diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index 9b5f386e0..492d7c79d 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -817,7 +817,7 @@ max_clearobjects_extra_loaded_blocks (Max. clearobjects extra blocks) int 4096 server_unload_unused_data_timeout (Unload unused server data) int 29 # Maximum number of statically stored objects in a block. -max_objects_per_block (Maximum objects per block) int 49 +max_objects_per_block (Maximum objects per block) int 64 # See http://www.sqlite.org/pragma.html#pragma_synchronous sqlite_synchronous (Synchronous SQLite) enum 2 0,1,2 diff --git a/minetest.conf.example b/minetest.conf.example index e24d3a384..b7d705bac 100644 --- a/minetest.conf.example +++ b/minetest.conf.example @@ -1008,7 +1008,7 @@ # Maximum number of statically stored objects in a block. # type: int -# max_objects_per_block = 49 +# max_objects_per_block = 64 # See http://www.sqlite.org/pragma.html#pragma_synchronous # type: enum values: 0, 1, 2 diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 522aa8481..a64840a8f 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -283,7 +283,7 @@ void set_default_settings(Settings *settings) settings->setDefault("time_send_interval", "5"); settings->setDefault("time_speed", "72"); settings->setDefault("server_unload_unused_data_timeout", "29"); - settings->setDefault("max_objects_per_block", "49"); + 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"); diff --git a/src/environment.cpp b/src/environment.cpp index ceaf40d89..ecda1b6a4 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -2175,13 +2175,13 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete) if(block) { - if(block->m_static_objects.m_stored.size() >= g_settings->getU16("max_objects_per_block")){ - errorstream<<"ServerEnv: Trying to store id="<getId() - <<" statically but block "<m_static_objects.m_stored.size() - <<" objects." - <<" Forcing delete."<m_static_objects.m_stored.size() >= g_settings->getU16("max_objects_per_block")) { + warningstream << "ServerEnv: Trying to store id = " << obj->getId() + << " statically but block " << PP(blockpos) + << " already contains " + << block->m_static_objects.m_stored.size() + << " objects." + << " Forcing delete." << std::endl; force_delete = true; } else { // If static counterpart already exists in target block, -- cgit v1.2.3 From e1842ed370f7cab23e460979a08886b5df38e1b3 Mon Sep 17 00:00:00 2001 From: lhofhansl Date: Sun, 30 Oct 2016 20:35:55 -0700 Subject: Optionally disable optimization that causes underwater and cave rendering glitches. (#4686) --- builtin/settingtypes.txt | 7 +++++++ src/clientiface.cpp | 4 +++- src/defaultsettings.cpp | 1 + 3 files changed, 11 insertions(+), 1 deletion(-) (limited to 'src/defaultsettings.cpp') diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index 492d7c79d..e48fc9bc5 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -849,6 +849,13 @@ liquid_queue_purge_time (Liquid queue purge time) int 0 # Liquid update interval in seconds. liquid_update (Liquid update tick) float 1.0 +# At this distance the server will aggressively optimize which blocks are sent to clients. +# Small values potentially improve performance a lot, at the expense of visible rendering glitches. +# (some blocks will not be rendered under water and in caves, as well as sometimes on land) +# Setting this to a value greater than max_block_send_distance disables this optimization. +# Stated in mapblocks (16 nodes) +block_send_optimize_distance (block send optimize distance) int 4 2 + [*Mapgen] # Name of map generator to be used when creating a new world. diff --git a/src/clientiface.cpp b/src/clientiface.cpp index d2e3a6da0..7dce77cd7 100644 --- a/src/clientiface.cpp +++ b/src/clientiface.cpp @@ -174,6 +174,8 @@ void RemoteClient::GetNextBlocks ( s32 new_nearest_unsent_d = -1; const s16 full_d_max = g_settings->getS16("max_block_send_distance"); + const s16 d_opt = g_settings->getS16("block_send_optimize_distance"); + s16 d_max = full_d_max; s16 d_max_gen = g_settings->getS16("max_block_generate_distance"); @@ -300,7 +302,7 @@ void RemoteClient::GetNextBlocks ( Block is near ground level if night-time mesh differs from day-time mesh. */ - if(d >= 4) + if(d >= d_opt) { if(block->getDayNightDiff() == false) continue; diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index a64840a8f..2cb57532d 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -279,6 +279,7 @@ void set_default_settings(Settings *settings) settings->setDefault("max_simultaneous_block_sends_server_total", "40"); settings->setDefault("max_block_send_distance", "9"); settings->setDefault("max_block_generate_distance", "7"); + settings->setDefault("block_send_optimize_distance", "4"); settings->setDefault("max_clearobjects_extra_loaded_blocks", "4096"); settings->setDefault("time_send_interval", "5"); settings->setDefault("time_speed", "72"); -- cgit v1.2.3 From 075833e39368e63e06889f21140f816420e83541 Mon Sep 17 00:00:00 2001 From: Lars Hofhansl Date: Sat, 3 Dec 2016 21:43:25 -0800 Subject: Fog: Make fraction of visible distance at which fog starts configurable Optimise the fetching of global settings 'camera_smoothing', 'cinematic' and 'cinematic_camera_smoothing'. Cache 'cam_smoothing'. --- builtin/settingtypes.txt | 3 ++ client/shaders/nodes_shader/opengl_fragment.glsl | 2 +- .../water_surface_shader/opengl_fragment.glsl | 2 +- client/shaders/wielded_shader/opengl_fragment.glsl | 2 +- minetest.conf.example | 4 +++ src/defaultsettings.cpp | 1 + src/game.cpp | 37 ++++++++++++++++------ src/shader.cpp | 4 +++ 8 files changed, 43 insertions(+), 12 deletions(-) (limited to 'src/defaultsettings.cpp') diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index b1f31054e..10db4787d 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -529,6 +529,9 @@ ambient_occlusion_gamma (Ambient occlusion gamma) float 2.2 0.25 4.0 # Enables animation of inventory items. inventory_items_animations (Inventory items animations) bool false +# Fraction of the visible distance at which fog starts to be rendered +fog_start (Fog Start) float 0.4 0.0 0.99 + [**Menus] # Use a cloud animation for the main menu background. diff --git a/client/shaders/nodes_shader/opengl_fragment.glsl b/client/shaders/nodes_shader/opengl_fragment.glsl index 149aa2bc5..71ded2b9d 100644 --- a/client/shaders/nodes_shader/opengl_fragment.glsl +++ b/client/shaders/nodes_shader/opengl_fragment.glsl @@ -19,7 +19,7 @@ bool normalTexturePresent = false; const float e = 2.718281828459; const float BS = 10.0; -const float fogStart = 0.4; +const float fogStart = FOG_START; const float fogShadingParameter = 1 / ( 1 - fogStart); #ifdef ENABLE_TONE_MAPPING diff --git a/client/shaders/water_surface_shader/opengl_fragment.glsl b/client/shaders/water_surface_shader/opengl_fragment.glsl index 4164870c7..c4e78470d 100644 --- a/client/shaders/water_surface_shader/opengl_fragment.glsl +++ b/client/shaders/water_surface_shader/opengl_fragment.glsl @@ -21,7 +21,7 @@ bool texSeamless = false; const float e = 2.718281828459; const float BS = 10.0; -const float fogStart = 0.4; +const float fogStart = FOG_START; const float fogShadingParameter = 1 / ( 1 - fogStart); #ifdef ENABLE_TONE_MAPPING diff --git a/client/shaders/wielded_shader/opengl_fragment.glsl b/client/shaders/wielded_shader/opengl_fragment.glsl index 7c38b749a..ba7a8f12d 100644 --- a/client/shaders/wielded_shader/opengl_fragment.glsl +++ b/client/shaders/wielded_shader/opengl_fragment.glsl @@ -19,7 +19,7 @@ bool texSeamless = false; const float e = 2.718281828459; const float BS = 10.0; -const float fogStart = 0.4; +const float fogStart = FOG_START; const float fogShadingParameter = 1 / ( 1 - fogStart); void get_texture_flags() diff --git a/minetest.conf.example b/minetest.conf.example index 361311ba0..90d7af0a3 100644 --- a/minetest.conf.example +++ b/minetest.conf.example @@ -615,6 +615,10 @@ # type: bool # inventory_items_animations = false +# Fraction of the visible distance at which fog starts to be rendered +# Range 0 - 0.99 +# fog_start = 0.4 + ### Menus # Use a cloud animation for the main menu background. diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 2cb57532d..bd88cf530 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -106,6 +106,7 @@ void set_default_settings(Settings *settings) settings->setDefault("client_unload_unused_data_timeout", "600"); settings->setDefault("client_mapblock_limit", "5000"); settings->setDefault("enable_fog", "true"); + settings->setDefault("fog_start", "0.4"); settings->setDefault("fov", "72"); settings->setDefault("view_bobbing", "true"); settings->setDefault("leaves_style", "fancy"); diff --git a/src/game.cpp b/src/game.cpp index e6d38d0a0..cc6e5a0e3 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -1825,6 +1825,8 @@ private: f32 m_cache_mouse_sensitivity; f32 m_cache_joystick_frustum_sensitivity; f32 m_repeat_right_click_time; + f32 m_cache_cam_smoothing; + f32 m_cache_fog_start; #ifdef __ANDROID__ bool m_cache_hold_aux1; @@ -1876,6 +1878,12 @@ Game::Game() : &settingChangedCallback, this); g_settings->registerChangedCallback("free_move", &settingChangedCallback, this); + g_settings->registerChangedCallback("cinematic", + &settingChangedCallback, this); + g_settings->registerChangedCallback("cinematic_camera_smoothing", + &settingChangedCallback, this); + g_settings->registerChangedCallback("camera_smoothing", + &settingChangedCallback, this); readSettings(); @@ -1929,6 +1937,12 @@ Game::~Game() &settingChangedCallback, this); g_settings->deregisterChangedCallback("free_move", &settingChangedCallback, this); + g_settings->deregisterChangedCallback("cinematic", + &settingChangedCallback, this); + g_settings->deregisterChangedCallback("cinematic_camera_smoothing", + &settingChangedCallback, this); + g_settings->deregisterChangedCallback("camera_smoothing", + &settingChangedCallback, this); } bool Game::startup(bool *kill, @@ -2034,16 +2048,10 @@ void Game::run() processUserInput(&flags, &runData, dtime); // Update camera before player movement to avoid camera lag of one frame updateCameraDirection(&cam_view_target, &flags, dtime); - float cam_smoothing = 0; - if (g_settings->getBool("cinematic")) - cam_smoothing = 1 - g_settings->getFloat("cinematic_camera_smoothing"); - else - cam_smoothing = 1 - g_settings->getFloat("camera_smoothing"); - cam_smoothing = rangelim(cam_smoothing, 0.01f, 1.0f); cam_view.camera_yaw += (cam_view_target.camera_yaw - - cam_view.camera_yaw) * cam_smoothing; + cam_view.camera_yaw) * m_cache_cam_smoothing; cam_view.camera_pitch += (cam_view_target.camera_pitch - - cam_view.camera_pitch) * cam_smoothing; + cam_view.camera_pitch) * m_cache_cam_smoothing; updatePlayerControl(cam_view); step(&dtime); processClientEvents(&cam_view_target, &runData.damage_flash); @@ -4284,7 +4292,7 @@ void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, driver->setFog( sky->getBgColor(), video::EFT_FOG_LINEAR, - runData->fog_range * 0.4, + runData->fog_range * m_cache_fog_start, runData->fog_range * 1.0, 0.01, false, // pixel fog @@ -4660,7 +4668,18 @@ void Game::readSettings() m_cache_enable_noclip = g_settings->getBool("noclip"); m_cache_enable_free_move = g_settings->getBool("free_move"); + m_cache_fog_start = g_settings->getFloat("fog_start"); + + m_cache_cam_smoothing = 0; + if (g_settings->getBool("cinematic")) + m_cache_cam_smoothing = 1 - g_settings->getFloat("cinematic_camera_smoothing"); + else + m_cache_cam_smoothing = 1 - g_settings->getFloat("camera_smoothing"); + + m_cache_fog_start = rangelim(m_cache_fog_start, 0.0f, 0.99f); + m_cache_cam_smoothing = rangelim(m_cache_cam_smoothing, 0.01f, 1.0f); m_cache_mouse_sensitivity = rangelim(m_cache_mouse_sensitivity, 0.001, 100.0); + } /****************************************************************************/ diff --git a/src/shader.cpp b/src/shader.cpp index d51c1e308..c0ecf738d 100644 --- a/src/shader.cpp +++ b/src/shader.cpp @@ -751,6 +751,10 @@ ShaderInfo generate_shader(std::string name, u8 material_type, u8 drawtype, if (g_settings->getBool("tone_mapping")) shaders_header += "#define ENABLE_TONE_MAPPING\n"; + shaders_header += "#define FOG_START "; + shaders_header += ftos(rangelim(g_settings->getFloat("fog_start"), 0.0f, 0.99f)); + shaders_header += "\n"; + // Call addHighLevelShaderMaterial() or addShaderMaterial() const c8* vertex_program_ptr = 0; const c8* pixel_program_ptr = 0; -- cgit v1.2.3 From 78bf7c46e5fe8845e9a9f65b98db32b0ff398ad3 Mon Sep 17 00:00:00 2001 From: Auke Kok Date: Thu, 15 Dec 2016 20:55:41 -0800 Subject: Mapgen: Make mgv7 the default in UI The actual menu default comes from defaultsettings.cpp. --- builtin/settingtypes.txt | 2 +- minetest.conf.example | 2 +- src/defaultsettings.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/defaultsettings.cpp') diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index ea0ca9992..f0ddd5bc0 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -862,7 +862,7 @@ block_send_optimize_distance (block send optimize distance) int 4 2 # Name of map generator to be used when creating a new world. # Creating a world in the main menu will override this. -mg_name (Mapgen name) enum v6 v5,v6,v7,flat,valleys,fractal,singlenode +mg_name (Mapgen name) enum v7 v5,v6,v7,flat,valleys,fractal,singlenode # Water surface level of the world. water_level (Water level) int 1 diff --git a/minetest.conf.example b/minetest.conf.example index ff365466f..6c7d1e66b 100644 --- a/minetest.conf.example +++ b/minetest.conf.example @@ -1053,7 +1053,7 @@ # Name of map generator to be used when creating a new world. # Creating a world in the main menu will override this. # type: enum values: v5, v6, v7, flat, valleys, fractal, singlenode -# mg_name = v6 +# mg_name = v7 # Water surface level of the world. # type: int diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index bd88cf530..60a34cf63 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -327,7 +327,7 @@ void set_default_settings(Settings *settings) settings->setDefault("liquid_update", "1.0"); //mapgen stuff - settings->setDefault("mg_name", "v6"); + settings->setDefault("mg_name", "v7"); settings->setDefault("water_level", "1"); settings->setDefault("chunksize", "5"); settings->setDefault("mg_flags", "dungeons"); -- cgit v1.2.3 From 09f1a0c1ff8b5d73443603d85fccc3eb25cf4650 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Wed, 21 Dec 2016 14:04:46 +0100 Subject: Disable mod security by default (closes #4944) --- builtin/settingtypes.txt | 2 +- minetest.conf.example | 2 +- src/defaultsettings.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/defaultsettings.cpp') diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index f0ddd5bc0..1818b5a18 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -1186,7 +1186,7 @@ mgvalleys_np_inter_valley_slope (Valley Slope) noise_params 0.5, 0.5, (128, 128, [*Security] # Prevent mods from doing insecure things like running shell commands. -secure.enable_security (Enable mod security) bool true +secure.enable_security (Enable mod security) bool false # Comma-separated list of trusted mods that are allowed to access insecure # functions even when mod security is on (via request_insecure_environment()). diff --git a/minetest.conf.example b/minetest.conf.example index 6c7d1e66b..867d98584 100644 --- a/minetest.conf.example +++ b/minetest.conf.example @@ -1530,7 +1530,7 @@ # Prevent mods from doing insecure things like running shell commands. # type: bool -# secure.enable_security = true +# secure.enable_security = false # Comma-separated list of trusted mods that are allowed to access insecure # functions even when mod security is on (via request_insecure_environment()). diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 60a34cf63..0b4be6322 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -303,7 +303,7 @@ void set_default_settings(Settings *settings) settings->setDefault("emergequeue_limit_diskonly", "32"); settings->setDefault("emergequeue_limit_generate", "32"); settings->setDefault("num_emerge_threads", "1"); - settings->setDefault("secure.enable_security", "true"); + settings->setDefault("secure.enable_security", "false"); settings->setDefault("secure.trusted_mods", ""); settings->setDefault("secure.http_mods", ""); -- cgit v1.2.3