From e18b6c5a21880125284d2a1e9dfb5471d5bc2bec Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Wed, 22 Jan 2020 20:23:40 +0100 Subject: [PATCH 01/31] GUIFormSpecMenu: Shift+Click listring workaround for MacOS event.MouseInput.Shift is not implemented for MacOS --- src/gui/guiFormSpecMenu.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/gui/guiFormSpecMenu.cpp b/src/gui/guiFormSpecMenu.cpp index 632b15992..74578111e 100644 --- a/src/gui/guiFormSpecMenu.cpp +++ b/src/gui/guiFormSpecMenu.cpp @@ -4075,6 +4075,9 @@ enum ButtonEventType : u8 bool GUIFormSpecMenu::OnEvent(const SEvent& event) { + // WORKAROUND: event.MouseInput.Shift is not implemented for MacOS + static thread_local bool is_shift_down = false; + if (event.EventType==EET_KEY_INPUT_EVENT) { KeyPress kp(event.KeyInput); if (event.KeyInput.PressedDown && ( @@ -4084,6 +4087,8 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) return true; } + is_shift_down = event.KeyInput.Shift; + if (m_client != NULL && event.KeyInput.PressedDown && (kp == getKeySetting("keymap_screenshot"))) { m_client->makeScreenshot(); @@ -4133,6 +4138,9 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) event.MouseInput.isRightPressed() && getItemAtPos(m_pointer).i != getItemAtPos(m_old_pointer).i))) { + // WORKAROUND: In case shift was pressed prior showing the formspec + is_shift_down |= event.MouseInput.Shift; + // Get selected item and hovered/clicked item (s) m_old_tooltip_id = -1; @@ -4263,7 +4271,7 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) else // left count = s_count; - if (!event.MouseInput.Shift) { + if (!is_shift_down) { // no shift: select item m_selected_amount = count; m_selected_dragging = button != BET_WHEEL_DOWN; From f2c8c6bf51e608ad6f71710032b8ae017b84fd3d Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Sun, 13 Dec 2020 18:25:13 +0100 Subject: [PATCH 02/31] Revert "GUIFormSpecMenu: Shift+Click listring workaround for MacOS" The commit caused Shift-Clicking issues on Linux due to another Irrlicht bug where KeyInput.Shift released keys do not trigger OnEvent() MacOS users should build using a recent Irrlicht 1.8 development version. See also: https://sourceforge.net/p/irrlicht/patches/321/ --- src/gui/guiFormSpecMenu.cpp | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/gui/guiFormSpecMenu.cpp b/src/gui/guiFormSpecMenu.cpp index 74578111e..632b15992 100644 --- a/src/gui/guiFormSpecMenu.cpp +++ b/src/gui/guiFormSpecMenu.cpp @@ -4075,9 +4075,6 @@ enum ButtonEventType : u8 bool GUIFormSpecMenu::OnEvent(const SEvent& event) { - // WORKAROUND: event.MouseInput.Shift is not implemented for MacOS - static thread_local bool is_shift_down = false; - if (event.EventType==EET_KEY_INPUT_EVENT) { KeyPress kp(event.KeyInput); if (event.KeyInput.PressedDown && ( @@ -4087,8 +4084,6 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) return true; } - is_shift_down = event.KeyInput.Shift; - if (m_client != NULL && event.KeyInput.PressedDown && (kp == getKeySetting("keymap_screenshot"))) { m_client->makeScreenshot(); @@ -4138,9 +4133,6 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) event.MouseInput.isRightPressed() && getItemAtPos(m_pointer).i != getItemAtPos(m_old_pointer).i))) { - // WORKAROUND: In case shift was pressed prior showing the formspec - is_shift_down |= event.MouseInput.Shift; - // Get selected item and hovered/clicked item (s) m_old_tooltip_id = -1; @@ -4271,7 +4263,7 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) else // left count = s_count; - if (!is_shift_down) { + if (!event.MouseInput.Shift) { // no shift: select item m_selected_amount = count; m_selected_dragging = button != BET_WHEEL_DOWN; From 4d41ed09750c7a2fbfeeeccb7a2c3452e3dd26dc Mon Sep 17 00:00:00 2001 From: Zughy <63455151+Zughy@users.noreply.github.com> Date: Mon, 14 Dec 2020 23:49:30 +0100 Subject: [PATCH 03/31] Semi-transparent background for nametags (#10152) --- games/devtest/mods/testentities/visuals.lua | 29 +++++++++++++++++++++ src/client/camera.cpp | 27 ++++++++++++------- 2 files changed, 47 insertions(+), 9 deletions(-) diff --git a/games/devtest/mods/testentities/visuals.lua b/games/devtest/mods/testentities/visuals.lua index 8848ba49f..e3b758329 100644 --- a/games/devtest/mods/testentities/visuals.lua +++ b/games/devtest/mods/testentities/visuals.lua @@ -94,3 +94,32 @@ minetest.register_entity("testentities:upright_animated", { self.object:set_sprite({x=0, y=0}, 4, 1.0, false) end, }) + +minetest.register_entity("testentities:nametag", { + initial_properties = { + visual = "sprite", + textures = { "testentities_sprite.png" }, + }, + + on_activate = function(self, staticdata) + if staticdata ~= "" then + self.color = minetest.deserialize(staticdata).color + else + self.color = { + r = math.random(0, 255), + g = math.random(0, 255), + b = math.random(0, 255), + } + end + + assert(self.color) + self.object:set_properties({ + nametag = tostring(math.random(1000, 10000)), + nametag_color = self.color, + }) + end, + + get_staticdata = function(self) + return minetest.serialize({ color = self.color }) + end, +}) diff --git a/src/client/camera.cpp b/src/client/camera.cpp index 11f8a1c90..9a08254b4 100644 --- a/src/client/camera.cpp +++ b/src/client/camera.cpp @@ -691,10 +691,11 @@ void Camera::drawNametags() core::matrix4 trans = m_cameranode->getProjectionMatrix(); trans *= m_cameranode->getViewMatrix(); - for (std::list::const_iterator - i = m_nametags.begin(); - i != m_nametags.end(); ++i) { - Nametag *nametag = *i; + gui::IGUIFont *font = g_fontengine->getFont(); + video::IVideoDriver *driver = RenderingEngine::get_video_driver(); + v2u32 screensize = driver->getScreenSize(); + + for (const Nametag *nametag : m_nametags) { if (nametag->nametag_color.getAlpha() == 0) { // Enforce hiding nametag, // because if freetype is enabled, a grey @@ -707,21 +708,29 @@ void Camera::drawNametags() if (transformed_pos[3] > 0) { std::wstring nametag_colorless = unescape_translate(utf8_to_wide(nametag->nametag_text)); - core::dimension2d textsize = - g_fontengine->getFont()->getDimension( + core::dimension2d textsize = font->getDimension( nametag_colorless.c_str()); f32 zDiv = transformed_pos[3] == 0.0f ? 1.0f : core::reciprocal(transformed_pos[3]); - v2u32 screensize = RenderingEngine::get_video_driver()->getScreenSize(); v2s32 screen_pos; screen_pos.X = screensize.X * (0.5 * transformed_pos[0] * zDiv + 0.5) - textsize.Width / 2; screen_pos.Y = screensize.Y * (0.5 - transformed_pos[1] * zDiv * 0.5) - textsize.Height / 2; core::rect size(0, 0, textsize.Width, textsize.Height); - g_fontengine->getFont()->draw( + core::rect bg_size(-2, 0, textsize.Width+2, textsize.Height); + + video::SColor textColor = nametag->nametag_color; + + bool darkBackground = textColor.getLuminance() > 186; + video::SColor backgroundColor = darkBackground + ? video::SColor(50, 50, 50, 50) + : video::SColor(50, 255, 255, 255); + driver->draw2DRectangle(backgroundColor, bg_size + screen_pos); + + font->draw( translate_string(utf8_to_wide(nametag->nametag_text)).c_str(), - size + screen_pos, nametag->nametag_color); + size + screen_pos, textColor); } } } From 3ed940ff13fc2b4ef4b63f2c506ed9e5ab59f54f Mon Sep 17 00:00:00 2001 From: wsor4035 <24964441+wsor4035@users.noreply.github.com> Date: Tue, 15 Dec 2020 13:05:55 -0500 Subject: [PATCH 04/31] lua_api.txt: Add mod_orgin to node def (#10697) --- doc/lua_api.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 2fbbd4226..f5c07fe85 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -7612,6 +7612,13 @@ Used by `minetest.register_node`. -- intensity: 1.0 = mid range of regular TNT. -- If defined, called when an explosion touches the node, instead of -- removing the node. + + mod_origin = "modname", + -- stores which mod actually registered a node + -- if it can not find a source, returns "??" + -- useful for getting what mod truly registered something + -- example: if a node is registered as ":othermodname:nodename", + -- nodename will show "othermodname", but mod_orgin will say "modname" } Crafting recipes From d0a38f694d483fbd9c0554c8d7175a94097fd67e Mon Sep 17 00:00:00 2001 From: Thomas--S Date: Tue, 15 Dec 2020 19:06:36 +0100 Subject: [PATCH 05/31] Formspec: Allow to specify frame loop for model[] (#10679) Add the ability to specify an animation frame loop range for the model[] formspec element. --- doc/lua_api.txt | 6 +++++- src/gui/guiFormSpecMenu.cpp | 21 ++++++++++++++++----- src/gui/guiScene.cpp | 9 +++++++++ src/gui/guiScene.h | 1 + 4 files changed, 31 insertions(+), 6 deletions(-) diff --git a/doc/lua_api.txt b/doc/lua_api.txt index f5c07fe85..ddb6d4e19 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -2277,7 +2277,7 @@ Elements * `frame duration`: Milliseconds between each frame. `0` means the frames don't advance. * `frame start` (Optional): The index of the frame to start on. Default `1`. -### `model[,;,;;;;;;]` +### `model[,;,;;;;;;;]` * Show a mesh model. * `name`: Element name that can be used for styling @@ -2288,6 +2288,9 @@ Elements The axes are euler angles in degrees. * `continuous` (Optional): Whether the rotation is continuous. Default `false`. * `mouse control` (Optional): Whether the model can be controlled with the mouse. Default `true`. +* `frame loop range` (Optional): Range of the animation frames. + * Defaults to the full range of all available frames. + * Syntax: `,` ### `item_image[,;,;]` @@ -2789,6 +2792,7 @@ Some types may inherit styles from parent types. * image_button * item_image_button * label +* model * pwdfield, inherits from field * scrollbar * tabheader diff --git a/src/gui/guiFormSpecMenu.cpp b/src/gui/guiFormSpecMenu.cpp index 632b15992..ed197d0d1 100644 --- a/src/gui/guiFormSpecMenu.cpp +++ b/src/gui/guiFormSpecMenu.cpp @@ -70,7 +70,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #define MY_CHECKPOS(a,b) \ if (v_pos.size() != 2) { \ - errorstream<< "Invalid pos for element " << a << "specified: \"" \ + errorstream<< "Invalid pos for element " << a << " specified: \"" \ << parts[b] << "\"" << std::endl; \ return; \ } @@ -78,7 +78,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #define MY_CHECKGEOM(a,b) \ if (v_geom.size() != 2) { \ errorstream<< "Invalid geometry for element " << a << \ - "specified: \"" << parts[b] << "\"" << std::endl; \ + " specified: \"" << parts[b] << "\"" << std::endl; \ return; \ } /* @@ -2725,7 +2725,7 @@ void GUIFormSpecMenu::parseModel(parserData *data, const std::string &element) { std::vector parts = split(element, ';'); - if (parts.size() < 5 || (parts.size() > 8 && + if (parts.size() < 5 || (parts.size() > 9 && m_formspec_version <= FORMSPEC_API_VERSION)) { errorstream << "Invalid model element (" << parts.size() << "): '" << element << "'" << std::endl; @@ -2733,8 +2733,8 @@ void GUIFormSpecMenu::parseModel(parserData *data, const std::string &element) } // Avoid length checks by resizing - if (parts.size() < 8) - parts.resize(8); + if (parts.size() < 9) + parts.resize(9); std::vector v_pos = split(parts[0], ','); std::vector v_geom = split(parts[1], ','); @@ -2744,6 +2744,7 @@ void GUIFormSpecMenu::parseModel(parserData *data, const std::string &element) std::vector vec_rot = split(parts[5], ','); bool inf_rotation = is_yes(parts[6]); bool mousectrl = is_yes(parts[7]) || parts[7].empty(); // default true + std::vector frame_loop = split(parts[8], ','); MY_CHECKPOS("model", 0); MY_CHECKGEOM("model", 1); @@ -2794,6 +2795,16 @@ void GUIFormSpecMenu::parseModel(parserData *data, const std::string &element) e->enableContinuousRotation(inf_rotation); e->enableMouseControl(mousectrl); + s32 frame_loop_begin = 0; + s32 frame_loop_end = 0x7FFFFFFF; + + if (frame_loop.size() == 2) { + frame_loop_begin = stoi(frame_loop[0]); + frame_loop_end = stoi(frame_loop[1]); + } + + e->setFrameLoop(frame_loop_begin, frame_loop_end); + auto style = getStyleForElement("model", spec.fname); e->setStyles(style); e->drop(); diff --git a/src/gui/guiScene.cpp b/src/gui/guiScene.cpp index 08f119e07..5f4c50b91 100644 --- a/src/gui/guiScene.cpp +++ b/src/gui/guiScene.cpp @@ -152,6 +152,15 @@ void GUIScene::setStyles(const std::array &sty setBackgroundColor(style.getColor(StyleSpec::BGCOLOR, m_bgcolor)); } +/** + * Sets the frame loop range for the mesh + */ +void GUIScene::setFrameLoop(s32 begin, s32 end) +{ + if (m_mesh->getStartFrame() != begin || m_mesh->getEndFrame() != end) + m_mesh->setFrameLoop(begin, end); +} + /* Camera control functions */ inline void GUIScene::calcOptimalDistance() diff --git a/src/gui/guiScene.h b/src/gui/guiScene.h index 707e6f66a..08eb7f350 100644 --- a/src/gui/guiScene.h +++ b/src/gui/guiScene.h @@ -36,6 +36,7 @@ public: scene::IAnimatedMeshSceneNode *setMesh(scene::IAnimatedMesh *mesh = nullptr); void setTexture(u32 idx, video::ITexture *texture); void setBackgroundColor(const video::SColor &color) noexcept { m_bgcolor = color; }; + void setFrameLoop(s32 begin, s32 end); void enableMouseControl(bool enable) noexcept { m_mouse_ctrl = enable; }; void setRotation(v2f rot) noexcept { m_custom_rot = rot; }; void enableContinuousRotation(bool enable) noexcept { m_inf_rot = enable; }; From e6380565236d6d963acf75538f1f8fec807190cc Mon Sep 17 00:00:00 2001 From: Lars Date: Wed, 9 Dec 2020 14:30:37 -0800 Subject: [PATCH 06/31] Allow configuring block disk and net compression. Change default disk level. --- builtin/settingtypes.txt | 14 ++++++++++++++ src/defaultsettings.cpp | 4 ++++ src/map.cpp | 8 +++++--- src/map.h | 3 ++- src/mapblock.cpp | 10 +++++----- src/mapblock.h | 2 +- src/mapgen/mg_schematic.cpp | 4 ++-- src/mapnode.cpp | 34 ++++++++++------------------------ src/mapnode.h | 4 ++-- src/server.cpp | 4 ++-- 10 files changed, 47 insertions(+), 40 deletions(-) diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index c9f16578c..251b6d868 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -1048,6 +1048,13 @@ full_block_send_enable_min_time_from_building (Delay in sending blocks after bui # client number. max_packets_per_iteration (Max. packets per iteration) int 1024 +# ZLib compression level to use when sending mapblocks to the client. +# -1 - Zlib's default compression level +# 0 - no compresson, fastest +# 9 - best compression, slowest +# (levels 1-3 use Zlib's "fast" method, 4-9 use the normal method) +map_compression_level_net (Map Compression Level for Network Transfer) int -1 -1 9 + [*Game] # Default game when creating a new world. @@ -1240,6 +1247,13 @@ max_objects_per_block (Maximum objects per block) int 64 # See https://www.sqlite.org/pragma.html#pragma_synchronous sqlite_synchronous (Synchronous SQLite) enum 2 0,1,2 +# ZLib compression level to use when saving mapblocks to disk. +# -1 - Zlib's default compression level +# 0 - no compresson, fastest +# 9 - best compression, slowest +# (levels 1-3 use Zlib's "fast" method, 4-9 use the normal method) +map_compression_level_disk (Map Compression Level for Disk Storage) int 3 -1 9 + # Length of a server tick and the interval at which objects are generally updated over # network. dedicated_server_step (Dedicated server step) float 0.09 diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 177955589..e13977fe3 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -385,6 +385,8 @@ void set_default_settings(Settings *settings) settings->setDefault("chat_message_limit_per_10sec", "8.0"); settings->setDefault("chat_message_limit_trigger_kick", "50"); settings->setDefault("sqlite_synchronous", "2"); + settings->setDefault("map_compression_level_disk", "3"); + settings->setDefault("map_compression_level_net", "-1"); settings->setDefault("full_block_send_enable_min_time_from_building", "2.0"); settings->setDefault("dedicated_server_step", "0.09"); settings->setDefault("active_block_mgmt_interval", "2.0"); @@ -470,6 +472,8 @@ void set_default_settings(Settings *settings) settings->setDefault("fps_max_unfocused", "10"); settings->setDefault("max_objects_per_block", "20"); settings->setDefault("sqlite_synchronous", "1"); + settings->setDefault("map_compression_level_disk", "-1"); + settings->setDefault("map_compression_level_net", "3"); settings->setDefault("server_map_save_interval", "15"); settings->setDefault("client_mapblock_limit", "1000"); settings->setDefault("active_block_range", "2"); diff --git a/src/map.cpp b/src/map.cpp index 37b6e9b6b..6a7cadca5 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -1235,6 +1235,8 @@ ServerMap::ServerMap(const std::string &savedir, IGameDef *gamedef, m_save_time_counter = mb->addCounter("minetest_core_map_save_time", "Map save time (in nanoseconds)"); + m_map_compression_level = rangelim(g_settings->getS16("map_compression_level_disk"), -1, 9); + try { // If directory exists, check contents and load if possible if (fs::PathExists(m_savedir)) { @@ -1863,10 +1865,10 @@ void ServerMap::endSave() bool ServerMap::saveBlock(MapBlock *block) { - return saveBlock(block, dbase); + return saveBlock(block, dbase, m_map_compression_level); } -bool ServerMap::saveBlock(MapBlock *block, MapDatabase *db) +bool ServerMap::saveBlock(MapBlock *block, MapDatabase *db, int compression_level) { v3s16 p3d = block->getPos(); @@ -1886,7 +1888,7 @@ bool ServerMap::saveBlock(MapBlock *block, MapDatabase *db) */ std::ostringstream o(std::ios_base::binary); o.write((char*) &version, 1); - block->serialize(o, version, true); + block->serialize(o, version, true, compression_level); bool ret = db->saveBlock(p3d, o.str()); if (ret) { diff --git a/src/map.h b/src/map.h index 3bc30c482..c8bae9451 100644 --- a/src/map.h +++ b/src/map.h @@ -381,7 +381,7 @@ public: MapgenParams *getMapgenParams(); bool saveBlock(MapBlock *block); - static bool saveBlock(MapBlock *block, MapDatabase *db); + static bool saveBlock(MapBlock *block, MapDatabase *db, int compression_level = -1); MapBlock* loadBlock(v3s16 p); // Database version void loadBlock(std::string *blob, v3s16 p3d, MapSector *sector, bool save_after_load=false); @@ -416,6 +416,7 @@ private: std::string m_savedir; bool m_map_saving_enabled; + int m_map_compression_level; #if 0 // Chunk size in MapSectors // If 0, chunks are disabled. diff --git a/src/mapblock.cpp b/src/mapblock.cpp index 8bfecd755..0ca71e643 100644 --- a/src/mapblock.cpp +++ b/src/mapblock.cpp @@ -355,7 +355,7 @@ static void correctBlockNodeIds(const NameIdMapping *nimap, MapNode *nodes, } } -void MapBlock::serialize(std::ostream &os, u8 version, bool disk) +void MapBlock::serialize(std::ostream &os, u8 version, bool disk, int compression_level) { if(!ser_ver_supported(version)) throw VersionMismatchException("ERROR: MapBlock format not supported"); @@ -394,7 +394,7 @@ void MapBlock::serialize(std::ostream &os, u8 version, bool disk) writeU8(os, content_width); writeU8(os, params_width); MapNode::serializeBulk(os, version, tmp_nodes, nodecount, - content_width, params_width, true); + content_width, params_width, compression_level); delete[] tmp_nodes; } else @@ -404,7 +404,7 @@ void MapBlock::serialize(std::ostream &os, u8 version, bool disk) writeU8(os, content_width); writeU8(os, params_width); MapNode::serializeBulk(os, version, data, nodecount, - content_width, params_width, true); + content_width, params_width, compression_level); } /* @@ -412,7 +412,7 @@ void MapBlock::serialize(std::ostream &os, u8 version, bool disk) */ std::ostringstream oss(std::ios_base::binary); m_node_metadata.serialize(oss, version, disk); - compressZlib(oss.str(), os); + compressZlib(oss.str(), os, compression_level); /* Data that goes to disk, but not the network @@ -485,7 +485,7 @@ void MapBlock::deSerialize(std::istream &is, u8 version, bool disk) if(params_width != 2) throw SerializationError("MapBlock::deSerialize(): invalid params_width"); MapNode::deSerializeBulk(is, version, data, nodecount, - content_width, params_width, true); + content_width, params_width); /* NodeMetadata diff --git a/src/mapblock.h b/src/mapblock.h index 6b5015cab..641a1b69b 100644 --- a/src/mapblock.h +++ b/src/mapblock.h @@ -482,7 +482,7 @@ public: // These don't write or read version by itself // Set disk to true for on-disk format, false for over-the-network format // Precondition: version >= SER_FMT_VER_LOWEST_WRITE - void serialize(std::ostream &os, u8 version, bool disk); + void serialize(std::ostream &os, u8 version, bool disk, int compression_level); // If disk == true: In addition to doing other things, will add // unknown blocks from id-name mapping to wndef void deSerialize(std::istream &is, u8 version, bool disk); diff --git a/src/mapgen/mg_schematic.cpp b/src/mapgen/mg_schematic.cpp index dfd414709..e70e97e48 100644 --- a/src/mapgen/mg_schematic.cpp +++ b/src/mapgen/mg_schematic.cpp @@ -334,7 +334,7 @@ bool Schematic::deserializeFromMts(std::istream *is, schemdata = new MapNode[nodecount]; MapNode::deSerializeBulk(ss, SER_FMT_VER_HIGHEST_READ, schemdata, - nodecount, 2, 2, true); + nodecount, 2, 2); // Fix probability values for nodes that were ignore; removed in v2 if (version < 2) { @@ -376,7 +376,7 @@ bool Schematic::serializeToMts(std::ostream *os, // compressed bulk node data MapNode::serializeBulk(ss, SER_FMT_VER_HIGHEST_WRITE, - schemdata, size.X * size.Y * size.Z, 2, 2, true); + schemdata, size.X * size.Y * size.Z, 2, 2, -1); return true; } diff --git a/src/mapnode.cpp b/src/mapnode.cpp index dcf1f6d6e..0551f3b6f 100644 --- a/src/mapnode.cpp +++ b/src/mapnode.cpp @@ -706,7 +706,7 @@ void MapNode::deSerialize(u8 *source, u8 version) } void MapNode::serializeBulk(std::ostream &os, int version, const MapNode *nodes, u32 nodecount, - u8 content_width, u8 params_width, bool compressed) + u8 content_width, u8 params_width, int compression_level) { if (!ser_ver_supported(version)) throw VersionMismatchException("ERROR: MapNode format not supported"); @@ -737,10 +737,7 @@ void MapNode::serializeBulk(std::ostream &os, int version, Compress data to output stream */ - if (compressed) - compressZlib(databuf, databuf_size, os); - else - os.write((const char*) &databuf[0], databuf_size); + compressZlib(databuf, databuf_size, os, compression_level); delete [] databuf; } @@ -748,7 +745,7 @@ void MapNode::serializeBulk(std::ostream &os, int version, // Deserialize bulk node data void MapNode::deSerializeBulk(std::istream &is, int version, MapNode *nodes, u32 nodecount, - u8 content_width, u8 params_width, bool compressed) + u8 content_width, u8 params_width) { if(!ser_ver_supported(version)) throw VersionMismatchException("ERROR: MapNode format not supported"); @@ -760,24 +757,13 @@ void MapNode::deSerializeBulk(std::istream &is, int version, // Uncompress or read data u32 len = nodecount * (content_width + params_width); - SharedBuffer databuf(len); - if(compressed) - { - std::ostringstream os(std::ios_base::binary); - decompressZlib(is, os); - std::string s = os.str(); - if(s.size() != len) - throw SerializationError("deSerializeBulkNodes: " - "decompress resulted in invalid size"); - memcpy(&databuf[0], s.c_str(), len); - } - else - { - is.read((char*) &databuf[0], len); - if(is.eof() || is.fail()) - throw SerializationError("deSerializeBulkNodes: " - "failed to read bulk node data"); - } + std::ostringstream os(std::ios_base::binary); + decompressZlib(is, os); + std::string s = os.str(); + if(s.size() != len) + throw SerializationError("deSerializeBulkNodes: " + "decompress resulted in invalid size"); + const u8 *databuf = reinterpret_cast(s.c_str()); // Deserialize content if(content_width == 1) diff --git a/src/mapnode.h b/src/mapnode.h index 32ac1b4f6..a9ae63ba3 100644 --- a/src/mapnode.h +++ b/src/mapnode.h @@ -292,10 +292,10 @@ struct MapNode // compressed = true to zlib-compress output static void serializeBulk(std::ostream &os, int version, const MapNode *nodes, u32 nodecount, - u8 content_width, u8 params_width, bool compressed); + u8 content_width, u8 params_width, int compression_level); static void deSerializeBulk(std::istream &is, int version, MapNode *nodes, u32 nodecount, - u8 content_width, u8 params_width, bool compressed); + u8 content_width, u8 params_width); private: // Deprecated serialization methods diff --git a/src/server.cpp b/src/server.cpp index 8f6257afe..b5352749c 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -2332,9 +2332,9 @@ void Server::SendBlockNoLock(session_t peer_id, MapBlock *block, u8 ver, /* Create a packet with the block in the right format */ - + thread_local const int net_compression_level = rangelim(g_settings->getS16("map_compression_level_net"), -1, 9); std::ostringstream os(std::ios_base::binary); - block->serialize(os, ver, false); + block->serialize(os, ver, false, net_compression_level); block->serializeNetworkSpecific(os); std::string s = os.str(); From 6f8a1c99d5a30de0021c2c03bb5f79eb8281f868 Mon Sep 17 00:00:00 2001 From: DS Date: Fri, 18 Dec 2020 19:38:07 +0100 Subject: [PATCH 07/31] Documentation for highest formspec_version[] and changelog (#10592) --- doc/lua_api.txt | 17 +++++++++++++++++ src/network/networkprotocol.h | 17 +---------------- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/doc/lua_api.txt b/doc/lua_api.txt index ddb6d4e19..708d6b0bc 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -2113,6 +2113,22 @@ Examples list[current_player;main;0,3.5;8,4;] list[current_player;craft;3,0;3,3;] list[current_player;craftpreview;7,1;1,1;] + +Version History +--------------- + +* FORMSPEC VERSION 1: + * (too much) +* FORMSPEC VERSION 2: + * Forced real coordinates + * background9[]: 9-slice scaling parameters +* FORMSPEC VERSION 3: + * Formspec elements are drawn in the order of definition + * bgcolor[]: use 3 parameters (bgcolor, formspec (now an enum), fbgcolor) + * box[] and image[] elements enable clipping by default + * new element: scroll_container[] +* FORMSPEC VERSION 4: + * Allow dropdown indexing events Elements -------- @@ -2125,6 +2141,7 @@ Elements * Clients older than this version can neither show newer elements nor display elements with new arguments correctly. * Available since feature `formspec_version_element`. +* See also: [Version History] ### `size[,,]` diff --git a/src/network/networkprotocol.h b/src/network/networkprotocol.h index 666e75e45..838bf0b2c 100644 --- a/src/network/networkprotocol.h +++ b/src/network/networkprotocol.h @@ -226,22 +226,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #define PASSWORD_SIZE 28 // Maximum password length. Allows for // base64-encoded SHA-1 (27+\0). -/* - Changes by FORMSPEC_API_VERSION: - - FORMSPEC VERSION 1: - (too much) - FORMSPEC VERSION 2: - Forced real coordinates - background9[]: 9-slice scaling parameters - FORMSPEC VERSION 3: - Formspec elements are drawn in the order of definition - bgcolor[]: use 3 parameters (bgcolor, formspec (now an enum), fbgcolor) - box[] and image[] elements enable clipping by default - new element: scroll_container[] - FORMSPEC VERSION 4: - Allow dropdown indexing events -*/ +// See also: Formspec Version History in doc/lua_api.txt #define FORMSPEC_API_VERSION 4 #define TEXTURENAME_ALLOWED_CHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_.-" From d5a481b4e610768480b1f57470a4724baa479e4b Mon Sep 17 00:00:00 2001 From: LoneWolfHT Date: Fri, 18 Dec 2020 10:38:27 -0800 Subject: [PATCH 08/31] Make installer create its own Minetest folder (#10445) This changes the installer to create its own Minetest folder instead of having the user create it themselves. This prevents spewing the contents of Minetest everywhere when users change the install directory and expect the installer to create a folder to put it in --- CMakeLists.txt | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 31f548be7..78d551168 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -165,7 +165,7 @@ if(RUN_IN_PLACE) install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/textures/texture_packs_here.txt" DESTINATION "${SHAREDIR}/textures") endif() -install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/games/minetest_game" DESTINATION "${SHAREDIR}/games/" +install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/games/minetest_game" DESTINATION "${SHAREDIR}/games/" COMPONENT "SUBGAME_MINETEST_GAME" OPTIONAL PATTERN ".git*" EXCLUDE ) install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/games/devtest" DESTINATION "${SHAREDIR}/games/" COMPONENT "SUBGAME_MINIMAL" OPTIONAL PATTERN ".git*" EXCLUDE ) @@ -278,19 +278,20 @@ if(WIN32) set(CPACK_GENERATOR ZIP) else() - set(CPACK_GENERATOR WIX ZIP) + set(CPACK_GENERATOR WIX) set(CPACK_PACKAGE_NAME "${PROJECT_NAME_CAPITALIZED}") - set(CPACK_PACKAGE_INSTALL_DIRECTORY "${PROJECT_NAME_CAPITALIZED}") + set(CPACK_PACKAGE_INSTALL_DIRECTORY ".") set(CPACK_PACKAGE_EXECUTABLES ${PROJECT_NAME} "${PROJECT_NAME_CAPITALIZED}") set(CPACK_CREATE_DESKTOP_LINKS ${PROJECT_NAME}) + set(CPACK_PACKAGING_INSTALL_PREFIX "/${PROJECT_NAME_CAPITALIZED}") set(CPACK_WIX_PRODUCT_ICON "${CMAKE_CURRENT_SOURCE_DIR}/misc/minetest-icon.ico") - # Supported languages can be found at + # Supported languages can be found at # http://wixtoolset.org/documentation/manual/v3/wixui/wixui_localization.html #set(CPACK_WIX_CULTURES "ar-SA,bg-BG,ca-ES,hr-HR,cs-CZ,da-DK,nl-NL,en-US,et-EE,fi-FI,fr-FR,de-DE") set(CPACK_WIX_UI_BANNER "${CMAKE_CURRENT_SOURCE_DIR}/misc/CPACK_WIX_UI_BANNER.BMP") set(CPACK_WIX_UI_DIALOG "${CMAKE_CURRENT_SOURCE_DIR}/misc/CPACK_WIX_UI_DIALOG.BMP") - + set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/doc/lgpl-2.1.txt") # The correct way would be to include both x32 and x64 into one installer From 025035db5c87e9eaa9f83859f860539fc4fb4dc0 Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Fri, 18 Dec 2020 19:38:39 +0100 Subject: [PATCH 09/31] DevTest: Add food item to test food replacement (#10642) --- games/devtest/mods/testfood/init.lua | 7 +++++++ .../mods/testfood/textures/testfood_replace.png | Bin 0 -> 135 bytes 2 files changed, 7 insertions(+) create mode 100644 games/devtest/mods/testfood/textures/testfood_replace.png diff --git a/games/devtest/mods/testfood/init.lua b/games/devtest/mods/testfood/init.lua index a6236ff68..39b121306 100644 --- a/games/devtest/mods/testfood/init.lua +++ b/games/devtest/mods/testfood/init.lua @@ -22,3 +22,10 @@ minetest.register_craftitem("testfood:bad5", { on_use = minetest.item_eat(-5), }) +minetest.register_craftitem("testfood:replace1", { + description = S("Replacing Food (+1)").."\n".. + S("Replaced with 'Good Food (+1)' when eaten"), + inventory_image = "testfood_replace.png", + on_use = minetest.item_eat(1, "testfood:good1"), +}) + diff --git a/games/devtest/mods/testfood/textures/testfood_replace.png b/games/devtest/mods/testfood/textures/testfood_replace.png new file mode 100644 index 0000000000000000000000000000000000000000..1ef6876e5bbf794803a9282601a1836def754849 GIT binary patch literal 135 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`ex5FlAr*|t5;Gsz%PelRulP_e z67yMpwPL-4&;FG+o!SS~|M{*mZpZEf)hIr*f@dT^6ZjBwh h!bOagoEa6246|yNc^<#LY(LOs22WQ%mvv4FO#sNwDZu~$ literal 0 HcmV?d00001 From 664f5ce9605b580b9500547fff1e54eac553f295 Mon Sep 17 00:00:00 2001 From: rubenwardy Date: Sat, 19 Dec 2020 13:27:15 +0000 Subject: [PATCH 10/31] Add open user data button to main menu (#10579) --- .../net/minetest/minetest/GameActivity.java | 4 +-- builtin/mainmenu/tab_credits.lua | 20 +++++++++-- doc/menu_lua_api.txt | 7 ++++ src/porting.cpp | 35 ++++++++++++++----- src/porting.h | 20 ++++++++++- src/porting_android.cpp | 6 ++-- src/porting_android.h | 2 +- src/script/lua_api/l_mainmenu.cpp | 21 ++++++++++- src/script/lua_api/l_mainmenu.h | 4 +++ 9 files changed, 100 insertions(+), 19 deletions(-) diff --git a/build/android/app/src/main/java/net/minetest/minetest/GameActivity.java b/build/android/app/src/main/java/net/minetest/minetest/GameActivity.java index db126a2b9..38a388230 100644 --- a/build/android/app/src/main/java/net/minetest/minetest/GameActivity.java +++ b/build/android/app/src/main/java/net/minetest/minetest/GameActivity.java @@ -142,8 +142,8 @@ public class GameActivity extends NativeActivity { return getResources().getDisplayMetrics().widthPixels; } - public void openURL(String url) { - Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); + public void openURI(String uri) { + Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(uri)); startActivity(browserIntent); } } diff --git a/builtin/mainmenu/tab_credits.lua b/builtin/mainmenu/tab_credits.lua index c2b7e503a..075274798 100644 --- a/builtin/mainmenu/tab_credits.lua +++ b/builtin/mainmenu/tab_credits.lua @@ -100,9 +100,10 @@ return { cbf_formspec = function(tabview, name, tabdata) local logofile = defaulttexturedir .. "logo.png" local version = core.get_version() - return "image[0.5,1;" .. core.formspec_escape(logofile) .. "]" .. - "label[0.5,2.8;" .. version.project .. " " .. version.string .. "]" .. - "button[0.5,3;2,2;homepage;minetest.net]" .. + local fs = "image[0.75,0.5;2.2,2.2;" .. core.formspec_escape(logofile) .. "]" .. + "style[label_button;border=false]" .. + "button[0.5,2;2.5,2;label_button;" .. version.project .. " " .. version.string .. "]" .. + "button[0.75,2.75;2,2;homepage;minetest.net]" .. "tablecolumns[color;text]" .. "tableoptions[background=#00000000;highlight=#00000000;border=false]" .. "table[3.5,-0.25;8.5,6.05;list_credits;" .. @@ -115,10 +116,23 @@ return { "#FFFF00," .. fgettext("Previous Contributors") .. ",," .. buildCreditList(previous_contributors) .. "," .. ";1]" + + if PLATFORM ~= "Android" then + fs = fs .. "tooltip[userdata;" .. + fgettext("Opens the directory that contains user-provided worlds, games, mods,\n" .. + "and texture packs in a file manager / explorer.") .. "]" + fs = fs .. "button[0,4.75;3.5,1;userdata;" .. fgettext("Open User Data Directory") .. "]" + end + + return fs end, cbf_button_handler = function(this, fields, name, tabdata) if fields.homepage then core.open_url("https://www.minetest.net") end + + if fields.userdata then + core.open_dir(core.get_user_path()) + end end, } diff --git a/doc/menu_lua_api.txt b/doc/menu_lua_api.txt index 76bebe08b..8908552d5 100644 --- a/doc/menu_lua_api.txt +++ b/doc/menu_lua_api.txt @@ -43,10 +43,14 @@ core.get_max_supp_proto() core.open_url(url) ^ opens the URL in a web browser, returns false on failure. ^ Must begin with http:// or https:// +core.open_dir(path) +^ opens the path in the system file browser/explorer, returns false on failure. +^ Must be an existing directory. core.get_version() (possible in async calls) ^ returns current core version + Filesystem ---------- @@ -207,6 +211,9 @@ Content and Packages Content - an installed mod, modpack, game, or texture pack (txt) Package - content which is downloadable from the content db, may or may not be installed. +* core.get_user_path() (possible in async calls) + * returns path to global user data, + the directory that contains user-provided mods, worlds, games, and texture packs. * core.get_modpath() (possible in async calls) * returns path to global modpath * core.get_clientmodpath() (possible in async calls) diff --git a/src/porting.cpp b/src/porting.cpp index e7ed4e090..4c87bddee 100644 --- a/src/porting.cpp +++ b/src/porting.cpp @@ -719,29 +719,48 @@ int mt_snprintf(char *buf, const size_t buf_size, const char *fmt, ...) return c; } -bool openURL(const std::string &url) +static bool open_uri(const std::string &uri) { - if ((url.substr(0, 7) != "http://" && url.substr(0, 8) != "https://") || - url.find_first_of("\r\n") != std::string::npos) { - errorstream << "Invalid url: " << url << std::endl; + if (uri.find_first_of("\r\n") != std::string::npos) { + errorstream << "Unable to open URI as it is invalid, contains new line: " << uri << std::endl; return false; } #if defined(_WIN32) - return (intptr_t)ShellExecuteA(NULL, NULL, url.c_str(), NULL, NULL, SW_SHOWNORMAL) > 32; + return (intptr_t)ShellExecuteA(NULL, NULL, uri.c_str(), NULL, NULL, SW_SHOWNORMAL) > 32; #elif defined(__ANDROID__) - openURLAndroid(url); + openURIAndroid(uri); return true; #elif defined(__APPLE__) - const char *argv[] = {"open", url.c_str(), NULL}; + const char *argv[] = {"open", uri.c_str(), NULL}; return posix_spawnp(NULL, "open", NULL, NULL, (char**)argv, (*_NSGetEnviron())) == 0; #else - const char *argv[] = {"xdg-open", url.c_str(), NULL}; + const char *argv[] = {"xdg-open", uri.c_str(), NULL}; return posix_spawnp(NULL, "xdg-open", NULL, NULL, (char**)argv, environ) == 0; #endif } +bool open_url(const std::string &url) +{ + if (url.substr(0, 7) != "http://" && url.substr(0, 8) != "https://") { + errorstream << "Unable to open browser as URL is missing schema: " << url << std::endl; + return false; + } + + return open_uri(url); +} + +bool open_directory(const std::string &path) +{ + if (!fs::IsDir(path)) { + errorstream << "Unable to open directory as it does not exist: " << path << std::endl; + return false; + } + + return open_uri(path); +} + // Load performance counter frequency only once at startup #ifdef _WIN32 diff --git a/src/porting.h b/src/porting.h index c7adf12a2..e4ebe36fd 100644 --- a/src/porting.h +++ b/src/porting.h @@ -332,7 +332,25 @@ void attachOrCreateConsole(); int mt_snprintf(char *buf, const size_t buf_size, const char *fmt, ...); -bool openURL(const std::string &url); +/** + * Opens URL in default web browser + * + * Must begin with http:// or https://, and not contain any new lines + * + * @param url The URL + * @return true on success, false on failure + */ +bool open_url(const std::string &url); + +/** + * Opens a directory in the default file manager + * + * The directory must exist. + * + * @param path Path to directory + * @return true on success, false on failure + */ +bool open_directory(const std::string &path); } // namespace porting diff --git a/src/porting_android.cpp b/src/porting_android.cpp index 41b521ec2..f5870c174 100644 --- a/src/porting_android.cpp +++ b/src/porting_android.cpp @@ -213,13 +213,13 @@ void showInputDialog(const std::string &acceptButton, const std::string &hint, jacceptButton, jhint, jcurrent, jeditType); } -void openURLAndroid(const std::string &url) +void openURIAndroid(const std::string &url) { - jmethodID url_open = jnienv->GetMethodID(nativeActivity, "openURL", + jmethodID url_open = jnienv->GetMethodID(nativeActivity, "openURI", "(Ljava/lang/String;)V"); FATAL_ERROR_IF(url_open == nullptr, - "porting::openURLAndroid unable to find java openURL method"); + "porting::openURIAndroid unable to find java openURI method"); jstring jurl = jnienv->NewStringUTF(url.c_str()); jnienv->CallVoidMethod(app_global->activity->clazz, url_open, jurl); diff --git a/src/porting_android.h b/src/porting_android.h index 6eb054041..239815922 100644 --- a/src/porting_android.h +++ b/src/porting_android.h @@ -58,7 +58,7 @@ void initializePathsAndroid(); void showInputDialog(const std::string &acceptButton, const std::string &hint, const std::string ¤t, int editType); -void openURLAndroid(const std::string &url); +void openURIAndroid(const std::string &url); /** * WORKAROUND for not working callbacks from java -> c++ diff --git a/src/script/lua_api/l_mainmenu.cpp b/src/script/lua_api/l_mainmenu.cpp index 0aa2760e9..0b0b2de3b 100644 --- a/src/script/lua_api/l_mainmenu.cpp +++ b/src/script/lua_api/l_mainmenu.cpp @@ -686,6 +686,14 @@ int ModApiMainMenu::l_get_mapgen_names(lua_State *L) } +/******************************************************************************/ +int ModApiMainMenu::l_get_user_path(lua_State *L) +{ + std::string path = fs::RemoveRelativePathComponents(porting::path_user); + lua_pushstring(L, path.c_str()); + return 1; +} + /******************************************************************************/ int ModApiMainMenu::l_get_modpath(lua_State *L) { @@ -1067,7 +1075,15 @@ int ModApiMainMenu::l_get_max_supp_proto(lua_State *L) int ModApiMainMenu::l_open_url(lua_State *L) { std::string url = luaL_checkstring(L, 1); - lua_pushboolean(L, porting::openURL(url)); + lua_pushboolean(L, porting::open_url(url)); + return 1; +} + +/******************************************************************************/ +int ModApiMainMenu::l_open_dir(lua_State *L) +{ + std::string path = luaL_checkstring(L, 1); + lua_pushboolean(L, porting::open_directory(path)); return 1; } @@ -1113,6 +1129,7 @@ void ModApiMainMenu::Initialize(lua_State *L, int top) API_FCT(set_background); API_FCT(set_topleft_text); API_FCT(get_mapgen_names); + API_FCT(get_user_path); API_FCT(get_modpath); API_FCT(get_clientmodpath); API_FCT(get_gamepath); @@ -1134,6 +1151,7 @@ void ModApiMainMenu::Initialize(lua_State *L, int top) API_FCT(get_min_supp_proto); API_FCT(get_max_supp_proto); API_FCT(open_url); + API_FCT(open_dir); API_FCT(do_async_callback); } @@ -1144,6 +1162,7 @@ void ModApiMainMenu::InitializeAsync(lua_State *L, int top) API_FCT(get_games); API_FCT(get_favorites); API_FCT(get_mapgen_names); + API_FCT(get_user_path); API_FCT(get_modpath); API_FCT(get_clientmodpath); API_FCT(get_gamepath); diff --git a/src/script/lua_api/l_mainmenu.h b/src/script/lua_api/l_mainmenu.h index 5a16b3bfe..faa2bf273 100644 --- a/src/script/lua_api/l_mainmenu.h +++ b/src/script/lua_api/l_mainmenu.h @@ -112,6 +112,8 @@ private: static int l_get_mainmenu_path(lua_State *L); + static int l_get_user_path(lua_State *L); + static int l_get_modpath(lua_State *L); static int l_get_clientmodpath(lua_State *L); @@ -148,6 +150,8 @@ private: // other static int l_open_url(lua_State *L); + static int l_open_dir(lua_State *L); + // async static int l_do_async_callback(lua_State *L); From ccbf8029ea6bfc5bb5d4af340bd4c2c0d58fe0ff Mon Sep 17 00:00:00 2001 From: Vitaliy Date: Sat, 19 Dec 2020 22:57:10 +0300 Subject: [PATCH 11/31] Cleanup shader generation code (#10663) Shader generation is a mess. This commit cleans some parts up, including dropping remains of HLSL support which was never actually implemented. --- .../shaders/nodes_shader/opengl_fragment.glsl | 4 +- .../object_shader/opengl_fragment.glsl | 4 +- src/client/clientenvironment.cpp | 6 +- src/client/game.cpp | 6 +- src/client/hud.cpp | 2 +- src/client/minimap.cpp | 2 +- src/client/render/interlaced.cpp | 2 +- src/client/shader.cpp | 479 +++++------------- src/client/shader.h | 21 +- src/client/sky.cpp | 2 +- src/nodedef.cpp | 6 +- 11 files changed, 157 insertions(+), 377 deletions(-) diff --git a/client/shaders/nodes_shader/opengl_fragment.glsl b/client/shaders/nodes_shader/opengl_fragment.glsl index b0f6d45d0..b5d85da64 100644 --- a/client/shaders/nodes_shader/opengl_fragment.glsl +++ b/client/shaders/nodes_shader/opengl_fragment.glsl @@ -22,7 +22,7 @@ varying vec3 eyeVec; const float fogStart = FOG_START; const float fogShadingParameter = 1.0 / ( 1.0 - fogStart); -#ifdef ENABLE_TONE_MAPPING +#if ENABLE_TONE_MAPPING /* Hable's UC2 Tone mapping parameters A = 0.22; @@ -73,7 +73,7 @@ void main(void) vec4 col = vec4(color.rgb * varColor.rgb, 1.0); -#ifdef ENABLE_TONE_MAPPING +#if ENABLE_TONE_MAPPING col = applyToneMapping(col); #endif diff --git a/client/shaders/object_shader/opengl_fragment.glsl b/client/shaders/object_shader/opengl_fragment.glsl index bf18c1499..12cc54ae7 100644 --- a/client/shaders/object_shader/opengl_fragment.glsl +++ b/client/shaders/object_shader/opengl_fragment.glsl @@ -19,7 +19,7 @@ const float BS = 10.0; const float fogStart = FOG_START; const float fogShadingParameter = 1.0 / (1.0 - fogStart); -#ifdef ENABLE_TONE_MAPPING +#if ENABLE_TONE_MAPPING /* Hable's UC2 Tone mapping parameters A = 0.22; @@ -75,7 +75,7 @@ void main(void) col.rgb *= emissiveColor.rgb * vIDiff; -#ifdef ENABLE_TONE_MAPPING +#if ENABLE_TONE_MAPPING col = applyToneMapping(col); #endif diff --git a/src/client/clientenvironment.cpp b/src/client/clientenvironment.cpp index ea7be4200..da1e6e9c7 100644 --- a/src/client/clientenvironment.cpp +++ b/src/client/clientenvironment.cpp @@ -51,12 +51,8 @@ public: ~CAOShaderConstantSetter() override = default; - void onSetConstants(video::IMaterialRendererServices *services, - bool is_highlevel) override + void onSetConstants(video::IMaterialRendererServices *services) override { - if (!is_highlevel) - return; - // Ambient color video::SColorf emissive_color(m_emissive_color); diff --git a/src/client/game.cpp b/src/client/game.cpp index 575fd46ff..fd4d09394 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -475,12 +475,8 @@ public: g_settings->deregisterChangedCallback("enable_fog", settingsCallback, this); } - virtual void onSetConstants(video::IMaterialRendererServices *services, - bool is_highlevel) + void onSetConstants(video::IMaterialRendererServices *services) override { - if (!is_highlevel) - return; - // Background color video::SColor bgcolor = m_sky->getBgColor(); video::SColorf bgcolorf(bgcolor); diff --git a/src/client/hud.cpp b/src/client/hud.cpp index f6497fe25..8d8411ca1 100644 --- a/src/client/hud.cpp +++ b/src/client/hud.cpp @@ -100,7 +100,7 @@ Hud::Hud(gui::IGUIEnvironment *guienv, Client *client, LocalPlayer *player, if (g_settings->getBool("enable_shaders")) { IShaderSource *shdrsrc = client->getShaderSource(); u16 shader_id = shdrsrc->getShader( - m_mode == HIGHLIGHT_HALO ? "selection_shader" : "default_shader", 1, 1); + m_mode == HIGHLIGHT_HALO ? "selection_shader" : "default_shader", TILE_MATERIAL_ALPHA); m_selection_material.MaterialType = shdrsrc->getShaderInfo(shader_id).material; } else { m_selection_material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; diff --git a/src/client/minimap.cpp b/src/client/minimap.cpp index d068ad5f7..c6ccf86e8 100644 --- a/src/client/minimap.cpp +++ b/src/client/minimap.cpp @@ -612,7 +612,7 @@ void Minimap::drawMinimap(core::rect rect) { material.TextureLayer[1].Texture = data->heightmap_texture; if (m_enable_shaders && data->mode.type == MINIMAP_TYPE_SURFACE) { - u16 sid = m_shdrsrc->getShader("minimap_shader", 1, 1); + u16 sid = m_shdrsrc->getShader("minimap_shader", TILE_MATERIAL_ALPHA); material.MaterialType = m_shdrsrc->getShaderInfo(sid).material; } else { material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; diff --git a/src/client/render/interlaced.cpp b/src/client/render/interlaced.cpp index 2aadadc17..ce8e92f21 100644 --- a/src/client/render/interlaced.cpp +++ b/src/client/render/interlaced.cpp @@ -36,7 +36,7 @@ void RenderingCoreInterlaced::initMaterial() mat.UseMipMaps = false; mat.ZBuffer = false; mat.ZWriteEnable = false; - u32 shader = s->getShader("3d_interlaced_merge", TILE_MATERIAL_BASIC, 0); + u32 shader = s->getShader("3d_interlaced_merge", TILE_MATERIAL_BASIC); mat.MaterialType = s->getShaderInfo(shader).material; for (int k = 0; k < 3; ++k) { mat.TextureLayer[k].AnisotropicFilter = false; diff --git a/src/client/shader.cpp b/src/client/shader.cpp index 1cec20d2c..b3e4911f4 100644 --- a/src/client/shader.cpp +++ b/src/client/shader.cpp @@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include "shader.h" #include "irrlichttypes_extrabloated.h" +#include "irr_ptr.h" #include "debug.h" #include "filesys.h" #include "util/container.h" @@ -189,19 +190,14 @@ private: class ShaderCallback : public video::IShaderConstantSetCallBack { - std::vector m_setters; + std::vector> m_setters; public: - ShaderCallback(const std::vector &factories) + template + ShaderCallback(const Factories &factories) { - for (IShaderConstantSetterFactory *factory : factories) - m_setters.push_back(factory->create()); - } - - ~ShaderCallback() - { - for (IShaderConstantSetter *setter : m_setters) - delete setter; + for (auto &&factory : factories) + m_setters.push_back(std::unique_ptr(factory->create())); } virtual void OnSetConstants(video::IMaterialRendererServices *services, s32 userData) override @@ -209,15 +205,13 @@ public: video::IVideoDriver *driver = services->getVideoDriver(); sanity_check(driver != NULL); - bool is_highlevel = userData; - - for (IShaderConstantSetter *setter : m_setters) - setter->onSetConstants(services, is_highlevel); + for (auto &&setter : m_setters) + setter->onSetConstants(services); } virtual void OnSetMaterial(const video::SMaterial& material) override { - for (IShaderConstantSetter *setter : m_setters) + for (auto &&setter : m_setters) setter->onSetMaterial(material); } }; @@ -252,47 +246,39 @@ public: {} ~MainShaderConstantSetter() = default; - virtual void onSetConstants(video::IMaterialRendererServices *services, - bool is_highlevel) + virtual void onSetConstants(video::IMaterialRendererServices *services) override { video::IVideoDriver *driver = services->getVideoDriver(); sanity_check(driver); // Set world matrix core::matrix4 world = driver->getTransform(video::ETS_WORLD); - if (is_highlevel) - m_world.set(*reinterpret_cast(world.pointer()), services); - else - services->setVertexShaderConstant(world.pointer(), 4, 4); + m_world.set(*reinterpret_cast(world.pointer()), services); // Set clip matrix core::matrix4 worldView; worldView = driver->getTransform(video::ETS_VIEW); worldView *= world; + core::matrix4 worldViewProj; worldViewProj = driver->getTransform(video::ETS_PROJECTION); worldViewProj *= worldView; - if (is_highlevel) - m_world_view_proj.set(*reinterpret_cast(worldViewProj.pointer()), services); - else - services->setVertexShaderConstant(worldViewProj.pointer(), 0, 4); + m_world_view_proj.set(*reinterpret_cast(worldViewProj.pointer()), services); #if ENABLE_GLES - if (is_highlevel) { - core::matrix4 texture = driver->getTransform(video::ETS_TEXTURE_0); - m_world_view.set(*reinterpret_cast(worldView.pointer()), services); - m_texture.set(*reinterpret_cast(texture.pointer()), services); + core::matrix4 texture = driver->getTransform(video::ETS_TEXTURE_0); + m_world_view.set(*reinterpret_cast(worldView.pointer()), services); + m_texture.set(*reinterpret_cast(texture.pointer()), services); - core::matrix4 normal; - worldView.getTransposed(normal); - sanity_check(normal.makeInverse()); - float m[9] = { - normal[0], normal[1], normal[2], - normal[4], normal[5], normal[6], - normal[8], normal[9], normal[10], - }; - m_normal.set(m, services); - } + core::matrix4 normal; + worldView.getTransposed(normal); + sanity_check(normal.makeInverse()); + float m[9] = { + normal[0], normal[1], normal[2], + normal[4], normal[5], normal[6], + normal[8], normal[9], normal[10], + }; + m_normal.set(m, services); #endif } }; @@ -314,7 +300,6 @@ class ShaderSource : public IWritableShaderSource { public: ShaderSource(); - ~ShaderSource(); /* - If shader material specified by name is found from cache, @@ -324,7 +309,7 @@ public: The id 0 points to a null shader. Its material is EMT_SOLID. */ u32 getShaderIdDirect(const std::string &name, - const u8 material_type, const u8 drawtype); + MaterialType material_type, NodeDrawType drawtype) override; /* If shader specified by the name pointed by the id doesn't @@ -336,26 +321,26 @@ public: */ u32 getShader(const std::string &name, - const u8 material_type, const u8 drawtype); + MaterialType material_type, NodeDrawType drawtype) override; - ShaderInfo getShaderInfo(u32 id); + ShaderInfo getShaderInfo(u32 id) override; // Processes queued shader requests from other threads. // Shall be called from the main thread. - void processQueue(); + void processQueue() override; // Insert a shader program into the cache without touching the // filesystem. Shall be called from the main thread. void insertSourceShader(const std::string &name_of_shader, - const std::string &filename, const std::string &program); + const std::string &filename, const std::string &program) override; // Rebuild shaders from the current set of source shaders // Shall be called from the main thread. - void rebuildShaders(); + void rebuildShaders() override; - void addShaderConstantSetterFactory(IShaderConstantSetterFactory *setter) + void addShaderConstantSetterFactory(IShaderConstantSetterFactory *setter) override { - m_setter_factories.push_back(setter); + m_setter_factories.push_back(std::unique_ptr(setter)); } private: @@ -377,10 +362,11 @@ private: RequestQueue m_get_shader_queue; // Global constant setter factories - std::vector m_setter_factories; + std::vector> m_setter_factories; - // Shader callbacks - std::vector m_callbacks; + // Generate shader given the shader name. + ShaderInfo generateShader(const std::string &name, + MaterialType material_type, NodeDrawType drawtype); }; IWritableShaderSource *createShaderSource() @@ -388,22 +374,6 @@ IWritableShaderSource *createShaderSource() return new ShaderSource(); } -/* - Generate shader given the shader name. -*/ -ShaderInfo generate_shader(const std::string &name, - u8 material_type, u8 drawtype, std::vector &callbacks, - const std::vector &setter_factories, - SourceShaderCache *sourcecache); - -/* - Load shader programs -*/ -void load_shaders(const std::string &name, SourceShaderCache *sourcecache, - video::E_DRIVER_TYPE drivertype, bool enable_shaders, - std::string &vertex_program, std::string &pixel_program, - std::string &geometry_program, bool &is_highlevel); - ShaderSource::ShaderSource() { m_main_thread = std::this_thread::get_id(); @@ -415,18 +385,8 @@ ShaderSource::ShaderSource() addShaderConstantSetterFactory(new MainShaderConstantSetterFactory()); } -ShaderSource::~ShaderSource() -{ - for (ShaderCallback *callback : m_callbacks) { - delete callback; - } - for (IShaderConstantSetterFactory *setter_factorie : m_setter_factories) { - delete setter_factorie; - } -} - u32 ShaderSource::getShader(const std::string &name, - const u8 material_type, const u8 drawtype) + MaterialType material_type, NodeDrawType drawtype) { /* Get shader @@ -468,7 +428,7 @@ u32 ShaderSource::getShader(const std::string &name, This method generates all the shaders */ u32 ShaderSource::getShaderIdDirect(const std::string &name, - const u8 material_type, const u8 drawtype) + MaterialType material_type, NodeDrawType drawtype) { //infostream<<"getShaderIdDirect(): name=\""<name.empty()) { - *info = generate_shader(info->name, info->material_type, - info->drawtype, m_callbacks, - m_setter_factories, &m_sourcecache); + *info = generateShader(info->name, info->material_type, info->drawtype); } } } -ShaderInfo generate_shader(const std::string &name, u8 material_type, u8 drawtype, - std::vector &callbacks, - const std::vector &setter_factories, - SourceShaderCache *sourcecache) +ShaderInfo ShaderSource::generateShader(const std::string &name, + MaterialType material_type, NodeDrawType drawtype) { ShaderInfo shaderinfo; shaderinfo.name = name; @@ -604,64 +559,27 @@ ShaderInfo generate_shader(const std::string &name, u8 material_type, u8 drawtyp return shaderinfo; video::IVideoDriver *driver = RenderingEngine::get_video_driver(); - + if (!driver->queryFeature(video::EVDF_ARB_GLSL)) { + errorstream << "Shaders are enabled but GLSL is not supported by the driver\n"; + return shaderinfo; + } video::IGPUProgrammingServices *gpu = driver->getGPUProgrammingServices(); - if(!gpu){ - errorstream<<"generate_shader(): " - "failed to generate \""<getDriverType(), - enable_shaders, vertex_program, pixel_program, - geometry_program, is_highlevel); - // Check hardware/driver support - if (!vertex_program.empty() && - !driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1) && - !driver->queryFeature(video::EVDF_ARB_VERTEX_PROGRAM_1)){ - infostream<<"generate_shader(): vertex shaders disabled " - "because of missing driver/hardware support." - <queryFeature(video::EVDF_PIXEL_SHADER_1_1) && - !driver->queryFeature(video::EVDF_ARB_FRAGMENT_PROGRAM_1)){ - infostream<<"generate_shader(): pixel shaders disabled " - "because of missing driver/hardware support." - <queryFeature(video::EVDF_GEOMETRY_SHADER)){ - infostream<<"generate_shader(): geometry shaders disabled " - "because of missing driver/hardware support." - <getDriverType() == video::EDT_OGLES2; #endif - std::string shaders_header, vertex_header, pixel_header; // geometry shaders aren’t supported in GLES<3 + std::stringstream shaders_header; + shaders_header + << std::noboolalpha + << std::showpoint // for GLSL ES + ; + std::string vertex_header, fragment_header, geometry_header; if (use_gles) { - shaders_header = - "#version 100\n" - ; + shaders_header << R"( + #version 100 + )"; vertex_header = R"( uniform highp mat4 mWorldView; uniform highp mat4 mWorldViewProj; @@ -675,11 +593,11 @@ ShaderInfo generate_shader(const std::string &name, u8 material_type, u8 drawtyp attribute mediump vec4 inVertexTangent; attribute mediump vec4 inVertexBinormal; )"; - pixel_header = R"( + fragment_header = R"( precision mediump float; )"; } else { - shaders_header = R"( + shaders_header << R"( #version 120 #define lowp #define mediump @@ -708,224 +626,97 @@ ShaderInfo generate_shader(const std::string &name, u8 material_type, u8 drawtyp use_discard = true; #endif if (use_discard && shaderinfo.base_material != video::EMT_SOLID) - shaders_header += "#define USE_DISCARD\n"; + shaders_header << "#define USE_DISCARD 1\n"; - static const char* drawTypes[] = { - "NDT_NORMAL", - "NDT_AIRLIKE", - "NDT_LIQUID", - "NDT_FLOWINGLIQUID", - "NDT_GLASSLIKE", - "NDT_ALLFACES", - "NDT_ALLFACES_OPTIONAL", - "NDT_TORCHLIKE", - "NDT_SIGNLIKE", - "NDT_PLANTLIKE", - "NDT_FENCELIKE", - "NDT_RAILLIKE", - "NDT_NODEBOX", - "NDT_GLASSLIKE_FRAMED", - "NDT_FIRELIKE", - "NDT_GLASSLIKE_FRAMED_OPTIONAL", - "NDT_PLANTLIKE_ROOTED", - }; +#define PROVIDE(constant) shaders_header << "#define " #constant " " << (int)constant << "\n" - for (int i = 0; i < 14; i++){ - shaders_header += "#define "; - shaders_header += drawTypes[i]; - shaders_header += " "; - shaders_header += itos(i); - shaders_header += "\n"; + PROVIDE(NDT_NORMAL); + PROVIDE(NDT_AIRLIKE); + PROVIDE(NDT_LIQUID); + PROVIDE(NDT_FLOWINGLIQUID); + PROVIDE(NDT_GLASSLIKE); + PROVIDE(NDT_ALLFACES); + PROVIDE(NDT_ALLFACES_OPTIONAL); + PROVIDE(NDT_TORCHLIKE); + PROVIDE(NDT_SIGNLIKE); + PROVIDE(NDT_PLANTLIKE); + PROVIDE(NDT_FENCELIKE); + PROVIDE(NDT_RAILLIKE); + PROVIDE(NDT_NODEBOX); + PROVIDE(NDT_GLASSLIKE_FRAMED); + PROVIDE(NDT_FIRELIKE); + PROVIDE(NDT_GLASSLIKE_FRAMED_OPTIONAL); + PROVIDE(NDT_PLANTLIKE_ROOTED); + + PROVIDE(TILE_MATERIAL_BASIC); + PROVIDE(TILE_MATERIAL_ALPHA); + PROVIDE(TILE_MATERIAL_LIQUID_TRANSPARENT); + PROVIDE(TILE_MATERIAL_LIQUID_OPAQUE); + PROVIDE(TILE_MATERIAL_WAVING_LEAVES); + PROVIDE(TILE_MATERIAL_WAVING_PLANTS); + PROVIDE(TILE_MATERIAL_OPAQUE); + PROVIDE(TILE_MATERIAL_WAVING_LIQUID_BASIC); + PROVIDE(TILE_MATERIAL_WAVING_LIQUID_TRANSPARENT); + PROVIDE(TILE_MATERIAL_WAVING_LIQUID_OPAQUE); + PROVIDE(TILE_MATERIAL_PLAIN); + PROVIDE(TILE_MATERIAL_PLAIN_ALPHA); + +#undef PROVIDE + + shaders_header << "#define MATERIAL_TYPE " << (int)material_type << "\n"; + shaders_header << "#define DRAW_TYPE " << (int)drawtype << "\n"; + + bool enable_waving_water = g_settings->getBool("enable_waving_water"); + shaders_header << "#define ENABLE_WAVING_WATER " << enable_waving_water << "\n"; + if (enable_waving_water) { + shaders_header << "#define WATER_WAVE_HEIGHT " << g_settings->getFloat("water_wave_height") << "\n"; + shaders_header << "#define WATER_WAVE_LENGTH " << g_settings->getFloat("water_wave_length") << "\n"; + shaders_header << "#define WATER_WAVE_SPEED " << g_settings->getFloat("water_wave_speed") << "\n"; } - static const char* materialTypes[] = { - "TILE_MATERIAL_BASIC", - "TILE_MATERIAL_ALPHA", - "TILE_MATERIAL_LIQUID_TRANSPARENT", - "TILE_MATERIAL_LIQUID_OPAQUE", - "TILE_MATERIAL_WAVING_LEAVES", - "TILE_MATERIAL_WAVING_PLANTS", - "TILE_MATERIAL_OPAQUE", - "TILE_MATERIAL_WAVING_LIQUID_BASIC", - "TILE_MATERIAL_WAVING_LIQUID_TRANSPARENT", - "TILE_MATERIAL_WAVING_LIQUID_OPAQUE", - "TILE_MATERIAL_PLAIN", - "TILE_MATERIAL_PLAIN_ALPHA", - }; + shaders_header << "#define ENABLE_WAVING_LEAVES " << g_settings->getBool("enable_waving_leaves") << "\n"; + shaders_header << "#define ENABLE_WAVING_PLANTS " << g_settings->getBool("enable_waving_plants") << "\n"; + shaders_header << "#define ENABLE_TONE_MAPPING " << g_settings->getBool("tone_mapping") << "\n"; - for (int i = 0; i < 12; i++){ - shaders_header += "#define "; - shaders_header += materialTypes[i]; - shaders_header += " "; - shaders_header += itos(i); - shaders_header += "\n"; + shaders_header << "#define FOG_START " << core::clamp(g_settings->getFloat("fog_start"), 0.0f, 0.99f) << "\n"; + + std::string common_header = shaders_header.str(); + + std::string vertex_shader = m_sourcecache.getOrLoad(name, "opengl_vertex.glsl"); + std::string fragment_shader = m_sourcecache.getOrLoad(name, "opengl_fragment.glsl"); + std::string geometry_shader = m_sourcecache.getOrLoad(name, "opengl_geometry.glsl"); + + vertex_shader = common_header + vertex_header + vertex_shader; + fragment_shader = common_header + fragment_header + fragment_shader; + const char *geometry_shader_ptr = nullptr; // optional + if (!geometry_shader.empty()) { + geometry_shader = common_header + geometry_header + geometry_shader; + geometry_shader_ptr = geometry_shader.c_str(); } - shaders_header += "#define MATERIAL_TYPE "; - shaders_header += itos(material_type); - shaders_header += "\n"; - shaders_header += "#define DRAW_TYPE "; - shaders_header += itos(drawtype); - shaders_header += "\n"; - - if (g_settings->getBool("enable_waving_water")){ - shaders_header += "#define ENABLE_WAVING_WATER 1\n"; - shaders_header += "#define WATER_WAVE_HEIGHT "; - shaders_header += std::to_string(g_settings->getFloat("water_wave_height")); - shaders_header += "\n"; - shaders_header += "#define WATER_WAVE_LENGTH "; - shaders_header += std::to_string(g_settings->getFloat("water_wave_length")); - shaders_header += "\n"; - shaders_header += "#define WATER_WAVE_SPEED "; - shaders_header += std::to_string(g_settings->getFloat("water_wave_speed")); - shaders_header += "\n"; - } else{ - shaders_header += "#define ENABLE_WAVING_WATER 0\n"; + irr_ptr cb{new ShaderCallback(m_setter_factories)}; + infostream<<"Compiling high level shaders for "<addHighLevelShaderMaterial( + vertex_shader.c_str(), nullptr, video::EVST_VS_1_1, + fragment_shader.c_str(), nullptr, video::EPST_PS_1_1, + geometry_shader_ptr, nullptr, video::EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLES, 0, + cb.get(), shaderinfo.base_material, 1); + if (shadermat == -1) { + errorstream<<"generate_shader(): " + "failed to generate \""<getBool("enable_waving_leaves")) - shaders_header += "1\n"; - else - shaders_header += "0\n"; - - shaders_header += "#define ENABLE_WAVING_PLANTS "; - if (g_settings->getBool("enable_waving_plants")) - shaders_header += "1\n"; - else - shaders_header += "0\n"; - - if (g_settings->getBool("tone_mapping")) - shaders_header += "#define ENABLE_TONE_MAPPING\n"; - - shaders_header += "#define FOG_START "; - shaders_header += std::to_string(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; - const c8* geometry_program_ptr = 0; - if (!vertex_program.empty()) { - vertex_program = shaders_header + vertex_header + vertex_program; - vertex_program_ptr = vertex_program.c_str(); - } - if (!pixel_program.empty()) { - pixel_program = shaders_header + pixel_header + pixel_program; - pixel_program_ptr = pixel_program.c_str(); - } - if (!geometry_program.empty()) { - geometry_program = shaders_header + geometry_program; - geometry_program_ptr = geometry_program.c_str(); - } - ShaderCallback *cb = new ShaderCallback(setter_factories); - s32 shadermat = -1; - if(is_highlevel){ - infostream<<"Compiling high level shaders for "<addHighLevelShaderMaterial( - vertex_program_ptr, // Vertex shader program - "vertexMain", // Vertex shader entry point - video::EVST_VS_1_1, // Vertex shader version - pixel_program_ptr, // Pixel shader program - "pixelMain", // Pixel shader entry point - video::EPST_PS_1_2, // Pixel shader version - geometry_program_ptr, // Geometry shader program - "geometryMain", // Geometry shader entry point - video::EGST_GS_4_0, // Geometry shader version - scene::EPT_TRIANGLES, // Geometry shader input - scene::EPT_TRIANGLE_STRIP, // Geometry shader output - 0, // Support maximum number of vertices - cb, // Set-constant callback - shaderinfo.base_material, // Base material - 1 // Userdata passed to callback - ); - if(shadermat == -1){ - errorstream<<"generate_shader(): " - "failed to generate \""<addShaderMaterial( - vertex_program_ptr, // Vertex shader program - pixel_program_ptr, // Pixel shader program - cb, // Set-constant callback - shaderinfo.base_material, // Base material - 0 // Userdata passed to callback - ); - - if(shadermat == -1){ - errorstream<<"generate_shader(): " - "failed to generate \""<getMaterialRenderer(shadermat)->grab(); - // Apply the newly created material type shaderinfo.material = (video::E_MATERIAL_TYPE) shadermat; return shaderinfo; } -void load_shaders(const std::string &name, SourceShaderCache *sourcecache, - video::E_DRIVER_TYPE drivertype, bool enable_shaders, - std::string &vertex_program, std::string &pixel_program, - std::string &geometry_program, bool &is_highlevel) -{ - vertex_program = ""; - pixel_program = ""; - geometry_program = ""; - is_highlevel = false; - - if (!enable_shaders) - return; - - // Look for high level shaders - switch (drivertype) { - case video::EDT_DIRECT3D9: - // Direct3D 9: HLSL - // (All shaders in one file) - vertex_program = sourcecache->getOrLoad(name, "d3d9.hlsl"); - pixel_program = vertex_program; - geometry_program = vertex_program; - break; - - case video::EDT_OPENGL: -#if ENABLE_GLES - case video::EDT_OGLES2: -#endif - // OpenGL: GLSL - vertex_program = sourcecache->getOrLoad(name, "opengl_vertex.glsl"); - pixel_program = sourcecache->getOrLoad(name, "opengl_fragment.glsl"); - geometry_program = sourcecache->getOrLoad(name, "opengl_geometry.glsl"); - break; - - default: - // e.g. OpenGL ES 1 (with no shader support) - break; - } - if (!vertex_program.empty() || !pixel_program.empty() || !geometry_program.empty()){ - is_highlevel = true; - return; - } -} - void dumpShaderProgram(std::ostream &output_stream, const std::string &program_type, const std::string &program) { diff --git a/src/client/shader.h b/src/client/shader.h index 109d39336..d99182693 100644 --- a/src/client/shader.h +++ b/src/client/shader.h @@ -23,6 +23,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include "irrlichttypes_bloated.h" #include +#include "tile.h" +#include "nodedef.h" class IGameDef; @@ -46,8 +48,8 @@ struct ShaderInfo { std::string name = ""; video::E_MATERIAL_TYPE base_material = video::EMT_SOLID; video::E_MATERIAL_TYPE material = video::EMT_SOLID; - u8 drawtype = 0; - u8 material_type = 0; + NodeDrawType drawtype = NDT_NORMAL; + MaterialType material_type = TILE_MATERIAL_BASIC; ShaderInfo() = default; virtual ~ShaderInfo() = default; @@ -65,8 +67,7 @@ namespace irr { namespace video { class IShaderConstantSetter { public: virtual ~IShaderConstantSetter() = default; - virtual void onSetConstants(video::IMaterialRendererServices *services, - bool is_highlevel) = 0; + virtual void onSetConstants(video::IMaterialRendererServices *services) = 0; virtual void onSetMaterial(const video::SMaterial& material) { } }; @@ -128,10 +129,10 @@ public: virtual ~IShaderSource() = default; virtual u32 getShaderIdDirect(const std::string &name, - const u8 material_type, const u8 drawtype){return 0;} + MaterialType material_type, NodeDrawType drawtype = NDT_NORMAL){return 0;} virtual ShaderInfo getShaderInfo(u32 id){return ShaderInfo();} virtual u32 getShader(const std::string &name, - const u8 material_type, const u8 drawtype){return 0;} + MaterialType material_type, NodeDrawType drawtype = NDT_NORMAL){return 0;} }; class IWritableShaderSource : public IShaderSource { @@ -139,16 +140,12 @@ public: IWritableShaderSource() = default; virtual ~IWritableShaderSource() = default; - virtual u32 getShaderIdDirect(const std::string &name, - const u8 material_type, const u8 drawtype){return 0;} - virtual ShaderInfo getShaderInfo(u32 id){return ShaderInfo();} - virtual u32 getShader(const std::string &name, - const u8 material_type, const u8 drawtype){return 0;} - virtual void processQueue()=0; virtual void insertSourceShader(const std::string &name_of_shader, const std::string &filename, const std::string &program)=0; virtual void rebuildShaders()=0; + + /// @note Takes ownership of @p setter. virtual void addShaderConstantSetterFactory(IShaderConstantSetterFactory *setter) = 0; }; diff --git a/src/client/sky.cpp b/src/client/sky.cpp index 9a2614eda..3a40321dd 100644 --- a/src/client/sky.cpp +++ b/src/client/sky.cpp @@ -65,7 +65,7 @@ Sky::Sky(s32 id, ITextureSource *tsrc, IShaderSource *ssrc) : // Create materials m_materials[0] = baseMaterial(); - m_materials[0].MaterialType = ssrc->getShaderInfo(ssrc->getShader("stars_shader", TILE_MATERIAL_ALPHA, 0)).material; + m_materials[0].MaterialType = ssrc->getShaderInfo(ssrc->getShader("stars_shader", TILE_MATERIAL_ALPHA)).material; m_materials[0].Lighting = true; m_materials[0].ColorMaterial = video::ECM_NONE; diff --git a/src/nodedef.cpp b/src/nodedef.cpp index 5c2e5cd09..80013192d 100644 --- a/src/nodedef.cpp +++ b/src/nodedef.cpp @@ -774,7 +774,7 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc bool is_liquid = false; - u8 material_type = (alpha == 255) ? + MaterialType material_type = (alpha == 255) ? TILE_MATERIAL_BASIC : TILE_MATERIAL_ALPHA; switch (drawtype) { @@ -892,7 +892,7 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc u32 tile_shader = shdsrc->getShader("nodes_shader", material_type, drawtype); - u8 overlay_material = material_type; + MaterialType overlay_material = material_type; if (overlay_material == TILE_MATERIAL_OPAQUE) overlay_material = TILE_MATERIAL_BASIC; else if (overlay_material == TILE_MATERIAL_LIQUID_OPAQUE) @@ -913,7 +913,7 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc tdef[j].backface_culling, tsettings); } - u8 special_material = material_type; + MaterialType special_material = material_type; if (drawtype == NDT_PLANTLIKE_ROOTED) { if (waving == 1) special_material = TILE_MATERIAL_WAVING_PLANTS; From 5066fe75830b98f592717b593099a757337c952d Mon Sep 17 00:00:00 2001 From: Andrey Date: Sun, 20 Dec 2020 00:00:20 +0300 Subject: [PATCH 12/31] MainMenu: Add clear button and icon for search input (#10363) --- LICENSE.txt | 2 ++ builtin/mainmenu/dlg_contentstore.lua | 11 +++++++++-- builtin/mainmenu/tab_online.lua | 9 ++++++++- textures/base/pack/clear.png | Bin 0 -> 708 bytes textures/base/pack/search.png | Bin 0 -> 1908 bytes 5 files changed, 19 insertions(+), 3 deletions(-) create mode 100644 textures/base/pack/clear.png create mode 100644 textures/base/pack/search.png diff --git a/LICENSE.txt b/LICENSE.txt index f5c51833b..9fbd23723 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -23,6 +23,8 @@ paramat: textures/base/pack/menu_header.png textures/base/pack/next_icon.png textures/base/pack/prev_icon.png + textures/base/pack/clear.png + textures/base/pack/search.png rubenwardy, paramat: textures/base/pack/start_icon.png diff --git a/builtin/mainmenu/dlg_contentstore.lua b/builtin/mainmenu/dlg_contentstore.lua index 6525f6013..7a96df2a5 100644 --- a/builtin/mainmenu/dlg_contentstore.lua +++ b/builtin/mainmenu/dlg_contentstore.lua @@ -340,7 +340,6 @@ function store.get_formspec(dlgdata) local W = 15.75 local H = 9.5 - local formspec if #store.packages_full > 0 then formspec = { @@ -353,7 +352,8 @@ function store.get_formspec(dlgdata) "container[0.375,0.375]", "field[0,0;7.225,0.8;search_string;;", core.formspec_escape(search_string), "]", "field_close_on_enter[search_string;false]", - "button[7.225,0;2,0.8;search;", fgettext("Search"), "]", + "image_button[7.3,0;0.8,0.8;", core.formspec_escape(defaulttexturedir .. "search.png"), ";search;]", + "image_button[8.125,0;0.8,0.8;", core.formspec_escape(defaulttexturedir .. "clear.png"), ";clear;]", "dropdown[9.6,0;2.4,0.8;type;", table.concat(filter_types_titles, ","), ";", filter_type, "]", "container_end[]", @@ -504,6 +504,13 @@ function store.handle_submit(this, fields) return true end + if fields.clear then + search_string = "" + cur_page = 1 + store.filter_packages("") + return true + end + if fields.back then this:delete() return true diff --git a/builtin/mainmenu/tab_online.lua b/builtin/mainmenu/tab_online.lua index 7985fd84a..8f1341161 100644 --- a/builtin/mainmenu/tab_online.lua +++ b/builtin/mainmenu/tab_online.lua @@ -34,7 +34,8 @@ local function get_formspec(tabview, name, tabdata) local retval = -- Search "field[0.15,0.075;5.91,1;te_search;;" .. core.formspec_escape(tabdata.search_for) .. "]" .. - "button[5.62,-0.25;1.5,1;btn_mp_search;" .. fgettext("Search") .. "]" .. + "image_button[5.63,-.165;.83,.83;" .. core.formspec_escape(defaulttexturedir .. "search.png") .. ";btn_mp_search;]" .. + "image_button[6.3,-.165;.83,.83;" .. core.formspec_escape(defaulttexturedir .. "clear.png") .. ";btn_mp_clear;]" .. "image_button[6.97,-.165;.83,.83;" .. core.formspec_escape(defaulttexturedir .. "refresh.png") .. ";btn_mp_refresh;]" .. @@ -243,6 +244,12 @@ local function main_button_handler(tabview, fields, name, tabdata) return true end + if fields.btn_mp_clear then + tabdata.search_for = "" + menudata.search_result = nil + return true + end + if fields.btn_mp_search or fields.key_enter_field == "te_search" then tabdata.fav_selected = 1 local input = fields.te_search:lower() diff --git a/textures/base/pack/clear.png b/textures/base/pack/clear.png new file mode 100644 index 0000000000000000000000000000000000000000..9244264adcf8a710ff13a2d684f148f997f1522f GIT binary patch literal 708 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7xzrVCwdCaSW-r_4ck|p0J|`+k@?8 z)4T38Ghetp_qK?~6E??3JeK}D7|j>(if@>5FNQ(xtQ%9xq#I|>oJ-rk-tWo9fB*MH zp5A261T+u{c%448b?emavpj!@3x2dSE|*=GYrgL7A+xn2b!l~{&a|J|bNs}_tEEWpk`5!2*`a}1RyVnJUKYCsTDmAJZ691N{Rw#iPDykKZKfD4SDBXYZavSfp zt(M8LUICfU&F8YHzp0s=(DY%oUz2h9J|Q20x{sb8K$MJ(p@+4@qz<4 z!kg0dK3Eysi%9);Rd;NiTfc_o`reublauX^hYkL8bi5ZVT=BywU-{9yDV`H%&hFSD z{eSy3XBU}c*&BW+C(O>xi5IGCE-m?*7^bhf!nSDs-Ve5G964XH7nBIy_{nX@*CKED zC9J9A$E62L@3|g1-|-{rXX!rIBX13O=8G=aFLdP6;d1{6XTq5t?lu(JC&Y2TP@!hB z!wW0ribzTW? zv>WHHXDQnUw9_l$Ihb?k|95ulYSoBmH}=bWKa)PledlLA%OVzTzIe`-^(=?Nn=}vK z|5|oXdfI~7>hssAan;KT<|{qg^yu`QKY#yx%+Ejmf9+EvCB5Qf=OwiwTl#JLZgovQ z!0-C6bfNb@zk-X!W`9H8=%_c!chCE&^5PxeZU@em`wuKW9OwuSX$khe@MP~-NmYTm zX3qx;1G)7Yj~~;r*hEgWpDPBKS7mN|uQ4@RU{bU;RZBGG9cM4QZ&YGw2;badcT z8^0=@n`5_k4cg)jkHrR_ZUs6C)#;ru{p*MnFzSSy14BnK9k99qvx%(Q|Ku6*tVeE= z;j}fOm}70k#m=-1{B|WKep=e`sqE6mH$a&vhfe)BT5{~=GqH7W4FDtAPF6XfUJMg0 zG)SRiFgWX|#Hdo<6h%bjftQL_(g^a6TBkuGS!%-M3?v2!!-LD$RV3F+$;z#Y3Lq&# z_lXLz)euUtSfqnLL7jl2b-JcIw!dO0JQC!^>f882mU~^SkXzr`0xD$%3+f2q+OnxW z1#r9If&|iNnfe3`b*4|E043HiVCS~J?2$Nf98bhA$TsSxMtQ>bU0iB`d;--0U8=Ry zJ$(nF6is0}714=%paq!4^8&7*G-=qVnCc)Uq1GXZTEy1xasEqQke2{%ythu6(G*D6 zDF?-+D!Ue41yd=tX`8nuzFuMdv3v8p=sx4(#)k(VUp+7uXc=E9WXOjk_@2pQs9(A3 z%Fe+(gW#yEwq~Ezh<5oM;;RAsmL}jVtqyDg;3RO6+(ZS+wa!eGy%Xv)cY8sdSn&;K z=Ps^SBI2ddjn|*vyW-*bv2?_ZIuz7pOr~qbsWd5m^(%dw z+V538xQ3H(-4_xppDzC3sA8pkh`&sY6Nru)^Z(SD+qXv7TA(SYSIuP68ayyP+H0?< zaowVMuFU-jk-0cLhl6vgDyMeXaRacK-*^{WOw9U|9&j|Vd<#9+JeGf*Iy5>ye)R3f z!qwGPGPOQQ{6H;&(Wc;AI2huTl){mQQt=*;F&g!IJS<08ZLf>0u+ENg7s343c&1m7mb$YSA$oW=Ou(;WVMAGQ+9 zU{v(RH~IzT(6ZnE)c?h#57hs2bs8di1zc28QeyD_;W>7ZU(8N^yT}Ash708loHCa&7K!Wixy30l1~_H zt%s71ttI{vsu(~*IL^WdO-8p|;mo$+Ut=}jyoU52j>@^LpIy;y;Aknl_Rb!tje;t0 z4`ZQ&Pd~ODxH|QAh4G_8Ov>8b6FKrNMcniQ{aQW-sL+^9m+j?+iW)Y8u-@$4+ZyKqr5_OPwunRDLxq8ZX8<(~$=F88q9F&sb0`#Qm~!Ma?^gL*o;c9xJrXIg(l#>Bs<*5P z_Oorurv`1CY#wa(+`Gd3dpUO9?{|2zxdX|~OX;BN^lt;g?q=M*AyZzwcOF=an-aR$ zWvqD9Pja5@lpfUFh3giFZ@YlBpa8ns&|&HPv69cekehvTx1-3K!uJ{pthx&pQMU_X zz_OYBuTku;iCT@2eL`2sndtrXyaIV!7w1Pc;qV4`&`*DVI@)O3>nZp58l2 zh86Z3I>$`!bGRg_`o{BU|3AaXW{t-BrPl3lJI0##E>?4JbBElN!tO>W;jyUC9TP&C zcdY$f=J{hbR^H#JQa?PKHouPy0s)EE-W+MDc;Xz%zs`T$`R%Yt?QXQVAN^tty#4`5(6Lbv2~siR@4 z@`h)pegmd;G66wTd;1v6$`5#mabMDZA>){oRw~(J+i2oaY0;7FQaR<-xTRoy>!JU5 oz)Hy+PJ7*y{67!tO!d0_mw-1lpr~N2?{5lnuywWJ5y{E_0lF-AYXATM literal 0 HcmV?d00001 From af22dd86e3867a35e9e5ab911faa6e1e7671729d Mon Sep 17 00:00:00 2001 From: Markus Date: Sat, 19 Dec 2020 22:01:05 +0100 Subject: [PATCH 13/31] Fix some more joystick issues (#10624) --- builtin/settingtypes.txt | 3 ++ minetest.conf.example | 3 ++ src/client/game.cpp | 4 +-- src/client/inputhandler.h | 2 +- src/client/joystick_controller.cpp | 50 ++++++++++++++++-------------- src/client/joystick_controller.h | 42 ++++++++++++------------- src/defaultsettings.cpp | 1 + 7 files changed, 55 insertions(+), 50 deletions(-) diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index 251b6d868..7060a0b6e 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -152,6 +152,9 @@ joystick_type (Joystick type) enum auto auto,generic,xbox # when holding down a joystick button combination. repeat_joystick_button_time (Joystick button repetition interval) float 0.17 0.001 +# The deadzone of the joystick +joystick_deadzone (Joystick deadzone) int 2048 + # The sensitivity of the joystick axes for moving the # ingame view frustum around. joystick_frustum_sensitivity (Joystick frustum sensitivity) float 170 diff --git a/minetest.conf.example b/minetest.conf.example index 6b315b6ea..086339037 100644 --- a/minetest.conf.example +++ b/minetest.conf.example @@ -129,6 +129,9 @@ # type: float min: 0.001 # repeat_joystick_button_time = 0.17 +# The deadzone of the joystick +# joystick_deadzone = 2048 + # The sensitivity of the joystick axes for moving the # ingame view frustum around. # type: float diff --git a/src/client/game.cpp b/src/client/game.cpp index fd4d09394..6151d2aa6 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -3139,8 +3139,8 @@ void Game::processPlayerInteraction(f32 dtime, bool show_hud, bool show_debug) wasKeyDown(KeyType::DIG); wasKeyDown(KeyType::PLACE); - input->joystick.clearWasKeyDown(KeyType::DIG); - input->joystick.clearWasKeyDown(KeyType::PLACE); + input->joystick.clearWasKeyPressed(KeyType::DIG); + input->joystick.clearWasKeyPressed(KeyType::PLACE); input->joystick.clearWasKeyReleased(KeyType::DIG); input->joystick.clearWasKeyReleased(KeyType::PLACE); diff --git a/src/client/inputhandler.h b/src/client/inputhandler.h index def147a82..7487bbdc7 100644 --- a/src/client/inputhandler.h +++ b/src/client/inputhandler.h @@ -279,7 +279,7 @@ public: } virtual bool wasKeyPressed(GameKeyType k) { - return m_receiver->WasKeyPressed(keycache.key[k]) || joystick.wasKeyReleased(k); + return m_receiver->WasKeyPressed(keycache.key[k]) || joystick.wasKeyPressed(k); } virtual bool wasKeyReleased(GameKeyType k) { diff --git a/src/client/joystick_controller.cpp b/src/client/joystick_controller.cpp index 742115046..f61ae4ae6 100644 --- a/src/client/joystick_controller.cpp +++ b/src/client/joystick_controller.cpp @@ -37,7 +37,7 @@ 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); + return (ax_val * direction < -thresh); } // spares many characters @@ -48,7 +48,7 @@ JoystickLayout create_default_layout() { JoystickLayout jlo; - jlo.axes_dead_border = 1024; + jlo.axes_deadzone = g_settings->getU16("joystick_deadzone"); const JoystickAxisLayout axes[JA_COUNT] = { {0, 1}, // JA_SIDEWARD_MOVE @@ -93,14 +93,14 @@ JoystickLayout create_default_layout() // 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); + JLO_A_PB(KeyType::FORWARD, 1, 1, jlo.axes_deadzone); + JLO_A_PB(KeyType::BACKWARD, 1, -1, jlo.axes_deadzone); + JLO_A_PB(KeyType::LEFT, 0, 1, jlo.axes_deadzone); + JLO_A_PB(KeyType::RIGHT, 0, -1, jlo.axes_deadzone); // Scroll buttons - JLO_A_PB(KeyType::HOTBAR_PREV, 2, -1, 1024); - JLO_A_PB(KeyType::HOTBAR_NEXT, 5, -1, 1024); + JLO_A_PB(KeyType::HOTBAR_PREV, 2, -1, jlo.axes_deadzone); + JLO_A_PB(KeyType::HOTBAR_NEXT, 5, -1, jlo.axes_deadzone); return jlo; } @@ -109,7 +109,7 @@ JoystickLayout create_xbox_layout() { JoystickLayout jlo; - jlo.axes_dead_border = 7000; + jlo.axes_deadzone = 7000; const JoystickAxisLayout axes[JA_COUNT] = { {0, 1}, // JA_SIDEWARD_MOVE @@ -146,10 +146,10 @@ JoystickLayout create_xbox_layout() JLO_B_PB(KeyType::FREEMOVE, 1 << 16, 1 << 16); // down // 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); + JLO_A_PB(KeyType::FORWARD, 1, 1, jlo.axes_deadzone); + JLO_A_PB(KeyType::BACKWARD, 1, -1, jlo.axes_deadzone); + JLO_A_PB(KeyType::LEFT, 0, 1, jlo.axes_deadzone); + JLO_A_PB(KeyType::RIGHT, 0, -1, jlo.axes_deadzone); return jlo; } @@ -219,16 +219,19 @@ bool JoystickController::handleEvent(const irr::SEvent::SJoystickEvent &ev) for (size_t i = 0; i < KeyType::INTERNAL_ENUM_COUNT; i++) { if (keys_pressed[i]) { - if (!m_past_pressed_keys[i] && + if (!m_past_keys_pressed[i] && m_past_pressed_time[i] < m_internal_time - doubling_dtime) { - m_past_pressed_keys[i] = true; + m_past_keys_pressed[i] = true; m_past_pressed_time[i] = m_internal_time; } - } else if (m_pressed_keys[i]) { - m_past_released_keys[i] = true; + } else if (m_keys_down[i]) { + m_keys_released[i] = true; } - m_pressed_keys[i] = keys_pressed[i]; + if (keys_pressed[i] && !(m_keys_down[i])) + m_keys_pressed[i] = true; + + m_keys_down[i] = keys_pressed[i]; } for (size_t i = 0; i < JA_COUNT; i++) { @@ -236,23 +239,22 @@ bool JoystickController::handleEvent(const irr::SEvent::SJoystickEvent &ev) 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(); + m_keys_pressed.reset(); + m_keys_down.reset(); + m_past_keys_pressed.reset(); + m_keys_released.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))) + if (abs(v) < m_layout.axes_deadzone) return 0; return v; } diff --git a/src/client/joystick_controller.h b/src/client/joystick_controller.h index 7baacd81b..3f361e4ef 100644 --- a/src/client/joystick_controller.h +++ b/src/client/joystick_controller.h @@ -96,7 +96,7 @@ struct JoystickLayout { std::vector button_keys; std::vector axis_keys; JoystickAxisLayout axes[JA_COUNT]; - s16 axes_dead_border; + s16 axes_deadzone; }; class JoystickController { @@ -111,37 +111,32 @@ public: bool wasKeyDown(GameKeyType b) { - bool r = m_past_pressed_keys[b]; - m_past_pressed_keys[b] = false; + bool r = m_past_keys_pressed[b]; + m_past_keys_pressed[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]; + return m_keys_released[b]; } void clearWasKeyReleased(GameKeyType b) { - m_past_pressed_keys[b] = false; + m_keys_released[b] = false; + } + + bool wasKeyPressed(GameKeyType b) + { + return m_keys_pressed[b]; + } + void clearWasKeyPressed(GameKeyType b) + { + m_keys_pressed[b] = false; } bool isKeyDown(GameKeyType b) { - return m_pressed_keys[b]; + return m_keys_down[b]; } s16 getAxis(JoystickAxis axis) @@ -162,12 +157,13 @@ private: u8 m_joystick_id = 0; - std::bitset m_pressed_keys; + std::bitset m_keys_down; + std::bitset m_keys_pressed; 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; + std::bitset m_past_keys_pressed; + std::bitset m_keys_released; }; diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index e13977fe3..e8fb18e05 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -279,6 +279,7 @@ void set_default_settings(Settings *settings) settings->setDefault("joystick_type", ""); settings->setDefault("repeat_joystick_button_time", "0.17"); settings->setDefault("joystick_frustum_sensitivity", "170"); + settings->setDefault("joystick_deadzone", "2048"); // Main menu settings->setDefault("main_menu_path", ""); From 03540e7140fc5d54e7b8406415b53e708c7b0bea Mon Sep 17 00:00:00 2001 From: Vitaliy Date: Tue, 22 Dec 2020 16:53:52 +0300 Subject: [PATCH 14/31] Fix GLES shader support after #9247 (#10727) --- client/shaders/nodes_shader/opengl_fragment.glsl | 6 +++++- client/shaders/nodes_shader/opengl_vertex.glsl | 6 +++++- client/shaders/object_shader/opengl_fragment.glsl | 6 +++++- client/shaders/object_shader/opengl_vertex.glsl | 6 +++++- 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/client/shaders/nodes_shader/opengl_fragment.glsl b/client/shaders/nodes_shader/opengl_fragment.glsl index b5d85da64..b58095063 100644 --- a/client/shaders/nodes_shader/opengl_fragment.glsl +++ b/client/shaders/nodes_shader/opengl_fragment.glsl @@ -16,7 +16,11 @@ varying vec3 vPosition; // precision must be considered). varying vec3 worldPosition; varying lowp vec4 varColor; -centroid varying mediump vec2 varTexCoord; +#ifdef GL_ES +varying mediump vec2 varTexCoord; +#else +centroid varying vec2 varTexCoord; +#endif varying vec3 eyeVec; const float fogStart = FOG_START; diff --git a/client/shaders/nodes_shader/opengl_vertex.glsl b/client/shaders/nodes_shader/opengl_vertex.glsl index 5742ec1d3..c68df4a8e 100644 --- a/client/shaders/nodes_shader/opengl_vertex.glsl +++ b/client/shaders/nodes_shader/opengl_vertex.glsl @@ -19,7 +19,11 @@ varying lowp vec4 varColor; // The centroid keyword ensures that after interpolation the texture coordinates // lie within the same bounds when MSAA is en- and disabled. // This fixes the stripes problem with nearest-neighbour textures and MSAA. -centroid varying mediump vec2 varTexCoord; +#ifdef GL_ES +varying mediump vec2 varTexCoord; +#else +centroid varying vec2 varTexCoord; +#endif varying vec3 eyeVec; // Color of the light emitted by the light sources. diff --git a/client/shaders/object_shader/opengl_fragment.glsl b/client/shaders/object_shader/opengl_fragment.glsl index 12cc54ae7..9a81d8185 100644 --- a/client/shaders/object_shader/opengl_fragment.glsl +++ b/client/shaders/object_shader/opengl_fragment.glsl @@ -9,7 +9,11 @@ varying vec3 vNormal; varying vec3 vPosition; varying vec3 worldPosition; varying lowp vec4 varColor; -centroid varying mediump vec2 varTexCoord; +#ifdef GL_ES +varying mediump vec2 varTexCoord; +#else +centroid varying vec2 varTexCoord; +#endif varying vec3 eyeVec; varying float vIDiff; diff --git a/client/shaders/object_shader/opengl_vertex.glsl b/client/shaders/object_shader/opengl_vertex.glsl index f31b842ee..b4a4d0aaa 100644 --- a/client/shaders/object_shader/opengl_vertex.glsl +++ b/client/shaders/object_shader/opengl_vertex.glsl @@ -7,7 +7,11 @@ varying vec3 vNormal; varying vec3 vPosition; varying vec3 worldPosition; varying lowp vec4 varColor; -centroid varying mediump vec2 varTexCoord; +#ifdef GL_ES +varying mediump vec2 varTexCoord; +#else +centroid varying vec2 varTexCoord; +#endif varying vec3 eyeVec; varying float vIDiff; From 535557cc2e972c555bc5a294b95f2c2974b81eea Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Tue, 22 Dec 2020 14:54:27 +0100 Subject: [PATCH 15/31] Fix fallnode rotation of wallmounted nodebox/mesh (#10643) --- builtin/game/falling.lua | 40 +++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/builtin/game/falling.lua b/builtin/game/falling.lua index f489ea702..057d0d0ed 100644 --- a/builtin/game/falling.lua +++ b/builtin/game/falling.lua @@ -152,8 +152,8 @@ core.register_entity(":__builtin:falling_node", { else self.object:set_yaw(-math.pi*0.25) end - elseif (node.param2 ~= 0 and (def.wield_image == "" - or def.wield_image == nil)) + elseif ((node.param2 ~= 0 or def.drawtype == "nodebox" or def.drawtype == "mesh") + and (def.wield_image == "" or def.wield_image == nil)) or def.drawtype == "signlike" or def.drawtype == "mesh" or def.drawtype == "normal" @@ -168,16 +168,30 @@ core.register_entity(":__builtin:falling_node", { elseif (def.paramtype2 == "wallmounted" or def.paramtype2 == "colorwallmounted") then local rot = node.param2 % 8 local pitch, yaw, roll = 0, 0, 0 - if rot == 1 then - pitch, yaw = math.pi, math.pi - elseif rot == 2 then - pitch, yaw = math.pi/2, math.pi/2 - elseif rot == 3 then - pitch, yaw = math.pi/2, -math.pi/2 - elseif rot == 4 then - pitch, yaw = math.pi/2, math.pi - elseif rot == 5 then - pitch, yaw = math.pi/2, 0 + if def.drawtype == "nodebox" or def.drawtype == "mesh" then + if rot == 0 then + pitch, yaw = math.pi/2, 0 + elseif rot == 1 then + pitch, yaw = -math.pi/2, math.pi + elseif rot == 2 then + pitch, yaw = 0, math.pi/2 + elseif rot == 3 then + pitch, yaw = 0, -math.pi/2 + elseif rot == 4 then + pitch, yaw = 0, math.pi + end + else + if rot == 1 then + pitch, yaw = math.pi, math.pi + elseif rot == 2 then + pitch, yaw = math.pi/2, math.pi/2 + elseif rot == 3 then + pitch, yaw = math.pi/2, -math.pi/2 + elseif rot == 4 then + pitch, yaw = math.pi/2, math.pi + elseif rot == 5 then + pitch, yaw = math.pi/2, 0 + end end if def.drawtype == "signlike" then pitch = pitch - math.pi/2 @@ -186,7 +200,7 @@ core.register_entity(":__builtin:falling_node", { elseif rot == 1 then yaw = yaw - math.pi/2 end - elseif def.drawtype == "mesh" or def.drawtype == "normal" then + elseif def.drawtype == "mesh" or def.drawtype == "normal" or def.drawtype == "nodebox" then if rot >= 0 and rot <= 1 then roll = roll + math.pi else From d2bbf13dfe61c48c1051ab5bd8b2b0e97ad7599e Mon Sep 17 00:00:00 2001 From: rubenwardy Date: Wed, 23 Dec 2020 14:42:18 +0000 Subject: [PATCH 16/31] Add dependency resolution to ContentDB (#9997) --- builtin/mainmenu/dlg_contentstore.lua | 301 +++++++++++++++++++++++++- builtin/mainmenu/dlg_create_world.lua | 2 +- builtin/mainmenu/init.lua | 1 + builtin/settingtypes.txt | 1 + 4 files changed, 300 insertions(+), 5 deletions(-) diff --git a/builtin/mainmenu/dlg_contentstore.lua b/builtin/mainmenu/dlg_contentstore.lua index 7a96df2a5..548bae67e 100644 --- a/builtin/mainmenu/dlg_contentstore.lua +++ b/builtin/mainmenu/dlg_contentstore.lua @@ -159,6 +159,290 @@ local function queue_download(package) end end +local function get_raw_dependencies(package) + if package.raw_deps then + return package.raw_deps + end + + local url_fmt = "/api/packages/%s/dependencies/?only_hard=1&protocol_version=%s&engine_version=%s" + local version = core.get_version() + local base_url = core.settings:get("contentdb_url") + local url = base_url .. url_fmt:format(package.id, core.get_max_supp_proto(), version.string) + + local response = http.fetch_sync({ url = url }) + if not response.succeeded then + return + end + + local data = core.parse_json(response.data) or {} + + local content_lookup = {} + for _, pkg in pairs(store.packages_full) do + content_lookup[pkg.id] = pkg + end + + for id, raw_deps in pairs(data) do + local package2 = content_lookup[id:lower()] + if package2 and not package2.raw_deps then + package2.raw_deps = raw_deps + + for _, dep in pairs(raw_deps) do + local packages = {} + for i=1, #dep.packages do + packages[#packages + 1] = content_lookup[dep.packages[i]:lower()] + end + dep.packages = packages + end + end + end + + return package.raw_deps +end + +local function has_hard_deps(raw_deps) + for i=1, #raw_deps do + if not raw_deps[i].is_optional then + return true + end + end + + return false +end + +-- Recursively resolve dependencies, given the installed mods +local function resolve_dependencies_2(raw_deps, installed_mods, out) + local function resolve_dep(dep) + -- Check whether it's already installed + if installed_mods[dep.name] then + return { + is_optional = dep.is_optional, + name = dep.name, + installed = true, + } + end + + -- Find exact name matches + local fallback + for _, package in pairs(dep.packages) do + if package.type ~= "game" then + if package.name == dep.name then + return { + is_optional = dep.is_optional, + name = dep.name, + installed = false, + package = package, + } + elseif not fallback then + fallback = package + end + end + end + + -- Otherwise, find the first mod that fulfils it + if fallback then + return { + is_optional = dep.is_optional, + name = dep.name, + installed = false, + package = fallback, + } + end + + return { + is_optional = dep.is_optional, + name = dep.name, + installed = false, + } + end + + for _, dep in pairs(raw_deps) do + if not dep.is_optional and not out[dep.name] then + local result = resolve_dep(dep) + out[dep.name] = result + if result and result.package and not result.installed then + local raw_deps2 = get_raw_dependencies(result.package) + if raw_deps2 then + resolve_dependencies_2(raw_deps2, installed_mods, out) + end + end + end + end + + return true +end + +-- Resolve dependencies for a package, calls the recursive version. +local function resolve_dependencies(raw_deps, game) + assert(game) + + local installed_mods = {} + + local mods = {} + pkgmgr.get_game_mods(game, mods) + for _, mod in pairs(mods) do + installed_mods[mod.name] = true + end + + for _, mod in pairs(pkgmgr.global_mods:get_list()) do + installed_mods[mod.name] = true + end + + local out = {} + if not resolve_dependencies_2(raw_deps, installed_mods, out) then + return nil + end + + local retval = {} + for _, dep in pairs(out) do + retval[#retval + 1] = dep + end + + table.sort(retval, function(a, b) + return a.name < b.name + end) + + return retval +end + +local install_dialog = {} +function install_dialog.get_formspec() + local package = install_dialog.package + local raw_deps = install_dialog.raw_deps + local will_install_deps = install_dialog.will_install_deps + + local selected_game_idx = 1 + local selected_gameid = core.settings:get("menu_last_game") + local games = table.copy(pkgmgr.games) + for i=1, #games do + if selected_gameid and games[i].id == selected_gameid then + selected_game_idx = i + end + + games[i] = minetest.formspec_escape(games[i].name) + end + + local selected_game = pkgmgr.games[selected_game_idx] + local deps_to_install = 0 + local deps_not_found = 0 + + install_dialog.dependencies = resolve_dependencies(raw_deps, selected_game) + local formatted_deps = {} + for _, dep in pairs(install_dialog.dependencies) do + formatted_deps[#formatted_deps + 1] = "#fff" + formatted_deps[#formatted_deps + 1] = minetest.formspec_escape(dep.name) + if dep.installed then + formatted_deps[#formatted_deps + 1] = "#ccf" + formatted_deps[#formatted_deps + 1] = fgettext("Already installed") + elseif dep.package then + formatted_deps[#formatted_deps + 1] = "#cfc" + formatted_deps[#formatted_deps + 1] = fgettext("$1 by $2", dep.package.title, dep.package.author) + deps_to_install = deps_to_install + 1 + else + formatted_deps[#formatted_deps + 1] = "#f00" + formatted_deps[#formatted_deps + 1] = fgettext("Not found") + deps_not_found = deps_not_found + 1 + end + end + + local message_bg = "#3333" + local message + if will_install_deps then + message = fgettext("$1 and $2 dependencies will be installed.", package.title, deps_to_install) + else + message = fgettext("$1 will be installed, and $2 dependencies will be skipped.", package.title, deps_to_install) + end + if deps_not_found > 0 then + message = fgettext("$1 required dependencies could not be found.", deps_not_found) .. + " " .. fgettext("Please check that the base game is correct.", deps_not_found) .. + "\n" .. message + message_bg = mt_color_orange + end + + local formspec = { + "formspec_version[3]", + "size[7,7.85]", + "style[title;border=false]", + "box[0,0;7,0.5;#3333]", + "button[0,0;7,0.5;title;", fgettext("Install $1", package.title) , "]", + + "container[0.375,0.70]", + + "label[0,0.25;", fgettext("Base Game:"), "]", + "dropdown[2,0;4.25,0.5;gameid;", table.concat(games, ","), ";", selected_game_idx, "]", + + "label[0,0.8;", fgettext("Dependencies:"), "]", + + "tablecolumns[color;text;color;text]", + "table[0,1.1;6.25,3;packages;", table.concat(formatted_deps, ","), "]", + + "container_end[]", + + "checkbox[0.375,5.1;will_install_deps;", + fgettext("Install missing dependencies"), ";", + will_install_deps and "true" or "false", "]", + + "box[0,5.4;7,1.2;", message_bg, "]", + "textarea[0.375,5.5;6.25,1;;;", message, "]", + + "container[1.375,6.85]", + "button[0,0;2,0.8;install_all;", fgettext("Install"), "]", + "button[2.25,0;2,0.8;cancel;", fgettext("Cancel"), "]", + "container_end[]", + } + + return table.concat(formspec, "") +end + +function install_dialog.handle_submit(this, fields) + if fields.cancel then + this:delete() + return true + end + + if fields.will_install_deps ~= nil then + install_dialog.will_install_deps = minetest.is_yes(fields.will_install_deps) + return true + end + + if fields.install_all then + queue_download(install_dialog.package) + + if install_dialog.will_install_deps then + for _, dep in pairs(install_dialog.dependencies) do + if not dep.is_optional and not dep.installed and dep.package then + queue_download(dep.package) + end + end + end + + this:delete() + return true + end + + if fields.gameid then + for _, game in pairs(pkgmgr.games) do + if game.name == fields.gameid then + core.settings:set("menu_last_game", game.id) + break + end + end + return true + end + + return false +end + +function install_dialog.create(package, raw_deps) + install_dialog.dependencies = nil + install_dialog.package = package + install_dialog.raw_deps = raw_deps + install_dialog.will_install_deps = true + return dialog_create("package_view", + install_dialog.get_formspec, + install_dialog.handle_submit, + nil) +end + local function get_file_extension(path) local parts = path:split(".") return parts[#parts] @@ -570,15 +854,24 @@ function store.handle_submit(this, fields) assert(package) if fields["install_" .. i] then - queue_download(package) + local deps = get_raw_dependencies(package) + if deps and has_hard_deps(deps) then + local dlg = install_dialog.create(package, deps) + dlg:set_parent(this) + this:hide() + dlg:show() + else + queue_download(package) + end + return true end if fields["uninstall_" .. i] then - local dlg_delmod = create_delete_content_dlg(package) - dlg_delmod:set_parent(this) + local dlg = create_delete_content_dlg(package) + dlg:set_parent(this) this:hide() - dlg_delmod:show() + dlg:show() return true end diff --git a/builtin/mainmenu/dlg_create_world.lua b/builtin/mainmenu/dlg_create_world.lua index 7566d2409..5931496c1 100644 --- a/builtin/mainmenu/dlg_create_world.lua +++ b/builtin/mainmenu/dlg_create_world.lua @@ -98,7 +98,7 @@ local function create_world_formspec(dialogdata) -- Error out when no games found if #pkgmgr.games == 0 then return "size[12.25,3,true]" .. - "box[0,0;12,2;#ff8800]" .. + "box[0,0;12,2;" .. mt_color_orange .. "]" .. "textarea[0.3,0;11.7,2;;;".. fgettext("You have no games installed.") .. "\n" .. fgettext("Download one from minetest.net") .. "]" .. diff --git a/builtin/mainmenu/init.lua b/builtin/mainmenu/init.lua index 96d02d06c..2fc0ae64c 100644 --- a/builtin/mainmenu/init.lua +++ b/builtin/mainmenu/init.lua @@ -19,6 +19,7 @@ mt_color_grey = "#AAAAAA" mt_color_blue = "#6389FF" mt_color_green = "#72FF63" mt_color_dark_green = "#25C191" +mt_color_orange = "#FF8800" local menupath = core.get_mainmenu_path() local basepath = core.get_builtin_path() diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index 7060a0b6e..7e23b5641 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -2205,4 +2205,5 @@ contentdb_url (ContentDB URL) string https://content.minetest.net contentdb_flag_blacklist (ContentDB Flag Blacklist) string nonfree, desktop_default # Maximum number of concurrent downloads. Downloads exceeding this limit will be queued. +# This should be lower than curl_parallel_limit. contentdb_max_concurrent_downloads (ContentDB Max Concurrent Downloads) int 3 From 2bdf4955c8427dd5a9ad1287344e416643b397a4 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Wed, 23 Dec 2020 21:24:27 +0100 Subject: [PATCH 17/31] CI: fix build --- .github/workflows/build.yml | 25 +++++++++---------------- util/ci/common.sh | 6 +----- 2 files changed, 10 insertions(+), 21 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 71fdf3652..a3cc92a8e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -33,9 +33,8 @@ jobs: - 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 + install_linux_deps g++-6 - name: Build run: | @@ -55,9 +54,8 @@ jobs: - uses: actions/checkout@v2 - name: Install deps run: | - sudo apt-get install g++-8 gcc-8 -qyy source ./util/ci/common.sh - install_linux_deps + install_linux_deps g++-8 - name: Build run: | @@ -77,9 +75,8 @@ jobs: - uses: actions/checkout@v2 - name: Install deps run: | - sudo apt-get install clang-3.9 -qyy source ./util/ci/common.sh - install_linux_deps + install_linux_deps clang-3.9 - name: Build run: | @@ -99,11 +96,8 @@ jobs: - uses: actions/checkout@v2 - name: Install deps run: | - sudo apt-get install clang-9 valgrind -qyy source ./util/ci/common.sh - install_linux_deps - env: - WITH_LUAJIT: 1 + install_linux_deps clang-9 valgrind libluajit-5.1-dev - name: Build run: | @@ -111,6 +105,7 @@ jobs: env: CC: clang-9 CXX: clang++-9 + CMAKE_FLAGS: "-DREQUIRE_LUAJIT=1" - name: Test run: | @@ -128,9 +123,8 @@ jobs: - uses: actions/checkout@v2 - name: Install deps run: | - sudo apt-get install clang-9 -qyy source ./util/ci/common.sh - install_linux_deps + install_linux_deps clang-9 - name: Build prometheus-cpp run: | @@ -156,9 +150,8 @@ jobs: - uses: actions/checkout@v2 - name: Install deps run: | - sudo apt-get install clang-9 -qyy source ./util/ci/common.sh - install_linux_deps + install_linux_deps clang-9 - name: Build run: | @@ -188,7 +181,7 @@ jobs: - uses: actions/checkout@v2 - name: Install compiler run: | - sudo apt-get install gettext -qyy + sudo apt-get update -q && sudo apt-get install gettext -qyy wget http://minetest.kitsunemimi.pw/mingw-w64-i686_9.2.0_ubuntu18.04.tar.xz -O mingw.tar.xz sudo tar -xaf mingw.tar.xz -C /usr @@ -206,7 +199,7 @@ jobs: - uses: actions/checkout@v2 - name: Install compiler run: | - sudo apt-get install gettext -qyy + sudo apt-get update -q && sudo apt-get install gettext -qyy wget http://minetest.kitsunemimi.pw/mingw-w64-x86_64_9.2.0_ubuntu18.04.tar.xz -O mingw.tar.xz sudo tar -xaf mingw.tar.xz -C /usr diff --git a/util/ci/common.sh b/util/ci/common.sh index a2e4beac9..7523fa7ff 100644 --- a/util/ci/common.sh +++ b/util/ci/common.sh @@ -7,13 +7,9 @@ install_linux_deps() { libhiredis-dev libogg-dev libgmp-dev libvorbis-dev libopenal-dev \ gettext libpq-dev postgresql-server-dev-all libleveldb-dev \ libcurl4-openssl-dev) - # for better coverage, build some jobs with luajit - if [ -n "$WITH_LUAJIT" ]; then - pkgs+=(libluajit-5.1-dev) - fi sudo apt-get update - sudo apt-get install -y --no-install-recommends ${pkgs[@]} + sudo apt-get install -y --no-install-recommends ${pkgs[@]} "$@" } # Mac OSX build only From 2c3593b51eef193eb543a08eb1e83c37e2fafe72 Mon Sep 17 00:00:00 2001 From: rubenwardy Date: Wed, 23 Dec 2020 16:39:29 +0000 Subject: [PATCH 18/31] Fix unsafe cast in l_object --- src/script/lua_api/l_object.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index bc59bd55c..4d7a1bc41 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -1409,7 +1409,7 @@ int ObjectRef::l_set_physics_override(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); - PlayerSAO *playersao = (PlayerSAO *) getobject(ref); + PlayerSAO *playersao = getplayersao(ref); if (playersao == nullptr) return 0; @@ -1449,7 +1449,7 @@ int ObjectRef::l_get_physics_override(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); - PlayerSAO *playersao = (PlayerSAO *)getobject(ref); + PlayerSAO *playersao = getplayersao(ref); if (playersao == nullptr) return 0; From 289425f6bd6cfe1f66218918d9d5bd1b9f89aa7c Mon Sep 17 00:00:00 2001 From: Lars Date: Sun, 20 Dec 2020 19:22:04 -0800 Subject: [PATCH 19/31] Minor profiler fixes. --- src/client/clientmap.cpp | 3 +++ src/profiler.cpp | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/client/clientmap.cpp b/src/client/clientmap.cpp index fa47df3f4..b9e0cc2ce 100644 --- a/src/client/clientmap.cpp +++ b/src/client/clientmap.cpp @@ -290,6 +290,7 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass) */ u32 vertex_count = 0; + u32 drawcall_count = 0; // For limiting number of mesh animations per frame u32 mesh_animate_count = 0; @@ -391,6 +392,7 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass) } driver->setMaterial(list.m); + drawcall_count += list.bufs.size(); for (auto &pair : list.bufs) { scene::IMeshBuffer *buf = pair.second; @@ -411,6 +413,7 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass) } g_profiler->avg(prefix + "vertices drawn [#]", vertex_count); + g_profiler->avg(prefix + "drawcalls [#]", drawcall_count); } static bool getVisibleBrightness(Map *map, const v3f &p0, v3f dir, float step, diff --git a/src/profiler.cpp b/src/profiler.cpp index be8be591e..d05b7abfe 100644 --- a/src/profiler.cpp +++ b/src/profiler.cpp @@ -38,7 +38,7 @@ ScopeProfiler::~ScopeProfiler() return; float duration_ms = m_timer->stop(true); - float duration = duration_ms / 1000.0; + float duration = duration_ms; if (m_profiler) { switch (m_type) { case SPT_ADD: From 74762470b2aa11a5271b846549ff14b86c1705d2 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Wed, 23 Dec 2020 22:03:49 +0100 Subject: [PATCH 20/31] Fix some minor code issues all over the place --- CMakeLists.txt | 8 +------ lib/lua/CMakeLists.txt | 13 ++--------- src/CMakeLists.txt | 23 ------------------ src/client/content_cao.cpp | 4 ++-- src/client/game.cpp | 36 ++++------------------------- src/client/hud.cpp | 6 ++--- src/client/mapblock_mesh.cpp | 4 ++-- src/client/tile.cpp | 7 ++++++ src/filesys.cpp | 22 +++++++----------- src/gui/touchscreengui.cpp | 3 +-- src/irrlicht_changes/CGUITTFont.h | 2 +- src/irrlicht_changes/irrUString.h | 4 ++-- src/mapgen/mapgen_v7.cpp | 2 +- src/mapgen/treegen.cpp | 3 ++- src/network/serverpackethandler.cpp | 2 +- src/nodedef.cpp | 2 +- src/script/cpp_api/s_security.cpp | 7 +++--- src/util/srp.cpp | 4 ++-- src/util/string.cpp | 2 +- 19 files changed, 45 insertions(+), 109 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 78d551168..1d53fcffd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,15 +1,9 @@ -cmake_minimum_required(VERSION 2.6) - -if(${CMAKE_VERSION} STREQUAL "2.8.2") - # Bug http://vtk.org/Bug/view.php?id=11020 - message(WARNING "CMake/CPack version 2.8.2 will not create working .deb packages!") -endif() +cmake_minimum_required(VERSION 3.5) # This can be read from ${PROJECT_NAME} after project() is called project(minetest) set(PROJECT_NAME_CAPITALIZED "Minetest") -# Works only for cmake 3.1 and greater set(CMAKE_CXX_STANDARD 11) set(GCC_MINIMUM_VERSION "4.8") set(CLANG_MINIMUM_VERSION "3.4") diff --git a/lib/lua/CMakeLists.txt b/lib/lua/CMakeLists.txt index 119dd6302..5d0dc0f70 100644 --- a/lib/lua/CMakeLists.txt +++ b/lib/lua/CMakeLists.txt @@ -1,5 +1,3 @@ -cmake_minimum_required(VERSION 2.4 FATAL_ERROR) - project(lua C) set(LUA_VERSION_MAJOR 5) @@ -15,9 +13,8 @@ set(LIBS) if(APPLE) set(DEFAULT_POSIX TRUE) - set(DEFAULT_DLOPEN ON) - # use this on Mac OS X 10.3- - option(LUA_USE_MACOSX "Mac OS X 10.3-" OFF) + set(DEFAULT_DLOPEN OFF) + set(COMMON_CFLAGS "${COMMON_CFLAGS} -DLUA_USE_MACOSX") elseif(UNIX OR CYGWIN) set(DEFAULT_POSIX TRUE) elseif(WIN32) @@ -32,12 +29,6 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux") set(DEFAULT_DLOPEN ON) endif() -# For "Mac OS X 10.3-" -if(LUA_USE_MACOSX) - set(COMMON_CFLAGS "${COMMON_CFLAGS} -DLUA_USE_MACOSX") - set(LUA_USE_DLOPEN FALSE) -endif(LUA_USE_MACOSX) - option(LUA_USE_DLOPEN "Enable dlopen support." ${DEFAULT_DLOPEN}) mark_as_advanced(LUA_USE_DLOPEN) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b8ce69f1d..b6bba6e8d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,5 +1,3 @@ -cmake_minimum_required(VERSION 2.6) - project(minetest) INCLUDE(CheckIncludeFiles) @@ -124,27 +122,6 @@ option(ENABLE_FREETYPE "Enable FreeType2 (TrueType fonts and basic unicode suppo set(USE_FREETYPE FALSE) if(ENABLE_FREETYPE) -## -## Note: FindFreetype.cmake seems to have been fixed in recent versions of -## CMake. If issues persist, re-enable this workaround specificially for the -## failing platforms. -## -# if(UNIX) -# include(FindPkgConfig) -# if(PKG_CONFIG_FOUND) -# pkg_check_modules(FREETYPE QUIET freetype2) -# if(FREETYPE_FOUND) -# SET(FREETYPE_PKGCONFIG_FOUND TRUE) -# SET(FREETYPE_LIBRARY ${FREETYPE_LIBRARIES}) -# # Because CMake is idiotic -# string(REPLACE ";" " " FREETYPE_CFLAGS_STR ${FREETYPE_CFLAGS}) -# string(REPLACE ";" " " FREETYPE_LDFLAGS_STR ${FREETYPE_LDFLAGS}) -# endif(FREETYPE_FOUND) -# endif(PKG_CONFIG_FOUND) -# endif(UNIX) -# if(NOT FREETYPE_FOUND) -# find_package(Freetype) -# endif() find_package(Freetype) if(FREETYPE_FOUND) message(STATUS "Freetype enabled.") diff --git a/src/client/content_cao.cpp b/src/client/content_cao.cpp index c645900aa..c65977b44 100644 --- a/src/client/content_cao.cpp +++ b/src/client/content_cao.cpp @@ -1165,7 +1165,7 @@ void GenericCAO::step(float dtime, ClientEnvironment *env) } } - if (!getParent() && std::fabs(m_prop.automatic_rotate) > 0.001) { + if (!getParent() && node && fabs(m_prop.automatic_rotate) > 0.001f) { // This is the child node's rotation. It is only used for automatic_rotate. v3f local_rot = node->getRotation(); local_rot.Y = modulo360f(local_rot.Y - dtime * core::RADTODEG * @@ -1174,7 +1174,7 @@ void GenericCAO::step(float dtime, ClientEnvironment *env) } if (!getParent() && m_prop.automatic_face_movement_dir && - (fabs(m_velocity.Z) > 0.001 || fabs(m_velocity.X) > 0.001)) { + (fabs(m_velocity.Z) > 0.001f || fabs(m_velocity.X) > 0.001f)) { float target_yaw = atan2(m_velocity.Z, m_velocity.X) * 180 / M_PI + m_prop.automatic_face_movement_dir_offset; float max_rotation_per_sec = diff --git a/src/client/game.cpp b/src/client/game.cpp index 6151d2aa6..9e942f47a 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -186,7 +186,7 @@ struct LocalFormspecHandler : public TextDest return; } - if (m_client && m_client->modsLoaded()) + if (m_client->modsLoaded()) m_client->getScript()->on_formspec_input(m_formname, fields); } @@ -583,7 +583,7 @@ public: virtual IShaderConstantSetter* create() { - GameGlobalShaderConstantSetter *scs = new GameGlobalShaderConstantSetter( + auto *scs = new GameGlobalShaderConstantSetter( m_sky, m_force_fog_off, m_fog_range, m_client); if (!m_sky) created_nosky.push_back(scs); @@ -1338,7 +1338,7 @@ bool Game::createClient(const GameStartData &start_data) return false; } - GameGlobalShaderConstantSetterFactory *scsf = new GameGlobalShaderConstantSetterFactory( + auto *scsf = new GameGlobalShaderConstantSetterFactory( &m_flags.force_fog_off, &runData.fog_range, client); shader_src->addShaderConstantSetterFactory(scsf); @@ -1348,20 +1348,14 @@ bool Game::createClient(const GameStartData &start_data) /* Camera */ camera = new Camera(*draw_control, client); - if (!camera || !camera->successfullyCreated(*error_message)) + if (!camera->successfullyCreated(*error_message)) return false; client->setCamera(camera); /* Clouds */ - if (m_cache_enable_clouds) { + if (m_cache_enable_clouds) clouds = new Clouds(smgr, -1, time(0)); - if (!clouds) { - *error_message = "Memory allocation error (clouds)"; - errorstream << *error_message << std::endl; - return false; - } - } /* Skybox */ @@ -1369,12 +1363,6 @@ bool Game::createClient(const GameStartData &start_data) scsf->setSky(sky); skybox = NULL; // This is used/set later on in the main run loop - if (!sky) { - *error_message = "Memory allocation error sky"; - errorstream << *error_message << std::endl; - return false; - } - /* Pre-calculated values */ video::ITexture *t = texture_src->getTexture("crack_anylength.png"); @@ -1404,12 +1392,6 @@ bool Game::createClient(const GameStartData &start_data) hud = new Hud(guienv, client, player, &player->inventory); - if (!hud) { - *error_message = "Memory error: could not create HUD"; - errorstream << *error_message << std::endl; - return false; - } - mapper = client->getMinimap(); if (mapper && client->modsLoaded()) @@ -1431,11 +1413,6 @@ bool Game::initGui() // Chat backend and console gui_chat_console = new GUIChatConsole(guienv, guienv->getRootGUIElement(), -1, chat_backend, client, &g_menumgr); - if (!gui_chat_console) { - *error_message = "Could not allocate memory for chat console"; - errorstream << *error_message << std::endl; - return false; - } #ifdef HAVE_TOUCHSCREENGUI @@ -1492,9 +1469,6 @@ bool Game::connectToServer(const GameStartData &start_data, itemdef_manager, nodedef_manager, sound, eventmgr, connect_address.isIPv6(), m_game_ui.get()); - if (!client) - return false; - client->m_simple_singleplayer_mode = simple_singleplayer_mode; infostream << "Connecting to server at "; diff --git a/src/client/hud.cpp b/src/client/hud.cpp index 8d8411ca1..e956c2738 100644 --- a/src/client/hud.cpp +++ b/src/client/hud.cpp @@ -1055,9 +1055,9 @@ void drawItemStack( if (def.type == ITEM_TOOL && item.wear != 0) { // Draw a progressbar - float barheight = rect.getHeight() / 16; - float barpad_x = rect.getWidth() / 16; - float barpad_y = rect.getHeight() / 16; + float barheight = static_cast(rect.getHeight()) / 16; + float barpad_x = static_cast(rect.getWidth()) / 16; + float barpad_y = static_cast(rect.getHeight()) / 16; core::rect progressrect( rect.UpperLeftCorner.X + barpad_x, diff --git a/src/client/mapblock_mesh.cpp b/src/client/mapblock_mesh.cpp index dac25a066..4c43fcb61 100644 --- a/src/client/mapblock_mesh.cpp +++ b/src/client/mapblock_mesh.cpp @@ -1201,13 +1201,13 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset): MapBlockMesh::~MapBlockMesh() { for (scene::IMesh *m : m_mesh) { - if (m_enable_vbo && m) + if (m_enable_vbo) { for (u32 i = 0; i < m->getMeshBufferCount(); i++) { scene::IMeshBuffer *buf = m->getMeshBuffer(i); RenderingEngine::get_video_driver()->removeHardwareBuffer(buf); } + } m->drop(); - m = NULL; } delete m_minimap_mapblock; } diff --git a/src/client/tile.cpp b/src/client/tile.cpp index d03588b2b..37836d0df 100644 --- a/src/client/tile.cpp +++ b/src/client/tile.cpp @@ -1633,6 +1633,13 @@ bool TextureSource::generateImagePart(std::string part_of_name, /* IMPORTANT: When changing this, getTextureForMesh() needs to be * updated too. */ + if (!baseimg) { + errorstream << "generateImagePart(): baseimg == NULL " + << "for part_of_name=\"" << part_of_name + << "\", cancelling." << std::endl; + return false; + } + // Apply the "clean transparent" filter, if configured. if (g_settings->getBool("texture_clean_transparent")) imageCleanTransparent(baseimg, 127); diff --git a/src/filesys.cpp b/src/filesys.cpp index 2470b1b64..28a33f4d0 100644 --- a/src/filesys.cpp +++ b/src/filesys.cpp @@ -295,31 +295,26 @@ bool RecursiveDelete(const std::string &path) infostream<<"Removing \""<(argv)); // Execv shouldn't return. Failed. _exit(1); @@ -331,7 +326,6 @@ bool RecursiveDelete(const std::string &path) pid_t tpid; do{ tpid = wait(&child_status); - //if(tpid != child_pid) process_terminated(tpid); }while(tpid != child_pid); return (child_status == 0); } diff --git a/src/gui/touchscreengui.cpp b/src/gui/touchscreengui.cpp index 0d64aa618..e1a971462 100644 --- a/src/gui/touchscreengui.cpp +++ b/src/gui/touchscreengui.cpp @@ -881,8 +881,7 @@ void TouchScreenGUI::translateEvent(const SEvent &event) s32 dyj = event.TouchInput.Y - m_screensize.Y + button_size * 5.0f / 2.0f; bool inside_joystick = (dxj * dxj + dyj * dyj <= button_size * button_size * 1.5 * 1.5); - if (m_joystick_has_really_moved || - (!m_joystick_has_really_moved && inside_joystick) || + if (m_joystick_has_really_moved || inside_joystick || (!m_fixed_joystick && distance_sq > m_touchscreen_threshold * m_touchscreen_threshold)) { m_joystick_has_really_moved = true; diff --git a/src/irrlicht_changes/CGUITTFont.h b/src/irrlicht_changes/CGUITTFont.h index cf64934a2..310f74f67 100644 --- a/src/irrlicht_changes/CGUITTFont.h +++ b/src/irrlicht_changes/CGUITTFont.h @@ -356,7 +356,7 @@ namespace gui load_flags = FT_LOAD_DEFAULT | FT_LOAD_RENDER; if (!useHinting()) load_flags |= FT_LOAD_NO_HINTING; if (!useAutoHinting()) load_flags |= FT_LOAD_NO_AUTOHINT; - if (useMonochrome()) load_flags |= FT_LOAD_MONOCHROME | FT_LOAD_TARGET_MONO | FT_RENDER_MODE_MONO; + if (useMonochrome()) load_flags |= FT_LOAD_MONOCHROME | FT_LOAD_TARGET_MONO; else load_flags |= FT_LOAD_TARGET_NORMAL; } u32 getWidthFromCharacter(wchar_t c) const; diff --git a/src/irrlicht_changes/irrUString.h b/src/irrlicht_changes/irrUString.h index b628c092c..09172ee6d 100644 --- a/src/irrlicht_changes/irrUString.h +++ b/src/irrlicht_changes/irrUString.h @@ -1331,7 +1331,7 @@ public: { u32 i; const uchar16_t* oa = other.c_str(); - for(i=0; array[i] && oa[i] && i < n; ++i) + for(i=0; i < n && array[i] && oa[i]; ++i) if (array[i] != oa[i]) return false; @@ -1350,7 +1350,7 @@ public: if (!str) return false; u32 i; - for(i=0; array[i] && str[i] && i < n; ++i) + for(i=0; i < n && array[i] && str[i]; ++i) if (array[i] != str[i]) return false; diff --git a/src/mapgen/mapgen_v7.cpp b/src/mapgen/mapgen_v7.cpp index cc5f5726d..91f004518 100644 --- a/src/mapgen/mapgen_v7.cpp +++ b/src/mapgen/mapgen_v7.cpp @@ -297,7 +297,7 @@ int MapgenV7::getSpawnLevelAtPoint(v2s16 p) int iters = 256; while (iters > 0 && y <= max_spawn_y) { if (!getMountainTerrainAtPoint(p.X, y + 1, p.Y)) { - if (y <= water_level || y > max_spawn_y) + if (y <= water_level) return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point // y + 1 due to biome 'dust' diff --git a/src/mapgen/treegen.cpp b/src/mapgen/treegen.cpp index e633d800a..ec7771439 100644 --- a/src/mapgen/treegen.cpp +++ b/src/mapgen/treegen.cpp @@ -406,7 +406,8 @@ treegen::error make_ltree(MMVManip &vmanip, v3s16 p0, v3f(position.X, position.Y, position.Z - 1), tree_definition ); - } if (!stack_orientation.empty()) { + } + if (!stack_orientation.empty()) { s16 size = 1; for (x = -size; x <= size; x++) for (y = -size; y <= size; y++) diff --git a/src/network/serverpackethandler.cpp b/src/network/serverpackethandler.cpp index 3db4eb286..c636d01e1 100644 --- a/src/network/serverpackethandler.cpp +++ b/src/network/serverpackethandler.cpp @@ -316,7 +316,7 @@ void Server::handleCommand_Init2(NetworkPacket* pkt) // Send active objects { PlayerSAO *sao = getPlayerSAO(peer_id); - if (client && sao) + if (sao) SendActiveObjectRemoveAdd(client, sao); } diff --git a/src/nodedef.cpp b/src/nodedef.cpp index 80013192d..f9d15a9f6 100644 --- a/src/nodedef.cpp +++ b/src/nodedef.cpp @@ -617,7 +617,7 @@ static void fillTileAttribs(ITextureSource *tsrc, TileLayer *layer, bool has_scale = tiledef.scale > 0; bool use_autoscale = tsettings.autoscale_mode == AUTOSCALE_FORCE || (tsettings.autoscale_mode == AUTOSCALE_ENABLE && !has_scale); - if (use_autoscale && layer->texture) { + if (use_autoscale) { auto texture_size = layer->texture->getOriginalSize(); float base_size = tsettings.node_texture_size; float size = std::fmin(texture_size.Width, texture_size.Height); diff --git a/src/script/cpp_api/s_security.cpp b/src/script/cpp_api/s_security.cpp index 01333b941..63058d7c3 100644 --- a/src/script/cpp_api/s_security.cpp +++ b/src/script/cpp_api/s_security.cpp @@ -398,10 +398,9 @@ bool ScriptApiSecurity::safeLoadFile(lua_State *L, const char *path, const char lua_pushfstring(L, "%s: %s", path, strerror(errno)); return false; } - chunk_name = new char[strlen(display_name) + 2]; - chunk_name[0] = '@'; - chunk_name[1] = '\0'; - strcat(chunk_name, display_name); + size_t len = strlen(display_name) + 2; + chunk_name = new char[len]; + snprintf(chunk_name, len, "@%s", display_name); } size_t start = 0; diff --git a/src/util/srp.cpp b/src/util/srp.cpp index f4d369d68..ceb2fef9e 100644 --- a/src/util/srp.cpp +++ b/src/util/srp.cpp @@ -1015,10 +1015,10 @@ void srp_user_process_challenge(struct SRPUser *usr, goto cleanup_and_exit; *bytes_M = usr->M; - if (len_M) *len_M = hash_length(usr->hash_alg); + *len_M = hash_length(usr->hash_alg); } else { *bytes_M = NULL; - if (len_M) *len_M = 0; + *len_M = 0; } cleanup_and_exit: diff --git a/src/util/string.cpp b/src/util/string.cpp index 8381a29c5..3ac3b8cf0 100644 --- a/src/util/string.cpp +++ b/src/util/string.cpp @@ -633,7 +633,7 @@ static bool parseNamedColorString(const std::string &value, video::SColor &color color_name = value; } - color_name = lowercase(value); + color_name = lowercase(color_name); std::map::const_iterator it; it = named_colors.colors.find(color_name); From 8f72d4b2940f0bd5486e38bd58127d14a1762be8 Mon Sep 17 00:00:00 2001 From: Lars Mueller Date: Thu, 24 Dec 2020 14:48:05 +0100 Subject: [PATCH 21/31] Fix minetest.is_nan --- builtin/common/misc_helpers.lua | 4 ++++ src/script/lua_api/l_util.cpp | 11 ----------- src/script/lua_api/l_util.h | 3 --- 3 files changed, 4 insertions(+), 14 deletions(-) diff --git a/builtin/common/misc_helpers.lua b/builtin/common/misc_helpers.lua index e29a9f422..0f3897f47 100644 --- a/builtin/common/misc_helpers.lua +++ b/builtin/common/misc_helpers.lua @@ -697,3 +697,7 @@ function core.privs_to_string(privs, delim) end return table.concat(list, delim) end + +function core.is_nan(number) + return number ~= number +end diff --git a/src/script/lua_api/l_util.cpp b/src/script/lua_api/l_util.cpp index cd63e20c2..6490eb578 100644 --- a/src/script/lua_api/l_util.cpp +++ b/src/script/lua_api/l_util.cpp @@ -239,15 +239,6 @@ int ModApiUtil::l_is_yes(lua_State *L) return 1; } -// is_nan(arg) -int ModApiUtil::l_is_nan(lua_State *L) -{ - NO_MAP_LOCK_REQUIRED; - - lua_pushboolean(L, isNaN(L, 1)); - return 1; -} - // get_builtin_path() int ModApiUtil::l_get_builtin_path(lua_State *L) { @@ -493,7 +484,6 @@ void ModApiUtil::Initialize(lua_State *L, int top) API_FCT(get_password_hash); API_FCT(is_yes); - API_FCT(is_nan); API_FCT(get_builtin_path); @@ -526,7 +516,6 @@ void ModApiUtil::InitializeClient(lua_State *L, int top) API_FCT(write_json); API_FCT(is_yes); - API_FCT(is_nan); API_FCT(compress); API_FCT(decompress); diff --git a/src/script/lua_api/l_util.h b/src/script/lua_api/l_util.h index 9ff91bb53..b6c1b58af 100644 --- a/src/script/lua_api/l_util.h +++ b/src/script/lua_api/l_util.h @@ -65,9 +65,6 @@ private: // is_yes(arg) static int l_is_yes(lua_State *L); - // is_nan(arg) - static int l_is_nan(lua_State *L); - // get_builtin_path() static int l_get_builtin_path(lua_State *L); From 55dba1bc6d90c90ddd77d60f4760e34e28a6382f Mon Sep 17 00:00:00 2001 From: Zughy <63455151+Zughy@users.noreply.github.com> Date: Mon, 28 Dec 2020 12:56:58 +0000 Subject: [PATCH 22/31] Display Minetest header when menu_last_game value isn't available anymore (#10751) --- builtin/mainmenu/init.lua | 10 ++++++++++ builtin/mainmenu/tab_local.lua | 1 + 2 files changed, 11 insertions(+) diff --git a/builtin/mainmenu/init.lua b/builtin/mainmenu/init.lua index 2fc0ae64c..656d1d149 100644 --- a/builtin/mainmenu/init.lua +++ b/builtin/mainmenu/init.lua @@ -106,6 +106,16 @@ local function init_globals() if last_tab and tv_main.current_tab ~= last_tab then tv_main:set_tab(last_tab) end + + -- In case the folder of the last selected game has been deleted, + -- display "Minetest" as a header + if tv_main.current_tab == "local" then + local game = pkgmgr.find_by_gameid(core.settings:get("menu_last_game")) + if game == nil then + mm_texture.reset() + end + end + ui.set_default("maintab") tv_main:show() diff --git a/builtin/mainmenu/tab_local.lua b/builtin/mainmenu/tab_local.lua index 1aee246fc..2eb4752bc 100644 --- a/builtin/mainmenu/tab_local.lua +++ b/builtin/mainmenu/tab_local.lua @@ -18,6 +18,7 @@ local enable_gamebar = PLATFORM ~= "Android" local current_game, singleplayer_refresh_gamebar + if enable_gamebar then function current_game() local last_game_id = core.settings:get("menu_last_game") From 09d7fbd645888aac32d089ff528ac1d1eb87e72d Mon Sep 17 00:00:00 2001 From: Lars Mueller Date: Thu, 24 Dec 2020 14:26:42 +0100 Subject: [PATCH 23/31] Fix item tooltip background color not working --- src/gui/guiFormSpecMenu.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gui/guiFormSpecMenu.cpp b/src/gui/guiFormSpecMenu.cpp index ed197d0d1..61112b570 100644 --- a/src/gui/guiFormSpecMenu.cpp +++ b/src/gui/guiFormSpecMenu.cpp @@ -3718,7 +3718,8 @@ void GUIFormSpecMenu::showTooltip(const std::wstring &text, { EnrichedString ntext(text); ntext.setDefaultColor(color); - ntext.setBackground(bgcolor); + if (!ntext.hasBackground()) + ntext.setBackground(bgcolor); setStaticText(m_tooltip_element, ntext); From 9250b5205a6c627dfa18b7870b454d74f8d9dae6 Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein <54945686+EliasFleckenstein03@users.noreply.github.com> Date: Tue, 29 Dec 2020 16:50:09 +0100 Subject: [PATCH 24/31] Add minetest.get_objects_in_area (#10668) --- doc/lua_api.txt | 3 +++ src/script/lua_api/l_env.cpp | 26 ++++++++++++++++++++++++++ src/script/lua_api/l_env.h | 3 +++ src/server/activeobjectmgr.cpp | 15 +++++++++++++++ src/server/activeobjectmgr.h | 3 +++ src/serverenvironment.h | 7 +++++++ 6 files changed, 57 insertions(+) diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 708d6b0bc..800fc0c24 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -4891,6 +4891,9 @@ Environment access * `minetest.get_objects_inside_radius(pos, radius)`: returns a list of ObjectRefs. * `radius`: using an euclidean metric +* `minetest.get_objects_in_area(pos1, pos2)`: returns a list of + ObjectRefs. + * `pos1` and `pos2` are the min and max positions of the area to search. * `minetest.set_timeofday(val)` * `val` is between `0` and `1`; `0` for midnight, `0.5` for midday * `minetest.get_timeofday()` diff --git a/src/script/lua_api/l_env.cpp b/src/script/lua_api/l_env.cpp index 021ef2ea7..c75fc8dc7 100644 --- a/src/script/lua_api/l_env.cpp +++ b/src/script/lua_api/l_env.cpp @@ -743,6 +743,31 @@ int ModApiEnvMod::l_get_objects_inside_radius(lua_State *L) return 1; } +// get_objects_in_area(pos, minp, maxp) +int ModApiEnvMod::l_get_objects_in_area(lua_State *L) +{ + GET_ENV_PTR; + ScriptApiBase *script = getScriptApiBase(L); + + v3f minp = read_v3f(L, 1) * BS; + v3f maxp = read_v3f(L, 2) * BS; + aabb3f box(minp, maxp); + box.repair(); + std::vector objs; + + auto include_obj_cb = [](ServerActiveObject *obj){ return !obj->isGone(); }; + env->getObjectsInArea(objs, box, include_obj_cb); + + int i = 0; + lua_createtable(L, objs.size(), 0); + for (const auto obj : objs) { + // Insert object reference into table + script->objectrefGetOrCreate(L, obj); + lua_rawseti(L, -2, ++i); + } + return 1; +} + // set_timeofday(val) // val = 0...1 int ModApiEnvMod::l_set_timeofday(lua_State *L) @@ -1413,6 +1438,7 @@ void ModApiEnvMod::Initialize(lua_State *L, int top) API_FCT(get_node_timer); API_FCT(get_connected_players); API_FCT(get_player_by_name); + API_FCT(get_objects_in_area); API_FCT(get_objects_inside_radius); API_FCT(set_timeofday); API_FCT(get_timeofday); diff --git a/src/script/lua_api/l_env.h b/src/script/lua_api/l_env.h index 7f212b5fc..42c2d64f8 100644 --- a/src/script/lua_api/l_env.h +++ b/src/script/lua_api/l_env.h @@ -114,6 +114,9 @@ private: // get_objects_inside_radius(pos, radius) static int l_get_objects_inside_radius(lua_State *L); + + // get_objects_in_area(pos, minp, maxp) + static int l_get_objects_in_area(lua_State *L); // set_timeofday(val) // val = 0...1 diff --git a/src/server/activeobjectmgr.cpp b/src/server/activeobjectmgr.cpp index 1b8e31409..acd6611f4 100644 --- a/src/server/activeobjectmgr.cpp +++ b/src/server/activeobjectmgr.cpp @@ -127,6 +127,21 @@ void ActiveObjectMgr::getObjectsInsideRadius(const v3f &pos, float radius, } } +void ActiveObjectMgr::getObjectsInArea(const aabb3f &box, + std::vector &result, + std::function include_obj_cb) +{ + for (auto &activeObject : m_active_objects) { + ServerActiveObject *obj = activeObject.second; + const v3f &objectpos = obj->getBasePosition(); + if (!box.isPointInside(objectpos)) + continue; + + if (!include_obj_cb || include_obj_cb(obj)) + result.push_back(obj); + } +} + void ActiveObjectMgr::getAddedActiveObjectsAroundPos(const v3f &player_pos, f32 radius, f32 player_radius, std::set ¤t_objects, std::queue &added_objects) diff --git a/src/server/activeobjectmgr.h b/src/server/activeobjectmgr.h index bc2085499..d43f5643c 100644 --- a/src/server/activeobjectmgr.h +++ b/src/server/activeobjectmgr.h @@ -38,6 +38,9 @@ public: void getObjectsInsideRadius(const v3f &pos, float radius, std::vector &result, std::function include_obj_cb); + void getObjectsInArea(const aabb3f &box, + std::vector &result, + std::function include_obj_cb); void getAddedActiveObjectsAroundPos(const v3f &player_pos, f32 radius, f32 player_radius, std::set ¤t_objects, diff --git a/src/serverenvironment.h b/src/serverenvironment.h index cfd5b8f3e..c76d34a37 100644 --- a/src/serverenvironment.h +++ b/src/serverenvironment.h @@ -331,6 +331,13 @@ public: { return m_ao_manager.getObjectsInsideRadius(pos, radius, objects, include_obj_cb); } + + // Find all active objects inside a box + void getObjectsInArea(std::vector &objects, const aabb3f &box, + std::function include_obj_cb) + { + return m_ao_manager.getObjectsInArea(box, objects, include_obj_cb); + } // Clear objects, loading and going through every MapBlock void clearObjects(ClearObjectsMode mode); From ff921f6989cc6e8e0be6bf9ac196e90331bb3eb4 Mon Sep 17 00:00:00 2001 From: Jean-Patrick Guerrero Date: Fri, 1 Jan 2021 17:03:34 +0100 Subject: [PATCH 25/31] Formspecs: Fix broken texture escaping with model[] --- src/gui/guiFormSpecMenu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/guiFormSpecMenu.cpp b/src/gui/guiFormSpecMenu.cpp index 61112b570..973fc60a8 100644 --- a/src/gui/guiFormSpecMenu.cpp +++ b/src/gui/guiFormSpecMenu.cpp @@ -2787,7 +2787,7 @@ void GUIFormSpecMenu::parseModel(parserData *data, const std::string &element) auto meshnode = e->setMesh(mesh); for (u32 i = 0; i < textures.size() && i < meshnode->getMaterialCount(); ++i) - e->setTexture(i, m_tsrc->getTexture(textures[i])); + e->setTexture(i, m_tsrc->getTexture(unescape_string(textures[i]))); if (vec_rot.size() >= 2) e->setRotation(v2f(stof(vec_rot[0]), stof(vec_rot[1]))); From 92aac69b36d37ace8d2e06721cfa5e488427dcdf Mon Sep 17 00:00:00 2001 From: Zughy <63455151+Zughy@users.noreply.github.com> Date: Sat, 2 Jan 2021 15:13:02 +0100 Subject: [PATCH 26/31] "Browse online content" formspec improvement (#10756) --- LICENSE.txt | 11 ++++ builtin/mainmenu/dlg_contentstore.lua | 68 +++++++++++++------------ textures/base/pack/cdb_add.png | Bin 0 -> 147 bytes textures/base/pack/cdb_clear.png | Bin 0 -> 182 bytes textures/base/pack/cdb_downloading.png | Bin 0 -> 201 bytes textures/base/pack/cdb_queued.png | Bin 0 -> 210 bytes textures/base/pack/cdb_update.png | Bin 0 -> 173 bytes textures/base/pack/cdb_viewonline.png | Bin 0 -> 191 bytes 8 files changed, 47 insertions(+), 32 deletions(-) create mode 100644 textures/base/pack/cdb_add.png create mode 100644 textures/base/pack/cdb_clear.png create mode 100644 textures/base/pack/cdb_downloading.png create mode 100644 textures/base/pack/cdb_queued.png create mode 100644 textures/base/pack/cdb_update.png create mode 100644 textures/base/pack/cdb_viewonline.png diff --git a/LICENSE.txt b/LICENSE.txt index 9fbd23723..9b8ee851a 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -11,6 +11,9 @@ http://creativecommons.org/licenses/by-sa/3.0/ textures/base/pack/refresh.png is under the Apache 2 license https://www.apache.org/licenses/LICENSE-2.0.html +Textures by Zughy are under CC BY-SA 4.0 +https://creativecommons.org/licenses/by-sa/4.0/ + Authors of media files ----------------------- Everything not listed in here: @@ -47,6 +50,14 @@ srifqi textures/base/pack/joystick_off.png textures/base/pack/minimap_btn.png +Zughy: + textures/base/pack/cdb_add.png + textures/base/pack/cdb_clear.png + textures/base/pack/cdb_downloading.png + textures/base/pack/cdb_queued.png + textures/base/pack/cdb_update.png + textures/base/pack/cdb_viewonline.png + License of Minetest source code ------------------------------- diff --git a/builtin/mainmenu/dlg_contentstore.lua b/builtin/mainmenu/dlg_contentstore.lua index 548bae67e..7f6b4b7e4 100644 --- a/builtin/mainmenu/dlg_contentstore.lua +++ b/builtin/mainmenu/dlg_contentstore.lua @@ -631,7 +631,7 @@ function store.get_formspec(dlgdata) "size[15.75,9.5]", "position[0.5,0.55]", - "style[status;border=false]", + "style[status,downloading,queued;border=false]", "container[0.375,0.375]", "field[0,0;7.225,0.8;search_string;;", core.formspec_escape(search_string), "]", @@ -658,7 +658,7 @@ function store.get_formspec(dlgdata) } if number_downloading > 0 then - formspec[#formspec + 1] = "button[12.75,0.375;2.625,0.8;status;" + formspec[#formspec + 1] = "button[12.75,0.375;2.625,0.8;downloading;" if #download_queue > 0 then formspec[#formspec + 1] = fgettext("$1 downloading,\n$2 queued", number_downloading, #download_queue) else @@ -702,11 +702,17 @@ function store.get_formspec(dlgdata) } end + -- download/queued tooltips always have the same message + local tooltip_colors = ";#dff6f5;#302c2e]" + formspec[#formspec + 1] = "tooltip[downloading;" .. fgettext("Downloading...") .. tooltip_colors + formspec[#formspec + 1] = "tooltip[queued;" .. fgettext("Queued") .. tooltip_colors + local start_idx = (cur_page - 1) * num_per_page + 1 for i=start_idx, math.min(#store.packages, start_idx+num_per_page-1) do local package = store.packages[i] + local container_y = (i - start_idx) * 1.375 + (2*0.375 + 0.8) formspec[#formspec + 1] = "container[0.375," - formspec[#formspec + 1] = (i - start_idx) * 1.375 + (2*0.375 + 0.8) + formspec[#formspec + 1] = container_y formspec[#formspec + 1] = "]" -- image @@ -722,52 +728,50 @@ function store.get_formspec(dlgdata) formspec[#formspec + 1] = "]" -- buttons - local description_width = W - 0.375*5 - 1 - 2*1.5 + local left_base = "image_button[-1.55,0;0.7,0.7;" .. core.formspec_escape(defaulttexturedir) formspec[#formspec + 1] = "container[" formspec[#formspec + 1] = W - 0.375*2 formspec[#formspec + 1] = ",0.1]" if package.downloading then - formspec[#formspec + 1] = "button[-3.5,0;2,0.8;status;" - formspec[#formspec + 1] = fgettext("Downloading...") - formspec[#formspec + 1] = "]" + formspec[#formspec + 1] = "animated_image[-1.7,-0.15;1,1;downloading;" + formspec[#formspec + 1] = core.formspec_escape(defaulttexturedir) + formspec[#formspec + 1] = "cdb_downloading.png;3;400;]" elseif package.queued then - formspec[#formspec + 1] = "button[-3.5,0;2,0.8;status;" - formspec[#formspec + 1] = fgettext("Queued") - formspec[#formspec + 1] = "]" + formspec[#formspec + 1] = left_base + formspec[#formspec + 1] = core.formspec_escape(defaulttexturedir) + formspec[#formspec + 1] = "cdb_queued.png;queued]" elseif not package.path then - formspec[#formspec + 1] = "button[-3,0;1.5,0.8;install_" - formspec[#formspec + 1] = tostring(i) - formspec[#formspec + 1] = ";" - formspec[#formspec + 1] = fgettext("Install") - formspec[#formspec + 1] = "]" + local elem_name = "install_" .. i .. ";" + formspec[#formspec + 1] = "style[" .. elem_name .. "bgcolor=#71aa34]" + formspec[#formspec + 1] = left_base .. "cdb_add.png;" .. elem_name .. "]" + formspec[#formspec + 1] = "tooltip[" .. elem_name .. fgettext("Install") .. tooltip_colors else if package.installed_release < package.release then - description_width = description_width - 1.5 -- The install_ action also handles updating - formspec[#formspec + 1] = "button[-4.5,0;1.5,0.8;install_" - formspec[#formspec + 1] = tostring(i) - formspec[#formspec + 1] = ";" - formspec[#formspec + 1] = fgettext("Update") - formspec[#formspec + 1] = "]" - end + local elem_name = "install_" .. i .. ";" + formspec[#formspec + 1] = "style[" .. elem_name .. "bgcolor=#28ccdf]" + formspec[#formspec + 1] = left_base .. "cdb_update.png;" .. elem_name .. "]" + formspec[#formspec + 1] = "tooltip[" .. elem_name .. fgettext("Update") .. tooltip_colors + else - formspec[#formspec + 1] = "button[-3,0;1.5,0.8;uninstall_" - formspec[#formspec + 1] = tostring(i) - formspec[#formspec + 1] = ";" - formspec[#formspec + 1] = fgettext("Uninstall") - formspec[#formspec + 1] = "]" + local elem_name = "uninstall_" .. i .. ";" + formspec[#formspec + 1] = "style[" .. elem_name .. "bgcolor=#a93b3b]" + formspec[#formspec + 1] = left_base .. "cdb_clear.png;" .. elem_name .. "]" + formspec[#formspec + 1] = "tooltip[" .. elem_name .. fgettext("Uninstall") .. tooltip_colors + end end - formspec[#formspec + 1] = "button[-1.5,0;1.5,0.8;view_" - formspec[#formspec + 1] = tostring(i) - formspec[#formspec + 1] = ";" - formspec[#formspec + 1] = fgettext("View") - formspec[#formspec + 1] = "]" + local web_elem_name = "view_" .. i .. ";" + formspec[#formspec + 1] = "image_button[-0.7,0;0.7,0.7;" .. + core.formspec_escape(defaulttexturedir) .. "cdb_viewonline.png;" .. web_elem_name .. "]" + formspec[#formspec + 1] = "tooltip[" .. web_elem_name .. + fgettext("View more information in a web browser") .. tooltip_colors formspec[#formspec + 1] = "container_end[]" -- description + local description_width = W - 0.375*5 - 0.85 - 2*0.7 formspec[#formspec + 1] = "textarea[1.855,0.3;" formspec[#formspec + 1] = tostring(description_width) formspec[#formspec + 1] = ",0.8;;;" diff --git a/textures/base/pack/cdb_add.png b/textures/base/pack/cdb_add.png new file mode 100644 index 0000000000000000000000000000000000000000..3e3d067e33b98a39c1e07e17a611fa88eeb23281 GIT binary patch literal 147 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnH3?%tPCZz)@o&cW^S0KIZs!ic46U%BBo0DHI z0{M(3L4Lsu4$p3+0Xe3gE{-7;w~`YU$UTT^IQPJ(!6<^cz%Z<>Ev-?~+u3<>fMmhS q|M8FiKQ>~|V_o+4kG#frVTP$m0*-x0uSx?AVDNPHb6Mw<&;$S-YA!PX literal 0 HcmV?d00001 diff --git a/textures/base/pack/cdb_clear.png b/textures/base/pack/cdb_clear.png new file mode 100644 index 0000000000000000000000000000000000000000..4490d41cbc082cc9f2271daf2a3a52ca46dba680 GIT binary patch literal 182 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnH3?%tPCZz)@o&cW^S0Me&LvN+Eb)1>=HJOB2 zKt5whkY6x^!?PP{Ku(0Gi(^Q|t>lCSb`O#gA{f##ObymH7%)XB@|+g9C}YrUZnA~p zOadRTEyKk!Q<+uqCM>5ocv~;@EL_MZFnRHOC*QbaR?|vm`If}ehDzQU2hSh)&{$Q+ Z$PoNa@QjJ(e~`-lg(ETw3ETp)z4*}Q$iB}B>zE{ literal 0 HcmV?d00001 diff --git a/textures/base/pack/cdb_queued.png b/textures/base/pack/cdb_queued.png new file mode 100644 index 0000000000000000000000000000000000000000..6972f7fb8328503589abfdb65cec902640e5f816 GIT binary patch literal 210 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnH3?%tPCZz)@o&cW^S0Mf6%)`lH5~`<4|e%426_ z0Qrn1L4Lsu4$p3+0XhDjE{-7;w~`YUNEjTF@ RIDtkpc)I$ztaD0e0sxzGGnoJY literal 0 HcmV?d00001 diff --git a/textures/base/pack/cdb_viewonline.png b/textures/base/pack/cdb_viewonline.png new file mode 100644 index 0000000000000000000000000000000000000000..ae2a146b855715506dcaacd5ec0fb55713762df2 GIT binary patch literal 191 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfv{s5m4S0Eh~9NbheWx?dW>-Vm$ z-@z#j6k;q1@(X5gcy=QV$cgiGaSW-rm7E|E(%|Xo$v9PiNr%#+6&g7jDlJPKJOXY6 z1Ozf}ZgpxuS3das?*KDHmN@U5yct51fi^LCy85}Sb4q9e08d;#XaE2J literal 0 HcmV?d00001 From ad58fb22064c7db223cb825596c12f93f2a75a26 Mon Sep 17 00:00:00 2001 From: OgelGames Date: Sun, 3 Jan 2021 01:13:53 +1100 Subject: [PATCH 27/31] Clarify documentation of minetest.get_modpath and minetest.get_modnames (#10771) --- doc/lua_api.txt | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 800fc0c24..8bf6ade69 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -4327,11 +4327,14 @@ Utilities * `minetest.get_current_modname()`: returns the currently loading mod's name, when loading a mod. -* `minetest.get_modpath(modname)`: returns e.g. - `"/home/user/.minetest/usermods/modname"`. - * Useful for loading additional `.lua` modules or static data from mod -* `minetest.get_modnames()`: returns a list of installed mods - * Return a list of installed mods, sorted alphabetically +* `minetest.get_modpath(modname)`: returns the directory path for a mod, + e.g. `"/home/user/.minetest/usermods/modname"`. + * Returns nil if the mod is not enabled or does not exist (not installed). + * Works regardless of whether the mod has been loaded yet. + * Useful for loading additional `.lua` modules or static data from a mod, + or checking if a mod is enabled. +* `minetest.get_modnames()`: returns a list of enabled mods, sorted alphabetically. + * Does not include disabled mods, even if they are installed. * `minetest.get_worldpath()`: returns e.g. `"/home/user/.minetest/world"` * Useful for storing custom data * `minetest.is_singleplayer()` From dd5a732fa90550066bb96305b64b6648903cc822 Mon Sep 17 00:00:00 2001 From: hecks <42101236+hecktest@users.noreply.github.com> Date: Sat, 2 Jan 2021 15:14:29 +0100 Subject: [PATCH 28/31] Add on_deactivate callback for luaentities (#10723) --- builtin/profiler/instrumentation.lua | 1 + doc/lua_api.txt | 2 + games/devtest/mods/testentities/callbacks.lua | 3 ++ src/script/cpp_api/s_entity.cpp | 26 ++++++++++ src/script/cpp_api/s_entity.h | 1 + src/script/lua_api/l_object.cpp | 2 +- src/server/luaentity_sao.cpp | 13 ++++- src/server/luaentity_sao.h | 5 ++ src/server/player_sao.cpp | 2 +- src/server/serveractiveobject.cpp | 16 ++++++ src/server/serveractiveobject.h | 50 ++++++++++++------- src/serverenvironment.cpp | 12 +++-- 12 files changed, 106 insertions(+), 27 deletions(-) diff --git a/builtin/profiler/instrumentation.lua b/builtin/profiler/instrumentation.lua index 237f048fb..6b951a2c2 100644 --- a/builtin/profiler/instrumentation.lua +++ b/builtin/profiler/instrumentation.lua @@ -160,6 +160,7 @@ local function init() -- Simple iteration would ignore lookup via __index. local entity_instrumentation = { "on_activate", + "on_deactivate", "on_step", "on_punch", "on_rightclick", diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 8bf6ade69..47c2776e6 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -4207,6 +4207,8 @@ Callbacks: * Called when the object is instantiated. * `dtime_s` is the time passed since the object was unloaded, which can be used for updating the entity state. +* `on_deactivate(self) + * Called when the object is about to get removed or unloaded. * `on_step(self, dtime)` * Called on every server tick, after movement and collision processing. `dtime` is usually 0.1 seconds, as per the `dedicated_server_step` setting diff --git a/games/devtest/mods/testentities/callbacks.lua b/games/devtest/mods/testentities/callbacks.lua index 711079f87..320690b39 100644 --- a/games/devtest/mods/testentities/callbacks.lua +++ b/games/devtest/mods/testentities/callbacks.lua @@ -31,6 +31,9 @@ minetest.register_entity("testentities:callback", { on_activate = function(self, staticdata, dtime_s) message("Callback entity: on_activate! pos="..spos(self).."; dtime_s="..dtime_s) end, + on_deactivate = function(self) + message("Callback entity: on_deactivate! pos="..spos(self)) + end, on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir, damage) local name = get_object_name(puncher) message( diff --git a/src/script/cpp_api/s_entity.cpp b/src/script/cpp_api/s_entity.cpp index ea9320051..746f7013e 100644 --- a/src/script/cpp_api/s_entity.cpp +++ b/src/script/cpp_api/s_entity.cpp @@ -103,6 +103,32 @@ void ScriptApiEntity::luaentity_Activate(u16 id, lua_pop(L, 2); // Pop object and error handler } +void ScriptApiEntity::luaentity_Deactivate(u16 id) +{ + SCRIPTAPI_PRECHECKHEADER + + verbosestream << "scriptapi_luaentity_deactivate: id=" << id << std::endl; + + int error_handler = PUSH_ERROR_HANDLER(L); + + // Get the entity + luaentity_get(L, id); + int object = lua_gettop(L); + + // Get on_deactivate + lua_getfield(L, -1, "on_deactivate"); + if (!lua_isnil(L, -1)) { + luaL_checktype(L, -1, LUA_TFUNCTION); + lua_pushvalue(L, object); + + setOriginFromTable(object); + PCALL_RES(lua_pcall(L, 1, 0, error_handler)); + } else { + lua_pop(L, 1); + } + lua_pop(L, 2); // Pop object and error handler +} + void ScriptApiEntity::luaentity_Remove(u16 id) { SCRIPTAPI_PRECHECKHEADER diff --git a/src/script/cpp_api/s_entity.h b/src/script/cpp_api/s_entity.h index b5f7a6586..b52f6e447 100644 --- a/src/script/cpp_api/s_entity.h +++ b/src/script/cpp_api/s_entity.h @@ -33,6 +33,7 @@ public: bool luaentity_Add(u16 id, const char *name); void luaentity_Activate(u16 id, const std::string &staticdata, u32 dtime_s); + void luaentity_Deactivate(u16 id); void luaentity_Remove(u16 id); std::string luaentity_GetStaticdata(u16 id); void luaentity_GetProperties(u16 id, diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index 4d7a1bc41..f52e4892e 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -110,7 +110,7 @@ int ObjectRef::l_remove(lua_State *L) sao->clearParentAttachment(); verbosestream << "ObjectRef::l_remove(): id=" << sao->getId() << std::endl; - sao->m_pending_removal = true; + sao->markForRemoval(); return 0; } diff --git a/src/server/luaentity_sao.cpp b/src/server/luaentity_sao.cpp index b39797531..c7277491a 100644 --- a/src/server/luaentity_sao.cpp +++ b/src/server/luaentity_sao.cpp @@ -112,6 +112,15 @@ void LuaEntitySAO::addedToEnvironment(u32 dtime_s) } } +void LuaEntitySAO::dispatchScriptDeactivate() +{ + // Ensure that this is in fact a registered entity, + // and that it isn't already gone. + // The latter also prevents this from ever being called twice. + if (m_registered && !isGone()) + m_env->getScriptIface()->luaentity_Deactivate(m_id); +} + void LuaEntitySAO::step(float dtime, bool send_recommended) { if(!m_properties_sent) @@ -302,7 +311,7 @@ u16 LuaEntitySAO::punch(v3f dir, { if (!m_registered) { // Delete unknown LuaEntities when punched - m_pending_removal = true; + markForRemoval(); return 0; } @@ -335,7 +344,7 @@ u16 LuaEntitySAO::punch(v3f dir, clearParentAttachment(); clearChildAttachments(); m_env->getScriptIface()->luaentity_on_death(m_id, puncher); - m_pending_removal = true; + markForRemoval(); } actionstream << puncher->getDescription() << " (id=" << puncher->getId() << diff --git a/src/server/luaentity_sao.h b/src/server/luaentity_sao.h index e060aa06d..6883ae1b9 100644 --- a/src/server/luaentity_sao.h +++ b/src/server/luaentity_sao.h @@ -71,6 +71,11 @@ public: bool getSelectionBox(aabb3f *toset) const; bool collideWithObjects() const; +protected: + void dispatchScriptDeactivate(); + virtual void onMarkedForDeactivation() { dispatchScriptDeactivate(); } + virtual void onMarkedForRemoval() { dispatchScriptDeactivate(); } + private: std::string getPropertyPacket(); void sendPosition(bool do_interpolate, bool is_movement_end); diff --git a/src/server/player_sao.cpp b/src/server/player_sao.cpp index 62515d1c9..232c6a01d 100644 --- a/src/server/player_sao.cpp +++ b/src/server/player_sao.cpp @@ -531,7 +531,7 @@ bool PlayerSAO::setWieldedItem(const ItemStack &item) void PlayerSAO::disconnected() { m_peer_id = PEER_ID_INEXISTENT; - m_pending_removal = true; + markForRemoval(); } void PlayerSAO::unlinkPlayerSessionAndSave() diff --git a/src/server/serveractiveobject.cpp b/src/server/serveractiveobject.cpp index 8cb59b2d6..96b433d1d 100644 --- a/src/server/serveractiveobject.cpp +++ b/src/server/serveractiveobject.cpp @@ -73,3 +73,19 @@ void ServerActiveObject::dumpAOMessagesToQueue(std::queue & m_messages_out.pop(); } } + +void ServerActiveObject::markForRemoval() +{ + if (!m_pending_removal) { + onMarkedForRemoval(); + m_pending_removal = true; + } +} + +void ServerActiveObject::markForDeactivation() +{ + if (!m_pending_deactivation) { + onMarkedForDeactivation(); + m_pending_deactivation = true; + } +} diff --git a/src/server/serveractiveobject.h b/src/server/serveractiveobject.h index 2764d159e..25653a1ad 100644 --- a/src/server/serveractiveobject.h +++ b/src/server/serveractiveobject.h @@ -70,6 +70,10 @@ public: virtual bool environmentDeletes() const { return true; } + // Safely mark the object for removal or deactivation + void markForRemoval(); + void markForDeactivation(); + // Create a certain type of ServerActiveObject static ServerActiveObject* create(ActiveObjectType type, ServerEnvironment *env, u16 id, v3f pos, @@ -213,25 +217,6 @@ public: */ u16 m_known_by_count = 0; - /* - - Whether this object is to be removed when nobody knows about - it anymore. - - Removal is delayed to preserve the id for the time during which - it could be confused to some other object by some client. - - This is usually set to true by the step() method when the object wants - to be deleted but can be set by anything else too. - */ - bool m_pending_removal = false; - - /* - Same purpose as m_pending_removal but for deactivation. - deactvation = save static data in block, remove active object - - If this is set alongside with m_pending_removal, removal takes - priority. - */ - bool m_pending_deactivation = false; - /* A getter that unifies the above to answer the question: "Can the environment still interact with this object?" @@ -239,6 +224,9 @@ public: inline bool isGone() const { return m_pending_removal || m_pending_deactivation; } + inline bool isPendingRemoval() const + { return m_pending_removal; } + /* Whether the object's static data has been stored to a block */ @@ -250,6 +238,9 @@ public: v3s16 m_static_block = v3s16(1337,1337,1337); protected: + virtual void onMarkedForDeactivation() {} + virtual void onMarkedForRemoval() {} + virtual void onAttach(int parent_id) {} virtual void onDetach(int parent_id) {} @@ -257,6 +248,27 @@ protected: v3f m_base_position; std::unordered_set m_attached_particle_spawners; + /* + Same purpose as m_pending_removal but for deactivation. + deactvation = save static data in block, remove active object + + If this is set alongside with m_pending_removal, removal takes + priority. + Note: Do not assign this directly, use markForDeactivation() instead. + */ + bool m_pending_deactivation = false; + + /* + - Whether this object is to be removed when nobody knows about + it anymore. + - Removal is delayed to preserve the id for the time during which + it could be confused to some other object by some client. + - This is usually set to true by the step() method when the object wants + to be deleted but can be set by anything else too. + Note: Do not assign this directly, use markForRemoval() instead. + */ + bool m_pending_removal = false; + /* Queue of messages to be sent to the client */ diff --git a/src/serverenvironment.cpp b/src/serverenvironment.cpp index d044b003d..56dbb0632 100644 --- a/src/serverenvironment.cpp +++ b/src/serverenvironment.cpp @@ -1164,7 +1164,7 @@ void ServerEnvironment::clearObjects(ClearObjectsMode mode) // If known by some client, don't delete immediately if (obj->m_known_by_count > 0) { - obj->m_pending_removal = true; + obj->markForRemoval(); return false; } @@ -1792,7 +1792,7 @@ void ServerEnvironment::removeRemovedObjects() /* Delete static data from block if removed */ - if (obj->m_pending_removal) + if (obj->isPendingRemoval()) deleteStaticFromBlock(obj, id, MOD_REASON_REMOVE_OBJECTS_REMOVE, false); // If still known by clients, don't actually remove. On some future @@ -1803,7 +1803,7 @@ void ServerEnvironment::removeRemovedObjects() /* Move static data from active to stored if deactivated */ - if (!obj->m_pending_removal && obj->m_static_exists) { + if (!obj->isPendingRemoval() && obj->m_static_exists) { MapBlock *block = m_map->emergeBlock(obj->m_static_block, false); if (block) { const auto i = block->m_static_objects.m_active.find(id); @@ -1991,6 +1991,7 @@ void ServerEnvironment::deactivateFarObjects(bool _force_delete) if (!force_delete && obj->m_static_exists && !m_active_blocks.contains(obj->m_static_block) && m_active_blocks.contains(blockpos_o)) { + // Delete from block where object was located deleteStaticFromBlock(obj, id, MOD_REASON_STATIC_DATA_REMOVED, false); @@ -2068,6 +2069,10 @@ void ServerEnvironment::deactivateFarObjects(bool _force_delete) force_delete = true; } + // Regardless of what happens to the object at this point, deactivate it first. + // This ensures that LuaEntity on_deactivate is always called. + obj->markForDeactivation(); + /* If known by some client, set pending deactivation. Otherwise delete it immediately. @@ -2077,7 +2082,6 @@ void ServerEnvironment::deactivateFarObjects(bool _force_delete) << "object id=" << id << " is known by clients" << "; not deleting yet" << std::endl; - obj->m_pending_deactivation = true; return false; } From edd083601173c1b67a2e5cd88e23122f46b88bbf Mon Sep 17 00:00:00 2001 From: rubenwardy Date: Mon, 4 Jan 2021 15:18:31 +0000 Subject: [PATCH 29/31] ContentDB: Add overwrite dialog when content is already installed (#10768) --- builtin/mainmenu/dlg_contentstore.lua | 74 +++++++++++++++++++++++++-- doc/menu_lua_api.txt | 2 + src/script/lua_api/l_mainmenu.cpp | 11 ++++ src/script/lua_api/l_mainmenu.h | 2 + 4 files changed, 84 insertions(+), 5 deletions(-) diff --git a/builtin/mainmenu/dlg_contentstore.lua b/builtin/mainmenu/dlg_contentstore.lua index 7f6b4b7e4..b5f71e753 100644 --- a/builtin/mainmenu/dlg_contentstore.lua +++ b/builtin/mainmenu/dlg_contentstore.lua @@ -437,12 +437,53 @@ function install_dialog.create(package, raw_deps) install_dialog.package = package install_dialog.raw_deps = raw_deps install_dialog.will_install_deps = true - return dialog_create("package_view", + return dialog_create("install_dialog", install_dialog.get_formspec, install_dialog.handle_submit, nil) end + +local confirm_overwrite = {} +function confirm_overwrite.get_formspec() + local package = confirm_overwrite.package + + return "size[11.5,4.5,true]" .. + "label[2,2;" .. + fgettext("\"$1\" already exists. Would you like to overwrite it?", package.name) .. "]".. + "style[install;bgcolor=red]" .. + "button[3.25,3.5;2.5,0.5;install;" .. fgettext("Overwrite") .. "]" .. + "button[5.75,3.5;2.5,0.5;cancel;" .. fgettext("Cancel") .. "]" +end + +function confirm_overwrite.handle_submit(this, fields) + if fields.cancel then + this:delete() + return true + end + + if fields.install then + this:delete() + confirm_overwrite.callback() + return true + end + + return false +end + +function confirm_overwrite.create(package, callback) + assert(type(package) == "table") + assert(type(callback) == "function") + + confirm_overwrite.package = package + confirm_overwrite.callback = callback + return dialog_create("confirm_overwrite", + confirm_overwrite.get_formspec, + confirm_overwrite.handle_submit, + nil) +end + + local function get_file_extension(path) local parts = path:split(".") return parts[#parts] @@ -858,14 +899,37 @@ function store.handle_submit(this, fields) assert(package) if fields["install_" .. i] then - local deps = get_raw_dependencies(package) - if deps and has_hard_deps(deps) then - local dlg = install_dialog.create(package, deps) + local install_parent + if package.type == "mod" then + install_parent = core.get_modpath() + elseif package.type == "game" then + install_parent = core.get_gamepath() + elseif package.type == "txp" then + install_parent = core.get_texturepath() + else + error("Unknown package type: " .. package.type) + end + + + local function on_confirm() + local deps = get_raw_dependencies(package) + if deps and has_hard_deps(deps) then + local dlg = install_dialog.create(package, deps) + dlg:set_parent(this) + this:hide() + dlg:show() + else + queue_download(package) + end + end + + if not package.path and core.is_dir(install_parent .. DIR_DELIM .. package.name) then + local dlg = confirm_overwrite.create(package, on_confirm) dlg:set_parent(this) this:hide() dlg:show() else - queue_download(package) + on_confirm() end return true diff --git a/doc/menu_lua_api.txt b/doc/menu_lua_api.txt index 8908552d5..1bcf697e9 100644 --- a/doc/menu_lua_api.txt +++ b/doc/menu_lua_api.txt @@ -67,6 +67,8 @@ core.copy_dir(source,destination,keep_soure) (possible in async calls) ^ destination folder ^ keep_source DEFAULT true --> if set to false source is deleted after copying ^ returns true/false +core.is_dir(path) (possible in async calls) +^ returns true if path is a valid dir core.extract_zip(zipfile,destination) [unzip within path required] ^ zipfile to extract ^ destination folder to extract to diff --git a/src/script/lua_api/l_mainmenu.cpp b/src/script/lua_api/l_mainmenu.cpp index 0b0b2de3b..5070ec7d4 100644 --- a/src/script/lua_api/l_mainmenu.cpp +++ b/src/script/lua_api/l_mainmenu.cpp @@ -803,6 +803,15 @@ int ModApiMainMenu::l_copy_dir(lua_State *L) return 1; } +/******************************************************************************/ +int ModApiMainMenu::l_is_dir(lua_State *L) +{ + const char *path = luaL_checkstring(L, 1); + + lua_pushboolean(L, fs::IsDir(path)); + return 1; +} + /******************************************************************************/ int ModApiMainMenu::l_extract_zip(lua_State *L) { @@ -1139,6 +1148,7 @@ void ModApiMainMenu::Initialize(lua_State *L, int top) API_FCT(create_dir); API_FCT(delete_dir); API_FCT(copy_dir); + API_FCT(is_dir); API_FCT(extract_zip); API_FCT(may_modify_path); API_FCT(get_mainmenu_path); @@ -1172,6 +1182,7 @@ void ModApiMainMenu::InitializeAsync(lua_State *L, int top) API_FCT(create_dir); API_FCT(delete_dir); API_FCT(copy_dir); + API_FCT(is_dir); //API_FCT(extract_zip); //TODO remove dependency to GuiEngine API_FCT(may_modify_path); API_FCT(download_file); diff --git a/src/script/lua_api/l_mainmenu.h b/src/script/lua_api/l_mainmenu.h index faa2bf273..0b02ed892 100644 --- a/src/script/lua_api/l_mainmenu.h +++ b/src/script/lua_api/l_mainmenu.h @@ -132,6 +132,8 @@ private: static int l_copy_dir(lua_State *L); + static int l_is_dir(lua_State *L); + static int l_extract_zip(lua_State *L); static int l_may_modify_path(lua_State *L); From e663aecbae122e172322898a584b9440d3f7cd4c Mon Sep 17 00:00:00 2001 From: sfan5 Date: Sat, 2 Jan 2021 15:43:35 +0100 Subject: [PATCH 30/31] Update Gitlab-CI pipeline --- .gitlab-ci.yml | 131 ++++++++++++++++---------------------------- misc/debpkg-control | 4 +- 2 files changed, 49 insertions(+), 86 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c3e120375..0441aeaa1 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -18,12 +18,12 @@ variables: - mkdir cmakebuild - mkdir -p artifact/minetest/usr/ - cd cmakebuild - - cmake -DCMAKE_INSTALL_PREFIX=../artifact/minetest/usr/ -DCMAKE_BUILD_TYPE=Release -DRUN_IN_PLACE=FALSE -DENABLE_GETTEXT=TRUE -DBUILD_SERVER=TRUE .. + - cmake -DCMAKE_INSTALL_PREFIX=../artifact/minetest/usr/ -DCMAKE_BUILD_TYPE=Release -DRUN_IN_PLACE=FALSE -DENABLE_GETTEXT=TRUE -DENABLE_SYSTEM_JSONCPP=TRUE -DBUILD_SERVER=TRUE .. - make -j2 - make install artifacts: when: on_success - expire_in: 2h + expire_in: 1h paths: - artifact/* @@ -34,15 +34,14 @@ variables: - apt-get install -y git - mkdir -p build/deb/minetest/DEBIAN/ - cp misc/debpkg-control build/deb/minetest/DEBIAN/control - - cp -Rp artifact/minetest/usr build/deb/minetest/ + - cp -a artifact/minetest/usr build/deb/minetest/ script: - git clone $MINETEST_GAME_REPO build/deb/minetest/usr/share/minetest/games/minetest_game - - rm -Rf build/deb/minetest/usr/share/minetest/games/minetest/.git + - rm -rf build/deb/minetest/usr/share/minetest/games/minetest/.git - sed -i 's/DATEPLACEHOLDER/'$(date +%y.%m.%d)'/g' build/deb/minetest/DEBIAN/control - sed -i 's/LEVELDB_PLACEHOLDER/'$LEVELDB_PKG'/g' build/deb/minetest/DEBIAN/control - cd build/deb/ && dpkg-deb -b minetest/ && mv minetest.deb ../../ artifacts: - when: on_success expire_in: 90 day paths: - ./*.deb @@ -51,44 +50,14 @@ variables: stage: deploy before_script: - apt-get update -y - - apt-get install -y libc6 libcurl3-gnutls libfreetype6 libirrlicht1.8 $LEVELDB_PKG liblua5.1-0 libluajit-5.1-2 libopenal1 libstdc++6 libvorbisfile3 libx11-6 zlib1g script: - - dpkg -i ./*.deb + - apt-get install -y ./*.deb + - minetest --version ## ## Debian ## -# Jessie - -build:debian-8: - extends: .build_template - image: debian:8 - before_script: - - echo "deb http://ppa.launchpad.net/ubuntu-toolchain-r/test/ubuntu trusty main" > /etc/apt/sources.list.d/uptodate-toolchain.list - - apt-key adv --keyserver keyserver.ubuntu.com --recv BA9EF27F - - apt-get update -y - - apt-get -y install build-essential gcc-6 g++-6 libirrlicht-dev cmake libbz2-dev libpng-dev libjpeg-dev libxxf86vm-dev libgl1-mesa-dev libsqlite3-dev libogg-dev libvorbis-dev libopenal-dev libcurl4-gnutls-dev libfreetype6-dev zlib1g-dev libgmp-dev libjsoncpp-dev - variables: - CC: gcc-6 - CXX: g++-6 - -package:debian-8: - extends: .debpkg_template - image: debian:8 - dependencies: - - build:debian-8 - variables: - LEVELDB_PKG: libleveldb1 - -deploy:debian-8: - extends: .debpkg_install - image: debian:8 - dependencies: - - package:debian-8 - variables: - LEVELDB_PKG: libleveldb1 - # Stretch build:debian-9: @@ -101,7 +70,7 @@ build:debian-9: package:debian-9: extends: .debpkg_template image: debian:9 - dependencies: + needs: - build:debian-9 variables: LEVELDB_PKG: libleveldb1v5 @@ -109,12 +78,10 @@ package:debian-9: deploy:debian-9: extends: .debpkg_install image: debian:9 - dependencies: + needs: - package:debian-9 - variables: - LEVELDB_PKG: libleveldb1v5 -# Stretch +# Buster build:debian-10: extends: .build_template @@ -126,7 +93,7 @@ build:debian-10: package:debian-10: extends: .debpkg_template image: debian:10 - dependencies: + needs: - build:debian-10 variables: LEVELDB_PKG: libleveldb1d @@ -134,10 +101,9 @@ package:debian-10: deploy:debian-10: extends: .debpkg_install image: debian:10 - dependencies: + needs: - package:debian-10 - variables: - LEVELDB_PKG: libleveldb1d + ## ## Ubuntu ## @@ -154,7 +120,7 @@ build:ubuntu-16.04: package:ubuntu-16.04: extends: .debpkg_template image: ubuntu:xenial - dependencies: + needs: - build:ubuntu-16.04 variables: LEVELDB_PKG: libleveldb1v5 @@ -162,10 +128,8 @@ package:ubuntu-16.04: deploy:ubuntu-16.04: extends: .debpkg_install image: ubuntu:xenial - dependencies: + needs: - package:ubuntu-16.04 - variables: - LEVELDB_PKG: libleveldb1v5 # Bionic @@ -179,7 +143,7 @@ build:ubuntu-18.04: package:ubuntu-18.04: extends: .debpkg_template image: ubuntu:bionic - dependencies: + needs: - build:ubuntu-18.04 variables: LEVELDB_PKG: libleveldb1v5 @@ -187,25 +151,22 @@ package:ubuntu-18.04: deploy:ubuntu-18.04: extends: .debpkg_install image: ubuntu:bionic - dependencies: + needs: - package:ubuntu-18.04 - variables: - LEVELDB_PKG: libleveldb1v5 ## ## Fedora ## -# Do we need to support this old version ? -build:fedora-24: +# Fedora 28 <-> RHEL 8 +build:fedora-28: extends: .build_template - image: fedora:24 + image: fedora:28 before_script: - - dnf -y install make automake gcc gcc-c++ kernel-devel cmake libcurl* openal* libvorbis* libXxf86vm-devel libogg-devel freetype-devel mesa-libGL-devel zlib-devel jsoncpp-devel irrlicht-devel bzip2-libs gmp-devel sqlite-devel luajit-devel leveldb-devel ncurses-devel doxygen spatialindex-devel bzip2-devel - + - dnf -y install make automake gcc gcc-c++ kernel-devel cmake libcurl-devel openal-soft-devel libvorbis-devel libXxf86vm-devel libogg-devel freetype-devel mesa-libGL-devel zlib-devel jsoncpp-devel irrlicht-devel gmp-devel sqlite-devel luajit-devel leveldb-devel ncurses-devel spatialindex-devel ## -## Mingw for Windows +## MinGW for Windows ## .generic_win_template: @@ -213,68 +174,63 @@ build:fedora-24: before_script: - apt-get update -y - apt-get install -y wget xz-utils unzip git cmake gettext - - wget -q http://minetest.kitsunemimi.pw/mingw-w64-${WIN_ARCH}_9.2.0_ubuntu18.04.tar.xz -O mingw.tar.xz + - wget -nv http://minetest.kitsunemimi.pw/mingw-w64-${WIN_ARCH}_9.2.0_ubuntu18.04.tar.xz -O mingw.tar.xz - tar -xaf mingw.tar.xz -C /usr .build_win_template: extends: .generic_win_template stage: build artifacts: - when: on_success - expire_in: 2h + expire_in: 1h paths: - - build/* + - build/minetest/_build/* .package_win_template: extends: .generic_win_template stage: package script: - - cd build/minetest/_build - - make package - - cd ../../../ - - mkdir minetest-win-${WIN_ARCH} - - unzip build/minetest/_build/minetest-*-win*.zip -d minetest-win-${WIN_ARCH} - - cp /usr/${WIN_ARCH}-w64-mingw32/bin/libgcc*.dll minetest-win-${WIN_ARCH}/minetest-*-win*/bin - - cp /usr/${WIN_ARCH}-w64-mingw32/bin/libstdc++*.dll minetest-win-${WIN_ARCH}/minetest-*-win*/bin - - cp /usr/${WIN_ARCH}-w64-mingw32/bin/libwinpthread*.dll minetest-win-${WIN_ARCH}/minetest-*-win*/bin + - unzip build/minetest/_build/minetest-*.zip + - cp -p /usr/${WIN_ARCH}-w64-mingw32/bin/libgcc*.dll minetest-*-win*/bin/ + - cp -p /usr/${WIN_ARCH}-w64-mingw32/bin/libstdc++*.dll minetest-*-win*/bin/ + - cp -p /usr/${WIN_ARCH}-w64-mingw32/bin/libwinpthread*.dll minetest-*-win*/bin/ artifacts: - when: on_success expire_in: 90 day paths: - - minetest-win-*/* + - minetest-*-win*/* build:win32: extends: .build_win_template script: - ./util/buildbot/buildwin32.sh build variables: - NO_PACKAGE: "1" WIN_ARCH: "i686" package:win32: extends: .package_win_template - dependencies: + needs: - build:win32 variables: - NO_PACKAGE: "1" WIN_ARCH: "i686" + build:win64: extends: .build_win_template script: - ./util/buildbot/buildwin64.sh build variables: - NO_PACKAGE: "1" WIN_ARCH: "x86_64" package:win64: extends: .package_win_template - dependencies: + needs: - build:win64 variables: - NO_PACKAGE: "1" WIN_ARCH: "x86_64" +## +## Docker +## + package:docker: stage: package image: docker:stable @@ -288,6 +244,10 @@ package:docker: - docker push ${CONTAINER_IMAGE}/server:$CI_COMMIT_REF_NAME - docker push ${CONTAINER_IMAGE}/server:latest +## +## Gitlab Pages (Lua API documentation) +## + pages: stage: deploy image: python:3.8 @@ -303,10 +263,14 @@ pages: only: - master +## +## AppImage +## + package:appimage-client: stage: package image: appimagecrafters/appimage-builder - dependencies: + needs: - build:ubuntu-18.04 before_script: - apt-get update -y @@ -315,16 +279,15 @@ package:appimage-client: - mkdir AppDir - cp -a artifact/minetest/usr/ AppDir/usr/ - rm AppDir/usr/bin/minetestserver - - cp -R clientmods AppDir/usr/share/minetest + - cp -a clientmods AppDir/usr/share/minetest script: - git clone $MINETEST_GAME_REPO AppDir/usr/share/minetest/games/minetest_game - - rm -Rf AppDir/usr/share/minetest/games/minetest/.git + - rm -rf AppDir/usr/share/minetest/games/minetest/.git - export VERSION=$CI_COMMIT_REF_NAME-$CI_COMMIT_SHORT_SHA # Remove PrefersNonDefaultGPU property due to validation errors - sed -i '/PrefersNonDefaultGPU/d' AppDir/usr/share/applications/net.minetest.minetest.desktop - appimage-builder --skip-test artifacts: - when: on_success expire_in: 90 day paths: - ./*.AppImage diff --git a/misc/debpkg-control b/misc/debpkg-control index b228f4c79..30dc94088 100644 --- a/misc/debpkg-control +++ b/misc/debpkg-control @@ -3,9 +3,9 @@ Priority: extra Standards-Version: 3.6.2 Package: minetest-staging Version: 0.4.15-DATEPLACEHOLDER -Depends: libc6, libcurl3-gnutls, libfreetype6, libirrlicht1.8, LEVELDB_PLACEHOLDER, liblua5.1-0, libluajit-5.1-2, libopenal1, libstdc++6, libvorbisfile3, libx11-6, zlib1g +Depends: libc6, libcurl3-gnutls, libfreetype6, libirrlicht1.8, libjsoncpp1, LEVELDB_PLACEHOLDER, liblua5.1-0, libluajit-5.1-2, libopenal1, libsqlite3-0, libstdc++6, libvorbisfile3, libx11-6, zlib1g Maintainer: Loic Blot -Homepage: http://minetest.net/ +Homepage: https://www.minetest.net/ Vcs-Git: https://github.com/minetest/minetest.git Vcs-Browser: https://github.com/minetest/minetest.git Architecture: amd64 From 58a709096ef8ff17644cf201f25b1831d9506514 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Blot?= Date: Mon, 4 Jan 2021 20:19:20 +0100 Subject: [PATCH 31/31] refacto: factorize multiple code parts from guiEditbox childs (#10782) --- src/gui/CMakeLists.txt | 1 + src/gui/guiEditBox.cpp | 95 ++++++++++++ src/gui/guiEditBox.h | 103 +++++++++++++ src/gui/guiEditBoxWithScrollbar.cpp | 113 +-------------- src/gui/guiEditBoxWithScrollbar.h | 66 +-------- src/gui/intlGUIEditBox.cpp | 216 +++++++--------------------- src/gui/intlGUIEditBox.h | 63 +------- 7 files changed, 266 insertions(+), 391 deletions(-) create mode 100644 src/gui/guiEditBox.cpp create mode 100644 src/gui/guiEditBox.h diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 5305e7ad3..fdd36914a 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -7,6 +7,7 @@ set(gui_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/guiButtonItemImage.cpp ${CMAKE_CURRENT_SOURCE_DIR}/guiChatConsole.cpp ${CMAKE_CURRENT_SOURCE_DIR}/guiConfirmRegistration.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/guiEditBox.cpp ${CMAKE_CURRENT_SOURCE_DIR}/guiEditBoxWithScrollbar.cpp ${CMAKE_CURRENT_SOURCE_DIR}/guiEngine.cpp ${CMAKE_CURRENT_SOURCE_DIR}/guiFormSpecMenu.cpp diff --git a/src/gui/guiEditBox.cpp b/src/gui/guiEditBox.cpp new file mode 100644 index 000000000..159bd38ac --- /dev/null +++ b/src/gui/guiEditBox.cpp @@ -0,0 +1,95 @@ +/* +Minetest +Copyright (C) 2021 Minetest + +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 "guiEditBox.h" + +#include "IGUISkin.h" +#include "IGUIEnvironment.h" +#include "IGUIFont.h" + +GUIEditBox::~GUIEditBox() +{ + if (m_override_font) + m_override_font->drop(); +} + +void GUIEditBox::setOverrideFont(IGUIFont *font) +{ + if (m_override_font == font) + return; + + if (m_override_font) + m_override_font->drop(); + + m_override_font = font; + + if (m_override_font) + m_override_font->grab(); + + breakText(); +} + +//! Get the font which is used right now for drawing +IGUIFont *GUIEditBox::getActiveFont() const +{ + if (m_override_font) + return m_override_font; + IGUISkin *skin = Environment->getSkin(); + if (skin) + return skin->getFont(); + return 0; +} + +//! Sets another color for the text. +void GUIEditBox::setOverrideColor(video::SColor color) +{ + m_override_color = color; + m_override_color_enabled = true; +} + +video::SColor GUIEditBox::getOverrideColor() const +{ + return m_override_color; +} + +//! Sets if the text should use the overide color or the color in the gui skin. +void GUIEditBox::enableOverrideColor(bool enable) +{ + m_override_color_enabled = enable; +} + +//! Enables or disables word wrap +void GUIEditBox::setWordWrap(bool enable) +{ + m_word_wrap = enable; + breakText(); +} + +//! Enables or disables newlines. +void GUIEditBox::setMultiLine(bool enable) +{ + m_multiline = enable; +} + +//! Enables or disables automatic scrolling with cursor position +//! \param enable: If set to true, the text will move around with the cursor position +void GUIEditBox::setAutoScroll(bool enable) +{ + m_autoscroll = enable; +} diff --git a/src/gui/guiEditBox.h b/src/gui/guiEditBox.h new file mode 100644 index 000000000..c673f2f5f --- /dev/null +++ b/src/gui/guiEditBox.h @@ -0,0 +1,103 @@ +/* +Minetest +Copyright (C) 2021 Minetest + +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. +*/ + +#pragma once + +#include "IGUIEditBox.h" +#include "IOSOperator.h" +#include "guiScrollBar.h" + +using namespace irr; +using namespace irr::gui; + +class GUIEditBox : public IGUIEditBox +{ +public: + GUIEditBox(IGUIEnvironment *environment, IGUIElement *parent, s32 id, + core::rect rectangle) : + IGUIEditBox(environment, parent, id, rectangle) + { + } + + virtual ~GUIEditBox(); + + //! Sets another skin independent font. + virtual void setOverrideFont(IGUIFont *font = 0); + + virtual IGUIFont *getOverrideFont() const { return m_override_font; } + + //! Get the font which is used right now for drawing + /** Currently this is the override font when one is set and the + font of the active skin otherwise */ + virtual IGUIFont *getActiveFont() const; + + //! Sets another color for the text. + virtual void setOverrideColor(video::SColor color); + + //! Gets the override color + virtual video::SColor getOverrideColor() const; + + //! Sets if the text should use the overide color or the + //! color in the gui skin. + virtual void enableOverrideColor(bool enable); + + //! Checks if an override color is enabled + /** \return true if the override color is enabled, false otherwise */ + virtual bool isOverrideColorEnabled(void) const + { + return m_override_color_enabled; + } + + //! Enables or disables word wrap for using the edit box as multiline text editor. + virtual void setWordWrap(bool enable); + + //! Checks if word wrap is enabled + //! \return true if word wrap is enabled, false otherwise + virtual bool isWordWrapEnabled() const { return m_word_wrap; } + + //! Enables or disables newlines. + /** \param enable: If set to true, the EGET_EDITBOX_ENTER event will not be fired, + instead a newline character will be inserted. */ + virtual void setMultiLine(bool enable); + + //! Checks if multi line editing is enabled + //! \return true if mult-line is enabled, false otherwise + virtual bool isMultiLineEnabled() const { return m_multiline; } + + //! Enables or disables automatic scrolling with cursor position + //! \param enable: If set to true, the text will move around with the cursor + //! position + virtual void setAutoScroll(bool enable); + + //! Checks to see if automatic scrolling is enabled + //! \return true if automatic scrolling is enabled, false if not + virtual bool isAutoScrollEnabled() const { return m_autoscroll; } + +protected: + virtual void breakText() = 0; + + gui::IGUIFont *m_override_font = nullptr; + + bool m_override_color_enabled = false; + bool m_word_wrap = false; + bool m_multiline = false; + bool m_autoscroll = true; + + video::SColor m_override_color = video::SColor(101, 255, 255, 255); +}; \ No newline at end of file diff --git a/src/gui/guiEditBoxWithScrollbar.cpp b/src/gui/guiEditBoxWithScrollbar.cpp index 169425a9a..7f9fdafd7 100644 --- a/src/gui/guiEditBoxWithScrollbar.cpp +++ b/src/gui/guiEditBoxWithScrollbar.cpp @@ -22,16 +22,14 @@ optional? dragging selected text numerical */ - //! constructor GUIEditBoxWithScrollBar::GUIEditBoxWithScrollBar(const wchar_t* text, bool border, IGUIEnvironment* environment, IGUIElement* parent, s32 id, const core::rect& rectangle, bool writable, bool has_vscrollbar) - : IGUIEditBox(environment, parent, id, rectangle), m_mouse_marking(false), - m_border(border), m_background(true), m_override_color_enabled(false), m_mark_begin(0), m_mark_end(0), - m_override_color(video::SColor(101, 255, 255, 255)), m_override_font(0), m_last_break_font(0), + : GUIEditBox(environment, parent, id, rectangle), m_mouse_marking(false), + m_border(border), m_background(true), m_mark_begin(0), m_mark_end(0), m_last_break_font(0), m_operator(0), m_blink_start_time(0), m_cursor_pos(0), m_hscroll_pos(0), m_vscroll_pos(0), m_max(0), - m_word_wrap(false), m_multiline(false), m_autoscroll(true), m_passwordbox(false), + m_passwordbox(false), m_passwordchar(L'*'), m_halign(EGUIA_UPPERLEFT), m_valign(EGUIA_CENTER), m_current_text_rect(0, 0, 1, 1), m_frame_rect(rectangle), m_scrollbar_width(0), m_vscrollbar(NULL), m_writable(writable), @@ -69,9 +67,6 @@ GUIEditBoxWithScrollBar::GUIEditBoxWithScrollBar(const wchar_t* text, bool borde //! destructor GUIEditBoxWithScrollBar::~GUIEditBoxWithScrollBar() { - if (m_override_font) - m_override_font->drop(); - if (m_operator) m_operator->drop(); @@ -80,54 +75,6 @@ GUIEditBoxWithScrollBar::~GUIEditBoxWithScrollBar() } -//! Sets another skin independent font. -void GUIEditBoxWithScrollBar::setOverrideFont(IGUIFont* font) -{ - if (m_override_font == font) - return; - - if (m_override_font) - m_override_font->drop(); - - m_override_font = font; - - if (m_override_font) - m_override_font->grab(); - - breakText(); -} - -//! Gets the override font (if any) -IGUIFont * GUIEditBoxWithScrollBar::getOverrideFont() const -{ - return m_override_font; -} - -//! Get the font which is used right now for drawing -IGUIFont* GUIEditBoxWithScrollBar::getActiveFont() const -{ - if (m_override_font) - return m_override_font; - IGUISkin* skin = Environment->getSkin(); - if (skin) - return skin->getFont(); - return 0; -} - -//! Sets another color for the text. -void GUIEditBoxWithScrollBar::setOverrideColor(video::SColor color) -{ - m_override_color = color; - m_override_color_enabled = true; -} - - -video::SColor GUIEditBoxWithScrollBar::getOverrideColor() const -{ - return m_override_color; -} - - //! Turns the border on or off void GUIEditBoxWithScrollBar::setDrawBorder(bool border) { @@ -140,24 +87,6 @@ void GUIEditBoxWithScrollBar::setDrawBackground(bool draw) m_background = draw; } -//! Sets if the text should use the overide color or the color in the gui skin. -void GUIEditBoxWithScrollBar::enableOverrideColor(bool enable) -{ - m_override_color_enabled = enable; -} - -bool GUIEditBoxWithScrollBar::isOverrideColorEnabled() const -{ - return m_override_color_enabled; -} - -//! Enables or disables word wrap -void GUIEditBoxWithScrollBar::setWordWrap(bool enable) -{ - m_word_wrap = enable; - breakText(); -} - void GUIEditBoxWithScrollBar::updateAbsolutePosition() { @@ -170,26 +99,6 @@ void GUIEditBoxWithScrollBar::updateAbsolutePosition() } } -//! Checks if word wrap is enabled -bool GUIEditBoxWithScrollBar::isWordWrapEnabled() const -{ - return m_word_wrap; -} - - -//! Enables or disables newlines. -void GUIEditBoxWithScrollBar::setMultiLine(bool enable) -{ - m_multiline = enable; -} - - -//! Checks if multi line editing is enabled -bool GUIEditBoxWithScrollBar::isMultiLineEnabled() const -{ - return m_multiline; -} - void GUIEditBoxWithScrollBar::setPasswordBox(bool password_box, wchar_t password_char) { @@ -850,22 +759,6 @@ void GUIEditBoxWithScrollBar::setText(const wchar_t* text) } -//! Enables or disables automatic scrolling with cursor position -//! \param enable: If set to true, the text will move around with the cursor position -void GUIEditBoxWithScrollBar::setAutoScroll(bool enable) -{ - m_autoscroll = enable; -} - - -//! Checks to see if automatic scrolling is enabled -//! \return true if automatic scrolling is enabled, false if not -bool GUIEditBoxWithScrollBar::isAutoScrollEnabled() const -{ - return m_autoscroll; -} - - //! Gets the area of the text in the edit box //! \return Returns the size in pixels of the text core::dimension2du GUIEditBoxWithScrollBar::getTextDimension() diff --git a/src/gui/guiEditBoxWithScrollbar.h b/src/gui/guiEditBoxWithScrollbar.h index 77538e2f7..5ae58b934 100644 --- a/src/gui/guiEditBoxWithScrollbar.h +++ b/src/gui/guiEditBoxWithScrollbar.h @@ -5,15 +5,10 @@ #ifndef GUIEDITBOXWITHSCROLLBAR_HEADER #define GUIEDITBOXWITHSCROLLBAR_HEADER -#include "IGUIEditBox.h" -#include "IOSOperator.h" -#include "guiScrollBar.h" +#include "guiEditBox.h" #include -using namespace irr; -using namespace irr::gui; - -class GUIEditBoxWithScrollBar : public IGUIEditBox +class GUIEditBoxWithScrollBar : public GUIEditBox { public: @@ -25,61 +20,13 @@ public: //! destructor virtual ~GUIEditBoxWithScrollBar(); - //! Sets another skin independent font. - virtual void setOverrideFont(IGUIFont* font = 0); - - //! Gets the override font (if any) - /** \return The override font (may be 0) */ - virtual IGUIFont* getOverrideFont() const; - - //! Get the font which is used right now for drawing - /** Currently this is the override font when one is set and the - font of the active skin otherwise */ - virtual IGUIFont* getActiveFont() const; - - //! Sets another color for the text. - virtual void setOverrideColor(video::SColor color); - - //! Gets the override color - virtual video::SColor getOverrideColor() const; - - //! Sets if the text should use the overide color or the - //! color in the gui skin. - virtual void enableOverrideColor(bool enable); - - //! Checks if an override color is enabled - /** \return true if the override color is enabled, false otherwise */ - virtual bool isOverrideColorEnabled(void) const; - //! Sets whether to draw the background virtual void setDrawBackground(bool draw); //! Turns the border on or off virtual void setDrawBorder(bool border); - //! Enables or disables word wrap for using the edit box as multiline text editor. - virtual void setWordWrap(bool enable); - //! Checks if word wrap is enabled - //! \return true if word wrap is enabled, false otherwise - virtual bool isWordWrapEnabled() const; - - //! Enables or disables newlines. - /** \param enable: If set to true, the EGET_EDITBOX_ENTER event will not be fired, - instead a newline character will be inserted. */ - virtual void setMultiLine(bool enable); - - //! Checks if multi line editing is enabled - //! \return true if mult-line is enabled, false otherwise - virtual bool isMultiLineEnabled() const; - - //! Enables or disables automatic scrolling with cursor position - //! \param enable: If set to true, the text will move around with the cursor position - virtual void setAutoScroll(bool enable); - - //! Checks to see if automatic scrolling is enabled - //! \return true if automatic scrolling is enabled, false if not - virtual bool isAutoScrollEnabled() const; //! Gets the size area of the text in the edit box //! \return Returns the size in pixels of the text @@ -137,7 +84,7 @@ public: protected: //! Breaks the single text line. - void breakText(); + virtual void breakText(); //! sets the area of the given line void setTextRect(s32 line); //! returns the line number that the cursor is on @@ -164,12 +111,11 @@ protected: bool m_mouse_marking; bool m_border; bool m_background; - bool m_override_color_enabled; + s32 m_mark_begin; s32 m_mark_end; - video::SColor m_override_color; - gui::IGUIFont *m_override_font, *m_last_break_font; + gui::IGUIFont *m_last_break_font; IOSOperator* m_operator; u32 m_blink_start_time; @@ -177,7 +123,7 @@ protected: s32 m_hscroll_pos, m_vscroll_pos; // scroll position in characters u32 m_max; - bool m_word_wrap, m_multiline, m_autoscroll, m_passwordbox; + bool m_passwordbox; wchar_t m_passwordchar; EGUI_ALIGNMENT m_halign, m_valign; diff --git a/src/gui/intlGUIEditBox.cpp b/src/gui/intlGUIEditBox.cpp index 8be63fd6f..e917f73c1 100644 --- a/src/gui/intlGUIEditBox.cpp +++ b/src/gui/intlGUIEditBox.cpp @@ -59,7 +59,7 @@ namespace gui intlGUIEditBox::intlGUIEditBox(const wchar_t* text, bool border, IGUIEnvironment* environment, IGUIElement* parent, s32 id, const core::rect& rectangle, bool writable, bool has_vscrollbar) - : IGUIEditBox(environment, parent, id, rectangle), + : GUIEditBox(environment, parent, id, rectangle), Border(border), FrameRect(rectangle), m_scrollbar_width(0), m_vscrollbar(NULL), m_writable(writable) { @@ -108,9 +108,6 @@ intlGUIEditBox::intlGUIEditBox(const wchar_t* text, bool border, //! destructor intlGUIEditBox::~intlGUIEditBox() { - if (OverrideFont) - OverrideFont->drop(); - if (Operator) Operator->drop(); @@ -118,52 +115,6 @@ intlGUIEditBox::~intlGUIEditBox() m_vscrollbar->drop(); } - -//! Sets another skin independent font. -void intlGUIEditBox::setOverrideFont(IGUIFont* font) -{ - if (OverrideFont == font) - return; - - if (OverrideFont) - OverrideFont->drop(); - - OverrideFont = font; - - if (OverrideFont) - OverrideFont->grab(); - - breakText(); -} - -IGUIFont * intlGUIEditBox::getOverrideFont() const -{ - return OverrideFont; -} - -//! Get the font which is used right now for drawing -IGUIFont* intlGUIEditBox::getActiveFont() const -{ - if ( OverrideFont ) - return OverrideFont; - IGUISkin* skin = Environment->getSkin(); - if (skin) - return skin->getFont(); - return 0; -} - -//! Sets another color for the text. -void intlGUIEditBox::setOverrideColor(video::SColor color) -{ - OverrideColor = color; - OverrideColorEnabled = true; -} - -video::SColor intlGUIEditBox::getOverrideColor() const -{ - return OverrideColor; -} - //! Turns the border on or off void intlGUIEditBox::setDrawBorder(bool border) { @@ -175,25 +126,6 @@ void intlGUIEditBox::setDrawBackground(bool draw) { } -//! Sets if the text should use the overide color or the color in the gui skin. -void intlGUIEditBox::enableOverrideColor(bool enable) -{ - OverrideColorEnabled = enable; -} - -bool intlGUIEditBox::isOverrideColorEnabled() const -{ - return OverrideColorEnabled; -} - -//! Enables or disables word wrap -void intlGUIEditBox::setWordWrap(bool enable) -{ - WordWrap = enable; - breakText(); -} - - void intlGUIEditBox::updateAbsolutePosition() { core::rect oldAbsoluteRect(AbsoluteRect); @@ -204,28 +136,6 @@ void intlGUIEditBox::updateAbsolutePosition() } } - -//! Checks if word wrap is enabled -bool intlGUIEditBox::isWordWrapEnabled() const -{ - return WordWrap; -} - - -//! Enables or disables newlines. -void intlGUIEditBox::setMultiLine(bool enable) -{ - MultiLine = enable; -} - - -//! Checks if multi line editing is enabled -bool intlGUIEditBox::isMultiLineEnabled() const -{ - return MultiLine; -} - - void intlGUIEditBox::setPasswordBox(bool passwordBox, wchar_t passwordChar) { PasswordBox = passwordBox; @@ -464,7 +374,7 @@ bool intlGUIEditBox::processKey(const SEvent& event) case KEY_END: { s32 p = Text.size(); - if (WordWrap || MultiLine) + if (m_word_wrap || m_multiline) { p = getLineFromPos(CursorPos); p = BrokenTextPositions[p] + (s32)BrokenText[p].size(); @@ -492,7 +402,7 @@ bool intlGUIEditBox::processKey(const SEvent& event) { s32 p = 0; - if (WordWrap || MultiLine) + if (m_word_wrap || m_multiline) { p = getLineFromPos(CursorPos); p = BrokenTextPositions[p]; @@ -514,7 +424,7 @@ bool intlGUIEditBox::processKey(const SEvent& event) } break; case KEY_RETURN: - if (MultiLine) + if (m_multiline) { inputChar(L'\n'); return true; @@ -567,7 +477,7 @@ bool intlGUIEditBox::processKey(const SEvent& event) BlinkStartTime = porting::getTimeMs(); break; case KEY_UP: - if (MultiLine || (WordWrap && BrokenText.size() > 1) ) + if (m_multiline || (m_word_wrap && BrokenText.size() > 1) ) { s32 lineNo = getLineFromPos(CursorPos); s32 mb = (MarkBegin == MarkEnd) ? CursorPos : (MarkBegin > MarkEnd ? MarkBegin : MarkEnd); @@ -598,7 +508,7 @@ bool intlGUIEditBox::processKey(const SEvent& event) } break; case KEY_DOWN: - if (MultiLine || (WordWrap && BrokenText.size() > 1) ) + if (m_multiline || (m_word_wrap && BrokenText.size() > 1) ) { s32 lineNo = getLineFromPos(CursorPos); s32 mb = (MarkBegin == MarkEnd) ? CursorPos : (MarkBegin < MarkEnd ? MarkBegin : MarkEnd); @@ -791,8 +701,8 @@ void intlGUIEditBox::draw() // draw the text - IGUIFont* font = OverrideFont; - if (!OverrideFont) + IGUIFont* font = m_override_font; + if (!m_override_font) font = skin->getFont(); s32 cursorLine = 0; @@ -813,7 +723,7 @@ void intlGUIEditBox::draw() core::stringw s, s2; // get mark position - const bool ml = (!PasswordBox && (WordWrap || MultiLine)); + const bool ml = (!PasswordBox && (m_word_wrap || m_multiline)); const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd; const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin; const s32 hlineStart = ml ? getLineFromPos(realmbgn) : 0; @@ -822,14 +732,14 @@ void intlGUIEditBox::draw() // Save the override color information. // Then, alter it if the edit box is disabled. - const bool prevOver = OverrideColorEnabled; - const video::SColor prevColor = OverrideColor; + const bool prevOver = m_override_color_enabled; + const video::SColor prevColor = m_override_color; if (!Text.empty()) { - if (!IsEnabled && !OverrideColorEnabled) + if (!IsEnabled && !m_override_color_enabled) { - OverrideColorEnabled = true; - OverrideColor = skin->getColor(EGDC_GRAY_TEXT); + m_override_color_enabled = true; + m_override_color = skin->getColor(EGDC_GRAY_TEXT); } for (s32 i=0; i < lineCount; ++i) @@ -870,7 +780,7 @@ void intlGUIEditBox::draw() // draw normal text font->draw(txtLine->c_str(), CurrentTextRect, - OverrideColorEnabled ? OverrideColor : skin->getColor(EGDC_BUTTON_TEXT), + m_override_color_enabled ? m_override_color : skin->getColor(EGDC_BUTTON_TEXT), false, true, &localClipRect); // draw mark and marked text @@ -914,20 +824,20 @@ void intlGUIEditBox::draw() if (!s.empty()) font->draw(s.c_str(), CurrentTextRect, - OverrideColorEnabled ? OverrideColor : skin->getColor(EGDC_HIGH_LIGHT_TEXT), + m_override_color_enabled ? m_override_color : skin->getColor(EGDC_HIGH_LIGHT_TEXT), false, true, &localClipRect); } } // Return the override color information to its previous settings. - OverrideColorEnabled = prevOver; - OverrideColor = prevColor; + m_override_color_enabled = prevOver; + m_override_color = prevColor; } // draw cursor - if (WordWrap || MultiLine) + if (m_word_wrap || m_multiline) { cursorLine = getLineFromPos(CursorPos); txtLine = &BrokenText[cursorLine]; @@ -943,7 +853,7 @@ void intlGUIEditBox::draw() CurrentTextRect.UpperLeftCorner.X += charcursorpos; font->draw(L"_", CurrentTextRect, - OverrideColorEnabled ? OverrideColor : skin->getColor(EGDC_BUTTON_TEXT), + m_override_color_enabled ? m_override_color : skin->getColor(EGDC_BUTTON_TEXT), false, true, &localClipRect); } } @@ -965,22 +875,6 @@ void intlGUIEditBox::setText(const wchar_t* text) } -//! Enables or disables automatic scrolling with cursor position -//! \param enable: If set to true, the text will move around with the cursor position -void intlGUIEditBox::setAutoScroll(bool enable) -{ - AutoScroll = enable; -} - - -//! Checks to see if automatic scrolling is enabled -//! \return true if automatic scrolling is enabled, false if not -bool intlGUIEditBox::isAutoScrollEnabled() const -{ - return AutoScroll; -} - - //! Gets the area of the text in the edit box //! \return Returns the size in pixels of the text core::dimension2du intlGUIEditBox::getTextDimension() @@ -1096,12 +990,12 @@ bool intlGUIEditBox::processMouse(const SEvent& event) s32 intlGUIEditBox::getCursorPos(s32 x, s32 y) { - IGUIFont* font = OverrideFont; + IGUIFont* font = m_override_font; IGUISkin* skin = Environment->getSkin(); - if (!OverrideFont) + if (!m_override_font) font = skin->getFont(); - const u32 lineCount = (WordWrap || MultiLine) ? BrokenText.size() : 1; + const u32 lineCount = (m_word_wrap || m_multiline) ? BrokenText.size() : 1; core::stringw *txtLine = NULL; s32 startPos = 0; @@ -1118,8 +1012,8 @@ s32 intlGUIEditBox::getCursorPos(s32 x, s32 y) // is it inside this region? if (y >= CurrentTextRect.UpperLeftCorner.Y && y <= CurrentTextRect.LowerRightCorner.Y) { // we've found the clicked line - txtLine = (WordWrap || MultiLine) ? &BrokenText[curr_line_idx] : &Text; - startPos = (WordWrap || MultiLine) ? BrokenTextPositions[curr_line_idx] : 0; + txtLine = (m_word_wrap || m_multiline) ? &BrokenText[curr_line_idx] : &Text; + startPos = (m_word_wrap || m_multiline) ? BrokenTextPositions[curr_line_idx] : 0; break; } } @@ -1144,14 +1038,14 @@ void intlGUIEditBox::breakText() { IGUISkin* skin = Environment->getSkin(); - if ((!WordWrap && !MultiLine) || !skin) + if ((!m_word_wrap && !m_multiline) || !skin) return; BrokenText.clear(); // need to reallocate :/ BrokenTextPositions.set_used(0); - IGUIFont* font = OverrideFont; - if (!OverrideFont) + IGUIFont* font = m_override_font; + if (!m_override_font) font = skin->getFont(); if (!font) @@ -1190,7 +1084,7 @@ void intlGUIEditBox::breakText() } // don't break if we're not a multi-line edit box - if (!MultiLine) + if (!m_multiline) lineBreak = false; if (c == L' ' || c == 0 || i == (size-1)) @@ -1201,7 +1095,7 @@ void intlGUIEditBox::breakText() s32 whitelgth = font->getDimension(whitespace.c_str()).Width; s32 worldlgth = font->getDimension(word.c_str()).Width; - if (WordWrap && length + worldlgth + whitelgth > elWidth) + if (m_word_wrap && length + worldlgth + whitelgth > elWidth) { // break to next line length = worldlgth; @@ -1260,14 +1154,14 @@ void intlGUIEditBox::setTextRect(s32 line) if (!skin) return; - IGUIFont* font = OverrideFont ? OverrideFont : skin->getFont(); + IGUIFont* font = m_override_font ? m_override_font : skin->getFont(); if (!font) return; // get text dimension - const u32 lineCount = (WordWrap || MultiLine) ? BrokenText.size() : 1; - if (WordWrap || MultiLine) + const u32 lineCount = (m_word_wrap || m_multiline) ? BrokenText.size() : 1; + if (m_word_wrap || m_multiline) { d = font->getDimension(BrokenText[line].c_str()); } @@ -1328,7 +1222,7 @@ void intlGUIEditBox::setTextRect(s32 line) s32 intlGUIEditBox::getLineFromPos(s32 pos) { - if (!WordWrap && !MultiLine) + if (!m_word_wrap && !m_multiline) return 0; s32 i=0; @@ -1387,7 +1281,7 @@ void intlGUIEditBox::inputChar(wchar_t c) void intlGUIEditBox::calculateScrollPos() { - if (!AutoScroll) + if (!m_autoscroll) return; // calculate horizontal scroll position @@ -1395,18 +1289,18 @@ void intlGUIEditBox::calculateScrollPos() setTextRect(cursLine); // don't do horizontal scrolling when wordwrap is enabled. - if (!WordWrap) + if (!m_word_wrap) { // get cursor position IGUISkin* skin = Environment->getSkin(); if (!skin) return; - IGUIFont* font = OverrideFont ? OverrideFont : skin->getFont(); + IGUIFont* font = m_override_font ? m_override_font : skin->getFont(); if (!font) return; - core::stringw *txtLine = MultiLine ? &BrokenText[cursLine] : &Text; - s32 cPos = MultiLine ? CursorPos - BrokenTextPositions[cursLine] : CursorPos; + core::stringw *txtLine = m_multiline ? &BrokenText[cursLine] : &Text; + s32 cPos = m_multiline ? CursorPos - BrokenTextPositions[cursLine] : CursorPos; s32 cStart = CurrentTextRect.UpperLeftCorner.X + HScrollPos + font->getDimension(txtLine->subString(0, cPos).c_str()).Width; @@ -1423,7 +1317,7 @@ void intlGUIEditBox::calculateScrollPos() // todo: adjust scrollbar } - if (!WordWrap && !MultiLine) + if (!m_word_wrap && !m_multiline) return; // vertical scroll position @@ -1468,8 +1362,8 @@ void intlGUIEditBox::createVScrollBar() { s32 fontHeight = 1; - if (OverrideFont) { - fontHeight = OverrideFont->getDimension(L"").Height; + if (m_override_font) { + fontHeight = m_override_font->getDimension(L"").Height; } else { if (IGUISkin* skin = Environment->getSkin()) { if (IGUIFont* font = skin->getFont()) { @@ -1520,7 +1414,7 @@ void intlGUIEditBox::updateVScrollBar() m_vscrollbar->setPageSize(s32(getTextDimension().Height)); } - if (!m_vscrollbar->isVisible() && MultiLine) { + if (!m_vscrollbar->isVisible() && m_multiline) { AbsoluteRect.LowerRightCorner.X -= m_scrollbar_width; m_vscrollbar->setVisible(true); @@ -1548,20 +1442,20 @@ void intlGUIEditBox::serializeAttributes(io::IAttributes* out, io::SAttributeRea { // IGUIEditBox::serializeAttributes(out,options); - out->addBool ("OverrideColorEnabled",OverrideColorEnabled ); - out->addColor ("OverrideColor", OverrideColor); - // out->addFont("OverrideFont",OverrideFont); - out->addInt ("MaxChars", Max); - out->addBool ("WordWrap", WordWrap); - out->addBool ("MultiLine", MultiLine); - out->addBool ("AutoScroll", AutoScroll); - out->addBool ("PasswordBox", PasswordBox); + out->addBool ("OverrideColorEnabled", m_override_color_enabled ); + out->addColor ("OverrideColor", m_override_color); + // out->addFont("OverrideFont",m_override_font); + out->addInt ("MaxChars", Max); + out->addBool ("WordWrap", m_word_wrap); + out->addBool ("MultiLine", m_multiline); + out->addBool ("AutoScroll", m_autoscroll); + out->addBool ("PasswordBox", PasswordBox); core::stringw ch = L" "; ch[0] = PasswordChar; - out->addString("PasswordChar", ch.c_str()); - out->addEnum ("HTextAlign", HAlign, GUIAlignmentNames); - out->addEnum ("VTextAlign", VAlign, GUIAlignmentNames); - out->addBool ("Writable", m_writable); + out->addString("PasswordChar", ch.c_str()); + out->addEnum ("HTextAlign", HAlign, GUIAlignmentNames); + out->addEnum ("VTextAlign", VAlign, GUIAlignmentNames); + out->addBool ("Writable", m_writable); IGUIEditBox::serializeAttributes(out,options); } diff --git a/src/gui/intlGUIEditBox.h b/src/gui/intlGUIEditBox.h index 9d643495e..a1e423aa2 100644 --- a/src/gui/intlGUIEditBox.h +++ b/src/gui/intlGUIEditBox.h @@ -7,16 +7,15 @@ #include "IrrCompileConfig.h" //#ifdef _IRR_COMPILE_WITH_GUI_ -#include +#include "guiEditBox.h" #include "irrArray.h" #include "IOSOperator.h" -#include "guiScrollBar.h" namespace irr { namespace gui { - class intlGUIEditBox : public IGUIEditBox + class intlGUIEditBox : public GUIEditBox { public: @@ -28,32 +27,6 @@ namespace gui //! destructor virtual ~intlGUIEditBox(); - //! Sets another skin independent font. - virtual void setOverrideFont(IGUIFont* font=0); - - //! Gets the override font (if any) - /** \return The override font (may be 0) */ - virtual IGUIFont* getOverrideFont() const; - - //! Get the font which is used right now for drawing - /** Currently this is the override font when one is set and the - font of the active skin otherwise */ - virtual IGUIFont* getActiveFont() const; - - //! Sets another color for the text. - virtual void setOverrideColor(video::SColor color); - - //! Gets the override color - virtual video::SColor getOverrideColor() const; - - //! Sets if the text should use the overide color or the - //! color in the gui skin. - virtual void enableOverrideColor(bool enable); - - //! Checks if an override color is enabled - /** \return true if the override color is enabled, false otherwise */ - virtual bool isOverrideColorEnabled(void) const; - //! Sets whether to draw the background virtual void setDrawBackground(bool draw); @@ -64,30 +37,6 @@ namespace gui virtual bool isDrawBorderEnabled() const { return Border; } - //! Enables or disables word wrap for using the edit box as multiline text editor. - virtual void setWordWrap(bool enable); - - //! Checks if word wrap is enabled - //! \return true if word wrap is enabled, false otherwise - virtual bool isWordWrapEnabled() const; - - //! Enables or disables newlines. - /** \param enable: If set to true, the EGET_EDITBOX_ENTER event will not be fired, - instead a newline character will be inserted. */ - virtual void setMultiLine(bool enable); - - //! Checks if multi line editing is enabled - //! \return true if mult-line is enabled, false otherwise - virtual bool isMultiLineEnabled() const; - - //! Enables or disables automatic scrolling with cursor position - //! \param enable: If set to true, the text will move around with the cursor position - virtual void setAutoScroll(bool enable); - - //! Checks to see if automatic scrolling is enabled - //! \return true if automatic scrolling is enabled, false if not - virtual bool isAutoScrollEnabled() const; - //! Gets the size area of the text in the edit box //! \return Returns the size in pixels of the text virtual core::dimension2du getTextDimension(); @@ -143,7 +92,7 @@ namespace gui protected: //! Breaks the single text line. - void breakText(); + virtual void breakText(); //! sets the area of the given line void setTextRect(s32 line); //! returns the line number that the cursor is on @@ -169,12 +118,9 @@ namespace gui bool MouseMarking = false; bool Border; - bool OverrideColorEnabled = false; s32 MarkBegin = 0; s32 MarkEnd = 0; - video::SColor OverrideColor = video::SColor(101,255,255,255); - gui::IGUIFont *OverrideFont = nullptr; gui::IGUIFont *LastBreakFont = nullptr; IOSOperator *Operator = nullptr; @@ -184,9 +130,6 @@ namespace gui s32 VScrollPos = 0; // scroll position in characters u32 Max = 0; - bool WordWrap = false; - bool MultiLine = false; - bool AutoScroll = true; bool PasswordBox = false; wchar_t PasswordChar = L'*'; EGUI_ALIGNMENT HAlign = EGUIA_UPPERLEFT;