From 76afde861de0afa4c69020b16cf52b023ac88de5 Mon Sep 17 00:00:00 2001 From: Maksim Date: Tue, 21 Jul 2020 14:16:25 +0200 Subject: Android: Fix ConfirmRegistration and PasswordChange input and scale size (#10182) --- src/gui/guiConfirmRegistration.cpp | 19 +++++++++++++++---- src/gui/guiPasswordChange.cpp | 19 ++++++++++++++----- 2 files changed, 29 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/gui/guiConfirmRegistration.cpp b/src/gui/guiConfirmRegistration.cpp index 55c111df8..020a2796a 100644 --- a/src/gui/guiConfirmRegistration.cpp +++ b/src/gui/guiConfirmRegistration.cpp @@ -73,7 +73,11 @@ void GUIConfirmRegistration::regenerateGui(v2u32 screensize) /* Calculate new sizes and positions */ +#ifdef __ANDROID__ + const float s = m_gui_scale * porting::getDisplayDensity() / 2; +#else const float s = m_gui_scale; +#endif DesiredRect = core::rect( screensize.X / 2 - 600 * s / 2, screensize.Y / 2 - 360 * s / 2, @@ -257,12 +261,19 @@ bool GUIConfirmRegistration::getAndroidUIInput() if (!hasAndroidUIInput() || m_jni_field_name != "password") return false; - std::string text = porting::getInputDialogValue(); - gui::IGUIElement *e = getElementFromId(ID_confirmPassword); - if (e) - e->setText(utf8_to_wide(text).c_str()); + // still waiting + if (porting::getInputDialogState() == -1) + return true; m_jni_field_name.clear(); + + gui::IGUIElement *e = getElementFromId(ID_confirmPassword); + + if (!e || e->getType() != irr::gui::EGUIET_EDIT_BOX) + return false; + + std::string text = porting::getInputDialogValue(); + e->setText(utf8_to_wide(text).c_str()); return false; } #endif diff --git a/src/gui/guiPasswordChange.cpp b/src/gui/guiPasswordChange.cpp index 5311c6fef..74cd62f5b 100644 --- a/src/gui/guiPasswordChange.cpp +++ b/src/gui/guiPasswordChange.cpp @@ -79,7 +79,11 @@ void GUIPasswordChange::regenerateGui(v2u32 screensize) /* Calculate new sizes and positions */ +#ifdef __ANDROID__ + const float s = m_gui_scale * porting::getDisplayDensity() / 2; +#else const float s = m_gui_scale; +#endif DesiredRect = core::rect( screensize.X / 2 - 580 * s / 2, screensize.Y / 2 - 300 * s / 2, @@ -289,6 +293,10 @@ bool GUIPasswordChange::getAndroidUIInput() if (!hasAndroidUIInput()) return false; + // still waiting + if (porting::getInputDialogState() == -1) + return true; + gui::IGUIElement *e = nullptr; if (m_jni_field_name == "old_password") e = getElementFromId(ID_oldPassword); @@ -296,12 +304,13 @@ bool GUIPasswordChange::getAndroidUIInput() e = getElementFromId(ID_newPassword1); else if (m_jni_field_name == "new_password_2") e = getElementFromId(ID_newPassword2); - - if (e) { - std::string text = porting::getInputDialogValue(); - e->setText(utf8_to_wide(text).c_str()); - } m_jni_field_name.clear(); + + if (!e || e->getType() != irr::gui::EGUIET_EDIT_BOX) + return false; + + std::string text = porting::getInputDialogValue(); + e->setText(utf8_to_wide(text).c_str()); return false; } #endif -- cgit v1.2.3 From 8ca602150d4fdce6dcc63fa13e22aeaac5b927cc Mon Sep 17 00:00:00 2001 From: sfan5 Date: Thu, 23 Jul 2020 19:47:58 +0200 Subject: Replace std::list in networking code (#10215) --- src/network/connection.cpp | 3 ++- src/network/connection.h | 6 +++--- src/network/connectionthreads.cpp | 26 ++++++++++++-------------- 3 files changed, 17 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/network/connection.cpp b/src/network/connection.cpp index 3692e45a9..1875d1461 100644 --- a/src/network/connection.cpp +++ b/src/network/connection.cpp @@ -1269,7 +1269,8 @@ bool Connection::deletePeer(session_t peer_id, bool timeout) return false; peer = m_peers[peer_id]; m_peers.erase(peer_id); - m_peer_ids.remove(peer_id); + auto it = std::find(m_peer_ids.begin(), m_peer_ids.end(), peer_id); + m_peer_ids.erase(it); } Address peer_address; diff --git a/src/network/connection.h b/src/network/connection.h index 47b0805ce..2dc6d4397 100644 --- a/src/network/connection.h +++ b/src/network/connection.h @@ -30,7 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "networkprotocol.h" #include #include -#include +#include #include class NetworkPacket; @@ -795,7 +795,7 @@ protected: void PrintInfo(std::ostream &out); - std::list getPeerIDs() + std::vector getPeerIDs() { MutexAutoLock peerlock(m_peers_mutex); return m_peer_ids; @@ -816,7 +816,7 @@ private: u32 m_protocol_id; std::map m_peers; - std::list m_peer_ids; + std::vector m_peer_ids; std::mutex m_peers_mutex; std::unique_ptr m_sendThread; diff --git a/src/network/connectionthreads.cpp b/src/network/connectionthreads.cpp index 9a6617a1c..28ed798d9 100644 --- a/src/network/connectionthreads.cpp +++ b/src/network/connectionthreads.cpp @@ -144,7 +144,7 @@ void ConnectionSendThread::Trigger() bool ConnectionSendThread::packetsQueued() { - std::list peerIds = m_connection->getPeerIDs(); + std::vector peerIds = m_connection->getPeerIDs(); if (!m_outgoing_queue.empty() && !peerIds.empty()) return true; @@ -171,8 +171,8 @@ bool ConnectionSendThread::packetsQueued() void ConnectionSendThread::runTimeouts(float dtime) { - std::list timeouted_peers; - std::list peerIds = m_connection->getPeerIDs(); + std::vector timeouted_peers; + std::vector peerIds = m_connection->getPeerIDs(); for (session_t &peerId : peerIds) { PeerHelper peer = m_connection->getPeerNoEx(peerId); @@ -548,7 +548,7 @@ void ConnectionSendThread::disconnect() // Send to all - std::list peerids = m_connection->getPeerIDs(); + std::vector peerids = m_connection->getPeerIDs(); for (session_t peerid : peerids) { sendAsPacket(peerid, 0, data, false); @@ -620,7 +620,7 @@ void ConnectionSendThread::sendReliable(ConnectionCommand &c) void ConnectionSendThread::sendToAll(u8 channelnum, const SharedBuffer &data) { - std::list peerids = m_connection->getPeerIDs(); + std::vector peerids = m_connection->getPeerIDs(); for (session_t peerid : peerids) { send(peerid, channelnum, data); @@ -629,7 +629,7 @@ void ConnectionSendThread::sendToAll(u8 channelnum, const SharedBuffer &data void ConnectionSendThread::sendToAllReliable(ConnectionCommand &c) { - std::list peerids = m_connection->getPeerIDs(); + std::vector peerids = m_connection->getPeerIDs(); for (session_t peerid : peerids) { PeerHelper peer = m_connection->getPeerNoEx(peerid); @@ -643,8 +643,8 @@ void ConnectionSendThread::sendToAllReliable(ConnectionCommand &c) void ConnectionSendThread::sendPackets(float dtime) { - std::list peerIds = m_connection->getPeerIDs(); - std::list pendingDisconnect; + std::vector peerIds = m_connection->getPeerIDs(); + std::vector pendingDisconnect; std::map pending_unreliable; const unsigned int peer_packet_quota = m_iteration_packets_avaialble @@ -843,13 +843,11 @@ void *ConnectionReceiveThread::run() if (debug_print_timer > 20.0) { debug_print_timer -= 20.0; - std::list peerids = m_connection->getPeerIDs(); + std::vector peerids = m_connection->getPeerIDs(); - for (std::list::iterator i = peerids.begin(); - i != peerids.end(); - i++) + for (auto id : peerids) { - PeerHelper peer = m_connection->getPeerNoEx(*i); + PeerHelper peer = m_connection->getPeerNoEx(id); if (!peer) continue; @@ -1039,7 +1037,7 @@ void ConnectionReceiveThread::receive(SharedBuffer &packetdata, bool ConnectionReceiveThread::getFromBuffers(session_t &peer_id, SharedBuffer &dst) { - std::list peerids = m_connection->getPeerIDs(); + std::vector peerids = m_connection->getPeerIDs(); for (session_t peerid : peerids) { PeerHelper peer = m_connection->getPeerNoEx(peerid); -- cgit v1.2.3 From 808fa5ecb3ddfd5d993000cc6b4c972257e182db Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Thu, 23 Jul 2020 19:54:58 +0200 Subject: Improve default inventory+wield images of node drawtypes (#9299) --- doc/texture_packs.txt | 1 + src/client/content_mapblock.cpp | 4 +- src/client/content_mapblock.h | 2 +- src/client/wieldmesh.cpp | 207 +++++++++++++++--------------- src/nodedef.h | 16 +++ textures/base/pack/no_texture_airlike.png | Bin 0 -> 178 bytes 6 files changed, 126 insertions(+), 104 deletions(-) create mode 100644 textures/base/pack/no_texture_airlike.png (limited to 'src') diff --git a/doc/texture_packs.txt b/doc/texture_packs.txt index e7a7dfd3c..79d65a339 100644 --- a/doc/texture_packs.txt +++ b/doc/texture_packs.txt @@ -90,6 +90,7 @@ by texture packs. All existing fallback textures can be found in the directory * `minimap_mask_square.png`: mask used for the square minimap * `minimap_overlay_round.png`: overlay texture for the round minimap * `minimap_overlay_square.png`: overlay texture for the square minimap +* `no_texture_airlike.png`: fallback inventory image for airlike nodes * `object_marker_red.png`: texture for players on the minimap * `player_marker.png`: texture for the own player on the square minimap diff --git a/src/client/content_mapblock.cpp b/src/client/content_mapblock.cpp index 3d06584c4..65a85709b 100644 --- a/src/client/content_mapblock.cpp +++ b/src/client/content_mapblock.cpp @@ -1454,10 +1454,10 @@ void MapblockMeshGenerator::generate() } } -void MapblockMeshGenerator::renderSingle(content_t node) +void MapblockMeshGenerator::renderSingle(content_t node, u8 param2) { p = {0, 0, 0}; - n = MapNode(node, 0xff, 0x00); + n = MapNode(node, 0xff, param2); f = &nodedef->get(n); drawNode(); } diff --git a/src/client/content_mapblock.h b/src/client/content_mapblock.h index 97947cdbe..487d84a07 100644 --- a/src/client/content_mapblock.h +++ b/src/client/content_mapblock.h @@ -174,5 +174,5 @@ public: public: MapblockMeshGenerator(MeshMakeData *input, MeshCollector *output); void generate(); - void renderSingle(content_t node); + void renderSingle(content_t node, u8 param2 = 0x00); }; diff --git a/src/client/wieldmesh.cpp b/src/client/wieldmesh.cpp index 8cd3e29a9..a268895ed 100644 --- a/src/client/wieldmesh.cpp +++ b/src/client/wieldmesh.cpp @@ -303,13 +303,24 @@ void WieldMeshSceneNode::setExtruded(const std::string &imagename, } } -scene::SMesh *createSpecialNodeMesh(Client *client, content_t id, std::vector *colors) +scene::SMesh *createSpecialNodeMesh(Client *client, content_t id, std::vector *colors, const ContentFeatures &f) { MeshMakeData mesh_make_data(client, false, false); MeshCollector collector; mesh_make_data.setSmoothLighting(false); MapblockMeshGenerator gen(&mesh_make_data, &collector); - gen.renderSingle(id); + u8 param2 = 0; + if (f.param_type_2 == CPT2_WALLMOUNTED || + f.param_type_2 == CPT2_COLORED_WALLMOUNTED) { + if (f.drawtype == NDT_TORCHLIKE) + param2 = 1; + else if (f.drawtype == NDT_SIGNLIKE || + f.drawtype == NDT_NODEBOX || + f.drawtype == NDT_MESH) + param2 = 4; + } + gen.renderSingle(id, param2); + colors->clear(); scene::SMesh *mesh = new scene::SMesh(); for (auto &prebuffers : collector.prebuffers) @@ -319,8 +330,9 @@ scene::SMesh *createSpecialNodeMesh(Client *client, content_t id, std::vectorMaterial.setTexture(0, p.layer.texture); p.layer.applyMaterialOptions(buf->Material); @@ -368,73 +380,61 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client, bool che // Handle nodes // See also CItemDefManager::createClientCached() if (def.type == ITEM_NODE) { - if (f.mesh_ptr[0]) { - // e.g. mesh nodes and nodeboxes - mesh = cloneMesh(f.mesh_ptr[0]); - postProcessNodeMesh(mesh, f, m_enable_shaders, true, - &m_material_type, &m_colors); + bool cull_backface = f.needsBackfaceCulling(); + + // Select rendering method + switch (f.drawtype) { + case NDT_AIRLIKE: + setExtruded("no_texture_airlike.png", "", + v3f(1.0, 1.0, 1.0), tsrc, 1); + break; + case NDT_SIGNLIKE: + case NDT_TORCHLIKE: + case NDT_RAILLIKE: + case NDT_PLANTLIKE: + case NDT_PLANTLIKE_ROOTED: + case NDT_FLOWINGLIQUID: { + v3f wscale = def.wield_scale; + if (f.drawtype == NDT_FLOWINGLIQUID) + wscale.Z *= 0.1f; + setExtruded(tsrc->getTextureName(f.tiles[0].layers[0].texture_id), + tsrc->getTextureName(f.tiles[0].layers[1].texture_id), + wscale, tsrc, + f.tiles[0].layers[0].animation_frame_count); + // Add color + const TileLayer &l0 = f.tiles[0].layers[0]; + m_colors.emplace_back(l0.has_color, l0.color); + const TileLayer &l1 = f.tiles[0].layers[1]; + m_colors.emplace_back(l1.has_color, l1.color); + break; + } + case NDT_NORMAL: + case NDT_ALLFACES: + case NDT_LIQUID: + setCube(f, def.wield_scale); + break; + default: + // Render non-trivial drawtypes like the actual node + mesh = createSpecialNodeMesh(client, id, &m_colors, f); changeToMesh(mesh); mesh->drop(); - // mesh is pre-scaled by BS * f->visual_scale m_meshnode->setScale( - def.wield_scale * WIELD_SCALE_FACTOR - / (BS * f.visual_scale)); - } else { - switch (f.drawtype) { - case NDT_AIRLIKE: { - changeToMesh(nullptr); - break; - } - case NDT_PLANTLIKE: { - setExtruded(tsrc->getTextureName(f.tiles[0].layers[0].texture_id), - tsrc->getTextureName(f.tiles[0].layers[1].texture_id), - def.wield_scale, tsrc, - f.tiles[0].layers[0].animation_frame_count); - // Add color - const TileLayer &l0 = f.tiles[0].layers[0]; - m_colors.emplace_back(l0.has_color, l0.color); - const TileLayer &l1 = f.tiles[0].layers[1]; - m_colors.emplace_back(l1.has_color, l1.color); - break; - } - case NDT_PLANTLIKE_ROOTED: { - setExtruded(tsrc->getTextureName(f.special_tiles[0].layers[0].texture_id), - "", def.wield_scale, tsrc, - f.special_tiles[0].layers[0].animation_frame_count); - // Add color - const TileLayer &l0 = f.special_tiles[0].layers[0]; - m_colors.emplace_back(l0.has_color, l0.color); - break; - } - case NDT_NORMAL: - case NDT_ALLFACES: - case NDT_LIQUID: - case NDT_FLOWINGLIQUID: { - setCube(f, def.wield_scale); - break; - } - default: { - mesh = createSpecialNodeMesh(client, id, &m_colors); - changeToMesh(mesh); - mesh->drop(); - m_meshnode->setScale( - def.wield_scale * WIELD_SCALE_FACTOR - / (BS * f.visual_scale)); - } - } + def.wield_scale * WIELD_SCALE_FACTOR + / (BS * f.visual_scale)); + break; } + u32 material_count = m_meshnode->getMaterialCount(); for (u32 i = 0; i < material_count; ++i) { video::SMaterial &material = m_meshnode->getMaterial(i); material.MaterialType = m_material_type; material.MaterialTypeParam = 0.5f; - material.setFlag(video::EMF_BACK_FACE_CULLING, true); + material.setFlag(video::EMF_BACK_FACE_CULLING, cull_backface); material.setFlag(video::EMF_BILINEAR_FILTER, m_bilinear_filter); material.setFlag(video::EMF_TRILINEAR_FILTER, m_trilinear_filter); } return; - } - else if (!def.inventory_image.empty()) { + } else if (!def.inventory_image.empty()) { setExtruded(def.inventory_image, def.inventory_overlay, def.wield_scale, tsrc, 1); m_colors.emplace_back(); @@ -529,6 +529,8 @@ void getItemMesh(Client *client, const ItemStack &item, ItemMesh *result) // Shading is on by default result->needs_shading = true; + bool cull_backface = f.needsBackfaceCulling(); + // If inventory_image is defined, it overrides everything else if (!def.inventory_image.empty()) { mesh = getExtrudedMesh(tsrc, def.inventory_image, @@ -538,51 +540,54 @@ void getItemMesh(Client *client, const ItemStack &item, ItemMesh *result) result->buffer_colors.emplace_back(true, video::SColor(0xFFFFFFFF)); // Items with inventory images do not need shading result->needs_shading = false; + } else if (def.type == ITEM_NODE && f.drawtype == NDT_AIRLIKE) { + // Fallback image for airlike node + mesh = getExtrudedMesh(tsrc, "no_texture_airlike.png", + def.inventory_overlay); + result->needs_shading = false; } else if (def.type == ITEM_NODE) { - if (f.mesh_ptr[0]) { - mesh = cloneMesh(f.mesh_ptr[0]); - scaleMesh(mesh, v3f(0.12, 0.12, 0.12)); + switch (f.drawtype) { + case NDT_NORMAL: + case NDT_ALLFACES: + case NDT_LIQUID: + case NDT_FLOWINGLIQUID: { + scene::IMesh *cube = g_extrusion_mesh_cache->createCube(); + mesh = cloneMesh(cube); + cube->drop(); + if (f.drawtype == NDT_FLOWINGLIQUID) { + scaleMesh(mesh, v3f(1.2, 0.03, 1.2)); + translateMesh(mesh, v3f(0, -0.57, 0)); + } else + scaleMesh(mesh, v3f(1.2, 1.2, 1.2)); + // add overlays postProcessNodeMesh(mesh, f, false, false, nullptr, - &result->buffer_colors); - } else { - switch (f.drawtype) { - case NDT_PLANTLIKE: { - mesh = getExtrudedMesh(tsrc, - tsrc->getTextureName(f.tiles[0].layers[0].texture_id), - tsrc->getTextureName(f.tiles[0].layers[1].texture_id)); - // Add color - const TileLayer &l0 = f.tiles[0].layers[0]; - result->buffer_colors.emplace_back(l0.has_color, l0.color); - const TileLayer &l1 = f.tiles[0].layers[1]; - result->buffer_colors.emplace_back(l1.has_color, l1.color); - break; - } - case NDT_PLANTLIKE_ROOTED: { - mesh = getExtrudedMesh(tsrc, - tsrc->getTextureName(f.special_tiles[0].layers[0].texture_id), ""); - // Add color - const TileLayer &l0 = f.special_tiles[0].layers[0]; - result->buffer_colors.emplace_back(l0.has_color, l0.color); - break; - } - case NDT_NORMAL: - case NDT_ALLFACES: - case NDT_LIQUID: - case NDT_FLOWINGLIQUID: { - scene::IMesh *cube = g_extrusion_mesh_cache->createCube(); - mesh = cloneMesh(cube); - cube->drop(); - scaleMesh(mesh, v3f(1.2, 1.2, 1.2)); - // add overlays - postProcessNodeMesh(mesh, f, false, false, nullptr, - &result->buffer_colors); - break; - } - default: { - mesh = createSpecialNodeMesh(client, id, &result->buffer_colors); - scaleMesh(mesh, v3f(0.12, 0.12, 0.12)); - } - } + &result->buffer_colors, true); + break; + } + case NDT_PLANTLIKE: { + mesh = getExtrudedMesh(tsrc, + tsrc->getTextureName(f.tiles[0].layers[0].texture_id), + tsrc->getTextureName(f.tiles[0].layers[1].texture_id)); + // Add color + const TileLayer &l0 = f.tiles[0].layers[0]; + result->buffer_colors.emplace_back(l0.has_color, l0.color); + const TileLayer &l1 = f.tiles[0].layers[1]; + result->buffer_colors.emplace_back(l1.has_color, l1.color); + break; + } + case NDT_PLANTLIKE_ROOTED: { + mesh = getExtrudedMesh(tsrc, + tsrc->getTextureName(f.special_tiles[0].layers[0].texture_id), ""); + // Add color + const TileLayer &l0 = f.special_tiles[0].layers[0]; + result->buffer_colors.emplace_back(l0.has_color, l0.color); + break; + } + default: + // Render non-trivial drawtypes like the actual node + mesh = createSpecialNodeMesh(client, id, &result->buffer_colors, f); + scaleMesh(mesh, v3f(0.12, 0.12, 0.12)); + break; } u32 mc = mesh->getMeshBufferCount(); @@ -593,7 +598,7 @@ void getItemMesh(Client *client, const ItemStack &item, ItemMesh *result) material.MaterialTypeParam = 0.5f; material.setFlag(video::EMF_BILINEAR_FILTER, false); material.setFlag(video::EMF_TRILINEAR_FILTER, false); - material.setFlag(video::EMF_BACK_FACE_CULLING, true); + material.setFlag(video::EMF_BACK_FACE_CULLING, cull_backface); material.setFlag(video::EMF_LIGHTING, false); } diff --git a/src/nodedef.h b/src/nodedef.h index cf03abaae..ff52f976f 100644 --- a/src/nodedef.h +++ b/src/nodedef.h @@ -425,6 +425,22 @@ struct ContentFeatures /* Some handy methods */ + bool needsBackfaceCulling() const + { + switch (drawtype) { + case NDT_TORCHLIKE: + case NDT_SIGNLIKE: + case NDT_FIRELIKE: + case NDT_RAILLIKE: + case NDT_PLANTLIKE: + case NDT_PLANTLIKE_ROOTED: + case NDT_MESH: + return false; + default: + return true; + } + } + bool isLiquid() const{ return (liquid_type != LIQUID_NONE); } diff --git a/textures/base/pack/no_texture_airlike.png b/textures/base/pack/no_texture_airlike.png new file mode 100644 index 000000000..634ee8ca5 Binary files /dev/null and b/textures/base/pack/no_texture_airlike.png differ -- cgit v1.2.3 From ae83edd16581b2b5426b565e703a8766e88dbbf6 Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Mon, 27 Jul 2020 19:40:33 +0200 Subject: Play place_failed sound if occupied or cannot attach (#9486) --- doc/lua_api.txt | 7 +++++-- src/client/game.cpp | 2 ++ 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/doc/lua_api.txt b/doc/lua_api.txt index e0c895c97..5fe02b452 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -7217,10 +7217,13 @@ Used by `minetest.register_node`. -- Node was placed. Also played after falling place_failed = , - -- When node placement failed + -- When node placement failed. + -- Note: This happens if the _built-in_ node placement failed. + -- This sound will still be played if the node is placed in the + -- `on_place` callback manually. fall = , - -- When node starts to fall + -- When node starts to fall or is detached }, drop = "", diff --git a/src/client/game.cpp b/src/client/game.cpp index 42d60b21c..20d2c6f90 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -3379,6 +3379,7 @@ bool Game::nodePlacement(const ItemDefinition &selected_def, } else { node = map.getNode(p, &is_valid_position); if (is_valid_position && !nodedef->get(node).buildable_to) { + soundmaker->m_player_rightpunch_sound = selected_def.sound_place_failed; // Report to server client->interact(INTERACT_PLACE, pointed); return false; @@ -3451,6 +3452,7 @@ bool Game::nodePlacement(const ItemDefinition &selected_def, pp = p + v3s16(0, -1, 0); if (!nodedef->get(map.getNode(pp)).walkable) { + soundmaker->m_player_rightpunch_sound = selected_def.sound_place_failed; // Report to server client->interact(INTERACT_PLACE, pointed); return false; -- cgit v1.2.3 From 3ce03d1c2a63d261c83f5962cd13212697f19472 Mon Sep 17 00:00:00 2001 From: Hugues Ross Date: Tue, 28 Jul 2020 13:16:57 -0400 Subject: Sanitize world directory names on create. Keep original name separate (#9432) Blacklisted characters are replaced by '_' in the path. The display name is stored in world.mt, and duplicate file names are resolved by adding an incrementing suffix (_1, _2, _3, etc). --- src/content/subgames.cpp | 54 +++++++++++++++++++++++++------ src/content/subgames.h | 5 ++- src/script/lua_api/l_mainmenu.cpp | 9 +++--- src/server.cpp | 9 ++++-- src/util/string.cpp | 68 +++++++++++++++++++++++++++++++++++++++ src/util/string.h | 8 +++++ 6 files changed, 136 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/content/subgames.cpp b/src/content/subgames.cpp index 170f54e20..695ba431f 100644 --- a/src/content/subgames.cpp +++ b/src/content/subgames.cpp @@ -31,6 +31,9 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "client/tile.h" // getImagePath #endif +// The maximum number of identical world names allowed +#define MAX_WORLD_NAMES 100 + bool getGameMinetestConfig(const std::string &game_path, Settings &conf) { std::string conf_path = game_path + DIR_DELIM + "minetest.conf"; @@ -213,6 +216,21 @@ bool getWorldExists(const std::string &world_path) fs::PathExists(world_path + DIR_DELIM + "world.mt")); } +//! Try to get the displayed name of a world +std::string getWorldName(const std::string &world_path, const std::string &default_name) +{ + std::string conf_path = world_path + DIR_DELIM + "world.mt"; + Settings conf; + bool succeeded = conf.readConfigFile(conf_path.c_str()); + if (!succeeded) { + return default_name; + } + + if (!conf.exists("world_name")) + return default_name; + return conf.get("world_name"); +} + std::string getWorldGameId(const std::string &world_path, bool can_be_legacy) { std::string conf_path = world_path + DIR_DELIM + "world.mt"; @@ -259,7 +277,7 @@ std::vector getAvailableWorlds() if (!dln.dir) continue; std::string fullpath = worldspath + DIR_DELIM + dln.name; - std::string name = dln.name; + std::string name = getWorldName(fullpath, dln.name); // Just allow filling in the gameid always for now bool can_be_legacy = true; std::string gameid = getWorldGameId(fullpath, can_be_legacy); @@ -288,8 +306,24 @@ std::vector getAvailableWorlds() return worlds; } -bool loadGameConfAndInitWorld(const std::string &path, const SubgameSpec &gamespec) +void loadGameConfAndInitWorld(const std::string &path, const std::string &name, + const SubgameSpec &gamespec, bool create_world) { + std::string final_path = path; + + // If we're creating a new world, ensure that the path isn't already taken + if (create_world) { + int counter = 1; + while (fs::PathExists(final_path) && counter < MAX_WORLD_NAMES) { + final_path = path + "_" + std::to_string(counter); + counter++; + } + + if (fs::PathExists(final_path)) { + throw BaseException("Too many similar filenames"); + } + } + // Override defaults with those provided by the game. // We clear and reload the defaults because the defaults // might have been overridden by other subgame config @@ -300,15 +334,16 @@ bool loadGameConfAndInitWorld(const std::string &path, const SubgameSpec &gamesp getGameMinetestConfig(gamespec.path, game_defaults); g_settings->overrideDefaults(&game_defaults); - infostream << "Initializing world at " << path << std::endl; + infostream << "Initializing world at " << final_path << std::endl; - fs::CreateAllDirs(path); + fs::CreateAllDirs(final_path); // Create world.mt if does not already exist - std::string worldmt_path = path + DIR_DELIM "world.mt"; + std::string worldmt_path = final_path + DIR_DELIM "world.mt"; if (!fs::PathExists(worldmt_path)) { Settings conf; + conf.set("world_name", name); conf.set("gameid", gamespec.id); conf.set("backend", "sqlite3"); conf.set("player_backend", "sqlite3"); @@ -316,16 +351,16 @@ bool loadGameConfAndInitWorld(const std::string &path, const SubgameSpec &gamesp conf.setBool("creative_mode", g_settings->getBool("creative_mode")); conf.setBool("enable_damage", g_settings->getBool("enable_damage")); - if (!conf.updateConfigFile(worldmt_path.c_str())) - return false; + if (!conf.updateConfigFile(worldmt_path.c_str())) { + throw BaseException("Failed to update the config file"); + } } // Create map_meta.txt if does not already exist - std::string map_meta_path = path + DIR_DELIM + "map_meta.txt"; + std::string map_meta_path = final_path + DIR_DELIM + "map_meta.txt"; if (!fs::PathExists(map_meta_path)) { verbosestream << "Creating map_meta.txt (" << map_meta_path << ")" << std::endl; - fs::CreateAllDirs(path); std::ostringstream oss(std::ios_base::binary); Settings conf; @@ -338,5 +373,4 @@ bool loadGameConfAndInitWorld(const std::string &path, const SubgameSpec &gamesp fs::safeWriteToFile(map_meta_path, oss.str()); } - return true; } diff --git a/src/content/subgames.h b/src/content/subgames.h index 4198ea860..35b619aaf 100644 --- a/src/content/subgames.h +++ b/src/content/subgames.h @@ -63,6 +63,8 @@ std::set getAvailableGameIds(); std::vector getAvailableGames(); bool getWorldExists(const std::string &world_path); +//! Try to get the displayed name of a world +std::string getWorldName(const std::string &world_path, const std::string &default_name); std::string getWorldGameId(const std::string &world_path, bool can_be_legacy = false); struct WorldSpec @@ -88,4 +90,5 @@ std::vector getAvailableWorlds(); // loads the subgame's config and creates world directory // and world.mt if they don't exist -bool loadGameConfAndInitWorld(const std::string &path, const SubgameSpec &gamespec); +void loadGameConfAndInitWorld(const std::string &path, const std::string &name, + const SubgameSpec &gamespec, bool create_world); diff --git a/src/script/lua_api/l_mainmenu.cpp b/src/script/lua_api/l_mainmenu.cpp index f32c477c2..e49ec4052 100644 --- a/src/script/lua_api/l_mainmenu.cpp +++ b/src/script/lua_api/l_mainmenu.cpp @@ -618,7 +618,7 @@ int ModApiMainMenu::l_create_world(lua_State *L) std::string path = porting::path_user + DIR_DELIM "worlds" + DIR_DELIM - + name; + + sanitizeDirName(name, "world_"); std::vector games = getAvailableGames(); @@ -626,10 +626,11 @@ int ModApiMainMenu::l_create_world(lua_State *L) (gameidx < (int) games.size())) { // Create world if it doesn't exist - if (!loadGameConfAndInitWorld(path, games[gameidx])) { - lua_pushstring(L, "Failed to initialize world"); - } else { + try { + loadGameConfAndInitWorld(path, name, games[gameidx], true); lua_pushnil(L); + } catch (const BaseException &e) { + lua_pushstring(L, (std::string("Failed to initialize world: ") + e.what()).c_str()); } } else { lua_pushstring(L, "Invalid game index"); diff --git a/src/server.cpp b/src/server.cpp index fe2bb3840..53ee8c444 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -356,8 +356,13 @@ void Server::init() infostream << "- game: " << m_gamespec.path << std::endl; // Create world if it doesn't exist - if (!loadGameConfAndInitWorld(m_path_world, m_gamespec)) - throw ServerError("Failed to initialize world"); + try { + loadGameConfAndInitWorld(m_path_world, + fs::GetFilenameFromPath(m_path_world.c_str()), + m_gamespec, false); + } catch (const BaseException &e) { + throw ServerError(std::string("Failed to initialize world: ") + e.what()); + } // Create emerge manager m_emerge = new EmergeManager(this); diff --git a/src/util/string.cpp b/src/util/string.cpp index 6e1db798c..8381a29c5 100644 --- a/src/util/string.cpp +++ b/src/util/string.cpp @@ -27,6 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "translation.h" #include +#include #include #include #include @@ -889,3 +890,70 @@ std::wstring translate_string(const std::wstring &s) return translate_string(s, g_client_translations); #endif } + +static const std::array disallowed_dir_names = { + // Problematic filenames from here: + // https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file#file-and-directory-names + L"CON", + L"PRN", + L"AUX", + L"NUL", + L"COM1", + L"COM2", + L"COM3", + L"COM4", + L"COM5", + L"COM6", + L"COM7", + L"COM8", + L"COM9", + L"LPT1", + L"LPT2", + L"LPT3", + L"LPT4", + L"LPT5", + L"LPT6", + L"LPT7", + L"LPT8", + L"LPT9", +}; + +/** + * List of characters that are blacklisted from created directories + */ +static const std::wstring disallowed_path_chars = L"<>:\"/\\|?*."; + +/** + * Sanitize the name of a new directory. This consists of two stages: + * 1. Check for 'reserved filenames' that can't be used on some filesystems + * and add a prefix to them + * 2. Remove 'unsafe' characters from the name by replacing them with '_' + */ +std::string sanitizeDirName(const std::string &str, const std::string &optional_prefix) +{ + std::wstring safe_name = utf8_to_wide(str); + + for (std::wstring disallowed_name : disallowed_dir_names) { + if (str_equal(safe_name, disallowed_name, true)) { + safe_name = utf8_to_wide(optional_prefix) + safe_name; + break; + } + } + + for (unsigned long i = 0; i < safe_name.length(); i++) { + bool is_valid = true; + + // Unlikely, but control characters should always be blacklisted + if (safe_name[i] < 32) { + is_valid = false; + } else if (safe_name[i] < 128) { + is_valid = disallowed_path_chars.find_first_of(safe_name[i]) + == std::wstring::npos; + } + + if (!is_valid) + safe_name[i] = '_'; + } + + return wide_to_utf8(safe_name); +} diff --git a/src/util/string.h b/src/util/string.h index 185fb55e2..6fd11fadc 100644 --- a/src/util/string.h +++ b/src/util/string.h @@ -746,3 +746,11 @@ inline irr::core::stringw utf8_to_stringw(const std::string &input) std::wstring str = utf8_to_wide(input); return irr::core::stringw(str.c_str()); } + +/** + * Sanitize the name of a new directory. This consists of two stages: + * 1. Check for 'reserved filenames' that can't be used on some filesystems + * and prefix them + * 2. Remove 'unsafe' characters from the name by replacing them with '_' + */ +std::string sanitizeDirName(const std::string &str, const std::string &optional_prefix); -- cgit v1.2.3 From f34abaedd2b9277c1862cd9b82ca3338747f104e Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Wed, 29 Jul 2020 20:46:36 +0200 Subject: decode_base64: Allow '=' padding character '=' is a valid character, but minetest.decode_base64 returned nil when it was used for padding. --- src/util/base64.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/util/base64.cpp b/src/util/base64.cpp index c75f98598..6e1584410 100644 --- a/src/util/base64.cpp +++ b/src/util/base64.cpp @@ -34,8 +34,9 @@ static const std::string base64_chars = "0123456789+/"; -static inline bool is_base64(unsigned char c) { - return (isalnum(c) || (c == '+') || (c == '/')); +static inline bool is_base64(unsigned char c) +{ + return isalnum(c) || c == '+' || c == '/' || c == '='; } bool base64_is_valid(std::string const& s) -- cgit v1.2.3 From 715a123a33db7b0f191259ba68cbc9c565d0d4e8 Mon Sep 17 00:00:00 2001 From: Lejo Date: Thu, 30 Jul 2020 00:16:21 +0300 Subject: Add PUT and DELETE request + specific method value to HTTP API (#9909) --- doc/lua_api.txt | 12 ++++++-- src/client/clientmedia.cpp | 3 +- src/httpfetch.cpp | 66 +++++++++++++++++++++++++------------------ src/httpfetch.h | 22 +++++++++++---- src/network/networkprotocol.h | 2 +- src/script/lua_api/l_http.cpp | 29 +++++++++++++++++-- src/script/lua_api/l_http.h | 4 +-- src/serverlist.cpp | 4 +-- 8 files changed, 98 insertions(+), 44 deletions(-) (limited to 'src') diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 5fe02b452..2d22dc899 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -8071,11 +8071,13 @@ Used by `HTTPApiTable.fetch` and `HTTPApiTable.fetch_async`. timeout = 10, -- Timeout for connection in seconds. Default is 3 seconds. - post_data = "Raw POST request data string" OR {field1 = "data1", field2 = "data2"}, - -- Optional, if specified a POST request with post_data is performed. + method = "GET", "POST", "PUT" or "DELETE" + -- The http method to use. Defaults to "GET". + + data = "Raw request data string" OR {field1 = "data1", field2 = "data2"}, + -- Data for the POST, PUT or DELETE request. -- Accepts both a string and a table. If a table is specified, encodes -- table as x-www-form-urlencoded key-value pairs. - -- If post_data is not specified, a GET request is performed instead. user_agent = "ExampleUserAgent", -- Optional, if specified replaces the default minetest user agent with @@ -8089,6 +8091,10 @@ Used by `HTTPApiTable.fetch` and `HTTPApiTable.fetch_async`. multipart = boolean -- Optional, if true performs a multipart HTTP request. -- Default is false. + -- Post only, data must be array + + post_data = "Raw POST request data string" OR {field1 = "data1", field2 = "data2"}, + -- Deprecated, use `data` instead. Forces `method = "POST"`. } `HTTPRequestResult` definition diff --git a/src/client/clientmedia.cpp b/src/client/clientmedia.cpp index 8cd3b6bcc..c4c08c05d 100644 --- a/src/client/clientmedia.cpp +++ b/src/client/clientmedia.cpp @@ -260,7 +260,8 @@ void ClientMediaDownloader::initialStep(Client *client) fetch_request.request_id = m_httpfetch_next_id; // == i fetch_request.timeout = m_httpfetch_timeout; fetch_request.connect_timeout = m_httpfetch_timeout; - fetch_request.post_data = required_hash_set; + fetch_request.method = HTTP_POST; + fetch_request.raw_data = required_hash_set; fetch_request.extra_headers.emplace_back( "Content-Type: application/octet-stream"); diff --git a/src/httpfetch.cpp b/src/httpfetch.cpp index 326b5052f..65202ce3e 100644 --- a/src/httpfetch.cpp +++ b/src/httpfetch.cpp @@ -294,13 +294,11 @@ HTTPFetchOngoing::HTTPFetchOngoing(const HTTPFetchRequest &request_, curl_easy_setopt(curl, CURLOPT_WRITEDATA, &oss); } - // Set POST (or GET) data - if (request.post_fields.empty() && request.post_data.empty()) { - curl_easy_setopt(curl, CURLOPT_HTTPGET, 1); - } else if (request.multipart) { + // Set data from fields or raw_data + if (request.multipart) { curl_httppost *last = NULL; - for (StringMap::iterator it = request.post_fields.begin(); - it != request.post_fields.end(); ++it) { + for (StringMap::iterator it = request.fields.begin(); + it != request.fields.end(); ++it) { curl_formadd(&post, &last, CURLFORM_NAMELENGTH, it->first.size(), CURLFORM_PTRNAME, it->first.c_str(), @@ -311,28 +309,42 @@ HTTPFetchOngoing::HTTPFetchOngoing(const HTTPFetchRequest &request_, curl_easy_setopt(curl, CURLOPT_HTTPPOST, post); // request.post_fields must now *never* be // modified until CURLOPT_HTTPPOST is cleared - } else if (request.post_data.empty()) { - curl_easy_setopt(curl, CURLOPT_POST, 1); - std::string str; - for (auto &post_field : request.post_fields) { - if (!str.empty()) - str += "&"; - str += urlencode(post_field.first); - str += "="; - str += urlencode(post_field.second); - } - curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, - str.size()); - curl_easy_setopt(curl, CURLOPT_COPYPOSTFIELDS, - str.c_str()); } else { - curl_easy_setopt(curl, CURLOPT_POST, 1); - curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, - request.post_data.size()); - curl_easy_setopt(curl, CURLOPT_POSTFIELDS, - request.post_data.c_str()); - // request.post_data must now *never* be - // modified until CURLOPT_POSTFIELDS is cleared + switch (request.method) { + case HTTP_GET: + curl_easy_setopt(curl, CURLOPT_HTTPGET, 1); + break; + case HTTP_POST: + curl_easy_setopt(curl, CURLOPT_POST, 1); + break; + case HTTP_PUT: + curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT"); + break; + case HTTP_DELETE: + curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE"); + break; + } + if (request.method != HTTP_GET) { + if (!request.raw_data.empty()) { + curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, + request.raw_data.size()); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, + request.raw_data.c_str()); + } else if (!request.fields.empty()) { + std::string str; + for (auto &field : request.fields) { + if (!str.empty()) + str += "&"; + str += urlencode(field.first); + str += "="; + str += urlencode(field.second); + } + curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, + str.size()); + curl_easy_setopt(curl, CURLOPT_COPYPOSTFIELDS, + str.c_str()); + } + } } // Set additional HTTP headers for (const std::string &extra_header : request.extra_headers) { diff --git a/src/httpfetch.h b/src/httpfetch.h index ae8b5afb5..3b9f17f0a 100644 --- a/src/httpfetch.h +++ b/src/httpfetch.h @@ -28,6 +28,15 @@ with this program; if not, write to the Free Software Foundation, Inc., #define HTTPFETCH_DISCARD 0 #define HTTPFETCH_SYNC 1 +// Methods +enum HttpMethod : u8 +{ + HTTP_GET, + HTTP_POST, + HTTP_PUT, + HTTP_DELETE, +}; + struct HTTPFetchRequest { std::string url = ""; @@ -50,12 +59,15 @@ struct HTTPFetchRequest // application/x-www-form-urlencoded. POST-only. bool multipart = false; - // POST fields. Fields are escaped properly. - // If this is empty a GET request is done instead. - StringMap post_fields; + // The Method to use default = GET + // Avaible methods GET, POST, PUT, DELETE + HttpMethod method = HTTP_GET; + + // Fields of the request + StringMap fields; - // Raw POST data, overrides post_fields. - std::string post_data; + // Raw data of the request overrides fields + std::string raw_data; // If not empty, should contain entries such as "Accept: text/html" std::vector extra_headers; diff --git a/src/network/networkprotocol.h b/src/network/networkprotocol.h index 28abf02c0..05600cda9 100644 --- a/src/network/networkprotocol.h +++ b/src/network/networkprotocol.h @@ -1034,7 +1034,7 @@ const static std::string accessDeniedStrings[SERVER_ACCESSDENIED_MAX] = { "This server has experienced an internal error. You will now be disconnected." }; -enum PlayerListModifer: u8 +enum PlayerListModifer : u8 { PLAYER_LIST_INIT, PLAYER_LIST_ADD, diff --git a/src/script/lua_api/l_http.cpp b/src/script/lua_api/l_http.cpp index ec43bf174..5ea3b3f99 100644 --- a/src/script/lua_api/l_http.cpp +++ b/src/script/lua_api/l_http.cpp @@ -49,17 +49,40 @@ void ModApiHttp::read_http_fetch_request(lua_State *L, HTTPFetchRequest &req) req.multipart = getboolfield_default(L, 1, "multipart", false); req.timeout = getintfield_default(L, 1, "timeout", 3) * 1000; - // post_data: if table, post form data, otherwise raw data + lua_getfield(L, 1, "method"); + if (lua_isstring(L, -1)) { + std::string mth = getstringfield_default(L, 1, "method", ""); + if (mth == "GET") + req.method = HTTP_GET; + else if (mth == "POST") + req.method = HTTP_POST; + else if (mth == "PUT") + req.method = HTTP_PUT; + else if (mth == "DELETE") + req.method = HTTP_DELETE; + } + lua_pop(L, 1); + + // post_data: if table, post form data, otherwise raw data DEPRECATED use data and method instead lua_getfield(L, 1, "post_data"); + if (lua_isnil(L, 2)) { + lua_pop(L, 1); + lua_getfield(L, 1, "data"); + } + else { + req.method = HTTP_POST; + } + if (lua_istable(L, 2)) { lua_pushnil(L); while (lua_next(L, 2) != 0) { - req.post_fields[readParam(L, -2)] = readParam(L, -1); + req.fields[readParam(L, -2)] = readParam(L, -1); lua_pop(L, 1); } } else if (lua_isstring(L, 2)) { - req.post_data = readParam(L, 2); + req.raw_data = readParam(L, 2); } + lua_pop(L, 1); lua_getfield(L, 1, "extra_headers"); diff --git a/src/script/lua_api/l_http.h b/src/script/lua_api/l_http.h index de6e51b37..c3a2a5276 100644 --- a/src/script/lua_api/l_http.h +++ b/src/script/lua_api/l_http.h @@ -32,10 +32,10 @@ private: static void read_http_fetch_request(lua_State *L, HTTPFetchRequest &req); static void push_http_fetch_result(lua_State *L, HTTPFetchResult &res, bool completed = true); - // http_fetch_sync({url=, timeout=, post_data=}) + // http_fetch_sync({url=, timeout=, data=}) static int l_http_fetch_sync(lua_State *L); - // http_fetch_async({url=, timeout=, post_data=}) + // http_fetch_async({url=, timeout=, data=}) static int l_http_fetch_async(lua_State *L); // http_fetch_async_get(handle) diff --git a/src/serverlist.cpp b/src/serverlist.cpp index 18264e933..2f6ab2e61 100644 --- a/src/serverlist.cpp +++ b/src/serverlist.cpp @@ -261,11 +261,11 @@ void sendAnnounce(AnnounceAction action, HTTPFetchRequest fetch_request; fetch_request.url = g_settings->get("serverlist_url") + std::string("/announce"); - fetch_request.post_fields["json"] = fastWriteJson(server); + fetch_request.method = HTTP_POST; + fetch_request.fields["json"] = fastWriteJson(server); fetch_request.multipart = true; httpfetch_async(fetch_request); } #endif } // namespace ServerList - -- cgit v1.2.3 From 470f32821627a56b682ea1947ab5a50ef57c1c10 Mon Sep 17 00:00:00 2001 From: Lars Müller <34514239+appgurueu@users.noreply.github.com> Date: Wed, 29 Jul 2020 23:17:52 +0200 Subject: Revert "Get rid of non-ascii characters in the debug display code (#8821)" (#9828) This reverts commit 4f9ccd89b347dad3db5ce63d3405a8d60c163af5. --- src/client/gameui.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/client/gameui.cpp b/src/client/gameui.cpp index c216f405d..81c268e44 100644 --- a/src/client/gameui.cpp +++ b/src/client/gameui.cpp @@ -133,9 +133,9 @@ void GameUI::update(const RunStats &stats, Client *client, MapDrawControl *draw_ << "pos: (" << (player_position.X / BS) << ", " << (player_position.Y / BS) << ", " << (player_position.Z / BS) - << ") | yaw: " << (wrapDegrees_0_360(cam.camera_yaw)) << "\xC2\xB0 " + << ") | yaw: " << (wrapDegrees_0_360(cam.camera_yaw)) << "° " << yawToDirectionString(cam.camera_yaw) - << " | pitch: " << (-wrapDegrees_180(cam.camera_pitch)) << "\xC2\xB0" + << " | pitch: " << (-wrapDegrees_180(cam.camera_pitch)) << "°" << " | seed: " << ((u64)client->getMapSeed()); if (pointed_old.type == POINTEDTHING_NODE) { -- cgit v1.2.3 From e5725dfb8e476a5a6f63f020a23a53ca3ef610e9 Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Wed, 29 Jul 2020 23:20:01 +0200 Subject: Allow starting local server using --go again (#10229) --- src/client/clientlauncher.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/client/clientlauncher.cpp b/src/client/clientlauncher.cpp index ce16797e6..29427f609 100644 --- a/src/client/clientlauncher.cpp +++ b/src/client/clientlauncher.cpp @@ -327,13 +327,13 @@ void ClientLauncher::init_args(GameStartData &start_data, const Settings &cmd_ar // Join a remote server start_data.address = cmd_args.get("address"); start_data.world_path.clear(); + start_data.name = g_settings->get("name"); } if (!start_data.world_path.empty()) { // Start a singleplayer instance start_data.address = ""; } - start_data.name = g_settings->get("name"); if (cmd_args.exists("name")) start_data.name = cmd_args.get("name"); @@ -419,7 +419,6 @@ bool ClientLauncher::launch_game(std::string &error_message, /* Show the GUI menu */ std::string server_name, server_description; - start_data.local_server = false; if (!skip_main_menu) { // Initialize menu data // TODO: Re-use existing structs (GameStartData) @@ -467,6 +466,9 @@ bool ClientLauncher::launch_game(std::string &error_message, start_data.local_server = !menudata.simple_singleplayer_mode && start_data.address.empty(); + } else { + start_data.local_server = !start_data.world_path.empty() && + start_data.address.empty() && !start_data.name.empty(); } if (!RenderingEngine::run()) -- cgit v1.2.3 From 9bba52c4000a06043f5100dbb0ef66d869707ffc Mon Sep 17 00:00:00 2001 From: sfan5 Date: Thu, 30 Jul 2020 17:39:57 +0200 Subject: content_cao: Support texture animation for upright_sprite (#10020) --- doc/lua_api.txt | 18 +++++++++--------- games/devtest/mods/testentities/visuals.lua | 16 ++++++++++++++-- src/client/content_cao.cpp | 28 +++++++++++++++++++++++++--- src/client/mesh.cpp | 9 +++++++++ src/client/mesh.h | 7 +++++++ 5 files changed, 64 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 2d22dc899..8ac3ad7f2 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -6077,15 +6077,15 @@ object you are working with still exists. * `get_yaw()`: returns number in radians * `set_texture_mod(mod)` * `get_texture_mod()` returns current texture modifier -* `set_sprite(p, num_frames, framelength, select_horiz_by_yawpitch)` - * Select sprite from spritesheet with optional animation and Dungeon Master - style texture selection based on yaw relative to camera - * `p`: {x=number, y=number}, the coordinate of the first frame - (x: column, y: row), default: `{x=0, y=0}` - * `num_frames`: number, default: `1` - * `framelength`: number, default: `0.2` - * `select_horiz_by_yawpitch`: boolean, this was once used for the Dungeon - Master mob, default: `false` +* `set_sprite(p, num_frames, framelength, select_x_by_camera)` + * Specifies and starts a sprite animation + * Animations iterate along the frame `y` position. + * `p`: {x=column number, y=row number}, the coordinate of the first frame + default: `{x=0, y=0}` + * `num_frames`: Total frames in the texture, default: `1` + * `framelength`: Time per animated frame in seconds, default: `0.2` + * `select_x_by_camera`: Only for visual = `sprite`. Changes the frame `x` + position according to the view direction. default: `false`. * `get_entity_name()` (**Deprecated**: Will be removed in a future version) * `get_luaentity()` diff --git a/games/devtest/mods/testentities/visuals.lua b/games/devtest/mods/testentities/visuals.lua index 83f361f16..8848ba49f 100644 --- a/games/devtest/mods/testentities/visuals.lua +++ b/games/devtest/mods/testentities/visuals.lua @@ -68,7 +68,7 @@ minetest.register_entity("testentities:mesh_unshaded", { -- Advanced visual tests --- A test entity for testing animated and yaw-modulated sprites +-- An entity for testing animated and yaw-modulated sprites minetest.register_entity("testentities:yawsprite", { initial_properties = { selectionbox = {-0.3, -0.5, -0.3, 0.3, 0.3, 0.3}, @@ -79,6 +79,18 @@ minetest.register_entity("testentities:yawsprite", { initial_sprite_basepos = {x=0, y=0}, }, on_activate = function(self, staticdata) - self.object:set_sprite({x=0, y=0}, 1, 0, true) + self.object:set_sprite({x=0, y=0}, 3, 0.5, true) + end, +}) + +-- An entity for testing animated upright sprites +minetest.register_entity("testentities:upright_animated", { + initial_properties = { + visual = "upright_sprite", + textures = {"testnodes_anim.png"}, + spritediv = {x = 1, y = 4}, + }, + on_activate = function(self) + self.object:set_sprite({x=0, y=0}, 4, 1.0, false) end, }) diff --git a/src/client/content_cao.cpp b/src/client/content_cao.cpp index 4f949f6b0..88688d18c 100644 --- a/src/client/content_cao.cpp +++ b/src/client/content_cao.cpp @@ -1176,6 +1176,7 @@ void GenericCAO::updateTexturePos() int row = m_tx_basepos.Y; int col = m_tx_basepos.X; + // Yawpitch goes rightwards if (m_tx_select_horiz_by_yawpitch) { if (cam_to_entity.Y > 0.75) col += 5; @@ -1206,6 +1207,27 @@ void GenericCAO::updateTexturePos() float tys = m_tx_size.Y; setBillboardTextureMatrix(m_spritenode, txs, tys, col, row); } + + else if (m_meshnode) { + if (m_prop.visual == "upright_sprite") { + int row = m_tx_basepos.Y; + int col = m_tx_basepos.X; + + // Animation goes downwards + row += m_anim_frame; + + const auto &tx = m_tx_size; + v2f t[4] = { // cf. vertices in GenericCAO::addToScene() + tx * v2f(col+1, row+1), + tx * v2f(col, row+1), + tx * v2f(col, row), + tx * v2f(col+1, row), + }; + auto mesh = m_meshnode->getMesh(); + setMeshBufferTextureCoords(mesh->getMeshBuffer(0), t, 4); + setMeshBufferTextureCoords(mesh->getMeshBuffer(1), t, 4); + } + } } // Do not pass by reference, see header. @@ -1247,7 +1269,7 @@ void GenericCAO::updateTextures(std::string mod) } } - if (m_animated_meshnode) { + else if (m_animated_meshnode) { if (m_prop.visual == "mesh") { for (u32 i = 0; i < m_prop.textures.size() && i < m_animated_meshnode->getMaterialCount(); ++i) { @@ -1296,8 +1318,8 @@ void GenericCAO::updateTextures(std::string mod) } } } - if(m_meshnode) - { + + else if (m_meshnode) { if(m_prop.visual == "cube") { for (u32 i = 0; i < 6; ++i) diff --git a/src/client/mesh.cpp b/src/client/mesh.cpp index e1ec22068..2400a374c 100644 --- a/src/client/mesh.cpp +++ b/src/client/mesh.cpp @@ -203,6 +203,15 @@ void setMeshColor(scene::IMesh *mesh, const video::SColor &color) setMeshBufferColor(mesh->getMeshBuffer(j), color); } +void setMeshBufferTextureCoords(scene::IMeshBuffer *buf, const v2f *uv, u32 count) +{ + const u32 stride = getVertexPitchFromType(buf->getVertexType()); + assert(buf->getVertexCount() >= count); + u8 *vertices = (u8 *) buf->getVertices(); + for (u32 i = 0; i < count; i++) + ((video::S3DVertex*) (vertices + i * stride))->TCoords = uv[i]; +} + template static void applyToMesh(scene::IMesh *mesh, const F &fn) { diff --git a/src/client/mesh.h b/src/client/mesh.h index 103c61e45..dbc091a06 100644 --- a/src/client/mesh.h +++ b/src/client/mesh.h @@ -58,6 +58,13 @@ void setMeshBufferColor(scene::IMeshBuffer *buf, const video::SColor &color); */ void setMeshColor(scene::IMesh *mesh, const video::SColor &color); + +/* + Sets texture coords for vertices in the mesh buffer. + `uv[]` must have `count` elements +*/ +void setMeshBufferTextureCoords(scene::IMeshBuffer *buf, const v2f *uv, u32 count); + /* Set a constant color for an animated mesh */ -- cgit v1.2.3 From 542df11bed89ebad786220f1162597353ecc277d Mon Sep 17 00:00:00 2001 From: Paul Ouellette Date: Sat, 1 Aug 2020 11:25:33 -0400 Subject: Fix GCC class-memaccess warnings (#10239) --- src/client/mapblock_mesh.cpp | 7 +++++++ src/noise.cpp | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/mapblock_mesh.cpp b/src/client/mapblock_mesh.cpp index 1020e35f5..2f96ca61f 100644 --- a/src/client/mapblock_mesh.cpp +++ b/src/client/mapblock_mesh.cpp @@ -419,7 +419,14 @@ static void getNodeVertexDirs(const v3s16 &dir, v3s16 *vertex_dirs) u8 idx = (dir.X + 2 * dir.Y + 3 * dir.Z) & 7; idx = (idx - 1) * 4; +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wclass-memaccess" +#endif memcpy(vertex_dirs, &vertex_dirs_table[idx], 4 * sizeof(v3s16)); +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic pop +#endif } static void getNodeTextureCoords(v3f base, const v3f &scale, const v3s16 &dir, float *u, float *v) diff --git a/src/noise.cpp b/src/noise.cpp index 5a1d989cb..e16564b05 100644 --- a/src/noise.cpp +++ b/src/noise.cpp @@ -424,7 +424,7 @@ float NoisePerlin3D(NoiseParams *np, float x, float y, float z, s32 seed) Noise::Noise(NoiseParams *np_, s32 seed, u32 sx, u32 sy, u32 sz) { - memcpy(&np, np_, sizeof(np)); + np = *np_; this->seed = seed; this->sx = sx; this->sy = sy; -- cgit v1.2.3 From d22fd6fc348ecf393f535c9b172410f4a82a2d52 Mon Sep 17 00:00:00 2001 From: Seeker Date: Mon, 3 Aug 2020 14:38:45 -0700 Subject: Fix build for Visual Studio (explicitly cast pointers) (#10256) --- src/util/md32_common.h | 2 +- src/util/sha256.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/util/md32_common.h b/src/util/md32_common.h index a4c2099c9..2c050b72a 100644 --- a/src/util/md32_common.h +++ b/src/util/md32_common.h @@ -301,7 +301,7 @@ int HASH_UPDATE(HASH_CTX *c, const void *data_, size_t len) { - const unsigned char *data = data_; + const unsigned char *data = (const unsigned char *)data_; unsigned char *p; HASH_LONG l; size_t n; diff --git a/src/util/sha256.c b/src/util/sha256.c index 4241f31f3..5c8266f9a 100644 --- a/src/util/sha256.c +++ b/src/util/sha256.c @@ -18,13 +18,13 @@ const char SHA256_version[] = "SHA-256" OPENSSL_VERSION_PTEXT; unsigned static char cleanse_ctr = 0; static void OPENSSL_cleanse(void *ptr, size_t len) { - unsigned char *p = ptr; + unsigned char *p = (unsigned char *)ptr; size_t loop = len, ctr = cleanse_ctr; while (loop--) { *(p++) = (unsigned char)ctr; ctr += (17 + ((size_t)p & 0xF)); } - p = memchr(ptr, (unsigned char)ctr, len); + p = (unsigned char *)memchr(ptr, (unsigned char)ctr, len); if (p) ctr += (63 + (size_t)p); cleanse_ctr = (unsigned char)ctr; @@ -262,7 +262,7 @@ static void sha256_block_data_order(SHA256_CTX *ctx, const void *in, unsigned MD32_REG_T a, b, c, d, e, f, g, h, s0, s1, T1; SHA_LONG X[16]; int i; - const unsigned char *data = in; + const unsigned char *data = (const unsigned char *)in; const union { long one; char little; -- cgit v1.2.3 From 93ecc589bc49a80187705f6e06df23a71263d3d7 Mon Sep 17 00:00:00 2001 From: Hugues Ross Date: Tue, 4 Aug 2020 14:12:47 -0400 Subject: Implement override.txt support for special tiles (#10140) Add override targets for all special_tiles entries in node definitions, allowing texture packs to replace these textures. This makes overrides work properly with a variety of drawtypes. The targets are named special1 through special6, covering the the current length of the special_tiles array. --- doc/texture_packs.txt | 18 +++++++++++++++++- src/nodedef.cpp | 21 +++++++++++++++++++++ src/nodedef.h | 5 +++++ src/texture_override.cpp | 38 ++++++++++++++++++++++++++------------ src/texture_override.h | 18 +++++++++++++++--- util/ci/lint.sh | 0 6 files changed, 84 insertions(+), 16 deletions(-) mode change 100644 => 100755 util/ci/lint.sh (limited to 'src') diff --git a/doc/texture_packs.txt b/doc/texture_packs.txt index 79d65a339..8af2cbad6 100644 --- a/doc/texture_packs.txt +++ b/doc/texture_packs.txt @@ -195,11 +195,27 @@ Here are targets you can choose from: | bottom | y- face | | sides | x-, x+, z-, z+ faces | | all | All faces. You can also use '*' instead of 'all'. | +| special1 | The first entry in the special_tiles list | +| special2 | The second entry in the special_tiles list | +| special3 | The third entry in the special_tiles list | +| special4 | The fourth entry in the special_tiles list | +| special5 | The fifth entry in the special_tiles list | +| special6 | The sixth entry in the special_tiles list | | inventory | The inventory texture | | wield | The texture used when held by the player | Nodes support all targets, but other items only support 'inventory' -and 'wield' +and 'wield'. + +### Using the special targets + +The special* targets only apply to specific drawtypes: + +* `flowingliquid`: special1 sets the top texture, special2 sets the side texture +* `allfaces_optional`: special1 is used by simple mode, see below +* `glasslike_framed`: When containing a liquid, special1 sets the liquid texture +* `glasslike_framed_optional`: Same as `glasslike_framed` +* `plantlike_rooted`: special1 sets the plant's texture Designing leaves textures for the leaves rendering options ---------------------------------------------------------- diff --git a/src/nodedef.cpp b/src/nodedef.cpp index e5cd2c2a7..82c4581fa 100644 --- a/src/nodedef.cpp +++ b/src/nodedef.cpp @@ -1337,6 +1337,7 @@ void NodeDefManager::applyTextureOverrides(const std::vector &o ContentFeatures &nodedef = m_content_features[id]; + // Override tiles if (texture_override.hasTarget(OverrideTarget::TOP)) nodedef.tiledef[0].name = texture_override.texture; @@ -1354,6 +1355,26 @@ void NodeDefManager::applyTextureOverrides(const std::vector &o if (texture_override.hasTarget(OverrideTarget::FRONT)) nodedef.tiledef[5].name = texture_override.texture; + + + // Override special tiles, if applicable + if (texture_override.hasTarget(OverrideTarget::SPECIAL_1)) + nodedef.tiledef_special[0].name = texture_override.texture; + + if (texture_override.hasTarget(OverrideTarget::SPECIAL_2)) + nodedef.tiledef_special[1].name = texture_override.texture; + + if (texture_override.hasTarget(OverrideTarget::SPECIAL_3)) + nodedef.tiledef_special[2].name = texture_override.texture; + + if (texture_override.hasTarget(OverrideTarget::SPECIAL_4)) + nodedef.tiledef_special[3].name = texture_override.texture; + + if (texture_override.hasTarget(OverrideTarget::SPECIAL_5)) + nodedef.tiledef_special[4].name = texture_override.texture; + + if (texture_override.hasTarget(OverrideTarget::SPECIAL_6)) + nodedef.tiledef_special[5].name = texture_override.texture; } } diff --git a/src/nodedef.h b/src/nodedef.h index ff52f976f..d0da367ee 100644 --- a/src/nodedef.h +++ b/src/nodedef.h @@ -261,6 +261,11 @@ struct TileDef NodeDrawType drawtype); }; +// Defines the number of special tiles per nodedef +// +// NOTE: When changing this value, the enum entries of OverrideTarget and +// parser in TextureOverrideSource must be updated so that all special +// tiles can be overridden. #define CF_SPECIAL_COUNT 6 struct ContentFeatures diff --git a/src/texture_override.cpp b/src/texture_override.cpp index 10d129b87..effdb0efd 100644 --- a/src/texture_override.cpp +++ b/src/texture_override.cpp @@ -24,6 +24,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include +#define override_cast static_cast + TextureOverrideSource::TextureOverrideSource(std::string filepath) { std::ifstream infile(filepath.c_str()); @@ -56,25 +58,37 @@ TextureOverrideSource::TextureOverrideSource(std::string filepath) std::vector targets = str_split(splitted[1], ','); for (const std::string &target : targets) { if (target == "top") - texture_override.target |= static_cast(OverrideTarget::TOP); + texture_override.target |= override_cast(OverrideTarget::TOP); else if (target == "bottom") - texture_override.target |= static_cast(OverrideTarget::BOTTOM); + texture_override.target |= override_cast(OverrideTarget::BOTTOM); else if (target == "left") - texture_override.target |= static_cast(OverrideTarget::LEFT); + texture_override.target |= override_cast(OverrideTarget::LEFT); else if (target == "right") - texture_override.target |= static_cast(OverrideTarget::RIGHT); + texture_override.target |= override_cast(OverrideTarget::RIGHT); else if (target == "front") - texture_override.target |= static_cast(OverrideTarget::FRONT); + texture_override.target |= override_cast(OverrideTarget::FRONT); else if (target == "back") - texture_override.target |= static_cast(OverrideTarget::BACK); + texture_override.target |= override_cast(OverrideTarget::BACK); else if (target == "inventory") - texture_override.target |= static_cast(OverrideTarget::INVENTORY); + texture_override.target |= override_cast(OverrideTarget::INVENTORY); else if (target == "wield") - texture_override.target |= static_cast(OverrideTarget::WIELD); + texture_override.target |= override_cast(OverrideTarget::WIELD); + else if (target == "special1") + texture_override.target |= override_cast(OverrideTarget::SPECIAL_1); + else if (target == "special2") + texture_override.target |= override_cast(OverrideTarget::SPECIAL_2); + else if (target == "special3") + texture_override.target |= override_cast(OverrideTarget::SPECIAL_3); + else if (target == "special4") + texture_override.target |= override_cast(OverrideTarget::SPECIAL_4); + else if (target == "special5") + texture_override.target |= override_cast(OverrideTarget::SPECIAL_5); + else if (target == "special6") + texture_override.target |= override_cast(OverrideTarget::SPECIAL_6); else if (target == "sides") - texture_override.target |= static_cast(OverrideTarget::SIDES); + texture_override.target |= override_cast(OverrideTarget::SIDES); else if (target == "all" || target == "*") - texture_override.target |= static_cast(OverrideTarget::ALL_FACES); + texture_override.target |= override_cast(OverrideTarget::ALL_FACES); else { // Report invalid target warningstream << filepath << ":" << line_index @@ -85,7 +99,7 @@ TextureOverrideSource::TextureOverrideSource(std::string filepath) } // If there are no valid targets, skip adding this override - if (texture_override.target == static_cast(OverrideTarget::INVALID)) { + if (texture_override.target == override_cast(OverrideTarget::INVALID)) { continue; } @@ -112,7 +126,7 @@ std::vector TextureOverrideSource::getNodeTileOverrides() std::vector found_overrides; for (const TextureOverride &texture_override : m_overrides) { - if (texture_override.hasTarget(OverrideTarget::ALL_FACES)) + if (texture_override.hasTarget(OverrideTarget::NODE_TARGETS)) found_overrides.push_back(texture_override); } diff --git a/src/texture_override.h b/src/texture_override.h index db03bd014..bdc95e732 100644 --- a/src/texture_override.h +++ b/src/texture_override.h @@ -23,8 +23,10 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include +typedef u16 override_t; + //! Bitmask enum specifying what a texture override should apply to -enum class OverrideTarget : u8 +enum class OverrideTarget : override_t { INVALID = 0, TOP = 1 << 0, @@ -35,23 +37,33 @@ enum class OverrideTarget : u8 BACK = 1 << 5, INVENTORY = 1 << 6, WIELD = 1 << 7, + SPECIAL_1 = 1 << 8, + SPECIAL_2 = 1 << 9, + SPECIAL_3 = 1 << 10, + SPECIAL_4 = 1 << 11, + SPECIAL_5 = 1 << 12, + SPECIAL_6 = 1 << 13, + // clang-format off SIDES = LEFT | RIGHT | FRONT | BACK, ALL_FACES = TOP | BOTTOM | SIDES, + ALL_SPECIAL = SPECIAL_1 | SPECIAL_2 | SPECIAL_3 | SPECIAL_4 | SPECIAL_5 | SPECIAL_6, + NODE_TARGETS = ALL_FACES | ALL_SPECIAL, ITEM_TARGETS = INVENTORY | WIELD, + // clang-format on }; struct TextureOverride { std::string id; std::string texture; - u8 target; + override_t target; // Helper function for checking if an OverrideTarget is found in // a TextureOverride without casting inline bool hasTarget(OverrideTarget overrideTarget) const { - return (target & static_cast(overrideTarget)) != 0; + return (target & static_cast(overrideTarget)) != 0; } }; diff --git a/util/ci/lint.sh b/util/ci/lint.sh old mode 100644 new mode 100755 -- cgit v1.2.3 From f92a393f6f949377b1d78630a8f7d24e78e6ff9d Mon Sep 17 00:00:00 2001 From: Paramat Date: Wed, 5 Aug 2020 05:00:00 +0100 Subject: Mapgen Flat: Add caverns, disabled by default (#9913) Add the caverns used in V5, V7, Valleys, Carpathian. Disabled by default to not be force-enabled in existing worlds. --- builtin/mainmenu/dlg_create_world.lua | 1 + builtin/settingtypes.txt | 14 +++++++- src/mapgen/mapgen_flat.cpp | 64 +++++++++++++++++++++++++---------- src/mapgen/mapgen_flat.h | 22 +++++++----- 4 files changed, 75 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/builtin/mainmenu/dlg_create_world.lua b/builtin/mainmenu/dlg_create_world.lua index 36df23cce..b2e706b6b 100644 --- a/builtin/mainmenu/dlg_create_world.lua +++ b/builtin/mainmenu/dlg_create_world.lua @@ -61,6 +61,7 @@ local flag_checkboxes = { fgettext("Low humidity and high heat causes shallow or dry rivers") }, }, flat = { + cb_caverns, { "hills", fgettext("Hills"), "hills" }, { "lakes", fgettext("Lakes"), "lakes" }, }, diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index c0620542d..01736f586 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -1860,7 +1860,7 @@ mgcarpathian_np_dungeons (Dungeon noise) noise_params_3d 0.9, 0.5, (500, 500, 50 # Map generation attributes specific to Mapgen Flat. # Occasional lakes and hills can be added to the flat world. -mgflat_spflags (Mapgen Flat specific flags) flags nolakes,nohills lakes,hills,nolakes,nohills +mgflat_spflags (Mapgen Flat specific flags) flags nolakes,nohills,nocaverns lakes,hills,caverns,nolakes,nohills,nocaverns # Y of flat ground. mgflat_ground_level (Ground level) int 8 @@ -1904,6 +1904,15 @@ mgflat_hill_threshold (Hill threshold) float 0.45 # Controls steepness/height of hills. mgflat_hill_steepness (Hill steepness) float 64.0 +# Y-level of cavern upper limit. +mgflat_cavern_limit (Cavern limit) int -256 + +# Y-distance over which caverns expand to full size. +mgflat_cavern_taper (Cavern taper) int 256 + +# Defines full size of caverns, smaller values create larger caverns. +mgflat_cavern_threshold (Cavern threshold) float 0.7 + # Lower Y limit of dungeons. mgflat_dungeon_ymin (Dungeon minimum Y) int -31000 @@ -1924,6 +1933,9 @@ mgflat_np_cave1 (Cave1 noise) noise_params_3d 0, 12, (61, 61, 61), 52534, 3, 0.5 # Second of two 3D noises that together define tunnels. mgflat_np_cave2 (Cave2 noise) noise_params_3d 0, 12, (67, 67, 67), 10325, 3, 0.5, 2.0 +# 3D noise defining giant caverns. +mgflat_np_cavern (Cavern noise) noise_params_3d 0, 1, (384, 128, 384), 723, 5, 0.63, 2.0 + # 3D noise that determines number of dungeons per mapchunk. mgflat_np_dungeons (Dungeon noise) noise_params_3d 0.9, 0.5, (500, 500, 500), 0, 2, 0.8, 2.0 diff --git a/src/mapgen/mapgen_flat.cpp b/src/mapgen/mapgen_flat.cpp index 369777ad2..df6469ad9 100644 --- a/src/mapgen/mapgen_flat.cpp +++ b/src/mapgen/mapgen_flat.cpp @@ -1,7 +1,7 @@ /* Minetest -Copyright (C) 2015-2018 paramat -Copyright (C) 2015-2018 kwolekr, Ryan Kwolek +Copyright (C) 2015-2020 paramat +Copyright (C) 2015-2016 kwolekr, Ryan Kwolek 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 @@ -39,8 +39,9 @@ with this program; if not, write to the Free Software Foundation, Inc., FlagDesc flagdesc_mapgen_flat[] = { - {"lakes", MGFLAT_LAKES}, - {"hills", MGFLAT_HILLS}, + {"lakes", MGFLAT_LAKES}, + {"hills", MGFLAT_HILLS}, + {"caverns", MGFLAT_CAVERNS}, {NULL, 0} }; @@ -52,17 +53,21 @@ MapgenFlat::MapgenFlat(MapgenFlatParams *params, EmergeParams *emerge) { spflags = params->spflags; ground_level = params->ground_level; - large_cave_depth = params->large_cave_depth; + lake_threshold = params->lake_threshold; + lake_steepness = params->lake_steepness; + hill_threshold = params->hill_threshold; + hill_steepness = params->hill_steepness; + + cave_width = params->cave_width; small_cave_num_min = params->small_cave_num_min; small_cave_num_max = params->small_cave_num_max; large_cave_num_min = params->large_cave_num_min; large_cave_num_max = params->large_cave_num_max; + large_cave_depth = params->large_cave_depth; large_cave_flooded = params->large_cave_flooded; - cave_width = params->cave_width; - lake_threshold = params->lake_threshold; - lake_steepness = params->lake_steepness; - hill_threshold = params->hill_threshold; - hill_steepness = params->hill_steepness; + cavern_limit = params->cavern_limit; + cavern_taper = params->cavern_taper; + cavern_threshold = params->cavern_threshold; dungeon_ymin = params->dungeon_ymin; dungeon_ymax = params->dungeon_ymax; @@ -71,9 +76,11 @@ MapgenFlat::MapgenFlat(MapgenFlatParams *params, EmergeParams *emerge) if ((spflags & MGFLAT_LAKES) || (spflags & MGFLAT_HILLS)) noise_terrain = new Noise(¶ms->np_terrain, seed, csize.X, csize.Z); + // 3D noise MapgenBasic::np_cave1 = params->np_cave1; MapgenBasic::np_cave2 = params->np_cave2; + MapgenBasic::np_cavern = params->np_cavern; MapgenBasic::np_dungeons = params->np_dungeons; } @@ -88,11 +95,12 @@ MapgenFlat::~MapgenFlat() MapgenFlatParams::MapgenFlatParams(): - np_terrain (0, 1, v3f(600, 600, 600), 7244, 5, 0.6, 2.0), - np_filler_depth (0, 1.2, v3f(150, 150, 150), 261, 3, 0.7, 2.0), - np_cave1 (0, 12, v3f(61, 61, 61), 52534, 3, 0.5, 2.0), - np_cave2 (0, 12, v3f(67, 67, 67), 10325, 3, 0.5, 2.0), - np_dungeons (0.9, 0.5, v3f(500, 500, 500), 0, 2, 0.8, 2.0) + np_terrain (0, 1, v3f(600, 600, 600), 7244, 5, 0.6, 2.0), + np_filler_depth (0, 1.2, v3f(150, 150, 150), 261, 3, 0.7, 2.0), + np_cavern (0.0, 1.0, v3f(384, 128, 384), 723, 5, 0.63, 2.0), + np_cave1 (0, 12, v3f(61, 61, 61), 52534, 3, 0.5, 2.0), + np_cave2 (0, 12, v3f(67, 67, 67), 10325, 3, 0.5, 2.0), + np_dungeons (0.9, 0.5, v3f(500, 500, 500), 0, 2, 0.8, 2.0) { } @@ -112,11 +120,15 @@ void MapgenFlatParams::readParams(const Settings *settings) settings->getFloatNoEx("mgflat_lake_steepness", lake_steepness); settings->getFloatNoEx("mgflat_hill_threshold", hill_threshold); settings->getFloatNoEx("mgflat_hill_steepness", hill_steepness); + settings->getS16NoEx("mgflat_cavern_limit", cavern_limit); + settings->getS16NoEx("mgflat_cavern_taper", cavern_taper); + settings->getFloatNoEx("mgflat_cavern_threshold", cavern_threshold); settings->getS16NoEx("mgflat_dungeon_ymin", dungeon_ymin); settings->getS16NoEx("mgflat_dungeon_ymax", dungeon_ymax); settings->getNoiseParams("mgflat_np_terrain", np_terrain); settings->getNoiseParams("mgflat_np_filler_depth", np_filler_depth); + settings->getNoiseParams("mgflat_np_cavern", np_cavern); settings->getNoiseParams("mgflat_np_cave1", np_cave1); settings->getNoiseParams("mgflat_np_cave2", np_cave2); settings->getNoiseParams("mgflat_np_dungeons", np_dungeons); @@ -138,11 +150,15 @@ void MapgenFlatParams::writeParams(Settings *settings) const settings->setFloat("mgflat_lake_steepness", lake_steepness); settings->setFloat("mgflat_hill_threshold", hill_threshold); settings->setFloat("mgflat_hill_steepness", hill_steepness); + settings->setS16("mgflat_cavern_limit", cavern_limit); + settings->setS16("mgflat_cavern_taper", cavern_taper); + settings->setFloat("mgflat_cavern_threshold", cavern_threshold); settings->setS16("mgflat_dungeon_ymin", dungeon_ymin); settings->setS16("mgflat_dungeon_ymax", dungeon_ymax); settings->setNoiseParams("mgflat_np_terrain", np_terrain); settings->setNoiseParams("mgflat_np_filler_depth", np_filler_depth); + settings->setNoiseParams("mgflat_np_cavern", np_cavern); settings->setNoiseParams("mgflat_np_cave1", np_cave1); settings->setNoiseParams("mgflat_np_cave2", np_cave2); settings->setNoiseParams("mgflat_np_dungeons", np_dungeons); @@ -226,11 +242,25 @@ void MapgenFlat::makeChunk(BlockMakeData *data) generateBiomes(); } + // Generate tunnels, caverns and large randomwalk caves if (flags & MG_CAVES) { - // Generate tunnels + // Generate tunnels first as caverns confuse them generateCavesNoiseIntersection(stone_surface_max_y); + + // Generate caverns + bool near_cavern = false; + if (spflags & MGFLAT_CAVERNS) + near_cavern = generateCavernsNoise(stone_surface_max_y); + // Generate large randomwalk caves - generateCavesRandomWalk(stone_surface_max_y, large_cave_depth); + if (near_cavern) + // Disable large randomwalk caves in this mapchunk by setting + // 'large cave depth' to world base. Avoids excessive liquid in + // large caverns and floating blobs of overgenerated liquid. + generateCavesRandomWalk(stone_surface_max_y, + -MAX_MAP_GENERATION_LIMIT); + else + generateCavesRandomWalk(stone_surface_max_y, large_cave_depth); } // Generate the registered ores diff --git a/src/mapgen/mapgen_flat.h b/src/mapgen/mapgen_flat.h index 4902a802c..4b46aff27 100644 --- a/src/mapgen/mapgen_flat.h +++ b/src/mapgen/mapgen_flat.h @@ -1,7 +1,7 @@ /* Minetest -Copyright (C) 2015-2018 paramat -Copyright (C) 2015-2018 kwolekr, Ryan Kwolek +Copyright (C) 2015-2020 paramat +Copyright (C) 2015-2016 kwolekr, Ryan Kwolek 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 @@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc., /////// Mapgen Flat flags #define MGFLAT_LAKES 0x01 #define MGFLAT_HILLS 0x02 +#define MGFLAT_CAVERNS 0x04 class BiomeManager; @@ -33,22 +34,27 @@ extern FlagDesc flagdesc_mapgen_flat[]; struct MapgenFlatParams : public MapgenParams { s16 ground_level = 8; - s16 large_cave_depth = -33; + float lake_threshold = -0.45f; + float lake_steepness = 48.0f; + float hill_threshold = 0.45f; + float hill_steepness = 64.0f; + + float cave_width = 0.09f; u16 small_cave_num_min = 0; u16 small_cave_num_max = 0; u16 large_cave_num_min = 0; u16 large_cave_num_max = 2; + s16 large_cave_depth = -33; float large_cave_flooded = 0.5f; - float cave_width = 0.09f; - float lake_threshold = -0.45f; - float lake_steepness = 48.0f; - float hill_threshold = 0.45f; - float hill_steepness = 64.0f; + s16 cavern_limit = -256; + s16 cavern_taper = 256; + float cavern_threshold = 0.7f; s16 dungeon_ymin = -31000; s16 dungeon_ymax = 31000; NoiseParams np_terrain; NoiseParams np_filler_depth; + NoiseParams np_cavern; NoiseParams np_cave1; NoiseParams np_cave2; NoiseParams np_dungeons; -- cgit v1.2.3 From cd0e213a3640e980e15735f97dd874754f0dc679 Mon Sep 17 00:00:00 2001 From: v-rob Date: Tue, 11 Aug 2020 11:07:17 -0700 Subject: Add font styling options to tables and textlists (#10203) --- src/gui/guiFormSpecMenu.cpp | 2 ++ src/gui/guiTable.cpp | 27 ++++++++++++++++++++++++++- src/gui/guiTable.h | 6 ++++++ 3 files changed, 34 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/gui/guiFormSpecMenu.cpp b/src/gui/guiFormSpecMenu.cpp index 601c5c18e..98392f3c0 100644 --- a/src/gui/guiFormSpecMenu.cpp +++ b/src/gui/guiFormSpecMenu.cpp @@ -1225,6 +1225,7 @@ void GUIFormSpecMenu::parseTable(parserData* data, const std::string &element) auto style = getDefaultStyleForElement("table", name); e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false)); + e->setOverrideFont(style.getFont()); m_tables.emplace_back(spec, e); m_fields.push_back(spec); @@ -1302,6 +1303,7 @@ void GUIFormSpecMenu::parseTextList(parserData* data, const std::string &element auto style = getDefaultStyleForElement("textlist", name); e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false)); + e->setOverrideFont(style.getFont()); m_tables.emplace_back(spec, e); m_fields.push_back(spec); diff --git a/src/gui/guiTable.cpp b/src/gui/guiTable.cpp index c705e17fb..cab2e19fd 100644 --- a/src/gui/guiTable.cpp +++ b/src/gui/guiTable.cpp @@ -56,7 +56,7 @@ GUITable::GUITable(gui::IGUIEnvironment *env, m_font = skin->getFont(); if (m_font) { m_font->grab(); - m_rowheight = m_font->getDimension(L"A").Height + 4; + m_rowheight = m_font->getDimension(L"Ay").Height + 4; m_rowheight = MYMAX(m_rowheight, 1); } @@ -586,6 +586,31 @@ void GUITable::setSelected(s32 index) } } +void GUITable::setOverrideFont(IGUIFont *font) +{ + if (m_font == font) + return; + + if (font == nullptr) + font = Environment->getSkin()->getFont(); + + if (m_font) + m_font->drop(); + + m_font = font; + m_font->grab(); + + m_rowheight = m_font->getDimension(L"Ay").Height + 4; + m_rowheight = MYMAX(m_rowheight, 1); + + updateScrollBar(); +} + +IGUIFont *GUITable::getOverrideFont() const +{ + return m_font; +} + GUITable::DynamicData GUITable::getDynamicData() const { DynamicData dyndata; diff --git a/src/gui/guiTable.h b/src/gui/guiTable.h index 11093ea72..76a0e94d0 100644 --- a/src/gui/guiTable.h +++ b/src/gui/guiTable.h @@ -123,6 +123,12 @@ public: // Autoscroll to make the selected row fully visible void setSelected(s32 index); + //! Sets another skin independent font. If this is set to zero, the button uses the font of the skin. + virtual void setOverrideFont(gui::IGUIFont *font = nullptr); + + //! Gets the override font (if any) + virtual gui::IGUIFont *getOverrideFont() const; + /* Get selection, scroll position and opened (sub)trees */ DynamicData getDynamicData() const; -- cgit v1.2.3 From 1c38027c3a72402d752a8150701a44753e22990e Mon Sep 17 00:00:00 2001 From: Lars Müller <34514239+appgurueu@users.noreply.github.com> Date: Wed, 12 Aug 2020 11:51:50 +0200 Subject: Fix precision not working in hud_change (#10186) --- games/devtest/mods/util_commands/init.lua | 56 +++++++++++++++++++++++++++++++ src/hud.cpp | 1 + src/script/common/c_content.cpp | 5 ++- 3 files changed, 61 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/games/devtest/mods/util_commands/init.lua b/games/devtest/mods/util_commands/init.lua index 3a0e91a41..f2a155fb2 100644 --- a/games/devtest/mods/util_commands/init.lua +++ b/games/devtest/mods/util_commands/init.lua @@ -112,6 +112,62 @@ minetest.register_chatcommand("detach", { end, }) +-- Use this to test waypoint capabilities +minetest.register_chatcommand("test_waypoints", { + params = "[change_immediate]", + description = "tests waypoint capabilities", + func = function(name, params) + local player = minetest.get_player_by_name(name) + local regular = player:hud_add { + hud_elem_type = "waypoint", + name = "regular waypoint", + text = "m", + number = 0xFF0000, + world_pos = vector.add(player:get_pos(), {x = 0, y = 1.5, z = 0}) + } + local reduced_precision = player:hud_add { + hud_elem_type = "waypoint", + name = "better waypoint", + text = "m (0.5 steps, precision = 2)", + precision = 10, + number = 0xFFFF00, + world_pos = vector.add(player:get_pos(), {x = 0, y = 1, z = 0}) + } + local function change() + if regular then + player:hud_change(regular, "world_pos", vector.add(player:get_pos(), {x = 0, y = 3, z = 0})) + end + if reduced_precision then + player:hud_change(reduced_precision, "precision", 2) + end + end + if params ~= "" then + -- change immediate + change() + else + minetest.after(0.5, change) + end + regular = regular or "error" + reduced_precision = reduced_precision or "error" + local hidden_distance = player:hud_add { + hud_elem_type = "waypoint", + name = "waypoint with hidden distance", + text = "this text is hidden as well (precision = 0)", + precision = 0, + number = 0x0000FF, + world_pos = vector.add(player:get_pos(), {x = 0, y = 0.5, z = 0}) + } or "error" + local image_waypoint = player:hud_add { + hud_elem_type = "image_waypoint", + text = "wieldhand.png", + world_pos = player:get_pos(), + scale = {x = 10, y = 10}, + offset = {x = 0, y = -32} + } or "error" + minetest.chat_send_player(name, "Waypoint IDs: regular: " .. regular .. ", reduced precision: " .. reduced_precision .. + ", hidden distance: " .. hidden_distance .. ", image waypoint: " .. image_waypoint) + end +}) -- Unlimited node placement minetest.register_on_placenode(function(pos, newnode, placer, oldnode, itemstack) diff --git a/src/hud.cpp b/src/hud.cpp index 3079b5cd8..4830c56a4 100644 --- a/src/hud.cpp +++ b/src/hud.cpp @@ -40,6 +40,7 @@ const struct EnumString es_HudElementStat[] = {HUD_STAT_TEXT, "text"}, {HUD_STAT_NUMBER, "number"}, {HUD_STAT_ITEM, "item"}, + {HUD_STAT_ITEM, "precision"}, {HUD_STAT_DIR, "direction"}, {HUD_STAT_ALIGN, "alignment"}, {HUD_STAT_OFFSET, "offset"}, diff --git a/src/script/common/c_content.cpp b/src/script/common/c_content.cpp index 3dfd7ce61..774b6a326 100644 --- a/src/script/common/c_content.cpp +++ b/src/script/common/c_content.cpp @@ -1959,9 +1959,10 @@ void push_hud_element(lua_State *L, HudElement *elem) HudElementStat read_hud_change(lua_State *L, HudElement *elem, void **value) { HudElementStat stat = HUD_STAT_NUMBER; + std::string statstr; if (lua_isstring(L, 3)) { int statint; - std::string statstr = lua_tostring(L, 3); + statstr = lua_tostring(L, 3); stat = string_to_enum(es_HudElementStat, statint, statstr) ? (HudElementStat)statint : stat; } @@ -1989,6 +1990,8 @@ HudElementStat read_hud_change(lua_State *L, HudElement *elem, void **value) break; case HUD_STAT_ITEM: elem->item = luaL_checknumber(L, 4); + if (elem->type == HUD_ELEM_WAYPOINT && statstr == "precision") + elem->item++; *value = &elem->item; break; case HUD_STAT_DIR: -- cgit v1.2.3 From fff03931871b68e092e12bfce9056f760e8ec9dd Mon Sep 17 00:00:00 2001 From: sfan5 Date: Wed, 12 Aug 2020 11:52:50 +0200 Subject: Render nodeboxes with opaque material if possible (#10122) --- doc/lua_api.txt | 2 ++ src/nodedef.cpp | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--- src/nodedef.h | 12 ++++++++++++ 3 files changed, 68 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 8ac3ad7f2..6366a34c3 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -7065,6 +7065,8 @@ Used by `minetest.register_node`. use_texture_alpha = false, -- Use texture's alpha channel + -- If this is set to false, the node will be rendered fully opaque + -- regardless of any texture transparency. palette = "palette.png", -- The node's `param2` is used to select a pixel from the image. diff --git a/src/nodedef.cpp b/src/nodedef.cpp index 82c4581fa..392f5eb98 100644 --- a/src/nodedef.cpp +++ b/src/nodedef.cpp @@ -695,9 +695,54 @@ static void fillTileAttribs(ITextureSource *tsrc, TileLayer *layer, } } } -#endif -#ifndef SERVER +bool ContentFeatures::textureAlphaCheck(ITextureSource *tsrc, const TileDef *tiles, int length) +{ + video::IVideoDriver *driver = RenderingEngine::get_video_driver(); + static thread_local bool long_warning_printed = false; + std::set seen; + for (int i = 0; i < length; i++) { + if (seen.find(tiles[i].name) != seen.end()) + continue; + seen.insert(tiles[i].name); + + // Load the texture and see if there's any transparent pixels + video::ITexture *texture = tsrc->getTexture(tiles[i].name); + video::IImage *image = driver->createImage(texture, + core::position2d(0, 0), texture->getOriginalSize()); + if (!image) + continue; + core::dimension2d dim = image->getDimension(); + bool ok = true; + for (u16 x = 0; x < dim.Width; x++) { + for (u16 y = 0; y < dim.Height; y++) { + if (image->getPixel(x, y).getAlpha() < 255) { + ok = false; + goto break_loop; + } + } + } + +break_loop: + image->drop(); + if (!ok) { + warningstream << "Texture \"" << tiles[i].name << "\" of " + << name << " has transparent pixels, assuming " + "use_texture_alpha = true." << std::endl; + if (!long_warning_printed) { + warningstream << " This warning can be a false-positive if " + "unused pixels in the texture are transparent. However if " + "it is meant to be transparent, you *MUST* update the " + "nodedef and set use_texture_alpha = true! This compatibility " + "code will be removed in a few releases." << std::endl; + long_warning_printed = true; + } + return true; + } + } + return false; +} + bool isWorldAligned(AlignStyle style, WorldAlignMode mode, NodeDrawType drawtype) { if (style == ALIGN_STYLE_WORLD) @@ -814,13 +859,19 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc break; case NDT_MESH: case NDT_NODEBOX: + if (alpha == 255 && textureAlphaCheck(tsrc, tdef, 6)) + alpha = 0; + solidness = 0; if (waving == 1) material_type = TILE_MATERIAL_WAVING_PLANTS; else if (waving == 2) material_type = TILE_MATERIAL_WAVING_LEAVES; else if (waving == 3) - material_type = TILE_MATERIAL_WAVING_LIQUID_BASIC; + material_type = (alpha == 255) ? TILE_MATERIAL_WAVING_LIQUID_OPAQUE : + TILE_MATERIAL_WAVING_LIQUID_BASIC; + else if (alpha == 255) + material_type = TILE_MATERIAL_OPAQUE; break; case NDT_TORCHLIKE: case NDT_SIGNLIKE: diff --git a/src/nodedef.h b/src/nodedef.h index d0da367ee..71c56bda9 100644 --- a/src/nodedef.h +++ b/src/nodedef.h @@ -418,6 +418,7 @@ struct ContentFeatures void reset(); void serialize(std::ostream &os, u16 protocol_version) const; void deSerialize(std::istream &is); + /*! * Since vertex alpha is no longer supported, this method * adds opacity directly to the texture pixels. @@ -427,6 +428,17 @@ struct ContentFeatures */ void correctAlpha(TileDef *tiles, int length); +#ifndef SERVER + /* + * Checks if any tile texture has any transparent pixels. + * Prints a warning and returns true if that is the case, false otherwise. + * This is supposed to be used for use_texture_alpha backwards compatibility. + */ + bool textureAlphaCheck(ITextureSource *tsrc, const TileDef *tiles, + int length); +#endif + + /* Some handy methods */ -- cgit v1.2.3 From 291a6b70d674d9003f522b5875a60f7e2753e32b Mon Sep 17 00:00:00 2001 From: ANAND Date: Fri, 5 Jun 2020 18:36:35 +0530 Subject: Allow binding dig, place actions to keys; remove LMB/RMB hardcoding Co-authored-by: Sam Caulfield --- builtin/settingtypes.txt | 14 ++- doc/client_lua_api.txt | 4 +- doc/lua_api.txt | 24 +++-- src/client/client.cpp | 2 +- src/client/content_cao.cpp | 12 +-- src/client/game.cpp | 164 ++++++++++++++++++---------------- src/client/inputhandler.cpp | 166 +++++++++++++++++------------------ src/client/inputhandler.h | 154 +++++++++++--------------------- src/client/keys.h | 2 + src/defaultsettings.cpp | 4 +- src/network/serverpackethandler.cpp | 23 ++--- src/player.h | 12 +-- src/script/lua_api/l_localplayer.cpp | 4 +- src/script/lua_api/l_object.cpp | 9 +- 14 files changed, 284 insertions(+), 310 deletions(-) (limited to 'src') diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index 01736f586..3aa113190 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -110,9 +110,9 @@ doubletap_jump (Double tap jump for fly) bool false # enabled. always_fly_fast (Always fly and fast) bool true -# The time in seconds it takes between repeated right clicks when holding the right -# mouse button. -repeat_rightclick_time (Rightclick repetition interval) float 0.25 0.001 +# The time in seconds it takes between repeated node placements when holding +# the place button. +repeat_place_time (Place repetition interval) float 0.25 0.001 # Automatically jump up single-node obstacles. autojump (Automatic jumping) bool false @@ -182,6 +182,14 @@ keymap_jump (Jump key) key KEY_SPACE # See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3 keymap_sneak (Sneak key) key KEY_LSHIFT +# Key for digging. +# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3 +keymap_dig (Dig key) key KEY_LBUTTON + +# Key for placing. +# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3 +keymap_place (Place key) key KEY_RBUTTON + # Key for opening the inventory. # See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3 keymap_inventory (Inventory key) key KEY_KEY_I diff --git a/doc/client_lua_api.txt b/doc/client_lua_api.txt index 3b0046b4f..4c5231b79 100644 --- a/doc/client_lua_api.txt +++ b/doc/client_lua_api.txt @@ -1100,8 +1100,8 @@ Methods: aux1 = boolean, sneak = boolean, zoom = boolean, - LMB = boolean, - RMB = boolean, + dig = boolean, + place = boolean, } ``` diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 6366a34c3..88d99fcd5 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -6163,15 +6163,23 @@ object you are working with still exists. * Only affects formspecs shown after this is called. * `get_formspec_prepend(formspec)`: returns a formspec string. * `get_player_control()`: returns table with player pressed keys - * The table consists of fields with boolean value representing the pressed - keys, the fields are jump, right, left, LMB, RMB, sneak, aux1, down, up, zoom. - * example: `{jump=false, right=true, left=false, LMB=false, RMB=false, - sneak=true, aux1=false, down=false, up=false, zoom=false}` - * The `zoom` field is available since 5.3 + * The table consists of fields with the following boolean values + representing the pressed keys: `up`, `down`, `left`, `right`, `jump`, + `aux1`, `sneak`, `dig`, `place`, `LMB`, `RMB`, and `zoom`. + * The fields `LMB` and `RMB` are equal to `dig` and `place` respectively, + and exist only to preserve backwards compatibility. * `get_player_control_bits()`: returns integer with bit packed player pressed - keys. - * bit nr/meaning: 0/up, 1/down, 2/left, 3/right, 4/jump, 5/aux1, 6/sneak, - 7/LMB, 8/RMB, 9/zoom (zoom available since 5.3) + keys. Bits: + * 0 - up + * 1 - down + * 2 - left + * 3 - right + * 4 - jump + * 5 - aux1 + * 6 - sneak + * 7 - dig + * 8 - place + * 9 - zoom * `set_physics_override(override_table)` * `override_table` is a table with the following fields: * `speed`: multiplier to default walking speed value (default: `1`) diff --git a/src/client/client.cpp b/src/client/client.cpp index 65e5b3d8c..745cce900 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -1307,7 +1307,7 @@ void Client::sendPlayerPos() player->last_pitch == player->getPitch() && player->last_yaw == player->getYaw() && player->last_keyPressed == player->keyPressed && - player->last_camera_fov == camera_fov && + player->last_camera_fov == camera_fov && player->last_wanted_range == wanted_range) return; diff --git a/src/client/content_cao.cpp b/src/client/content_cao.cpp index 88688d18c..599139aa3 100644 --- a/src/client/content_cao.cpp +++ b/src/client/content_cao.cpp @@ -975,13 +975,13 @@ void GenericCAO::step(float dtime, ClientEnvironment *env) if (controls.sneak && walking) new_speed /= 2; - if (walking && (controls.LMB || controls.RMB)) { + if (walking && (controls.dig || controls.place)) { new_anim = player->local_animations[3]; player->last_animation = WD_ANIM; - } else if(walking) { + } else if (walking) { new_anim = player->local_animations[1]; player->last_animation = WALK_ANIM; - } else if(controls.LMB || controls.RMB) { + } else if (controls.dig || controls.place) { new_anim = player->local_animations[2]; player->last_animation = DIG_ANIM; } @@ -1004,9 +1004,9 @@ void GenericCAO::step(float dtime, ClientEnvironment *env) // Update local player animations if ((player->last_animation != old_anim || - m_animation_speed != old_anim_speed) && - player->last_animation != NO_ANIM && allow_update) - updateAnimation(); + m_animation_speed != old_anim_speed) && + player->last_animation != NO_ANIM && allow_update) + updateAnimation(); } } diff --git a/src/client/game.cpp b/src/client/game.cpp index 20d2c6f90..0d3a0ca15 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -604,7 +604,6 @@ public: #endif /**************************************************************************** - ****************************************************************************/ const float object_hit_delay = 0.2; @@ -625,15 +624,15 @@ struct GameRunData { u16 new_playeritem; PointedThing pointed_old; bool digging; - bool ldown_for_dig; + bool punching; + bool btn_down_for_dig; bool dig_instantly; bool digging_blocked; - bool left_punch; bool reset_jump_timer; float nodig_delay_timer; float dig_time; float dig_time_complete; - float repeat_rightclick_timer; + float repeat_place_timer; float object_hit_delay_timer; float time_from_last_punch; ClientActiveObject *selected_object; @@ -787,6 +786,14 @@ protected: { return input->wasKeyDown(k); } + inline bool wasKeyPressed(GameKeyType k) + { + return input->wasKeyPressed(k); + } + inline bool wasKeyReleased(GameKeyType k) + { + return input->wasKeyReleased(k); + } #ifdef __ANDROID__ void handleAndroidChatInput(); @@ -900,7 +907,7 @@ private: bool m_cache_enable_free_move; f32 m_cache_mouse_sensitivity; f32 m_cache_joystick_frustum_sensitivity; - f32 m_repeat_right_click_time; + f32 m_repeat_place_time; f32 m_cache_cam_smoothing; f32 m_cache_fog_start; @@ -934,7 +941,7 @@ Game::Game() : &settingChangedCallback, this); g_settings->registerChangedCallback("joystick_frustum_sensitivity", &settingChangedCallback, this); - g_settings->registerChangedCallback("repeat_rightclick_time", + g_settings->registerChangedCallback("repeat_place_time", &settingChangedCallback, this); g_settings->registerChangedCallback("noclip", &settingChangedCallback, this); @@ -992,7 +999,7 @@ Game::~Game() &settingChangedCallback, this); g_settings->deregisterChangedCallback("mouse_sensitivity", &settingChangedCallback, this); - g_settings->deregisterChangedCallback("repeat_rightclick_time", + g_settings->deregisterChangedCallback("repeat_place_time", &settingChangedCallback, this); g_settings->deregisterChangedCallback("noclip", &settingChangedCallback, this); @@ -2465,8 +2472,8 @@ void Game::updatePlayerControl(const CameraOrientation &cam) isKeyDown(KeyType::SPECIAL1), isKeyDown(KeyType::SNEAK), isKeyDown(KeyType::ZOOM), - input->getLeftState(), - input->getRightState(), + isKeyDown(KeyType::DIG), + isKeyDown(KeyType::PLACE), cam.camera_pitch, cam.camera_yaw, input->joystick.getAxisWithoutDead(JA_SIDEWARD_MOVE), @@ -2481,8 +2488,8 @@ void Game::updatePlayerControl(const CameraOrientation &cam) ( (u32)(isKeyDown(KeyType::JUMP) & 0x1) << 4) | ( (u32)(isKeyDown(KeyType::SPECIAL1) & 0x1) << 5) | ( (u32)(isKeyDown(KeyType::SNEAK) & 0x1) << 6) | - ( (u32)(input->getLeftState() & 0x1) << 7) | - ( (u32)(input->getRightState() & 0x1) << 8) | + ( (u32)(isKeyDown(KeyType::DIG) & 0x1) << 7) | + ( (u32)(isKeyDown(KeyType::PLACE) & 0x1) << 8) | ( (u32)(isKeyDown(KeyType::ZOOM) & 0x1) << 9) ); @@ -3064,7 +3071,7 @@ void Game::processPlayerInteraction(f32 dtime, bool show_hud, bool show_debug) PointedThing pointed = updatePointedThing(shootline, selected_def.liquids_pointable, - !runData.ldown_for_dig, + !runData.btn_down_for_dig, camera_offset); if (pointed != runData.pointed_old) { @@ -3072,20 +3079,18 @@ void Game::processPlayerInteraction(f32 dtime, bool show_hud, bool show_debug) hud->updateSelectionMesh(camera_offset); } - if (runData.digging_blocked && !input->getLeftState()) { - // allow digging again if button is not pressed + // Allow digging again if button is not pressed + if (runData.digging_blocked && !isKeyDown(KeyType::DIG)) runData.digging_blocked = false; - } /* Stop digging when - - releasing left mouse button + - releasing dig button - pointing away from node */ if (runData.digging) { - if (input->getLeftReleased()) { - infostream << "Left button released" - << " (stopped digging)" << std::endl; + if (wasKeyReleased(KeyType::DIG)) { + infostream << "Dig button released (stopped digging)" << std::endl; runData.digging = false; } else if (pointed != runData.pointed_old) { if (pointed.type == POINTEDTHING_NODE @@ -3095,8 +3100,7 @@ void Game::processPlayerInteraction(f32 dtime, bool show_hud, bool show_debug) // Still pointing to the same node, but a different face. // Don't reset. } else { - infostream << "Pointing away from node" - << " (stopped digging)" << std::endl; + infostream << "Pointing away from node (stopped digging)" << std::endl; runData.digging = false; hud->updateSelectionMesh(camera_offset); } @@ -3107,55 +3111,57 @@ void Game::processPlayerInteraction(f32 dtime, bool show_hud, bool show_debug) client->setCrack(-1, v3s16(0, 0, 0)); runData.dig_time = 0.0; } - } else if (runData.dig_instantly && input->getLeftReleased()) { - // Remove e.g. torches faster when clicking instead of holding LMB + } else if (runData.dig_instantly && wasKeyReleased(KeyType::DIG)) { + // Remove e.g. torches faster when clicking instead of holding dig button runData.nodig_delay_timer = 0; runData.dig_instantly = false; } - if (!runData.digging && runData.ldown_for_dig && !input->getLeftState()) { - runData.ldown_for_dig = false; - } + if (!runData.digging && runData.btn_down_for_dig && !isKeyDown(KeyType::DIG)) + runData.btn_down_for_dig = false; - runData.left_punch = false; + runData.punching = false; soundmaker->m_player_leftpunch_sound.name = ""; // Prepare for repeating, unless we're not supposed to - if (input->getRightState() && !g_settings->getBool("safe_dig_and_place")) - runData.repeat_rightclick_timer += dtime; + if (isKeyDown(KeyType::PLACE) && !g_settings->getBool("safe_dig_and_place")) + runData.repeat_place_timer += dtime; else - runData.repeat_rightclick_timer = 0; + runData.repeat_place_timer = 0; - if (selected_def.usable && input->getLeftState()) { - if (input->getLeftClicked() && (!client->modsLoaded() - || !client->getScript()->on_item_use(selected_item, pointed))) + if (selected_def.usable && isKeyDown(KeyType::DIG)) { + if (wasKeyPressed(KeyType::DIG) && (!client->modsLoaded() || + !client->getScript()->on_item_use(selected_item, pointed))) client->interact(INTERACT_USE, pointed); } else if (pointed.type == POINTEDTHING_NODE) { handlePointingAtNode(pointed, selected_item, hand_item, dtime); } else if (pointed.type == POINTEDTHING_OBJECT) { v3f player_position = player->getPosition(); handlePointingAtObject(pointed, tool_item, player_position, show_debug); - } else if (input->getLeftState()) { + } else if (isKeyDown(KeyType::DIG)) { // When button is held down in air, show continuous animation - runData.left_punch = true; + runData.punching = true; // Run callback even though item is not usable - if (input->getLeftClicked() && client->modsLoaded()) + if (wasKeyPressed(KeyType::DIG) && client->modsLoaded()) client->getScript()->on_item_use(selected_item, pointed); - } else if (input->getRightClicked()) { + } else if (wasKeyPressed(KeyType::PLACE)) { handlePointingAtNothing(selected_item); } runData.pointed_old = pointed; - if (runData.left_punch || input->getLeftClicked()) - camera->setDigging(0); // left click animation + if (runData.punching || wasKeyPressed(KeyType::DIG)) + camera->setDigging(0); // dig animation - input->resetLeftClicked(); - input->resetRightClicked(); + input->clearWasKeyPressed(); + input->clearWasKeyReleased(); - input->resetLeftReleased(); - input->resetRightReleased(); + input->joystick.clearWasKeyDown(KeyType::MOUSE_L); + input->joystick.clearWasKeyDown(KeyType::MOUSE_R); + + input->joystick.clearWasKeyReleased(KeyType::MOUSE_L); + input->joystick.clearWasKeyReleased(KeyType::MOUSE_R); } @@ -3255,7 +3261,7 @@ PointedThing Game::updatePointedThing( void Game::handlePointingAtNothing(const ItemStack &playerItem) { - infostream << "Right Clicked in Air" << std::endl; + infostream << "Attempted to place item while pointing at nothing" << std::endl; PointedThing fauxPointed; fauxPointed.type = POINTEDTHING_NOTHING; client->interact(INTERACT_ACTIVATE, fauxPointed); @@ -3274,7 +3280,7 @@ void Game::handlePointingAtNode(const PointedThing &pointed, ClientMap &map = client->getEnv().getClientMap(); - if (runData.nodig_delay_timer <= 0.0 && input->getLeftState() + if (runData.nodig_delay_timer <= 0.0 && isKeyDown(KeyType::DIG) && !runData.digging_blocked && client->checkPrivilege("interact")) { handleDigging(pointed, nodepos, selected_item, hand_item, dtime); @@ -3295,13 +3301,14 @@ void Game::handlePointingAtNode(const PointedThing &pointed, } } - if ((input->getRightClicked() || - runData.repeat_rightclick_timer >= m_repeat_right_click_time) && + if ((wasKeyPressed(KeyType::PLACE) || + runData.repeat_place_timer >= m_repeat_place_time) && client->checkPrivilege("interact")) { - runData.repeat_rightclick_timer = 0; - infostream << "Ground right-clicked" << std::endl; + runData.repeat_place_timer = 0; + infostream << "Place button pressed while looking at ground" << std::endl; - camera->setDigging(1); // right click animation (always shown for feedback) + // Placing animation (always shown for feedback) + camera->setDigging(1); soundmaker->m_player_rightpunch_sound = SimpleSoundSpec(); @@ -3367,8 +3374,7 @@ bool Game::nodePlacement(const ItemDefinition &selected_def, } verbosestream << "Node placement prediction for " - << selected_def.name << " is " - << prediction << std::endl; + << selected_def.name << " is " << prediction << std::endl; v3s16 p = neighbourpos; // Place inside node itself if buildable_to @@ -3529,7 +3535,7 @@ void Game::handlePointingAtObject(const PointedThing &pointed, m_game_ui->setInfoText(infotext); - if (input->getLeftState()) { + if (isKeyDown(KeyType::DIG)) { bool do_punch = false; bool do_punch_damage = false; @@ -3539,12 +3545,12 @@ void Game::handlePointingAtObject(const PointedThing &pointed, runData.object_hit_delay_timer = object_hit_delay; } - if (input->getLeftClicked()) + if (wasKeyPressed(KeyType::DIG)) do_punch = true; if (do_punch) { - infostream << "Left-clicked object" << std::endl; - runData.left_punch = true; + infostream << "Punched object" << std::endl; + runData.punching = true; } if (do_punch_damage) { @@ -3559,8 +3565,8 @@ void Game::handlePointingAtObject(const PointedThing &pointed, if (!disable_send) client->interact(INTERACT_START_DIGGING, pointed); } - } else if (input->getRightClicked()) { - infostream << "Right-clicked object" << std::endl; + } else if (wasKeyDown(KeyType::PLACE)) { + infostream << "Pressed place button while pointing at object" << std::endl; client->interact(INTERACT_PLACE, pointed); // place } } @@ -3606,7 +3612,7 @@ void Game::handleDigging(const PointedThing &pointed, const v3s16 &nodepos, return; client->interact(INTERACT_START_DIGGING, pointed); runData.digging = true; - runData.ldown_for_dig = true; + runData.btn_down_for_dig = true; } if (!runData.dig_instantly) { @@ -3700,7 +3706,7 @@ void Game::handleDigging(const PointedThing &pointed, const v3s16 &nodepos, client->setCrack(-1, nodepos); } - camera->setDigging(0); // left click animation + camera->setDigging(0); // Dig animation } @@ -4039,7 +4045,7 @@ void Game::readSettings() m_cache_enable_fog = g_settings->getBool("enable_fog"); m_cache_mouse_sensitivity = g_settings->getFloat("mouse_sensitivity"); m_cache_joystick_frustum_sensitivity = g_settings->getFloat("joystick_frustum_sensitivity"); - m_repeat_right_click_time = g_settings->getFloat("repeat_rightclick_time"); + m_repeat_place_time = g_settings->getFloat("repeat_place_time"); m_cache_enable_noclip = g_settings->getBool("noclip"); m_cache_enable_free_move = g_settings->getBool("free_move"); @@ -4131,30 +4137,32 @@ void Game::showPauseMenu() "- %s: move backwards\n" "- %s: move left\n" "- %s: move right\n" - "- %s: jump/climb\n" - "- %s: sneak/go down\n" + "- %s: jump/climb up\n" + "- %s: dig/punch\n" + "- %s: place/use\n" + "- %s: sneak/climb down\n" "- %s: drop item\n" "- %s: inventory\n" "- Mouse: turn/look\n" - "- Mouse left: dig/punch\n" - "- Mouse right: place/use\n" "- Mouse wheel: select item\n" "- %s: chat\n" ); - char control_text_buf[600]; - - porting::mt_snprintf(control_text_buf, sizeof(control_text_buf), control_text_template.c_str(), - GET_KEY_NAME(keymap_forward), - GET_KEY_NAME(keymap_backward), - GET_KEY_NAME(keymap_left), - GET_KEY_NAME(keymap_right), - GET_KEY_NAME(keymap_jump), - GET_KEY_NAME(keymap_sneak), - GET_KEY_NAME(keymap_drop), - GET_KEY_NAME(keymap_inventory), - GET_KEY_NAME(keymap_chat) - ); + char control_text_buf[600]; + + porting::mt_snprintf(control_text_buf, sizeof(control_text_buf), control_text_template.c_str(), + GET_KEY_NAME(keymap_forward), + GET_KEY_NAME(keymap_backward), + GET_KEY_NAME(keymap_left), + GET_KEY_NAME(keymap_right), + GET_KEY_NAME(keymap_jump), + GET_KEY_NAME(keymap_dig), + GET_KEY_NAME(keymap_place), + GET_KEY_NAME(keymap_sneak), + GET_KEY_NAME(keymap_drop), + GET_KEY_NAME(keymap_inventory), + GET_KEY_NAME(keymap_chat) + ); std::string control_text = std::string(control_text_buf); str_formspec_escape(control_text); diff --git a/src/client/inputhandler.cpp b/src/client/inputhandler.cpp index a79b04a90..608a405a8 100644 --- a/src/client/inputhandler.cpp +++ b/src/client/inputhandler.cpp @@ -37,6 +37,8 @@ void KeyCache::populate() key[KeyType::JUMP] = getKeySetting("keymap_jump"); key[KeyType::SPECIAL1] = getKeySetting("keymap_special1"); key[KeyType::SNEAK] = getKeySetting("keymap_sneak"); + key[KeyType::DIG] = getKeySetting("keymap_dig"); + key[KeyType::PLACE] = getKeySetting("keymap_place"); key[KeyType::AUTOFORWARD] = getKeySetting("keymap_autoforward"); @@ -111,57 +113,81 @@ bool MyEventReceiver::OnEvent(const SEvent &event) if (event.EventType == irr::EET_KEY_INPUT_EVENT) { const KeyPress &keyCode = event.KeyInput; if (keysListenedFor[keyCode]) { + // If the key is being held down then the OS may + // send a continuous stream of keydown events. + // In this case, we don't want to let this + // stream reach the application as it will cause + // certain actions to repeat constantly. if (event.KeyInput.PressedDown) { + if (!IsKeyDown(keyCode)) { + keyWasDown.set(keyCode); + keyWasPressed.set(keyCode); + } keyIsDown.set(keyCode); - keyWasDown.set(keyCode); } else { + if (IsKeyDown(keyCode)) + keyWasReleased.set(keyCode); + keyIsDown.unset(keyCode); } + return true; } - } #ifdef HAVE_TOUCHSCREENGUI - // case of touchscreengui we have to handle different events - if (m_touchscreengui && event.EventType == irr::EET_TOUCH_INPUT_EVENT) { + } else if (m_touchscreengui && event.EventType == irr::EET_TOUCH_INPUT_EVENT) { + // In case of touchscreengui, we have to handle different events m_touchscreengui->translateEvent(event); return true; - } #endif - if (event.EventType == irr::EET_JOYSTICK_INPUT_EVENT) { + } else if (event.EventType == irr::EET_JOYSTICK_INPUT_EVENT) { /* TODO add a check like: if (event.JoystickEvent != joystick_we_listen_for) return false; */ return joystick->handleEvent(event.JoystickEvent); - } - // handle mouse events - if (event.EventType == irr::EET_MOUSE_INPUT_EVENT) { - if (isMenuActive()) { - left_active = false; - middle_active = false; - right_active = false; - } else { - left_active = event.MouseInput.isLeftPressed(); - middle_active = event.MouseInput.isMiddlePressed(); - right_active = event.MouseInput.isRightPressed(); - - if (event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN) { - leftclicked = true; - } - if (event.MouseInput.Event == EMIE_RMOUSE_PRESSED_DOWN) { - rightclicked = true; - } - if (event.MouseInput.Event == EMIE_LMOUSE_LEFT_UP) { - leftreleased = true; - } - if (event.MouseInput.Event == EMIE_RMOUSE_LEFT_UP) { - rightreleased = true; - } - if (event.MouseInput.Event == EMIE_MOUSE_WHEEL) { - mouse_wheel += event.MouseInput.Wheel; - } + } else if (event.EventType == irr::EET_MOUSE_INPUT_EVENT) { + // Handle mouse events + KeyPress key; + switch (event.MouseInput.Event) { + case EMIE_LMOUSE_PRESSED_DOWN: + key = "KEY_LBUTTON"; + keyIsDown.set(key); + keyWasDown.set(key); + keyWasPressed.set(key); + break; + case EMIE_MMOUSE_PRESSED_DOWN: + key = "KEY_MBUTTON"; + keyIsDown.set(key); + keyWasDown.set(key); + keyWasPressed.set(key); + break; + case EMIE_RMOUSE_PRESSED_DOWN: + key = "KEY_RBUTTON"; + keyIsDown.set(key); + keyWasDown.set(key); + keyWasPressed.set(key); + break; + case EMIE_LMOUSE_LEFT_UP: + key = "KEY_LBUTTON"; + keyIsDown.unset(key); + keyWasReleased.set(key); + break; + case EMIE_MMOUSE_LEFT_UP: + key = "KEY_MBUTTON"; + keyIsDown.unset(key); + keyWasReleased.set(key); + break; + case EMIE_RMOUSE_LEFT_UP: + key = "KEY_RBUTTON"; + keyIsDown.unset(key); + keyWasReleased.set(key); + break; + case EMIE_MOUSE_WHEEL: + mouse_wheel += event.MouseInput.Wheel; + break; + default: break; } } else if (event.EventType == irr::EET_LOG_TEXT_EVENT) { static const LogLevel irr_loglev_conv[] = { @@ -188,38 +214,28 @@ s32 RandomInputHandler::Rand(s32 min, s32 max) return (myrand() % (max - min + 1)) + min; } +struct RandomInputHandlerSimData { + std::string key; + float counter; + int time_max; +}; + void RandomInputHandler::step(float dtime) { - { - static float counter1 = 0; - counter1 -= dtime; - if (counter1 < 0.0) { - counter1 = 0.1 * Rand(1, 40); - keydown.toggle(getKeySetting("keymap_jump")); - } - } - { - static float counter1 = 0; - counter1 -= dtime; - if (counter1 < 0.0) { - counter1 = 0.1 * Rand(1, 40); - keydown.toggle(getKeySetting("keymap_special1")); - } - } - { - static float counter1 = 0; - counter1 -= dtime; - if (counter1 < 0.0) { - counter1 = 0.1 * Rand(1, 40); - keydown.toggle(getKeySetting("keymap_forward")); - } - } - { - static float counter1 = 0; - counter1 -= dtime; - if (counter1 < 0.0) { - counter1 = 0.1 * Rand(1, 40); - keydown.toggle(getKeySetting("keymap_left")); + static RandomInputHandlerSimData rnd_data[] = { + { "keymap_jump", 0.0f, 40 }, + { "keymap_special1", 0.0f, 40 }, + { "keymap_forward", 0.0f, 40 }, + { "keymap_left", 0.0f, 40 }, + { "keymap_dig", 0.0f, 30 }, + { "keymap_place", 0.0f, 15 } + }; + + for (auto &i : rnd_data) { + i.counter -= dtime; + if (i.counter < 0.0) { + i.counter = 0.1 * Rand(1, i.time_max); + keydown.toggle(getKeySetting(i.key.c_str())); } } { @@ -230,29 +246,5 @@ void RandomInputHandler::step(float dtime) mousespeed = v2s32(Rand(-20, 20), Rand(-15, 20)); } } - { - static float counter1 = 0; - counter1 -= dtime; - if (counter1 < 0.0) { - counter1 = 0.1 * Rand(1, 30); - leftdown = !leftdown; - if (leftdown) - leftclicked = true; - if (!leftdown) - leftreleased = true; - } - } - { - static float counter1 = 0; - counter1 -= dtime; - if (counter1 < 0.0) { - counter1 = 0.1 * Rand(1, 15); - rightdown = !rightdown; - if (rightdown) - rightclicked = true; - if (!rightdown) - rightreleased = true; - } - } mousepos += mousespeed; } diff --git a/src/client/inputhandler.h b/src/client/inputhandler.h index fc7998f20..def147a82 100644 --- a/src/client/inputhandler.h +++ b/src/client/inputhandler.h @@ -144,6 +144,14 @@ public: return b; } + // Checks whether a key was just pressed. State will be cleared + // in the subsequent iteration of Game::processPlayerInteraction + bool WasKeyPressed(const KeyPress &keycode) const { return keyWasPressed[keycode]; } + + // Checks whether a key was just released. State will be cleared + // in the subsequent iteration of Game::processPlayerInteraction + bool WasKeyReleased(const KeyPress &keycode) const { return keyWasReleased[keycode]; } + void listenForKey(const KeyPress &keyCode) { keysListenedFor.set(keyCode); } void dontListenForKeys() { keysListenedFor.clear(); } @@ -158,17 +166,20 @@ public: { keyIsDown.clear(); keyWasDown.clear(); + keyWasPressed.clear(); + keyWasReleased.clear(); - leftclicked = false; - rightclicked = false; - leftreleased = false; - rightreleased = false; + mouse_wheel = 0; + } - left_active = false; - middle_active = false; - right_active = false; + void clearWasKeyPressed() + { + keyWasPressed.clear(); + } - mouse_wheel = 0; + void clearWasKeyReleased() + { + keyWasReleased.clear(); } MyEventReceiver() @@ -178,15 +189,6 @@ public: #endif } - bool leftclicked = false; - bool rightclicked = false; - bool leftreleased = false; - bool rightreleased = false; - - bool left_active = false; - bool middle_active = false; - bool right_active = false; - s32 mouse_wheel = 0; JoystickController *joystick = nullptr; @@ -198,8 +200,16 @@ public: private: // The current state of keys KeyList keyIsDown; - // Whether a key has been pressed or not + + // Whether a key was down KeyList keyWasDown; + + // Whether a key has just been pressed + KeyList keyWasPressed; + + // Whether a key has just been released + KeyList keyWasReleased; + // List of keys we listen for // TODO perhaps the type of this is not really // performant as KeyList is designed for few but @@ -226,27 +236,19 @@ public: virtual bool isKeyDown(GameKeyType k) = 0; virtual bool wasKeyDown(GameKeyType k) = 0; + virtual bool wasKeyPressed(GameKeyType k) = 0; + virtual bool wasKeyReleased(GameKeyType k) = 0; virtual bool cancelPressed() = 0; + virtual void clearWasKeyPressed() {} + virtual void clearWasKeyReleased() {} + virtual void listenForKey(const KeyPress &keyCode) {} virtual void dontListenForKeys() {} virtual v2s32 getMousePos() = 0; virtual void setMousePos(s32 x, s32 y) = 0; - virtual bool getLeftState() = 0; - virtual bool getRightState() = 0; - - virtual bool getLeftClicked() = 0; - virtual bool getRightClicked() = 0; - virtual void resetLeftClicked() = 0; - virtual void resetRightClicked() = 0; - - virtual bool getLeftReleased() = 0; - virtual bool getRightReleased() = 0; - virtual void resetLeftReleased() = 0; - virtual void resetRightReleased() = 0; - virtual s32 getMouseWheel() = 0; virtual void step(float dtime) {} @@ -275,10 +277,26 @@ public: { return m_receiver->WasKeyDown(keycache.key[k]) || joystick.wasKeyDown(k); } + virtual bool wasKeyPressed(GameKeyType k) + { + return m_receiver->WasKeyPressed(keycache.key[k]) || joystick.wasKeyReleased(k); + } + virtual bool wasKeyReleased(GameKeyType k) + { + return m_receiver->WasKeyReleased(keycache.key[k]) || joystick.wasKeyReleased(k); + } virtual bool cancelPressed() { return wasKeyDown(KeyType::ESC) || m_receiver->WasKeyDown(CancelKey); } + virtual void clearWasKeyPressed() + { + m_receiver->clearWasKeyPressed(); + } + virtual void clearWasKeyReleased() + { + m_receiver->clearWasKeyReleased(); + } virtual void listenForKey(const KeyPress &keyCode) { m_receiver->listenForKey(keyCode); @@ -306,59 +324,6 @@ public: } } - virtual bool getLeftState() - { - return m_receiver->left_active || joystick.isKeyDown(KeyType::MOUSE_L); - } - virtual bool getRightState() - { - return m_receiver->right_active || joystick.isKeyDown(KeyType::MOUSE_R); - } - - virtual bool getLeftClicked() - { - return m_receiver->leftclicked || - joystick.getWasKeyDown(KeyType::MOUSE_L); - } - virtual bool getRightClicked() - { - return m_receiver->rightclicked || - joystick.getWasKeyDown(KeyType::MOUSE_R); - } - - virtual void resetLeftClicked() - { - m_receiver->leftclicked = false; - joystick.clearWasKeyDown(KeyType::MOUSE_L); - } - virtual void resetRightClicked() - { - m_receiver->rightclicked = false; - joystick.clearWasKeyDown(KeyType::MOUSE_R); - } - - virtual bool getLeftReleased() - { - return m_receiver->leftreleased || - joystick.wasKeyReleased(KeyType::MOUSE_L); - } - virtual bool getRightReleased() - { - return m_receiver->rightreleased || - joystick.wasKeyReleased(KeyType::MOUSE_R); - } - - virtual void resetLeftReleased() - { - m_receiver->leftreleased = false; - joystick.clearWasKeyReleased(KeyType::MOUSE_L); - } - virtual void resetRightReleased() - { - m_receiver->rightreleased = false; - joystick.clearWasKeyReleased(KeyType::MOUSE_R); - } - virtual s32 getMouseWheel() { return m_receiver->getMouseWheel(); } void clear() @@ -384,23 +349,12 @@ public: virtual bool isKeyDown(GameKeyType k) { return keydown[keycache.key[k]]; } virtual bool wasKeyDown(GameKeyType k) { return false; } + virtual bool wasKeyPressed(GameKeyType k) { return false; } + virtual bool wasKeyReleased(GameKeyType k) { return false; } virtual bool cancelPressed() { return false; } virtual v2s32 getMousePos() { return mousepos; } virtual void setMousePos(s32 x, s32 y) { mousepos = v2s32(x, y); } - virtual bool getLeftState() { return leftdown; } - virtual bool getRightState() { return rightdown; } - - virtual bool getLeftClicked() { return leftclicked; } - virtual bool getRightClicked() { return rightclicked; } - virtual void resetLeftClicked() { leftclicked = false; } - virtual void resetRightClicked() { rightclicked = false; } - - virtual bool getLeftReleased() { return leftreleased; } - virtual bool getRightReleased() { return rightreleased; } - virtual void resetLeftReleased() { leftreleased = false; } - virtual void resetRightReleased() { rightreleased = false; } - virtual s32 getMouseWheel() { return 0; } virtual void step(float dtime); @@ -411,10 +365,4 @@ private: KeyList keydown; v2s32 mousepos; v2s32 mousespeed; - bool leftdown = false; - bool rightdown = false; - bool leftclicked = false; - bool rightclicked = false; - bool leftreleased = false; - bool rightreleased = false; }; diff --git a/src/client/keys.h b/src/client/keys.h index 50d3d194b..b6ce59b4a 100644 --- a/src/client/keys.h +++ b/src/client/keys.h @@ -35,6 +35,8 @@ public: SPECIAL1, SNEAK, AUTOFORWARD, + DIG, + PLACE, ESC, diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 07bf0ebb8..103f0fb02 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -73,6 +73,8 @@ void set_default_settings(Settings *settings) settings->setDefault("keymap_right", "KEY_KEY_D"); settings->setDefault("keymap_jump", "KEY_SPACE"); settings->setDefault("keymap_sneak", "KEY_LSHIFT"); + settings->setDefault("keymap_dig", "KEY_LBUTTON"); + settings->setDefault("keymap_place", "KEY_RBUTTON"); settings->setDefault("keymap_drop", "KEY_KEY_Q"); settings->setDefault("keymap_zoom", "KEY_KEY_Z"); settings->setDefault("keymap_inventory", "KEY_KEY_I"); @@ -269,7 +271,7 @@ void set_default_settings(Settings *settings) // Input settings->setDefault("invert_mouse", "false"); settings->setDefault("mouse_sensitivity", "0.2"); - settings->setDefault("repeat_rightclick_time", "0.25"); + settings->setDefault("repeat_place_time", "0.25"); settings->setDefault("safe_dig_and_place", "false"); settings->setDefault("random_input", "false"); settings->setDefault("aux1_descends", "false"); diff --git a/src/network/serverpackethandler.cpp b/src/network/serverpackethandler.cpp index b3008bb50..dcbb114bf 100644 --- a/src/network/serverpackethandler.cpp +++ b/src/network/serverpackethandler.cpp @@ -491,17 +491,18 @@ void Server::process_PlayerPos(RemotePlayer *player, PlayerSAO *playersao, playersao->setPlayerYaw(yaw); playersao->setFov(fov); playersao->setWantedRange(wanted_range); + player->keyPressed = keyPressed; - player->control.up = (keyPressed & 1); - player->control.down = (keyPressed & 2); - player->control.left = (keyPressed & 4); - player->control.right = (keyPressed & 8); - player->control.jump = (keyPressed & 16); - player->control.aux1 = (keyPressed & 32); - player->control.sneak = (keyPressed & 64); - player->control.LMB = (keyPressed & 128); - player->control.RMB = (keyPressed & 256); - player->control.zoom = (keyPressed & 512); + player->control.up = (keyPressed & (0x1 << 0)); + player->control.down = (keyPressed & (0x1 << 1)); + player->control.left = (keyPressed & (0x1 << 2)); + player->control.right = (keyPressed & (0x1 << 3)); + player->control.jump = (keyPressed & (0x1 << 4)); + player->control.aux1 = (keyPressed & (0x1 << 5)); + player->control.sneak = (keyPressed & (0x1 << 6)); + player->control.dig = (keyPressed & (0x1 << 7)); + player->control.place = (keyPressed & (0x1 << 8)); + player->control.zoom = (keyPressed & (0x1 << 9)); if (playersao->checkMovementCheat()) { // Call callbacks @@ -1670,7 +1671,7 @@ void Server::handleCommand_SrpBytesM(NetworkPacket* pkt) if (client->chosen_mech != AUTH_MECHANISM_SRP && client->chosen_mech != AUTH_MECHANISM_LEGACY_PASSWORD) { actionstream << "Server: got SRP _M packet, while auth" - << "is going on with mech " << client->chosen_mech << " from " + << "is going on with mech " << client->chosen_mech << " from " << addr_s << " (wantSudo=" << wantSudo << "). Denying." << std::endl; if (wantSudo) { DenySudoAccess(peer_id); diff --git a/src/player.h b/src/player.h index 3bc7762fa..ec068a8b1 100644 --- a/src/player.h +++ b/src/player.h @@ -57,8 +57,8 @@ struct PlayerControl bool a_aux1, bool a_sneak, bool a_zoom, - bool a_LMB, - bool a_RMB, + bool a_dig, + bool a_place, float a_pitch, float a_yaw, float a_sidew_move_joystick_axis, @@ -73,8 +73,8 @@ struct PlayerControl aux1 = a_aux1; sneak = a_sneak; zoom = a_zoom; - LMB = a_LMB; - RMB = a_RMB; + dig = a_dig; + place = a_place; pitch = a_pitch; yaw = a_yaw; sidew_move_joystick_axis = a_sidew_move_joystick_axis; @@ -88,8 +88,8 @@ struct PlayerControl bool aux1 = false; bool sneak = false; bool zoom = false; - bool LMB = false; - bool RMB = false; + bool dig = false; + bool place = false; float pitch = 0.0f; float yaw = 0.0f; float sidew_move_joystick_axis = 0.0f; diff --git a/src/script/lua_api/l_localplayer.cpp b/src/script/lua_api/l_localplayer.cpp index 851ede535..33fa27c8b 100644 --- a/src/script/lua_api/l_localplayer.cpp +++ b/src/script/lua_api/l_localplayer.cpp @@ -231,8 +231,8 @@ int LuaLocalPlayer::l_get_control(lua_State *L) set("aux1", c.aux1); set("sneak", c.sneak); set("zoom", c.zoom); - set("LMB", c.LMB); - set("RMB", c.RMB); + set("dig", c.dig); + set("place", c.place); return 1; } diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index e7394133a..495d8bced 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -1455,9 +1455,14 @@ int ObjectRef::l_get_player_control(lua_State *L) lua_setfield(L, -2, "aux1"); lua_pushboolean(L, control.sneak); lua_setfield(L, -2, "sneak"); - lua_pushboolean(L, control.LMB); + lua_pushboolean(L, control.dig); + lua_setfield(L, -2, "dig"); + lua_pushboolean(L, control.place); + lua_setfield(L, -2, "place"); + // Legacy fields to ensure mod compatibility + lua_pushboolean(L, control.dig); lua_setfield(L, -2, "LMB"); - lua_pushboolean(L, control.RMB); + lua_pushboolean(L, control.place); lua_setfield(L, -2, "RMB"); lua_pushboolean(L, control.zoom); lua_setfield(L, -2, "zoom"); -- cgit v1.2.3 From 7242de1d4bdb4cc98fce723044b2c8c5d9861c8b Mon Sep 17 00:00:00 2001 From: rubenwardy Date: Mon, 17 Aug 2020 19:09:33 +0100 Subject: ContentDB: Add Update All and download queuing (#9995) --- builtin/mainmenu/dlg_contentstore.lua | 91 +++++++++++++++++++++++++++++++---- builtin/settingtypes.txt | 3 ++ src/defaultsettings.cpp | 2 + 3 files changed, 86 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/builtin/mainmenu/dlg_contentstore.lua b/builtin/mainmenu/dlg_contentstore.lua index 37ceeb6c8..6525f6013 100644 --- a/builtin/mainmenu/dlg_contentstore.lua +++ b/builtin/mainmenu/dlg_contentstore.lua @@ -45,6 +45,9 @@ local filter_types_titles = { fgettext("Texture packs"), } +local number_downloading = 0 +local download_queue = {} + local filter_types_type = { nil, "game", @@ -67,12 +70,14 @@ local function download_package(param) end end -local function start_install(calling_dialog, package) +local function start_install(package) local params = { package = package, filename = os.tempfolder() .. "_MODNAME_" .. package.name .. ".zip", } + number_downloading = number_downloading + 1 + local function callback(result) if result.successful then local path, msg = pkgmgr.install(package.type, @@ -121,9 +126,20 @@ local function start_install(calling_dialog, package) end package.downloading = false + + number_downloading = number_downloading - 1 + + local next = download_queue[1] + if next then + table.remove(download_queue, 1) + + start_install(next) + end + ui.update() end + package.queued = false package.downloading = true if not core.handle_async(download_package, params, callback) then @@ -133,6 +149,16 @@ local function start_install(calling_dialog, package) end end +local function queue_download(package) + local max_concurrent_downloads = tonumber(minetest.settings:get("contentdb_max_concurrent_downloads")) + if number_downloading < max_concurrent_downloads then + start_install(package) + else + table.insert(download_queue, package) + package.queued = true + end +end + local function get_file_extension(path) local parts = path:split(".") return parts[#parts] @@ -279,7 +305,7 @@ function store.filter_packages(query) table.insert(keywords, word) end - local function matches_keywords(package, keywords) + local function matches_keywords(package) for k = 1, #keywords do local keyword = keywords[k] @@ -296,7 +322,7 @@ function store.filter_packages(query) store.packages = {} for _, package in pairs(store.packages_full) do - if (query == "" or matches_keywords(package, keywords)) and + if (query == "" or matches_keywords(package)) and (filter_type == 1 or package.type == filter_types_type[filter_type]) then store.packages[#store.packages + 1] = package end @@ -321,11 +347,14 @@ function store.get_formspec(dlgdata) "formspec_version[3]", "size[15.75,9.5]", "position[0.5,0.55]", + + "style[status;border=false]", + "container[0.375,0.375]", - "field[0,0;10.225,0.8;search_string;;", core.formspec_escape(search_string), "]", + "field[0,0;7.225,0.8;search_string;;", core.formspec_escape(search_string), "]", "field_close_on_enter[search_string;false]", - "button[10.225,0;2,0.8;search;", fgettext("Search"), "]", - "dropdown[12.6,0;2.4,0.8;type;", table.concat(filter_types_titles, ","), ";", filter_type, "]", + "button[7.225,0;2,0.8;search;", fgettext("Search"), "]", + "dropdown[9.6,0;2.4,0.8;type;", table.concat(filter_types_titles, ","), ";", filter_type, "]", "container_end[]", -- Page nav buttons @@ -344,6 +373,35 @@ function store.get_formspec(dlgdata) "container_end[]", } + if number_downloading > 0 then + formspec[#formspec + 1] = "button[12.75,0.375;2.625,0.8;status;" + if #download_queue > 0 then + formspec[#formspec + 1] = fgettext("$1 downloading,\n$2 queued", number_downloading, #download_queue) + else + formspec[#formspec + 1] = fgettext("$1 downloading...", number_downloading) + end + formspec[#formspec + 1] = "]" + else + local num_avail_updates = 0 + for i=1, #store.packages_full do + local package = store.packages_full[i] + if package.path and package.installed_release < package.release and + not (package.downloading or package.queued) then + num_avail_updates = num_avail_updates + 1 + end + end + + if num_avail_updates == 0 then + formspec[#formspec + 1] = "button[12.75,0.375;2.625,0.8;status;" + formspec[#formspec + 1] = fgettext("No updates") + formspec[#formspec + 1] = "]" + else + formspec[#formspec + 1] = "button[12.75,0.375;2.625,0.8;update_all;" + formspec[#formspec + 1] = fgettext("Update All [$1]", num_avail_updates) + formspec[#formspec + 1] = "]" + end + end + if #store.packages == 0 then formspec[#formspec + 1] = "label[4,3;" formspec[#formspec + 1] = fgettext("No results") @@ -386,11 +444,13 @@ function store.get_formspec(dlgdata) formspec[#formspec + 1] = ",0.1]" if package.downloading then - formspec[#formspec + 1] = "style[download;border=false]" - - formspec[#formspec + 1] = "button[-3.5,0;2,0.8;download;" + formspec[#formspec + 1] = "button[-3.5,0;2,0.8;status;" formspec[#formspec + 1] = fgettext("Downloading...") formspec[#formspec + 1] = "]" + elseif package.queued then + formspec[#formspec + 1] = "button[-3.5,0;2,0.8;status;" + formspec[#formspec + 1] = fgettext("Queued") + formspec[#formspec + 1] = "]" elseif not package.path then formspec[#formspec + 1] = "button[-3,0;1.5,0.8;install_" formspec[#formspec + 1] = tostring(i) @@ -485,6 +545,17 @@ function store.handle_submit(this, fields) end end + if fields.update_all then + for i=1, #store.packages_full do + local package = store.packages_full[i] + if package.path and package.installed_release < package.release and + not (package.downloading or package.queued) then + queue_download(package) + end + end + return true + end + local start_idx = (cur_page - 1) * num_per_page + 1 assert(start_idx ~= nil) for i=start_idx, math.min(#store.packages, start_idx+num_per_page-1) do @@ -492,7 +563,7 @@ function store.handle_submit(this, fields) assert(package) if fields["install_" .. i] then - start_install(this, package) + queue_download(package) return true end diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index 3aa113190..1f71e4cb9 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -2220,3 +2220,6 @@ contentdb_url (ContentDB URL) string https://content.minetest.net # These flags are independent from Minetest versions, # so see a full list at https://content.minetest.net/help/content_flags/ contentdb_flag_blacklist (ContentDB Flag Blacklist) string nonfree, desktop_default + +# Maximum number of concurrent downloads. Downloads exceeding this limit will be queued. +contentdb_max_concurrent_downloads (ContentDB Max Concurrent Downloads) int 3 diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 103f0fb02..8b6de0412 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -330,6 +330,8 @@ void set_default_settings(Settings *settings) // ContentDB settings->setDefault("contentdb_url", "https://content.minetest.net"); + settings->setDefault("contentdb_max_concurrent_downloads", "3"); + #ifdef __ANDROID__ settings->setDefault("contentdb_flag_blacklist", "nonfree, android_default"); #else -- cgit v1.2.3 From 649211bf272df2dc7057347992c2653cf1c3a6fb Mon Sep 17 00:00:00 2001 From: Lars Date: Wed, 12 Aug 2020 16:02:07 -0700 Subject: Allow the ABM time budget to be configurable. --- builtin/settingtypes.txt | 4 ++++ src/defaultsettings.cpp | 1 + src/environment.cpp | 1 + src/environment.h | 1 + src/serverenvironment.cpp | 4 ++-- 5 files changed, 9 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index 1f71e4cb9..af4dc1def 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -1282,6 +1282,10 @@ active_block_mgmt_interval (Active block management interval) float 2.0 # Length of time between Active Block Modifier (ABM) execution cycles abm_interval (ABM interval) float 1.0 +# The time budget allowed for ABMs to execute on each step +# (as a fraction of the ABM Interval) +abm_time_budget (ABM time budget) float 0.2 0.1 0.9 + # Length of time between NodeTimer execution cycles nodetimer_interval (NodeTimer interval) float 0.2 diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 8b6de0412..87c272630 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -403,6 +403,7 @@ void set_default_settings(Settings *settings) settings->setDefault("dedicated_server_step", "0.09"); settings->setDefault("active_block_mgmt_interval", "2.0"); settings->setDefault("abm_interval", "1.0"); + settings->setDefault("abm_time_budget", "0.2"); settings->setDefault("nodetimer_interval", "0.2"); settings->setDefault("ignore_world_load_errors", "false"); settings->setDefault("remote_media", ""); diff --git a/src/environment.cpp b/src/environment.cpp index 6751f39e4..06f2b8bf9 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -36,6 +36,7 @@ Environment::Environment(IGameDef *gamedef): m_cache_active_block_mgmt_interval = g_settings->getFloat("active_block_mgmt_interval"); m_cache_abm_interval = g_settings->getFloat("abm_interval"); m_cache_nodetimer_interval = g_settings->getFloat("nodetimer_interval"); + m_cache_abm_time_budget = g_settings->getFloat("abm_time_budget"); m_time_of_day = g_settings->getU32("world_start_time"); m_time_of_day_f = (float)m_time_of_day / 24000.0f; diff --git a/src/environment.h b/src/environment.h index 91c33ba15..b4884fdb3 100644 --- a/src/environment.h +++ b/src/environment.h @@ -147,6 +147,7 @@ protected: float m_cache_active_block_mgmt_interval; float m_cache_abm_interval; float m_cache_nodetimer_interval; + float m_cache_abm_time_budget; IGameDef *m_gamedef; diff --git a/src/serverenvironment.cpp b/src/serverenvironment.cpp index ad2ffc9a4..320042e19 100644 --- a/src/serverenvironment.cpp +++ b/src/serverenvironment.cpp @@ -1354,8 +1354,8 @@ void ServerEnvironment::step(float dtime) std::shuffle(output.begin(), output.end(), m_rgen); int i = 0; - // The time budget for ABMs is 20%. - u32 max_time_ms = m_cache_abm_interval * 1000 / 5; + // determine the time budget for ABMs + u32 max_time_ms = m_cache_abm_interval * 1000 * m_cache_abm_time_budget; for (const v3s16 &p : output) { MapBlock *block = m_map->getBlockNoCreateNoEx(p); if (!block) -- cgit v1.2.3 From 5bda36143f9bd332b6ba420d9b91be1713092eae Mon Sep 17 00:00:00 2001 From: hecks <42101236+hecktest@users.noreply.github.com> Date: Wed, 19 Aug 2020 19:26:37 +0200 Subject: Clean up sound_fade (#10119) Add proper documentation and correct gain reduction calculations. Co-authored-by: hecktest <> --- doc/lua_api.txt | 7 ++++-- src/client/sound_openal.cpp | 55 ++++++++++++++++++++++++--------------------- 2 files changed, 35 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 88d99fcd5..ba55033dd 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -5238,9 +5238,12 @@ Sounds * `minetest.sound_fade(handle, step, gain)` * `handle` is a handle returned by `minetest.sound_play` * `step` determines how fast a sound will fade. - Negative step will lower the sound volume, positive step will increase - the sound volume. + The gain will change by this much per second, + until it reaches the target gain. + Note: Older versions used a signed step. This is deprecated, but old + code will still work. (the client uses abs(step) to correct it) * `gain` the target gain for the fade. + Fading to zero will delete the sound. Timing ------ diff --git a/src/client/sound_openal.cpp b/src/client/sound_openal.cpp index 20a651c1d..c1c916e68 100644 --- a/src/client/sound_openal.cpp +++ b/src/client/sound_openal.cpp @@ -337,14 +337,12 @@ private: }; std::unordered_map m_sounds_fading; - float m_fade_delay; public: OpenALSoundManager(SoundManagerSingleton *smg, OnDemandSoundFetcher *fetcher): m_fetcher(fetcher), m_device(smg->m_device.get()), m_context(smg->m_context.get()), - m_next_id(1), - m_fade_delay(0) + m_next_id(1) { infostream << "Audio: Initialized: OpenAL " << std::endl; } @@ -616,38 +614,45 @@ public: void fadeSound(int soundid, float step, float gain) { - m_sounds_fading[soundid] = FadeState(step, getSoundGain(soundid), gain); + // Ignore the command if step isn't valid. + if (step == 0) + return; + float current_gain = getSoundGain(soundid); + step = gain - current_gain > 0 ? abs(step) : -abs(step); + if (m_sounds_fading.find(soundid) != m_sounds_fading.end()) { + auto current_fade = m_sounds_fading[soundid]; + // Do not replace the fade if it's equivalent. + if (current_fade.target_gain == gain && current_fade.step == step) + return; + m_sounds_fading.erase(soundid); + } + gain = rangelim(gain, 0, 1); + m_sounds_fading[soundid] = FadeState(step, current_gain, gain); } void doFades(float dtime) { - m_fade_delay += dtime; - - if (m_fade_delay < 0.1f) - return; + for (auto i = m_sounds_fading.begin(); i != m_sounds_fading.end();) { + FadeState& fade = i->second; + assert(fade.step != 0); + fade.current_gain += (fade.step * dtime); - float chkGain = 0; - for (auto i = m_sounds_fading.begin(); - i != m_sounds_fading.end();) { - if (i->second.step < 0.f) - chkGain = -(i->second.current_gain); + if (fade.step < 0.f) + fade.current_gain = std::max(fade.current_gain, fade.target_gain); else - chkGain = i->second.current_gain; + fade.current_gain = std::min(fade.current_gain, fade.target_gain); - if (chkGain < i->second.target_gain) { - i->second.current_gain += (i->second.step * m_fade_delay); - i->second.current_gain = rangelim(i->second.current_gain, 0, 1); - - updateSoundGain(i->first, i->second.current_gain); - ++i; - } else { - if (i->second.target_gain <= 0.f) - stopSound(i->first); + if (fade.current_gain <= 0.f) + stopSound(i->first); + else + updateSoundGain(i->first, fade.current_gain); + // The increment must happen during the erase call, or else it'll segfault. + if (fade.current_gain == fade.target_gain) m_sounds_fading.erase(i++); - } + else + i++; } - m_fade_delay = 0; } bool soundExists(int sound) -- cgit v1.2.3 From 471497fa9198695becae26a83097ec80643b4cc5 Mon Sep 17 00:00:00 2001 From: v-rob Date: Wed, 19 Aug 2020 16:13:29 -0700 Subject: Optimize formspec form size (#10144) --- src/gui/guiFormSpecMenu.cpp | 66 ++++++++++++++++++++++----------------------- 1 file changed, 33 insertions(+), 33 deletions(-) (limited to 'src') diff --git a/src/gui/guiFormSpecMenu.cpp b/src/gui/guiFormSpecMenu.cpp index 98392f3c0..f702b40bf 100644 --- a/src/gui/guiFormSpecMenu.cpp +++ b/src/gui/guiFormSpecMenu.cpp @@ -3112,42 +3112,42 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize) // and default scaling (1.00). use_imgsize = 0.5555 * screen_dpi * gui_scaling; } else { - // In variable-size mode, we prefer to make the - // inventory image size 1/15 of screen height, - // multiplied by the gui_scaling config parameter. - // If the preferred size won't fit the whole - // form on the screen, either horizontally or - // vertically, then we scale it down to fit. - // (The magic numbers in the computation of what - // fits arise from the scaling factors in the - // following stanza, including the form border, - // help text space, and 0.1 inventory slot spare.) - // However, a minimum size is also set, that - // the image size can't be less than 0.3 inch - // multiplied by gui_scaling, even if this means - // the form doesn't fit the screen. + // Variables for the maximum imgsize that can fit in the screen. + double fitx_imgsize; + double fity_imgsize; + + // Pad the screensize with 5% of the screensize on all sides to ensure + // that even the largest formspecs don't touch the screen borders. + v2f padded_screensize( + mydata.screensize.X * 0.9f, + mydata.screensize.Y * 0.9f + ); + + if (mydata.real_coordinates) { + fitx_imgsize = padded_screensize.X / mydata.invsize.X; + fity_imgsize = padded_screensize.Y / mydata.invsize.Y; + } else { + // The maximum imgsize in the old coordinate system also needs to + // factor in padding and spacing along with 0.1 inventory slot spare + // and help text space, hence the magic numbers. + fitx_imgsize = padded_screensize.X / + ((5.0 / 4.0) * (0.5 + mydata.invsize.X)); + fity_imgsize = padded_screensize.Y / + ((15.0 / 13.0) * (0.85 + mydata.invsize.Y)); + } + #ifdef __ANDROID__ - // For mobile devices these magic numbers are - // different and forms should always use the - // maximum screen space available. - double prefer_imgsize = mydata.screensize.Y / 10 * gui_scaling; - double fitx_imgsize = mydata.screensize.X / - ((12.0 / 8.0) * (0.5 + mydata.invsize.X)); - double fity_imgsize = mydata.screensize.Y / - ((15.0 / 11.0) * (0.85 + mydata.invsize.Y)); - use_imgsize = MYMIN(prefer_imgsize, - MYMIN(fitx_imgsize, fity_imgsize)); + // In Android, the preferred imgsize should be larger to accommodate the + // smaller screensize. + double prefer_imgsize = padded_screensize.Y / 10 * gui_scaling; #else - double prefer_imgsize = mydata.screensize.Y / 15 * gui_scaling; - double fitx_imgsize = mydata.screensize.X / - ((5.0 / 4.0) * (0.5 + mydata.invsize.X)); - double fity_imgsize = mydata.screensize.Y / - ((15.0 / 13.0) * (0.85 * mydata.invsize.Y)); - double screen_dpi = RenderingEngine::getDisplayDensity() * 96; - double min_imgsize = 0.3 * screen_dpi * gui_scaling; - use_imgsize = MYMAX(min_imgsize, MYMIN(prefer_imgsize, - MYMIN(fitx_imgsize, fity_imgsize))); + // Desktop computers have more space, so try to fit 15 coordinates. + double prefer_imgsize = padded_screensize.Y / 15 * gui_scaling; #endif + // Try to use the preferred imgsize, but if that's bigger than the maximum + // size, use the maximum size. + use_imgsize = std::min(prefer_imgsize, + std::min(fitx_imgsize, fity_imgsize)); } // Everything else is scaled in proportion to the -- cgit v1.2.3 From 83d0c360cc648e02650aa4d341dbf5205c1e708f Mon Sep 17 00:00:00 2001 From: v-rob Date: Wed, 19 Aug 2020 18:14:47 -0700 Subject: Add gradients and borders to FormSpec boxes (#8676) --- doc/lua_api.txt | 43 +++++++++++++++-------- src/gui/StyleSpec.h | 64 +++++++++++++++++++++++++++++++++ src/gui/guiBox.cpp | 86 ++++++++++++++++++++++++++++++++++++++++++--- src/gui/guiBox.h | 11 ++++-- src/gui/guiFormSpecMenu.cpp | 61 ++++++++++++++++++-------------- 5 files changed, 218 insertions(+), 47 deletions(-) (limited to 'src') diff --git a/doc/lua_api.txt b/doc/lua_api.txt index ba55033dd..49fbe0d94 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -2442,6 +2442,8 @@ Elements * Simple colored box * `color` is color specified as a `ColorString`. If the alpha component is left blank, the box will be semitransparent. + If the color is not specified, the box will use the options specified by + its style. If the color is specified, all styling options will be ignored. ### `dropdown[,;;;,, ...,;;]` @@ -2708,21 +2710,23 @@ Setting a property to nothing will reset it to the default value. For example: Some types may inherit styles from parent types. * animated_image, inherits from image +* box * button * button_exit, inherits from button * checkbox -* scrollbar -* table -* textlist * dropdown * field -* pwdfield, inherits from field -* textarea -* label -* vertlabel, inherits from field +* image * image_button * item_image_button +* label +* pwdfield, inherits from field +* scrollbar * tabheader +* table +* textarea +* textlist +* vertlabel, inherits from label ### Valid Properties @@ -2731,7 +2735,18 @@ Some types may inherit styles from parent types. * noclip - boolean, set to true to allow the element to exceed formspec bounds. * box * noclip - boolean, set to true to allow the element to exceed formspec bounds. - * Default to false in formspec_version version 3 or higher + * Defaults to false in formspec_version version 3 or higher + * **Note**: `colors`, `bordercolors`, and `borderwidths` accept multiple input types: + * Single value (e.g. `#FF0`): All corners/borders. + * Two values (e.g. `red,#FFAAFF`): top-left and bottom-right,top-right and bottom-left/ + top and bottom,left and right. + * Four values (e.g. `blue,#A0F,green,#FFFA`): top-left/top and rotates clockwise. + * These work similarly to CSS borders. + * colors - `ColorString`. Sets the color(s) of the box corners. Default `black`. + * bordercolors - `ColorString`. Sets the color(s) of the borders. Default `black`. + * borderwidths - Integer. Sets the width(s) of the borders in pixels. If the width is + negative, the border will extend inside the box, whereas positive extends outside + the box. A width of zero results in no border; this is default. * button, button_exit, image_button, item_image_button * alpha - boolean, whether to draw alpha in bgimg. Default true. * bgcolor - color, sets button tint. @@ -2767,12 +2782,6 @@ Some types may inherit styles from parent types. * textcolor - color, default white. * checkbox * noclip - boolean, set to true to allow the element to exceed formspec bounds. -* scrollbar - * noclip - boolean, set to true to allow the element to exceed formspec bounds. -* table, textlist - * font - Sets font type. See button `font` property for more information. - * font_size - Sets font size. See button `font_size` property for more information. - * noclip - boolean, set to true to allow the element to exceed formspec bounds. * dropdown * noclip - boolean, set to true to allow the element to exceed formspec bounds. * field, pwdfield, textarea @@ -2797,9 +2806,15 @@ Some types may inherit styles from parent types. * fgimg_pressed - image when pressed. Defaults to fgimg when not provided. * This is deprecated, use states instead. * NOTE: The parameters of any given image_button will take precedence over fgimg/fgimg_pressed +* scrollbar + * noclip - boolean, set to true to allow the element to exceed formspec bounds. * tabheader * noclip - boolean, set to true to allow the element to exceed formspec bounds. * textcolor - color. Default white. +* table, textlist + * font - Sets font type. See button `font` property for more information. + * font_size - Sets font size. See button `font_size` property for more information. + * noclip - boolean, set to true to allow the element to exceed formspec bounds. ### Valid States diff --git a/src/gui/StyleSpec.h b/src/gui/StyleSpec.h index 67caf4f7b..36ad51a89 100644 --- a/src/gui/StyleSpec.h +++ b/src/gui/StyleSpec.h @@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "util/string.h" #include #include +#include #pragma once @@ -50,6 +51,9 @@ public: PADDING, FONT, FONT_SIZE, + COLORS, + BORDERCOLORS, + BORDERWIDTHS, NUM_PROPERTIES, NONE }; @@ -106,6 +110,12 @@ public: return FONT; } else if (name == "font_size") { return FONT_SIZE; + } else if (name == "colors") { + return COLORS; + } else if (name == "bordercolors") { + return BORDERCOLORS; + } else if (name == "borderwidths") { + return BORDERWIDTHS; } else { return NONE; } @@ -187,6 +197,42 @@ public: return color; } + std::array getColorArray(Property prop, + std::array def) const + { + const auto &val = properties[prop]; + if (val.empty()) + return def; + + std::vector strs; + if (!parseArray(val, strs)) + return def; + + for (size_t i = 0; i <= 3; i++) { + video::SColor color; + if (parseColorString(strs[i], color, false, 0xff)) + def[i] = color; + } + + return def; + } + + std::array getIntArray(Property prop, std::array def) const + { + const auto &val = properties[prop]; + if (val.empty()) + return def; + + std::vector strs; + if (!parseArray(val, strs)) + return def; + + for (size_t i = 0; i <= 3; i++) + def[i] = stoi(strs[i]); + + return def; + } + irr::core::rect getRect(Property prop, irr::core::rect def) const { const auto &val = properties[prop]; @@ -334,6 +380,24 @@ public: } private: + bool parseArray(const std::string &value, std::vector &arr) const + { + std::vector strs = split(value, ','); + + if (strs.size() == 1) { + arr = {strs[0], strs[0], strs[0], strs[0]}; + } else if (strs.size() == 2) { + arr = {strs[0], strs[1], strs[0], strs[1]}; + } else if (strs.size() == 4) { + arr = strs; + } else { + warningstream << "Invalid array size (" << strs.size() + << " arguments): \"" << value << "\"" << std::endl; + return false; + } + return true; + } + bool parseRect(const std::string &value, irr::core::rect *parsed_rect) const { irr::core::rect rect; diff --git a/src/gui/guiBox.cpp b/src/gui/guiBox.cpp index 7f329cc32..99a115daf 100644 --- a/src/gui/guiBox.cpp +++ b/src/gui/guiBox.cpp @@ -20,9 +20,14 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "guiBox.h" GUIBox::GUIBox(gui::IGUIEnvironment *env, gui::IGUIElement *parent, s32 id, - const core::rect &rectangle, const video::SColor &color) : + const core::rect &rectangle, + const std::array &colors, + const std::array &bordercolors, + const std::array &borderwidths) : gui::IGUIElement(gui::EGUIET_ELEMENT, env, parent, id, rectangle), - m_color(color) + m_colors(colors), + m_bordercolors(bordercolors), + m_borderwidths(borderwidths) { } @@ -31,8 +36,81 @@ void GUIBox::draw() if (!IsVisible) return; - Environment->getVideoDriver()->draw2DRectangle(m_color, AbsoluteRect, - &AbsoluteClippingRect); + std::array negative_borders = {0, 0, 0, 0}; + std::array positive_borders = {0, 0, 0, 0}; + + for (size_t i = 0; i <= 3; i++) { + if (m_borderwidths[i] > 0) + positive_borders[i] = m_borderwidths[i]; + else + negative_borders[i] = m_borderwidths[i]; + } + + v2s32 upperleft = AbsoluteRect.UpperLeftCorner; + v2s32 lowerright = AbsoluteRect.LowerRightCorner; + + v2s32 topleft_border = { + upperleft.X - positive_borders[3], + upperleft.Y - positive_borders[0] + }; + v2s32 topleft_rect = { + upperleft.X - negative_borders[3], + upperleft.Y - negative_borders[0] + }; + + v2s32 lowerright_border = { + lowerright.X + positive_borders[1], + lowerright.Y + positive_borders[2] + }; + v2s32 lowerright_rect = { + lowerright.X + negative_borders[1], + lowerright.Y + negative_borders[2] + }; + + core::rect main_rect( + topleft_rect.X, + topleft_rect.Y, + lowerright_rect.X, + lowerright_rect.Y + ); + + std::array, 4> border_rects; + + border_rects[0] = core::rect( + topleft_border.X, + topleft_border.Y, + lowerright_border.X, + topleft_rect.Y + ); + + border_rects[1] = core::rect( + lowerright_rect.X, + topleft_rect.Y, + lowerright_border.X, + lowerright_rect.Y + ); + + border_rects[2] = core::rect( + topleft_border.X, + lowerright_rect.Y, + lowerright_border.X, + lowerright_border.Y + ); + + border_rects[3] = core::rect( + topleft_border.X, + topleft_rect.Y, + topleft_rect.X, + lowerright_rect.Y + ); + + video::IVideoDriver *driver = Environment->getVideoDriver(); + + driver->draw2DRectangle(main_rect, m_colors[0], m_colors[1], m_colors[3], + m_colors[2], nullptr); + + for (size_t i = 0; i <= 3; i++) + driver->draw2DRectangle(m_bordercolors[i], border_rects[i], nullptr); IGUIElement::draw(); } diff --git a/src/gui/guiBox.h b/src/gui/guiBox.h index 5306fdf65..ca8f83771 100644 --- a/src/gui/guiBox.h +++ b/src/gui/guiBox.h @@ -19,16 +19,23 @@ with this program; if not, write to the Free Software Foundation, Inc., #pragma once +#include +#include #include "irrlichttypes_extrabloated.h" class GUIBox : public gui::IGUIElement { public: GUIBox(gui::IGUIEnvironment *env, gui::IGUIElement *parent, s32 id, - const core::rect &rectangle, const video::SColor &color); + const core::rect &rectangle, + const std::array &colors, + const std::array &bordercolors, + const std::array &borderwidths); virtual void draw() override; private: - video::SColor m_color; + std::array m_colors; + std::array m_bordercolors; + std::array m_borderwidths; }; diff --git a/src/gui/guiFormSpecMenu.cpp b/src/gui/guiFormSpecMenu.cpp index f702b40bf..9bd5f27fd 100644 --- a/src/gui/guiFormSpecMenu.cpp +++ b/src/gui/guiFormSpecMenu.cpp @@ -2211,16 +2211,16 @@ void GUIFormSpecMenu::parseItemImageButton(parserData* data, const std::string & void GUIFormSpecMenu::parseBox(parserData* data, const std::string &element) { - std::vector parts = split(element,';'); + std::vector parts = split(element, ';'); if ((parts.size() == 3) || ((parts.size() > 3) && (m_formspec_version > FORMSPEC_API_VERSION))) { - std::vector v_pos = split(parts[0],','); - std::vector v_geom = split(parts[1],','); + std::vector v_pos = split(parts[0], ','); + std::vector v_geom = split(parts[1], ','); - MY_CHECKPOS("box",0); - MY_CHECKGEOM("box",1); + MY_CHECKPOS("box", 0); + MY_CHECKGEOM("box", 1); v2s32 pos; v2s32 geom; @@ -2234,36 +2234,43 @@ void GUIFormSpecMenu::parseBox(parserData* data, const std::string &element) geom.Y = stof(v_geom[1]) * spacing.Y; } - video::SColor tmp_color; - - if (parseColorString(parts[2], tmp_color, false, 0x8C)) { - FieldSpec spec( - "", - L"", - L"", - 258 + m_fields.size(), - -2 - ); - spec.ftype = f_Box; + FieldSpec spec( + "", + L"", + L"", + 258 + m_fields.size(), + -2 + ); + spec.ftype = f_Box; - core::rect rect(pos, pos + geom); + auto style = getDefaultStyleForElement("box", spec.fname); - GUIBox *e = new GUIBox(Environment, data->current_parent, spec.fid, - rect, tmp_color); + video::SColor tmp_color; + std::array colors; + std::array bordercolors = {0x0, 0x0, 0x0, 0x0}; + std::array borderwidths = {0, 0, 0, 0}; - auto style = getDefaultStyleForElement("box", spec.fname); - e->setNotClipped(style.getBool(StyleSpec::NOCLIP, m_formspec_version < 3)); + if (parseColorString(parts[2], tmp_color, true, 0x8C)) { + colors = {tmp_color, tmp_color, tmp_color, tmp_color}; + } else { + colors = style.getColorArray(StyleSpec::COLORS, {0x0, 0x0, 0x0, 0x0}); + bordercolors = style.getColorArray(StyleSpec::BORDERCOLORS, + {0x0, 0x0, 0x0, 0x0}); + borderwidths = style.getIntArray(StyleSpec::BORDERWIDTHS, {0, 0, 0, 0}); + } - e->drop(); + core::rect rect(pos, pos + geom); - m_fields.push_back(spec); + GUIBox *e = new GUIBox(Environment, data->current_parent, spec.fid, rect, + colors, bordercolors, borderwidths); + e->setNotClipped(style.getBool(StyleSpec::NOCLIP, m_formspec_version < 3)); + e->drop(); - } else { - errorstream<< "Invalid Box element(" << parts.size() << "): '" << element << "' INVALID COLOR" << std::endl; - } + m_fields.push_back(spec); return; } - errorstream<< "Invalid Box element(" << parts.size() << "): '" << element << "'" << std::endl; + errorstream << "Invalid Box element(" << parts.size() << "): '" << element + << "'" << std::endl; } void GUIFormSpecMenu::parseBackgroundColor(parserData* data, const std::string &element) -- cgit v1.2.3 From 71287894adbf3cbe092ded1cbf02755678305afb Mon Sep 17 00:00:00 2001 From: Pierre-Yves Rollo Date: Thu, 20 Aug 2020 12:25:02 +0200 Subject: Fix missing translation call in hypertext (#10296) --- src/gui/guiFormSpecMenu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/gui/guiFormSpecMenu.cpp b/src/gui/guiFormSpecMenu.cpp index 9bd5f27fd..76441c645 100644 --- a/src/gui/guiFormSpecMenu.cpp +++ b/src/gui/guiFormSpecMenu.cpp @@ -1740,7 +1740,7 @@ void GUIFormSpecMenu::parseHyperText(parserData *data, const std::string &elemen FieldSpec spec( name, - utf8_to_wide(unescape_string(text)), + translate_string(utf8_to_wide(unescape_string(text))), L"", 258 + m_fields.size() ); -- cgit v1.2.3 From 9c7340104a7ec4007e3dfe0bb4482f3c8f9878e0 Mon Sep 17 00:00:00 2001 From: Sebastien Marie Date: Thu, 20 Aug 2020 19:10:58 +0200 Subject: Define environ variable on OpenBSD (#10302) --- src/porting.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/porting.cpp b/src/porting.cpp index d902d3737..b3c8cae99 100644 --- a/src/porting.cpp +++ b/src/porting.cpp @@ -25,7 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "porting.h" -#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) +#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__OpenBSD__) #include #include extern char **environ; -- cgit v1.2.3 From 98faeac5a7b382e5d7ce0474bf7d52fc5975a23c Mon Sep 17 00:00:00 2001 From: DS Date: Thu, 20 Aug 2020 22:25:29 +0200 Subject: Load media from subfolders (#9065) --- doc/lua_api.txt | 24 +++++++++++++-------- .../mods/basenodes/textures/default_grass_side.png | Bin 796 -> 0 bytes .../textures/dirt_with_grass/default_grass.png | Bin 0 -> 829 bytes .../dirt_with_grass/default_grass_side.png | Bin 0 -> 796 bytes .../basenodes/textures/dirt_with_grass/info.txt | 3 +++ src/server.cpp | 16 +++++++++----- src/server/mods.cpp | 10 ++++----- src/unittest/test_servermodmanager.cpp | 2 -- 8 files changed, 34 insertions(+), 21 deletions(-) delete mode 100644 games/devtest/mods/basenodes/textures/default_grass_side.png create mode 100644 games/devtest/mods/basenodes/textures/dirt_with_grass/default_grass.png create mode 100644 games/devtest/mods/basenodes/textures/dirt_with_grass/default_grass_side.png create mode 100644 games/devtest/mods/basenodes/textures/dirt_with_grass/info.txt (limited to 'src') diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 49fbe0d94..9770ae4a9 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -152,7 +152,11 @@ Mod directory structure │   ├── models │   ├── textures │   │   ├── modname_stuff.png - │   │   └── modname_something_else.png + │   │   ├── modname_something_else.png + │   │   ├── subfolder_foo + │   │   │ ├── modname_more_stuff.png + │   │   │ └── another_subfolder + │   │   └── bar_subfolder │   ├── sounds │   ├── media │   ├── locale @@ -221,18 +225,20 @@ registered callbacks. `minetest.settings` can be used to read custom or existing settings at load time, if necessary. (See [`Settings`]) -### `models` - -Models for entities or meshnodes. - -### `textures`, `sounds`, `media` +### `textures`, `sounds`, `media`, `models`, `locale` Media files (textures, sounds, whatever) that will be transferred to the -client and will be available for use by the mod. +client and will be available for use by the mod and translation files for +the clients (see [Translations]). -### `locale` +It is suggested to use the folders for the purpous they are thought for, +eg. put textures into `textures`, translation files into `locale`, +models for entities or meshnodes into `models` et cetera. -Translation files for the clients. (See [Translations]) +These folders and subfolders can contain subfolders. +Subfolders with names starting with `_` or `.` are ignored. +If a subfolder contains a media file with the same name as a media file +in one of its parents, the parent's file is used. Naming conventions ------------------ diff --git a/games/devtest/mods/basenodes/textures/default_grass_side.png b/games/devtest/mods/basenodes/textures/default_grass_side.png deleted file mode 100644 index 04770b6f6..000000000 Binary files a/games/devtest/mods/basenodes/textures/default_grass_side.png and /dev/null differ diff --git a/games/devtest/mods/basenodes/textures/dirt_with_grass/default_grass.png b/games/devtest/mods/basenodes/textures/dirt_with_grass/default_grass.png new file mode 100644 index 000000000..29fde6b26 Binary files /dev/null and b/games/devtest/mods/basenodes/textures/dirt_with_grass/default_grass.png differ diff --git a/games/devtest/mods/basenodes/textures/dirt_with_grass/default_grass_side.png b/games/devtest/mods/basenodes/textures/dirt_with_grass/default_grass_side.png new file mode 100644 index 000000000..04770b6f6 Binary files /dev/null and b/games/devtest/mods/basenodes/textures/dirt_with_grass/default_grass_side.png differ diff --git a/games/devtest/mods/basenodes/textures/dirt_with_grass/info.txt b/games/devtest/mods/basenodes/textures/dirt_with_grass/info.txt new file mode 100644 index 000000000..8db21ed9c --- /dev/null +++ b/games/devtest/mods/basenodes/textures/dirt_with_grass/info.txt @@ -0,0 +1,3 @@ +This is for testing loading textures from subfolders. +If it works correctly, the default_grass_side.png file in this folder is used but +default_grass.png is not overwritten by the file in this folder. diff --git a/src/server.cpp b/src/server.cpp index 53ee8c444..ef36aedca 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -2494,19 +2494,25 @@ void Server::fillMediaCache() // Collect all media file paths std::vector paths; - m_modmgr->getModsMediaPaths(paths); - fs::GetRecursiveDirs(paths, m_gamespec.path + DIR_DELIM + "textures"); + // The paths are ordered in descending priority fs::GetRecursiveDirs(paths, porting::path_user + DIR_DELIM + "textures" + DIR_DELIM + "server"); + fs::GetRecursiveDirs(paths, m_gamespec.path + DIR_DELIM + "textures"); + m_modmgr->getModsMediaPaths(paths); // Collect media file information from paths into cache for (const std::string &mediapath : paths) { std::vector dirlist = fs::GetDirListing(mediapath); for (const fs::DirListNode &dln : dirlist) { - if (dln.dir) // Ignore dirs + if (dln.dir) // Ignore dirs (already in paths) continue; + + const std::string &filename = dln.name; + if (m_media.find(filename) != m_media.end()) // Do not override + continue; + std::string filepath = mediapath; - filepath.append(DIR_DELIM).append(dln.name); - addMediaFile(dln.name, filepath); + filepath.append(DIR_DELIM).append(filename); + addMediaFile(filename, filepath); } } diff --git a/src/server/mods.cpp b/src/server/mods.cpp index 6ac530739..cf1467648 100644 --- a/src/server/mods.cpp +++ b/src/server/mods.cpp @@ -99,10 +99,10 @@ void ServerModManager::getModNames(std::vector &modlist) const void ServerModManager::getModsMediaPaths(std::vector &paths) const { for (const ModSpec &spec : m_sorted_mods) { - paths.push_back(spec.path + DIR_DELIM + "textures"); - paths.push_back(spec.path + DIR_DELIM + "sounds"); - paths.push_back(spec.path + DIR_DELIM + "media"); - paths.push_back(spec.path + DIR_DELIM + "models"); - paths.push_back(spec.path + DIR_DELIM + "locale"); + fs::GetRecursiveDirs(paths, spec.path + DIR_DELIM + "textures"); + fs::GetRecursiveDirs(paths, spec.path + DIR_DELIM + "sounds"); + fs::GetRecursiveDirs(paths, spec.path + DIR_DELIM + "media"); + fs::GetRecursiveDirs(paths, spec.path + DIR_DELIM + "models"); + fs::GetRecursiveDirs(paths, spec.path + DIR_DELIM + "locale"); } } diff --git a/src/unittest/test_servermodmanager.cpp b/src/unittest/test_servermodmanager.cpp index 799936757..e3edb0c32 100644 --- a/src/unittest/test_servermodmanager.cpp +++ b/src/unittest/test_servermodmanager.cpp @@ -169,6 +169,4 @@ void TestServerModManager::testGetModMediaPaths() std::vector result; sm.getModsMediaPaths(result); UASSERTEQ(bool, result.empty(), false); - // We should have 5 folders for each mod (textures, media, locale, model, sounds) - UASSERTEQ(unsigned long, result.size() % 5, 0); } -- cgit v1.2.3 From cf5547227d9fffd9fb0043ce0b5633b831536eb6 Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Sun, 23 Aug 2020 14:39:32 +0100 Subject: Complete Haiku platform support. (#10311) Fixing linkage/libraries missing issue. Implements missing platform specifics. --- src/CMakeLists.txt | 4 ++++ src/network/CMakeLists.txt | 5 ----- src/porting.cpp | 10 ++++++++++ src/porting.h | 2 ++ src/threading/thread.cpp | 4 ++++ src/threading/thread.h | 4 ++++ 6 files changed, 24 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3d6d1b0ea..7e1d0bd39 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -351,6 +351,10 @@ else() if (ICONV_LIBRARY) set(PLATFORM_LIBS ${PLATFORM_LIBS} ${ICONV_LIBRARY}) endif() + if (HAIKU) + set(PLATFORM_LIBS ${PLATFORM_LIBS} intl network) + endif() + endif() check_include_files(endian.h HAVE_ENDIAN_H) diff --git a/src/network/CMakeLists.txt b/src/network/CMakeLists.txt index c6995ab22..d2e2f52e9 100644 --- a/src/network/CMakeLists.txt +++ b/src/network/CMakeLists.txt @@ -16,8 +16,3 @@ if (BUILD_CLIENT) PARENT_SCOPE ) endif() - -# Haiku networking support -if(HAIKU) - set(PLATFORM_LIBS -lnetwork ${PLATFORM_LIBS}) -endif() diff --git a/src/porting.cpp b/src/porting.cpp index b3c8cae99..e7ed4e090 100644 --- a/src/porting.cpp +++ b/src/porting.cpp @@ -56,6 +56,10 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #endif +#if defined(__HAIKU__) + #include +#endif + #include "config.h" #include "debug.h" #include "filesys.h" @@ -321,6 +325,12 @@ bool getCurrentExecPath(char *buf, size_t len) return true; } +#elif defined(__HAIKU__) + +bool getCurrentExecPath(char *buf, size_t len) +{ + return find_path(B_APP_IMAGE_SYMBOL, B_FIND_PATH_IMAGE_PATH, NULL, buf, len) == B_OK; +} //// Solaris #elif defined(__sun) || defined(sun) diff --git a/src/porting.h b/src/porting.h index f50f0a950..c7adf12a2 100644 --- a/src/porting.h +++ b/src/porting.h @@ -309,6 +309,8 @@ inline const char *getPlatformName() #else "SunOS" #endif +#elif defined(__HAIKU__) + "Haiku" #elif defined(__CYGWIN__) "Cygwin" #elif defined(__unix__) || defined(__unix) diff --git a/src/threading/thread.cpp b/src/threading/thread.cpp index e0f808c4d..f678a09be 100644 --- a/src/threading/thread.cpp +++ b/src/threading/thread.cpp @@ -225,6 +225,10 @@ void Thread::setName(const std::string &name) pthread_setname_np(name.c_str()); +#elif defined(__HAIKU__) + + rename_thread(find_thread(NULL), name.c_str()); + #elif defined(_MSC_VER) // Windows itself doesn't support thread names, diff --git a/src/threading/thread.h b/src/threading/thread.h index cea92226f..3946335f5 100644 --- a/src/threading/thread.h +++ b/src/threading/thread.h @@ -36,6 +36,10 @@ DEALINGS IN THE SOFTWARE. #include // for tid_t #endif +#ifdef __HAIKU__ + #include +#endif + /* * On platforms using pthreads, these five priority classes correlate to * even divisions between the minimum and maximum reported thread priority. -- cgit v1.2.3 From f5a203fbcd3af358bc1639467014063ba8409d3e Mon Sep 17 00:00:00 2001 From: BenjaminRi <28017860+BenjaminRi@users.noreply.github.com> Date: Sun, 23 Aug 2020 15:39:55 +0200 Subject: Fix light overflow of u8 if light is saturated at 255 (#10305) --- src/light.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/light.cpp b/src/light.cpp index 8196fedff..d5389b450 100644 --- a/src/light.cpp +++ b/src/light.cpp @@ -18,6 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc., */ #include "light.h" +#include #include #include "util/numeric.h" #include "settings.h" @@ -81,9 +82,11 @@ void set_light_table(float gamma) // Strictly speaking, rangelim is not necessary here—if the implementation // is conforming. But we don’t want problems in any case. light_LUT[i] = rangelim((s32)(255.0f * brightness), 0, 255); + // Ensure light brightens with each level - if (i > 1 && light_LUT[i] <= light_LUT[i - 1]) - light_LUT[i] = light_LUT[i - 1] + 1; + if (i > 0 && light_LUT[i] <= light_LUT[i - 1]) { + light_LUT[i] = std::min((u8)254, light_LUT[i - 1]) + 1; + } } } -- cgit v1.2.3 From 3c2890692bb4c292023a8260cf9ce70f82b2e780 Mon Sep 17 00:00:00 2001 From: adrido Date: Sun, 23 Aug 2020 15:41:04 +0200 Subject: Fix MSVC compiler warnings (#10197) --- src/client/fontengine.h | 2 +- src/gui/guiChatConsole.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/client/fontengine.h b/src/client/fontengine.h index 865b2d3ff..c6efa0df4 100644 --- a/src/client/fontengine.h +++ b/src/client/fontengine.h @@ -48,7 +48,7 @@ struct FontSpec { u16 getHash() { - return (mode << 2) | (bold << 1) | italic; + return (mode << 2) | (static_cast(bold) << 1) | static_cast(italic); } unsigned int size; diff --git a/src/gui/guiChatConsole.cpp b/src/gui/guiChatConsole.cpp index 8de00c12f..575c6ab25 100644 --- a/src/gui/guiChatConsole.cpp +++ b/src/gui/guiChatConsole.cpp @@ -545,7 +545,7 @@ bool GUIChatConsole::OnEvent(const SEvent& event) if (prompt.getCursorLength() <= 0) return true; std::wstring wselected = prompt.getSelection(); - std::string selected(wselected.begin(), wselected.end()); + std::string selected = wide_to_utf8(wselected); Environment->getOSOperator()->copyToClipboard(selected.c_str()); return true; } @@ -575,7 +575,7 @@ bool GUIChatConsole::OnEvent(const SEvent& event) if (prompt.getCursorLength() <= 0) return true; std::wstring wselected = prompt.getSelection(); - std::string selected(wselected.begin(), wselected.end()); + std::string selected = wide_to_utf8(wselected); Environment->getOSOperator()->copyToClipboard(selected.c_str()); prompt.cursorOperation( ChatPrompt::CURSOROP_DELETE, -- cgit v1.2.3 From 287f3fb2e3317bb6bd6d8608f1aa051c601aeca4 Mon Sep 17 00:00:00 2001 From: EvidenceB <49488517+EvidenceBKidscode@users.noreply.github.com> Date: Sun, 23 Aug 2020 22:50:14 +0200 Subject: Avoid drawing clipped out formspec elements (#10095) --- src/gui/guiFormSpecMenu.cpp | 10 +++++++--- src/gui/guiScrollContainer.cpp | 12 ++++++++++++ src/gui/guiScrollContainer.h | 2 ++ 3 files changed, 21 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/gui/guiFormSpecMenu.cpp b/src/gui/guiFormSpecMenu.cpp index 76441c645..7e3ad3b15 100644 --- a/src/gui/guiFormSpecMenu.cpp +++ b/src/gui/guiFormSpecMenu.cpp @@ -3483,10 +3483,14 @@ void GUIFormSpecMenu::drawMenu() e->setVisible(true); /* - Call base class - (This is where all the drawing happens.) + This is where all the drawing happens. */ - gui::IGUIElement::draw(); + core::list::Iterator it = Children.begin(); + for (; it != Children.end(); ++it) + if ((*it)->isNotClipped() || + AbsoluteClippingRect.isRectCollided( + (*it)->getAbsolutePosition())) + (*it)->draw(); for (gui::IGUIElement *e : m_clickthrough_elements) e->setVisible(false); diff --git a/src/gui/guiScrollContainer.cpp b/src/gui/guiScrollContainer.cpp index 88cdc7057..0fe4c41bd 100644 --- a/src/gui/guiScrollContainer.cpp +++ b/src/gui/guiScrollContainer.cpp @@ -56,6 +56,18 @@ bool GUIScrollContainer::OnEvent(const SEvent &event) return IGUIElement::OnEvent(event); } +void GUIScrollContainer::draw() +{ + if (isVisible()) { + core::list::Iterator it = Children.begin(); + for (; it != Children.end(); ++it) + if ((*it)->isNotClipped() || + AbsoluteClippingRect.isRectCollided( + (*it)->getAbsolutePosition())) + (*it)->draw(); + } +} + void GUIScrollContainer::updateScrolling() { s32 pos = m_scrollbar->getPos(); diff --git a/src/gui/guiScrollContainer.h b/src/gui/guiScrollContainer.h index a0306291e..9e3ec6e93 100644 --- a/src/gui/guiScrollContainer.h +++ b/src/gui/guiScrollContainer.h @@ -32,6 +32,8 @@ public: virtual bool OnEvent(const SEvent &event) override; + virtual void draw() override; + inline void onScrollEvent(gui::IGUIElement *caller) { if (caller == m_scrollbar) -- cgit v1.2.3 From 3e5bce2251deb8e5fcbaa266431f8c0f10078bf2 Mon Sep 17 00:00:00 2001 From: Kezi Date: Sun, 23 Aug 2020 22:50:45 +0200 Subject: darken tabheader background color (#10299) --- src/gui/guiSkin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/gui/guiSkin.cpp b/src/gui/guiSkin.cpp index 8892a00b4..e09209bd9 100644 --- a/src/gui/guiSkin.cpp +++ b/src/gui/guiSkin.cpp @@ -29,7 +29,7 @@ GUISkin::GUISkin(EGUI_SKIN_TYPE type, video::IVideoDriver* driver) { Colors[EGDC_3D_DARK_SHADOW] = video::SColor(101,50,50,50); Colors[EGDC_3D_SHADOW] = video::SColor(101,130,130,130); - Colors[EGDC_3D_FACE] = video::SColor(101,210,210,210); + Colors[EGDC_3D_FACE] = video::SColor(220,100,100,100); Colors[EGDC_3D_HIGH_LIGHT] = video::SColor(101,255,255,255); Colors[EGDC_3D_LIGHT] = video::SColor(101,210,210,210); Colors[EGDC_ACTIVE_BORDER] = video::SColor(101,16,14,115); -- cgit v1.2.3 From f27cf4777933f06f85fa2f013d56ca0a2cf1d588 Mon Sep 17 00:00:00 2001 From: Desour Date: Sun, 23 Aug 2020 19:44:25 +0200 Subject: Properly handle mod-errors in on_shutdown --- src/client/game.cpp | 3 ++- src/server.cpp | 17 +++++++++++++++-- src/server.h | 7 ++++++- 3 files changed, 23 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/client/game.cpp b/src/client/game.cpp index 0d3a0ca15..920383aaf 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -1300,7 +1300,8 @@ bool Game::createSingleplayerServer(const std::string &map_dir, return false; } - server = new Server(map_dir, gamespec, simple_singleplayer_mode, bind_addr, false); + server = new Server(map_dir, gamespec, simple_singleplayer_mode, bind_addr, + false, nullptr, error_message); server->start(); return true; diff --git a/src/server.cpp b/src/server.cpp index ef36aedca..7b3978462 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -213,7 +213,8 @@ Server::Server( bool simple_singleplayer_mode, Address bind_addr, bool dedicated, - ChatInterface *iface + ChatInterface *iface, + std::string *on_shutdown_errmsg ): m_bind_addr(bind_addr), m_path_world(path_world), @@ -232,6 +233,7 @@ Server::Server( m_thread(new ServerThread(this)), m_clients(m_con), m_admin_chat(iface), + m_on_shutdown_errmsg(on_shutdown_errmsg), m_modchannel_mgr(new ModChannelMgr()) { if (m_path_world.empty()) @@ -314,7 +316,18 @@ Server::~Server() // Execute script shutdown hooks infostream << "Executing shutdown hooks" << std::endl; - m_script->on_shutdown(); + try { + m_script->on_shutdown(); + } catch (ModError &e) { + errorstream << "ModError: " << e.what() << std::endl; + if (m_on_shutdown_errmsg) { + if (m_on_shutdown_errmsg->empty()) { + *m_on_shutdown_errmsg = std::string("ModError: ") + e.what(); + } else { + *m_on_shutdown_errmsg += std::string("\nModError: ") + e.what(); + } + } + } infostream << "Server: Saving environment metadata" << std::endl; m_env->saveMeta(); diff --git a/src/server.h b/src/server.h index f44716531..be6f60abc 100644 --- a/src/server.h +++ b/src/server.h @@ -131,7 +131,8 @@ public: bool simple_singleplayer_mode, Address bind_addr, bool dedicated, - ChatInterface *iface = nullptr + ChatInterface *iface = nullptr, + std::string *on_shutdown_errmsg = nullptr ); ~Server(); DISABLE_CLASS_COPY(Server); @@ -596,6 +597,10 @@ private: ChatInterface *m_admin_chat; std::string m_admin_nick; + // if a mod-error occurs in the on_shutdown callback, the error message will + // be written into this + std::string *const m_on_shutdown_errmsg; + /* Map edit event queue. Automatically receives all map edits. The constructor of this class registers us to receive them through -- cgit v1.2.3 From 44c98089cf923fda924902bceec4edb01f36ce2c Mon Sep 17 00:00:00 2001 From: mntmn Date: Tue, 25 Aug 2020 20:49:51 +0200 Subject: shaders: Fix transparency on GC7000L (#10036) Workaround for the missing GL_ALPHA_TEST implementation in Mesa (etnaviv driver). --- client/shaders/nodes_shader/opengl_fragment.glsl | 8 ++++++++ client/shaders/object_shader/opengl_fragment.glsl | 8 ++++++++ src/client/shader.cpp | 18 ++++++++++++++++++ 3 files changed, 34 insertions(+) (limited to 'src') diff --git a/client/shaders/nodes_shader/opengl_fragment.glsl b/client/shaders/nodes_shader/opengl_fragment.glsl index 19e6c2d86..7213612bd 100644 --- a/client/shaders/nodes_shader/opengl_fragment.glsl +++ b/client/shaders/nodes_shader/opengl_fragment.glsl @@ -190,6 +190,14 @@ void main(void) #endif vec4 base = texture2D(baseTexture, uv).rgba; +#ifdef USE_DISCARD + // If alpha is zero, we can just discard the pixel. This fixes transparency + // on GPUs like GC7000L, where GL_ALPHA_TEST is not implemented in mesa. + if (base.a == 0.0) { + discard; + } +#endif + #ifdef ENABLE_BUMPMAPPING if (use_normalmap) { vec3 L = normalize(lightVec); diff --git a/client/shaders/object_shader/opengl_fragment.glsl b/client/shaders/object_shader/opengl_fragment.glsl index 0534dc049..2d33ca439 100644 --- a/client/shaders/object_shader/opengl_fragment.glsl +++ b/client/shaders/object_shader/opengl_fragment.glsl @@ -129,6 +129,14 @@ void main(void) vec4 base = texture2D(baseTexture, uv).rgba; +#ifdef USE_DISCARD + // If alpha is zero, we can just discard the pixel. This fixes transparency + // on GPUs like GC7000L, where GL_ALPHA_TEST is not implemented in mesa. + if (base.a == 0.0) { + discard; + } +#endif + #ifdef ENABLE_BUMPMAPPING if (use_normalmap) { vec3 L = normalize(lightVec); diff --git a/src/client/shader.cpp b/src/client/shader.cpp index ee6079f7a..0aba7b118 100644 --- a/src/client/shader.cpp +++ b/src/client/shader.cpp @@ -38,6 +38,16 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "gamedef.h" #include "client/tile.h" +#if ENABLE_GLES +#ifdef _IRR_COMPILE_WITH_OGLES1_ +#include +#else +#include +#endif +#else +#include +#endif + /* A cache from shader name to shader path */ @@ -607,6 +617,14 @@ ShaderInfo generate_shader(const std::string &name, u8 material_type, u8 drawtyp // Create shaders header std::string shaders_header = "#version 120\n"; +#ifdef __unix__ + // For renderers that should use discard instead of GL_ALPHA_TEST + const char* gl_renderer = (const char*)glGetString(GL_RENDERER); + if (strstr(gl_renderer, "GC7000")) { + shaders_header += "#define USE_DISCARD\n"; + } +#endif + static const char* drawTypes[] = { "NDT_NORMAL", "NDT_AIRLIKE", -- cgit v1.2.3 From b262184acf34896f36b4270aba29546fc5b0e65b Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Tue, 25 Aug 2020 19:50:41 +0100 Subject: NetBSD build fix proposal. (#10308) Fixing thread naming call and let the class setting RANDOM_MIN/RANDOM_MAX. --- src/noise.h | 7 +++++++ src/threading/thread.cpp | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/noise.h b/src/noise.h index 7b5e83251..613879890 100644 --- a/src/noise.h +++ b/src/noise.h @@ -29,6 +29,13 @@ #include "exceptions.h" #include "util/string.h" +#if defined(RANDOM_MIN) +#undef RANDOM_MIN +#endif +#if defined(RANDOM_MAX) +#undef RANDOM_MAX +#endif + extern FlagDesc flagdesc_noiseparams[]; // Note: this class is not polymorphic so that its high level of diff --git a/src/threading/thread.cpp b/src/threading/thread.cpp index f678a09be..eb51516c6 100644 --- a/src/threading/thread.cpp +++ b/src/threading/thread.cpp @@ -219,7 +219,7 @@ void Thread::setName(const std::string &name) #elif defined(__NetBSD__) - pthread_setname_np(pthread_self(), name.c_str()); + pthread_setname_np(pthread_self(), "%s", const_cast(name.c_str())); #elif defined(__APPLE__) -- cgit v1.2.3 From 788f29759565f1eb35fb2189a79a6b2a41e1eb73 Mon Sep 17 00:00:00 2001 From: Maksim Date: Thu, 27 Aug 2020 21:46:57 +0200 Subject: Android: drop simple MainMenu (#10227) The default (PC-style) MainMenu works great on Android. Provides access to ContentDB and allows players to create many worlds in a few clicks. Makes the interface consistent and eliminates player confusion. --- builtin/mainmenu/init.lua | 102 +++++----------- builtin/mainmenu/tab_settings.lua | 67 +---------- builtin/mainmenu/tab_simple_main.lua | 220 ----------------------------------- builtin/settingtypes.txt | 6 - src/defaultsettings.cpp | 1 - 5 files changed, 33 insertions(+), 363 deletions(-) delete mode 100644 builtin/mainmenu/tab_simple_main.lua (limited to 'src') diff --git a/builtin/mainmenu/init.lua b/builtin/mainmenu/init.lua index c17e79270..96d02d06c 100644 --- a/builtin/mainmenu/init.lua +++ b/builtin/mainmenu/init.lua @@ -22,7 +22,6 @@ mt_color_dark_green = "#25C191" local menupath = core.get_mainmenu_path() local basepath = core.get_builtin_path() -local menustyle = core.settings:get("main_menu_style") defaulttexturedir = core.get_texturepath_share() .. DIR_DELIM .. "base" .. DIR_DELIM .. "pack" .. DIR_DELIM @@ -39,24 +38,18 @@ dofile(menupath .. DIR_DELIM .. "textures.lua") dofile(menupath .. DIR_DELIM .. "dlg_config_world.lua") dofile(menupath .. DIR_DELIM .. "dlg_settings_advanced.lua") dofile(menupath .. DIR_DELIM .. "dlg_contentstore.lua") -if menustyle ~= "simple" then - dofile(menupath .. DIR_DELIM .. "dlg_create_world.lua") - dofile(menupath .. DIR_DELIM .. "dlg_delete_content.lua") - dofile(menupath .. DIR_DELIM .. "dlg_delete_world.lua") - dofile(menupath .. DIR_DELIM .. "dlg_rename_modpack.lua") -end +dofile(menupath .. DIR_DELIM .. "dlg_create_world.lua") +dofile(menupath .. DIR_DELIM .. "dlg_delete_content.lua") +dofile(menupath .. DIR_DELIM .. "dlg_delete_world.lua") +dofile(menupath .. DIR_DELIM .. "dlg_rename_modpack.lua") local tabs = {} tabs.settings = dofile(menupath .. DIR_DELIM .. "tab_settings.lua") tabs.content = dofile(menupath .. DIR_DELIM .. "tab_content.lua") tabs.credits = dofile(menupath .. DIR_DELIM .. "tab_credits.lua") -if menustyle == "simple" then - tabs.simple_main = dofile(menupath .. DIR_DELIM .. "tab_simple_main.lua") -else - tabs.local_game = dofile(menupath .. DIR_DELIM .. "tab_local.lua") - tabs.play_online = dofile(menupath .. DIR_DELIM .. "tab_online.lua") -end +tabs.local_game = dofile(menupath .. DIR_DELIM .. "tab_local.lua") +tabs.play_online = dofile(menupath .. DIR_DELIM .. "tab_online.lua") -------------------------------------------------------------------------------- local function main_event_handler(tabview, event) @@ -71,68 +64,35 @@ local function init_globals() -- Init gamedata gamedata.worldindex = 0 - if menustyle == "simple" then - local world_list = core.get_worlds() - local world_index - - local found_singleplayerworld = false - for i, world in ipairs(world_list) do - if world.name == "singleplayerworld" then - found_singleplayerworld = true - world_index = i - break - end - end - - if not found_singleplayerworld then - core.create_world("singleplayerworld", 1) - - world_list = core.get_worlds() - - for i, world in ipairs(world_list) do - if world.name == "singleplayerworld" then - world_index = i - break - end - end + menudata.worldlist = filterlist.create( + core.get_worlds, + compare_worlds, + -- Unique id comparison function + function(element, uid) + return element.name == uid + end, + -- Filter function + function(element, gameid) + return element.gameid == gameid end + ) - gamedata.worldindex = world_index - else - menudata.worldlist = filterlist.create( - core.get_worlds, - compare_worlds, - -- Unique id comparison function - function(element, uid) - return element.name == uid - end, - -- Filter function - function(element, gameid) - return element.gameid == gameid - end - ) - - menudata.worldlist:add_sort_mechanism("alphabetic", sort_worlds_alphabetic) - menudata.worldlist:set_sortmode("alphabetic") - - if not core.settings:get("menu_last_game") then - local default_game = core.settings:get("default_game") or "minetest" - core.settings:set("menu_last_game", default_game) - end + menudata.worldlist:add_sort_mechanism("alphabetic", sort_worlds_alphabetic) + menudata.worldlist:set_sortmode("alphabetic") - mm_texture.init() + if not core.settings:get("menu_last_game") then + local default_game = core.settings:get("default_game") or "minetest" + core.settings:set("menu_last_game", default_game) end + mm_texture.init() + -- Create main tabview local tv_main = tabview_create("maintab", {x = 12, y = 5.4}, {x = 0, y = 0}) - if menustyle == "simple" then - tv_main:add(tabs.simple_main) - else - tv_main:set_autosave_tab(true) - tv_main:add(tabs.local_game) - tv_main:add(tabs.play_online) - end + tv_main:set_autosave_tab(true) + tv_main:add(tabs.local_game) + tv_main:add(tabs.play_online) tv_main:add(tabs.content) tv_main:add(tabs.settings) @@ -141,11 +101,9 @@ local function init_globals() tv_main:set_global_event_handler(main_event_handler) tv_main:set_fixed_size(false) - if menustyle ~= "simple" then - local last_tab = core.settings:get("maintab_LAST") - if last_tab and tv_main.current_tab ~= last_tab then - tv_main:set_tab(last_tab) - end + local last_tab = core.settings:get("maintab_LAST") + if last_tab and tv_main.current_tab ~= last_tab then + tv_main:set_tab(last_tab) end ui.set_default("maintab") tv_main:show() diff --git a/builtin/mainmenu/tab_settings.lua b/builtin/mainmenu/tab_settings.lua index 1e5264904..02b15c81b 100644 --- a/builtin/mainmenu/tab_settings.lua +++ b/builtin/mainmenu/tab_settings.lua @@ -122,56 +122,6 @@ local function antialiasing_fname_to_name(fname) return 0 end -local function dlg_confirm_reset_formspec(data) - return "size[8,3]" .. - "label[1,1;" .. fgettext("Are you sure to reset your singleplayer world?") .. "]" .. - "button[1,2;2.6,0.5;dlg_reset_singleplayer_confirm;" .. fgettext("Yes") .. "]" .. - "button[4,2;2.8,0.5;dlg_reset_singleplayer_cancel;" .. fgettext("No") .. "]" -end - -local function dlg_confirm_reset_btnhandler(this, fields, dialogdata) - - if fields["dlg_reset_singleplayer_confirm"] ~= nil then - local worldlist = core.get_worlds() - local found_singleplayerworld = false - - for i = 1, #worldlist do - if worldlist[i].name == "singleplayerworld" then - found_singleplayerworld = true - gamedata.worldindex = i - end - end - - if found_singleplayerworld then - core.delete_world(gamedata.worldindex) - end - - core.create_world("singleplayerworld", 1) - worldlist = core.get_worlds() - - for i = 1, #worldlist do - if worldlist[i].name == "singleplayerworld" then - gamedata.worldindex = i - end - end - end - - this.parent:show() - this:hide() - this:delete() - return true -end - -local function showconfirm_reset(tabview) - local new_dlg = dialog_create("reset_spworld", - dlg_confirm_reset_formspec, - dlg_confirm_reset_btnhandler, - nil) - new_dlg:set_parent(tabview) - tabview:hide() - new_dlg:show() -end - local function formspec(tabview, name, tabdata) local tab_string = "box[0,0;3.75,4.5;#999999]" .. @@ -218,16 +168,9 @@ local function formspec(tabview, name, tabdata) fgettext("Shaders (unavailable)")) .. "]" end - if core.settings:get("main_menu_style") == "simple" then - -- 'Reset singleplayer world' only functions with simple menu - tab_string = tab_string .. - "button[8,4.75;3.95,1;btn_reset_singleplayer;" - .. fgettext("Reset singleplayer world") .. "]" - else - tab_string = tab_string .. - "button[8,4.75;3.95,1;btn_change_keys;" - .. fgettext("Change Keys") .. "]" - end + tab_string = tab_string .. + "button[8,4.75;3.95,1;btn_change_keys;" + .. fgettext("Change Keys") .. "]" tab_string = tab_string .. "button[0,4.75;3.95,1;btn_advanced_settings;" @@ -359,10 +302,6 @@ local function handle_settings_buttons(this, fields, tabname, tabdata) core.settings:set("touchtarget", fields["cb_touchscreen_target"]) return true end - if fields["btn_reset_singleplayer"] then - showconfirm_reset(this) - return true - end --Note dropdowns have to be handled LAST! local ddhandled = false diff --git a/builtin/mainmenu/tab_simple_main.lua b/builtin/mainmenu/tab_simple_main.lua deleted file mode 100644 index 7ec95158a..000000000 --- a/builtin/mainmenu/tab_simple_main.lua +++ /dev/null @@ -1,220 +0,0 @@ ---Minetest ---Copyright (C) 2013 sapier --- ---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. - --------------------------------------------------------------------------------- -local function get_formspec(tabview, name, tabdata) - -- Update the cached supported proto info, - -- it may have changed after a change by the settings menu. - common_update_cached_supp_proto() - local fav_selected = menudata.favorites[tabdata.fav_selected] - - local retval = - "label[9.5,0;".. fgettext("Name / Password") .. "]" .. - "field[0.25,3.35;5.5,0.5;te_address;;" .. - core.formspec_escape(core.settings:get("address")) .."]" .. - "field[5.75,3.35;2.25,0.5;te_port;;" .. - core.formspec_escape(core.settings:get("remote_port")) .."]" .. - "button[10,2.6;2,1.5;btn_mp_connect;".. fgettext("Connect") .. "]" .. - "field[9.8,1;2.6,0.5;te_name;;" .. - core.formspec_escape(core.settings:get("name")) .."]" .. - "pwdfield[9.8,2;2.6,0.5;te_pwd;]" - - - if tabdata.fav_selected and fav_selected then - if gamedata.fav then - retval = retval .. "button[7.7,2.6;2.3,1.5;btn_delete_favorite;" .. - fgettext("Del. Favorite") .. "]" - end - end - - retval = retval .. "tablecolumns[" .. - image_column(fgettext("Favorite"), "favorite") .. ";" .. - image_column(fgettext("Ping"), "") .. ",padding=0.25;" .. - "color,span=3;" .. - "text,align=right;" .. -- clients - "text,align=center,padding=0.25;" .. -- "/" - "text,align=right,padding=0.25;" .. -- clients_max - image_column(fgettext("Creative mode"), "creative") .. ",padding=1;" .. - image_column(fgettext("Damage enabled"), "damage") .. ",padding=0.25;" .. - image_column(fgettext("PvP enabled"), "pvp") .. ",padding=0.25;" .. - "color,span=1;" .. - "text,padding=1]" .. -- name - "table[-0.05,0;9.2,2.75;favourites;" - - if #menudata.favorites > 0 then - local favs = core.get_favorites("local") - if #favs > 0 then - for i = 1, #favs do - for j = 1, #menudata.favorites do - if menudata.favorites[j].address == favs[i].address and - menudata.favorites[j].port == favs[i].port then - table.insert(menudata.favorites, i, - table.remove(menudata.favorites, j)) - end - end - if favs[i].address ~= menudata.favorites[i].address then - table.insert(menudata.favorites, i, favs[i]) - end - end - end - retval = retval .. render_serverlist_row(menudata.favorites[1], (#favs > 0)) - for i = 2, #menudata.favorites do - retval = retval .. "," .. render_serverlist_row(menudata.favorites[i], (i <= #favs)) - end - end - - if tabdata.fav_selected then - retval = retval .. ";" .. tabdata.fav_selected .. "]" - else - retval = retval .. ";0]" - end - - -- separator - retval = retval .. "box[-0.28,3.75;12.4,0.1;#FFFFFF]" - - -- checkboxes - retval = retval .. - "checkbox[8.0,3.9;cb_creative;".. fgettext("Creative Mode") .. ";" .. - dump(core.settings:get_bool("creative_mode")) .. "]".. - "checkbox[8.0,4.4;cb_damage;".. fgettext("Enable Damage") .. ";" .. - dump(core.settings:get_bool("enable_damage")) .. "]" - -- buttons - retval = retval .. - "button[0,3.7;8,1.5;btn_start_singleplayer;" .. fgettext("Start Singleplayer") .. "]" .. - "button[0,4.5;8,1.5;btn_config_sp_world;" .. fgettext("Config mods") .. "]" - - return retval -end - --------------------------------------------------------------------------------- -local function main_button_handler(tabview, fields, name, tabdata) - if fields.btn_start_singleplayer then - gamedata.selected_world = gamedata.worldindex - gamedata.singleplayer = true - core.start() - return true - end - - if fields.favourites then - local event = core.explode_table_event(fields.favourites) - if event.type == "CHG" then - if event.row <= #menudata.favorites then - gamedata.fav = false - local favs = core.get_favorites("local") - local fav = menudata.favorites[event.row] - local address = fav.address - local port = fav.port - gamedata.serverdescription = fav.description - - for i = 1, #favs do - if fav.address == favs[i].address and - fav.port == favs[i].port then - gamedata.fav = true - end - end - - if address and port then - core.settings:set("address", address) - core.settings:set("remote_port", port) - end - tabdata.fav_selected = event.row - end - return true - end - end - - if fields.btn_delete_favorite then - local current_favourite = core.get_table_index("favourites") - if not current_favourite then return end - - core.delete_favorite(current_favourite) - asyncOnlineFavourites() - tabdata.fav_selected = nil - - core.settings:set("address", "") - core.settings:set("remote_port", "30000") - return true - end - - if fields.cb_creative then - core.settings:set("creative_mode", fields.cb_creative) - return true - end - - if fields.cb_damage then - core.settings:set("enable_damage", fields.cb_damage) - return true - end - - if fields.btn_mp_connect or fields.key_enter then - gamedata.playername = fields.te_name - gamedata.password = fields.te_pwd - gamedata.address = fields.te_address - gamedata.port = fields.te_port - local fav_idx = core.get_textlist_index("favourites") - - if fav_idx and fav_idx <= #menudata.favorites and - menudata.favorites[fav_idx].address == fields.te_address and - menudata.favorites[fav_idx].port == fields.te_port then - local fav = menudata.favorites[fav_idx] - gamedata.servername = fav.name - gamedata.serverdescription = fav.description - - if menudata.favorites_is_public and - not is_server_protocol_compat_or_error( - fav.proto_min, fav.proto_max) then - return true - end - else - gamedata.servername = "" - gamedata.serverdescription = "" - end - - gamedata.selected_world = 0 - - core.settings:set("address", fields.te_address) - core.settings:set("remote_port", fields.te_port) - - core.start() - return true - end - - if fields.btn_config_sp_world then - local configdialog = create_configure_world_dlg(1) - if configdialog then - configdialog:set_parent(tabview) - tabview:hide() - configdialog:show() - end - return true - end -end - --------------------------------------------------------------------------------- -local function on_activate(type,old_tab,new_tab) - if type == "LEAVE" then return end - asyncOnlineFavourites() -end - --------------------------------------------------------------------------------- -return { - name = "main", - caption = fgettext("Main"), - cbf_formspec = get_formspec, - cbf_button_handler = main_button_handler, - on_change = on_activate -} diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index af4dc1def..ef56f99bf 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -1446,12 +1446,6 @@ curl_file_download_timeout (cURL file download timeout) int 300000 # Makes DirectX work with LuaJIT. Disable if it causes troubles. high_precision_fpu (High-precision FPU) bool true -# Changes the main menu UI: -# - Full: Multiple singleplayer worlds, game choice, texture pack chooser, etc. -# - Simple: One singleplayer world, no game or texture pack choosers. May be -# necessary for smaller screens. -main_menu_style (Main menu style) enum full full,simple - # Replaces the default main menu with a custom one. main_menu_script (Main menu script) string diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 87c272630..c93af9506 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -290,7 +290,6 @@ void set_default_settings(Settings *settings) settings->setDefault("joystick_frustum_sensitivity", "170"); // Main menu - settings->setDefault("main_menu_style", "full"); settings->setDefault("main_menu_path", ""); settings->setDefault("serverlist_file", "favoriteservers.txt"); -- cgit v1.2.3 From d052593c7ab3c57f83ea250fc10f7c1927962c09 Mon Sep 17 00:00:00 2001 From: karamel59 Date: Thu, 27 Aug 2020 21:47:38 +0200 Subject: Lua API: Register missing get_texture_mod function (#10338) --- src/script/lua_api/l_object.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index 495d8bced..24667e769 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -2299,6 +2299,7 @@ luaL_Reg ObjectRef::methods[] = { luamethod(ObjectRef, set_rotation), luamethod(ObjectRef, get_rotation), luamethod_aliased(ObjectRef, set_texture_mod, settexturemod), + luamethod(ObjectRef, get_texture_mod), luamethod_aliased(ObjectRef, set_sprite, setsprite), luamethod(ObjectRef, get_entity_name), luamethod(ObjectRef, get_luaentity), -- cgit v1.2.3 From d28f1b01707dfa15e770096a26495452513bc56f Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Sat, 29 Aug 2020 00:14:38 +0200 Subject: Mapgen: Fix on-by-default flags broken since eca6ee9 (#10318) --- src/map_settings_manager.cpp | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/map_settings_manager.cpp b/src/map_settings_manager.cpp index 4f070e910..9c447b3d0 100644 --- a/src/map_settings_manager.cpp +++ b/src/map_settings_manager.cpp @@ -32,6 +32,10 @@ MapSettingsManager::MapSettingsManager(Settings *user_settings, m_user_settings(user_settings) { assert(m_user_settings != NULL); + + Mapgen::setDefaultSettings(m_map_settings); + // This inherits the combined defaults provided by loadGameConfAndInitWorld. + m_map_settings->overrideDefaults(user_settings); } @@ -179,20 +183,8 @@ MapgenParams *MapSettingsManager::makeMapgenParams() params->mgtype = mgtype; - // Load the mapgen param defaults - /* FIXME: Why is it done like this? MapgenParams should just - * set the defaults in its constructor instead. */ - { - Settings default_settings; - Mapgen::setDefaultSettings(&default_settings); - params->MapgenParams::readParams(&default_settings); - params->readParams(&default_settings); - } - // Load the rest of the mapgen params from our active settings - params->MapgenParams::readParams(m_user_settings); params->MapgenParams::readParams(m_map_settings); - params->readParams(m_user_settings); params->readParams(m_map_settings); // Hold onto our params -- cgit v1.2.3 From 3693b6871eba268ecc79b3f52d00d3cefe761131 Mon Sep 17 00:00:00 2001 From: Lars Müller <34514239+appgurueu@users.noreply.github.com> Date: Sat, 29 Aug 2020 17:41:03 +0200 Subject: Prevent players accessing inventories of other players (#10341) --- src/network/serverpackethandler.cpp | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/network/serverpackethandler.cpp b/src/network/serverpackethandler.cpp index dcbb114bf..abd9deff0 100644 --- a/src/network/serverpackethandler.cpp +++ b/src/network/serverpackethandler.cpp @@ -630,13 +630,19 @@ void Server::handleCommand_InventoryAction(NetworkPacket* pkt) if (ma->from_inv != ma->to_inv) m_inventory_mgr->setInventoryModified(ma->to_inv); - bool from_inv_is_current_player = - (ma->from_inv.type == InventoryLocation::PLAYER) && - (ma->from_inv.name == player->getName()); - - bool to_inv_is_current_player = - (ma->to_inv.type == InventoryLocation::PLAYER) && - (ma->to_inv.name == player->getName()); + bool from_inv_is_current_player = false; + if (ma->from_inv.type == InventoryLocation::PLAYER) { + if (ma->from_inv.name != player->getName()) + return; + from_inv_is_current_player = true; + } + + bool to_inv_is_current_player = false; + if (ma->to_inv.type == InventoryLocation::PLAYER) { + if (ma->to_inv.name != player->getName()) + return; + to_inv_is_current_player = true; + } InventoryLocation *remote = from_inv_is_current_player ? &ma->to_inv : &ma->from_inv; -- cgit v1.2.3 From 9976f36b18b8d227e3240feb24000dda0916ee44 Mon Sep 17 00:00:00 2001 From: Hugues Ross Date: Sat, 29 Aug 2020 11:41:19 -0400 Subject: Make bgcolor tint button background images (#9818) --- games/devtest/mods/testformspec/formspec.lua | 2 +- src/client/guiscalingfilter.cpp | 5 +---- src/client/guiscalingfilter.h | 3 ++- src/gui/guiButton.cpp | 21 ++++++++++++++------- src/gui/guiButton.h | 1 + 5 files changed, 19 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/games/devtest/mods/testformspec/formspec.lua b/games/devtest/mods/testformspec/formspec.lua index 08c1b6dc0..87a05fc96 100644 --- a/games/devtest/mods/testformspec/formspec.lua +++ b/games/devtest/mods/testformspec/formspec.lua @@ -164,7 +164,7 @@ local style_fs = [[ style[one_btn14:hovered+pressed;textcolor=purple] image_button[0,9.6;1,1;testformspec_button_image.png;one_btn14;Bg] - style[one_btn15;border=false;bgimg=testformspec_bg.png;bgimg_hovered=testformspec_bg_hovered.png;bgimg_pressed=testformspec_bg_pressed.png] + style[one_btn15;border=false;bgcolor=#1cc;bgimg=testformspec_bg.png;bgimg_hovered=testformspec_bg_hovered.png;bgimg_pressed=testformspec_bg_pressed.png] item_image_button[1.25,9.6;1,1;testformspec:item;one_btn15;Bg] style[one_btn16;border=false;bgimg=testformspec_bg_9slice.png;bgimg_hovered=testformspec_bg_9slice_hovered.png;bgimg_pressed=testformspec_bg_9slice_pressed.png;bgimg_middle=4,6] diff --git a/src/client/guiscalingfilter.cpp b/src/client/guiscalingfilter.cpp index 4262331bd..406c096e6 100644 --- a/src/client/guiscalingfilter.cpp +++ b/src/client/guiscalingfilter.cpp @@ -172,11 +172,8 @@ void draw2DImageFilterScaled(video::IVideoDriver *driver, video::ITexture *txr, void draw2DImage9Slice(video::IVideoDriver *driver, video::ITexture *texture, const core::rect &rect, const core::rect &middle, - const core::rect *cliprect) + const core::rect *cliprect, const video::SColor *const colors) { - const video::SColor color(255,255,255,255); - const video::SColor colors[] = {color,color,color,color}; - auto originalSize = texture->getOriginalSize(); core::vector2di lowerRightOffset = core::vector2di(originalSize.Width, originalSize.Height) - middle.LowerRightCorner; diff --git a/src/client/guiscalingfilter.h b/src/client/guiscalingfilter.h index b703d91f0..379a4bdb0 100644 --- a/src/client/guiscalingfilter.h +++ b/src/client/guiscalingfilter.h @@ -54,4 +54,5 @@ void draw2DImageFilterScaled(video::IVideoDriver *driver, video::ITexture *txr, */ void draw2DImage9Slice(video::IVideoDriver *driver, video::ITexture *texture, const core::rect &rect, const core::rect &middle, - const core::rect *cliprect = nullptr); + const core::rect *cliprect = nullptr, + const video::SColor *const colors = nullptr); diff --git a/src/gui/guiButton.cpp b/src/gui/guiButton.cpp index e0d6337cd..b98e5de82 100644 --- a/src/gui/guiButton.cpp +++ b/src/gui/guiButton.cpp @@ -313,11 +313,12 @@ void GUIButton::draw() // PATCH video::ITexture* texture = ButtonImages[(u32)imageState].Texture; + video::SColor image_colors[] = { BgColor, BgColor, BgColor, BgColor }; if (BgMiddle.getArea() == 0) { driver->draw2DImage(texture, ScaleImage? AbsoluteRect : core::rect(pos, sourceRect.getSize()), sourceRect, &AbsoluteClippingRect, - 0, UseAlphaChannel); + image_colors, UseAlphaChannel); } else { core::rect middle = BgMiddle; // `-x` is interpreted as `w - x` @@ -327,7 +328,7 @@ void GUIButton::draw() middle.LowerRightCorner.Y += texture->getOriginalSize().Height; draw2DImage9Slice(driver, texture, ScaleImage ? AbsoluteRect : core::rect(pos, sourceRect.getSize()), - middle, &AbsoluteClippingRect); + middle, &AbsoluteClippingRect, image_colors); } // END PATCH } @@ -722,6 +723,8 @@ GUIButton* GUIButton::addButton(IGUIEnvironment *environment, void GUIButton::setColor(video::SColor color) { + BgColor = color; + float d = 0.65f; for (size_t i = 0; i < 4; i++) { video::SColor base = Environment->getSkin()->getColor((gui::EGUI_DEFAULT_COLOR)i); @@ -750,22 +753,26 @@ void GUIButton::setFromStyle(const StyleSpec& style) bool pressed = (style.getState() & StyleSpec::STATE_PRESSED) != 0; if (style.isNotDefault(StyleSpec::BGCOLOR)) { - setColor(style.getColor(StyleSpec::BGCOLOR)); // If we have a propagated hover/press color, we need to automatically // lighten/darken it if (!Styles[style.getState()].isNotDefault(StyleSpec::BGCOLOR)) { - for (size_t i = 0; i < 4; i++) { if (pressed) { - Colors[i] = multiplyColorValue(Colors[i], COLOR_PRESSED_MOD); + BgColor = multiplyColorValue(BgColor, COLOR_PRESSED_MOD); + + for (size_t i = 0; i < 4; i++) + Colors[i] = multiplyColorValue(Colors[i], COLOR_PRESSED_MOD); } else if (hovered) { - Colors[i] = multiplyColorValue(Colors[i], COLOR_HOVERED_MOD); + BgColor = multiplyColorValue(BgColor, COLOR_HOVERED_MOD); + + for (size_t i = 0; i < 4; i++) + Colors[i] = multiplyColorValue(Colors[i], COLOR_HOVERED_MOD); } - } } } else { + BgColor = video::SColor(255, 255, 255, 255); for (size_t i = 0; i < 4; i++) { video::SColor base = Environment->getSkin()->getColor((gui::EGUI_DEFAULT_COLOR)i); diff --git a/src/gui/guiButton.h b/src/gui/guiButton.h index 95fa1a2a1..4e1b04aac 100644 --- a/src/gui/guiButton.h +++ b/src/gui/guiButton.h @@ -338,5 +338,6 @@ private: core::rect BgMiddle; core::rect Padding; core::vector2d ContentOffset; + video::SColor BgColor; // END PATCH }; -- cgit v1.2.3 From 5c4b560b6812bbdf7a9d3202c95bad5c9df97d66 Mon Sep 17 00:00:00 2001 From: EvidenceB <49488517+EvidenceBKidscode@users.noreply.github.com> Date: Sat, 29 Aug 2020 20:13:30 +0200 Subject: Add compass HUD element (#9312) Co-authored-by: Jean-Patrick Guerrero Co-authored-by: Pierre-Yves Rollo Co-authored-by: SmallJoker --- doc/lua_api.txt | 18 ++++++- src/client/hud.cpp | 140 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/client/hud.h | 8 +++ src/hud.cpp | 1 + src/hud.h | 10 +++- 5 files changed, 175 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 08bdba03e..c81824163 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -1451,7 +1451,23 @@ Same as `image`, but does not accept a `position`; the position is instead deter * `world_pos`: World position of the waypoint. * `offset`: offset in pixels from position. +### `compass` +Displays an image oriented or translated according to current heading direction. + +* `size`: The size of this element. Negative values represent percentage + of the screen; e.g. `x=-100` means 100% (width). +* `scale`: Scale of the translated image (used only for dir = 2 or dir = 3). +* `text`: The name of the texture to use. +* `alignment`: The alignment of the image. +* `offset`: Offset in pixels from position. +* `dir`: How the image is rotated/translated: + * 0 - Rotate as heading direction + * 1 - Rotate in reverse direction + * 2 - Translate as landscape direction + * 3 - Translate in reverse direction + +If translation is chosen, texture is repeated horizontally to fill the whole element. Representations of simple things ================================ @@ -7968,7 +7984,7 @@ Used by `Player:hud_add`. Returned by `Player:hud_get`. { hud_elem_type = "image", -- See HUD element types - -- Type of element, can be "image", "text", "statbar", or "inventory" + -- Type of element, can be "image", "text", "statbar", "inventory" or "compass" position = {x=0.5, y=0.5}, -- Left corner position of element diff --git a/src/client/hud.cpp b/src/client/hud.cpp index 2b347c1e0..d3038230c 100644 --- a/src/client/hud.cpp +++ b/src/client/hud.cpp @@ -114,6 +114,28 @@ Hud::Hud(gui::IGUIEnvironment *guienv, Client *client, LocalPlayer *player, } else { m_selection_material.MaterialType = video::EMT_SOLID; } + + // Prepare mesh for compass drawing + m_rotation_mesh_buffer.Vertices.set_used(4); + m_rotation_mesh_buffer.Indices.set_used(6); + + video::SColor white(255, 255, 255, 255); + v3f normal(0.f, 0.f, 1.f); + + m_rotation_mesh_buffer.Vertices[0] = video::S3DVertex(v3f(-1.f, -1.f, 0.f), normal, white, v2f(0.f, 1.f)); + m_rotation_mesh_buffer.Vertices[1] = video::S3DVertex(v3f(-1.f, 1.f, 0.f), normal, white, v2f(0.f, 0.f)); + m_rotation_mesh_buffer.Vertices[2] = video::S3DVertex(v3f( 1.f, 1.f, 0.f), normal, white, v2f(1.f, 0.f)); + m_rotation_mesh_buffer.Vertices[3] = video::S3DVertex(v3f( 1.f, -1.f, 0.f), normal, white, v2f(1.f, 1.f)); + + m_rotation_mesh_buffer.Indices[0] = 0; + m_rotation_mesh_buffer.Indices[1] = 1; + m_rotation_mesh_buffer.Indices[2] = 2; + m_rotation_mesh_buffer.Indices[3] = 2; + m_rotation_mesh_buffer.Indices[4] = 3; + m_rotation_mesh_buffer.Indices[5] = 0; + + m_rotation_mesh_buffer.getMaterial().Lighting = false; + m_rotation_mesh_buffer.getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; } Hud::~Hud() @@ -423,6 +445,54 @@ void Hud::drawLuaElements(const v3s16 &camera_offset) core::rect(core::position2d(0,0), imgsize), NULL, colors, true); break; } + case HUD_ELEM_COMPASS: { + video::ITexture *texture = tsrc->getTexture(e->text); + if (!texture) + continue; + + // Positionning : + v2s32 dstsize(e->size.X, e->size.Y); + if (e->size.X < 0) + dstsize.X = m_screensize.X * (e->size.X * -0.01); + if (e->size.Y < 0) + dstsize.Y = m_screensize.Y * (e->size.Y * -0.01); + + if (dstsize.X <= 0 || dstsize.Y <= 0) + return; // Avoid zero divides + + // Angle according to camera view + v3f fore(0.f, 0.f, 1.f); + scene::ICameraSceneNode *cam = RenderingEngine::get_scene_manager()->getActiveCamera(); + cam->getAbsoluteTransformation().rotateVect(fore); + int angle = - fore.getHorizontalAngle().Y; + + // Limit angle and ajust with given offset + angle = (angle + (int)e->number) % 360; + + core::rect dstrect(0, 0, dstsize.X, dstsize.Y); + dstrect += pos + v2s32( + (e->align.X - 1.0) * dstsize.X / 2, + (e->align.Y - 1.0) * dstsize.Y / 2) + + v2s32(e->offset.X * m_hud_scaling, e->offset.Y * m_hud_scaling); + + switch (e->dir) { + case HUD_COMPASS_ROTATE: + drawCompassRotate(e, texture, dstrect, angle); + break; + case HUD_COMPASS_ROTATE_REVERSE: + drawCompassRotate(e, texture, dstrect, -angle); + break; + case HUD_COMPASS_TRANSLATE: + drawCompassTranslate(e, texture, dstrect, angle); + break; + case HUD_COMPASS_TRANSLATE_REVERSE: + drawCompassTranslate(e, texture, dstrect, -angle); + break; + default: + break; + } + + break; } default: infostream << "Hud::drawLuaElements: ignoring drawform " << e->type << " of hud element ID " << i << " due to unrecognized type" << std::endl; @@ -430,6 +500,76 @@ void Hud::drawLuaElements(const v3s16 &camera_offset) } } +void Hud::drawCompassTranslate(HudElement *e, video::ITexture *texture, + const core::rect &rect, int angle) +{ + const video::SColor color(255, 255, 255, 255); + const video::SColor colors[] = {color, color, color, color}; + + // Compute source image scaling + core::dimension2di imgsize(texture->getOriginalSize()); + core::rect srcrect(0, 0, imgsize.Width, imgsize.Height); + + v2s32 dstsize(rect.getHeight() * e->scale.X * imgsize.Width / imgsize.Height, + rect.getHeight() * e->scale.Y); + + // Avoid infinite loop + if (dstsize.X <= 0 || dstsize.Y <= 0) + return; + + core::rect tgtrect(0, 0, dstsize.X, dstsize.Y); + tgtrect += v2s32( + (rect.getWidth() - dstsize.X) / 2, + (rect.getHeight() - dstsize.Y) / 2) + + rect.UpperLeftCorner; + + int offset = angle * dstsize.X / 360; + + tgtrect += v2s32(offset, 0); + + // Repeat image as much as needed + while (tgtrect.UpperLeftCorner.X > rect.UpperLeftCorner.X) + tgtrect -= v2s32(dstsize.X, 0); + + draw2DImageFilterScaled(driver, texture, tgtrect, srcrect, &rect, colors, true); + tgtrect += v2s32(dstsize.X, 0); + + while (tgtrect.UpperLeftCorner.X < rect.LowerRightCorner.X) { + draw2DImageFilterScaled(driver, texture, tgtrect, srcrect, &rect, colors, true); + tgtrect += v2s32(dstsize.X, 0); + } +} + +void Hud::drawCompassRotate(HudElement *e, video::ITexture *texture, + const core::rect &rect, int angle) +{ + core::dimension2di imgsize(texture->getOriginalSize()); + + core::rect oldViewPort = driver->getViewPort(); + core::matrix4 oldProjMat = driver->getTransform(video::ETS_PROJECTION); + core::matrix4 oldViewMat = driver->getTransform(video::ETS_VIEW); + + core::matrix4 Matrix; + Matrix.makeIdentity(); + Matrix.setRotationDegrees(v3f(0.f, 0.f, angle)); + + driver->setViewPort(rect); + driver->setTransform(video::ETS_PROJECTION, core::matrix4()); + driver->setTransform(video::ETS_VIEW, core::matrix4()); + driver->setTransform(video::ETS_WORLD, Matrix); + + video::SMaterial &material = m_rotation_mesh_buffer.getMaterial(); + material.TextureLayer[0].Texture = texture; + driver->setMaterial(material); + driver->drawMeshBuffer(&m_rotation_mesh_buffer); + + driver->setTransform(video::ETS_WORLD, core::matrix4()); + driver->setTransform(video::ETS_VIEW, oldViewMat); + driver->setTransform(video::ETS_PROJECTION, oldProjMat); + + // restore the view area + driver->setViewPort(oldViewPort); +} void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir, const std::string &texture, const std::string &bgtexture, diff --git a/src/client/hud.h b/src/client/hud.h index ba34d479d..cf83cb16e 100644 --- a/src/client/hud.h +++ b/src/client/hud.h @@ -95,6 +95,12 @@ private: void drawItem(const ItemStack &item, const core::rect &rect, bool selected); + void drawCompassTranslate(HudElement *e, video::ITexture *texture, + const core::rect &rect, int way); + + void drawCompassRotate(HudElement *e, video::ITexture *texture, + const core::rect &rect, int way); + float m_hud_scaling; // cached minetest setting float m_scale_factor; v3s16 m_camera_offset; @@ -115,6 +121,8 @@ private: video::SMaterial m_selection_material; + scene::SMeshBuffer m_rotation_mesh_buffer; + enum { HIGHLIGHT_BOX, diff --git a/src/hud.cpp b/src/hud.cpp index 4830c56a4..175701342 100644 --- a/src/hud.cpp +++ b/src/hud.cpp @@ -28,6 +28,7 @@ const struct EnumString es_HudElementType[] = {HUD_ELEM_INVENTORY, "inventory"}, {HUD_ELEM_WAYPOINT, "waypoint"}, {HUD_ELEM_IMAGE_WAYPOINT, "image_waypoint"}, + {HUD_ELEM_COMPASS, "compass"}, {0, NULL}, }; diff --git a/src/hud.h b/src/hud.h index e015baec1..0a6993c1b 100644 --- a/src/hud.h +++ b/src/hud.h @@ -60,7 +60,8 @@ enum HudElementType { HUD_ELEM_STATBAR = 2, HUD_ELEM_INVENTORY = 3, HUD_ELEM_WAYPOINT = 4, - HUD_ELEM_IMAGE_WAYPOINT = 5 + HUD_ELEM_IMAGE_WAYPOINT = 5, + HUD_ELEM_COMPASS = 6 }; enum HudElementStat { @@ -79,6 +80,13 @@ enum HudElementStat { HUD_STAT_TEXT2, }; +enum HudCompassDir { + HUD_COMPASS_ROTATE = 0, + HUD_COMPASS_ROTATE_REVERSE, + HUD_COMPASS_TRANSLATE, + HUD_COMPASS_TRANSLATE_REVERSE, +}; + struct HudElement { HudElementType type; v2f pos; -- cgit v1.2.3 From f5df70764d560addf747c707c8f9db7f5b0aea4e Mon Sep 17 00:00:00 2001 From: HybridDog <3192173+HybridDog@users.noreply.github.com> Date: Tue, 1 Sep 2020 08:08:18 +0200 Subject: [2] Code cleanup in serverpackethandler (#9349) * Code cleanup in serverpackethandler * do not define p_under unless a node is pointed * use switch-case and reduce indentation --- src/network/serverpackethandler.cpp | 379 +++++++++++++++++------------------- 1 file changed, 180 insertions(+), 199 deletions(-) (limited to 'src') diff --git a/src/network/serverpackethandler.cpp b/src/network/serverpackethandler.cpp index abd9deff0..d133b4ff9 100644 --- a/src/network/serverpackethandler.cpp +++ b/src/network/serverpackethandler.cpp @@ -986,10 +986,6 @@ void Server::handleCommand_Interact(NetworkPacket *pkt) // Update wielded item playersao->getPlayer()->setWieldIndex(item_i); - // Get pointed to node (undefined if not POINTEDTYPE_NODE) - v3s16 p_under = pointed.node_undersurface; - v3s16 p_above = pointed.node_abovesurface; - // Get pointed to object (NULL if not POINTEDTYPE_OBJECT) ServerActiveObject *pointed_object = NULL; if (pointed.type == POINTEDTHING_OBJECT) { @@ -1002,17 +998,6 @@ void Server::handleCommand_Interact(NetworkPacket *pkt) } - v3f pointed_pos_under = player_pos; - v3f pointed_pos_above = player_pos; - if (pointed.type == POINTEDTHING_NODE) { - pointed_pos_under = intToFloat(p_under, BS); - pointed_pos_above = intToFloat(p_above, BS); - } - else if (pointed.type == POINTEDTHING_OBJECT) { - pointed_pos_under = pointed_object->getBasePosition(); - pointed_pos_above = pointed_pos_under; - } - /* Make sure the player is allowed to do it */ @@ -1020,16 +1005,19 @@ void Server::handleCommand_Interact(NetworkPacket *pkt) actionstream << player->getName() << " attempted to interact with " << pointed.dump() << " without 'interact' privilege" << std::endl; + if (pointed.type != POINTEDTHING_NODE) + return; + // Re-send block to revert change on client-side RemoteClient *client = getClient(peer_id); // Digging completed -> under if (action == INTERACT_DIGGING_COMPLETED) { - v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_under, BS)); + v3s16 blockpos = getNodeBlockPos(pointed.node_undersurface); client->SetBlockNotSent(blockpos); } // Placement -> above else if (action == INTERACT_PLACE) { - v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_above, BS)); + v3s16 blockpos = getNodeBlockPos(pointed.node_abovesurface); client->SetBlockNotSent(blockpos); } return; @@ -1037,7 +1025,6 @@ void Server::handleCommand_Interact(NetworkPacket *pkt) /* Check that target is reasonably close - (only when digging or placing things) */ static thread_local const bool enable_anticheat = !g_settings->getBool("disable_anticheat"); @@ -1045,12 +1032,19 @@ void Server::handleCommand_Interact(NetworkPacket *pkt) if ((action == INTERACT_START_DIGGING || action == INTERACT_DIGGING_COMPLETED || action == INTERACT_PLACE || action == INTERACT_USE) && enable_anticheat && !isSingleplayer()) { - float d = playersao->getEyePosition().getDistanceFrom(pointed_pos_under); + v3f target_pos = player_pos; + if (pointed.type == POINTEDTHING_NODE) { + target_pos = intToFloat(pointed.node_undersurface, BS); + } else if (pointed.type == POINTEDTHING_OBJECT) { + target_pos = pointed_object->getBasePosition(); + } + float d = playersao->getEyePosition().getDistanceFrom(target_pos); - if (!checkInteractDistance(player, d, pointed.dump())) { + if (!checkInteractDistance(player, d, pointed.dump()) + && pointed.type == POINTEDTHING_NODE) { // Re-send block to revert change on client-side RemoteClient *client = getClient(peer_id); - v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_under, BS)); + v3s16 blockpos = getNodeBlockPos(pointed.node_undersurface); client->SetBlockNotSent(blockpos); return; } @@ -1062,20 +1056,20 @@ void Server::handleCommand_Interact(NetworkPacket *pkt) RollbackScopeActor rollback_scope(m_rollback, std::string("player:")+player->getName()); - /* - 0: start digging or punch object - */ - if (action == INTERACT_START_DIGGING) { + switch (action) { + // Start digging or punch object + case INTERACT_START_DIGGING: { if (pointed.type == POINTEDTHING_NODE) { MapNode n(CONTENT_IGNORE); bool pos_ok; + v3s16 p_under = pointed.node_undersurface; n = m_env->getMap().getNode(p_under, &pos_ok); if (!pos_ok) { infostream << "Server: Not punching: Node not found. " "Adding block to emerge queue." << std::endl; - m_emerge->enqueueBlockEmerge(peer_id, getNodeBlockPos(p_above), - false); + m_emerge->enqueueBlockEmerge(peer_id, + getNodeBlockPos(pointed.node_abovesurface), false); } if (n.getContent() != CONTENT_IGNORE) @@ -1083,159 +1077,155 @@ void Server::handleCommand_Interact(NetworkPacket *pkt) // Cheat prevention playersao->noCheatDigStart(p_under); + + return; } - else if (pointed.type == POINTEDTHING_OBJECT) { - // Skip if object can't be interacted with anymore - if (pointed_object->isGone()) - return; - ItemStack selected_item, hand_item; - ItemStack tool_item = playersao->getWieldedItem(&selected_item, &hand_item); - ToolCapabilities toolcap = - tool_item.getToolCapabilities(m_itemdef); - v3f dir = (pointed_object->getBasePosition() - - (playersao->getBasePosition() + playersao->getEyeOffset()) - ).normalize(); - float time_from_last_punch = - playersao->resetTimeFromLastPunch(); - - u16 src_original_hp = pointed_object->getHP(); - u16 dst_origin_hp = playersao->getHP(); - - u16 wear = pointed_object->punch(dir, &toolcap, playersao, - time_from_last_punch); - - // Callback may have changed item, so get it again - playersao->getWieldedItem(&selected_item); - bool changed = selected_item.addWear(wear, m_itemdef); - if (changed) - playersao->setWieldedItem(selected_item); - - // If the object is a player and its HP changed - if (src_original_hp != pointed_object->getHP() && - pointed_object->getType() == ACTIVEOBJECT_TYPE_PLAYER) { - SendPlayerHPOrDie((PlayerSAO *)pointed_object, - PlayerHPChangeReason(PlayerHPChangeReason::PLAYER_PUNCH, playersao)); - } + // Skip if the object can't be interacted with anymore + if (pointed.type != POINTEDTHING_OBJECT || pointed_object->isGone()) + return; - // If the puncher is a player and its HP changed - if (dst_origin_hp != playersao->getHP()) - SendPlayerHPOrDie(playersao, - PlayerHPChangeReason(PlayerHPChangeReason::PLAYER_PUNCH, pointed_object)); + ItemStack selected_item, hand_item; + ItemStack tool_item = playersao->getWieldedItem(&selected_item, &hand_item); + ToolCapabilities toolcap = + tool_item.getToolCapabilities(m_itemdef); + v3f dir = (pointed_object->getBasePosition() - + (playersao->getBasePosition() + playersao->getEyeOffset()) + ).normalize(); + float time_from_last_punch = + playersao->resetTimeFromLastPunch(); + + u16 src_original_hp = pointed_object->getHP(); + u16 dst_origin_hp = playersao->getHP(); + + u16 wear = pointed_object->punch(dir, &toolcap, playersao, + time_from_last_punch); + + // Callback may have changed item, so get it again + playersao->getWieldedItem(&selected_item); + bool changed = selected_item.addWear(wear, m_itemdef); + if (changed) + playersao->setWieldedItem(selected_item); + + // If the object is a player and its HP changed + if (src_original_hp != pointed_object->getHP() && + pointed_object->getType() == ACTIVEOBJECT_TYPE_PLAYER) { + SendPlayerHPOrDie((PlayerSAO *)pointed_object, + PlayerHPChangeReason(PlayerHPChangeReason::PLAYER_PUNCH, playersao)); } + // If the puncher is a player and its HP changed + if (dst_origin_hp != playersao->getHP()) + SendPlayerHPOrDie(playersao, + PlayerHPChangeReason(PlayerHPChangeReason::PLAYER_PUNCH, pointed_object)); + + return; } // action == INTERACT_START_DIGGING - /* - 1: stop digging - */ - else if (action == INTERACT_STOP_DIGGING) { - } // action == INTERACT_STOP_DIGGING + case INTERACT_STOP_DIGGING: + // Nothing to do + return; - /* - 2: Digging completed - */ - else if (action == INTERACT_DIGGING_COMPLETED) { + case INTERACT_DIGGING_COMPLETED: { // Only digging of nodes - if (pointed.type == POINTEDTHING_NODE) { - bool pos_ok; - MapNode n = m_env->getMap().getNode(p_under, &pos_ok); - if (!pos_ok) { - infostream << "Server: Not finishing digging: Node not found. " - "Adding block to emerge queue." << std::endl; - m_emerge->enqueueBlockEmerge(peer_id, getNodeBlockPos(p_above), - false); - } - - /* Cheat prevention */ - bool is_valid_dig = true; - if (enable_anticheat && !isSingleplayer()) { - v3s16 nocheat_p = playersao->getNoCheatDigPos(); - float nocheat_t = playersao->getNoCheatDigTime(); - playersao->noCheatDigEnd(); - // If player didn't start digging this, ignore dig - if (nocheat_p != p_under) { - infostream << "Server: " << player->getName() - << " started digging " - << PP(nocheat_p) << " and completed digging " - << PP(p_under) << "; not digging." << std::endl; - is_valid_dig = false; - // Call callbacks - m_script->on_cheat(playersao, "finished_unknown_dig"); - } + if (pointed.type != POINTEDTHING_NODE) + return; + bool pos_ok; + v3s16 p_under = pointed.node_undersurface; + MapNode n = m_env->getMap().getNode(p_under, &pos_ok); + if (!pos_ok) { + infostream << "Server: Not finishing digging: Node not found. " + "Adding block to emerge queue." << std::endl; + m_emerge->enqueueBlockEmerge(peer_id, + getNodeBlockPos(pointed.node_abovesurface), false); + } - // Get player's wielded item - // See also: Game::handleDigging - ItemStack selected_item, hand_item; - playersao->getPlayer()->getWieldedItem(&selected_item, &hand_item); - - // Get diggability and expected digging time - DigParams params = getDigParams(m_nodedef->get(n).groups, - &selected_item.getToolCapabilities(m_itemdef)); - // If can't dig, try hand - if (!params.diggable) { - params = getDigParams(m_nodedef->get(n).groups, - &hand_item.getToolCapabilities(m_itemdef)); - } - // If can't dig, ignore dig - if (!params.diggable) { - infostream << "Server: " << player->getName() - << " completed digging " << PP(p_under) - << ", which is not diggable with tool; not digging." - << std::endl; - is_valid_dig = false; - // Call callbacks - m_script->on_cheat(playersao, "dug_unbreakable"); - } - // Check digging time - // If already invalidated, we don't have to - if (!is_valid_dig) { - // Well not our problem then - } - // Clean and long dig - else if (params.time > 2.0 && nocheat_t * 1.2 > params.time) { - // All is good, but grab time from pool; don't care if - // it's actually available - playersao->getDigPool().grab(params.time); - } - // Short or laggy dig - // Try getting the time from pool - else if (playersao->getDigPool().grab(params.time)) { - // All is good - } - // Dig not possible - else { - infostream << "Server: " << player->getName() - << " completed digging " << PP(p_under) - << "too fast; not digging." << std::endl; - is_valid_dig = false; - // Call callbacks - m_script->on_cheat(playersao, "dug_too_fast"); - } + /* Cheat prevention */ + bool is_valid_dig = true; + if (enable_anticheat && !isSingleplayer()) { + v3s16 nocheat_p = playersao->getNoCheatDigPos(); + float nocheat_t = playersao->getNoCheatDigTime(); + playersao->noCheatDigEnd(); + // If player didn't start digging this, ignore dig + if (nocheat_p != p_under) { + infostream << "Server: " << player->getName() + << " started digging " + << PP(nocheat_p) << " and completed digging " + << PP(p_under) << "; not digging." << std::endl; + is_valid_dig = false; + // Call callbacks + m_script->on_cheat(playersao, "finished_unknown_dig"); } - /* Actually dig node */ - - if (is_valid_dig && n.getContent() != CONTENT_IGNORE) - m_script->node_on_dig(p_under, n, playersao); - - v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_under, BS)); - RemoteClient *client = getClient(peer_id); - // Send unusual result (that is, node not being removed) - if (m_env->getMap().getNode(p_under).getContent() != CONTENT_AIR) { - // Re-send block to revert change on client-side - client->SetBlockNotSent(blockpos); + // Get player's wielded item + // See also: Game::handleDigging + ItemStack selected_item, hand_item; + playersao->getPlayer()->getWieldedItem(&selected_item, &hand_item); + + // Get diggability and expected digging time + DigParams params = getDigParams(m_nodedef->get(n).groups, + &selected_item.getToolCapabilities(m_itemdef)); + // If can't dig, try hand + if (!params.diggable) { + params = getDigParams(m_nodedef->get(n).groups, + &hand_item.getToolCapabilities(m_itemdef)); + } + // If can't dig, ignore dig + if (!params.diggable) { + infostream << "Server: " << player->getName() + << " completed digging " << PP(p_under) + << ", which is not diggable with tool; not digging." + << std::endl; + is_valid_dig = false; + // Call callbacks + m_script->on_cheat(playersao, "dug_unbreakable"); + } + // Check digging time + // If already invalidated, we don't have to + if (!is_valid_dig) { + // Well not our problem then + } + // Clean and long dig + else if (params.time > 2.0 && nocheat_t * 1.2 > params.time) { + // All is good, but grab time from pool; don't care if + // it's actually available + playersao->getDigPool().grab(params.time); } + // Short or laggy dig + // Try getting the time from pool + else if (playersao->getDigPool().grab(params.time)) { + // All is good + } + // Dig not possible else { - client->ResendBlockIfOnWire(blockpos); + infostream << "Server: " << player->getName() + << " completed digging " << PP(p_under) + << "too fast; not digging." << std::endl; + is_valid_dig = false; + // Call callbacks + m_script->on_cheat(playersao, "dug_too_fast"); } } + + /* Actually dig node */ + + if (is_valid_dig && n.getContent() != CONTENT_IGNORE) + m_script->node_on_dig(p_under, n, playersao); + + v3s16 blockpos = getNodeBlockPos(p_under); + RemoteClient *client = getClient(peer_id); + // Send unusual result (that is, node not being removed) + if (m_env->getMap().getNode(p_under).getContent() != CONTENT_AIR) + // Re-send block to revert change on client-side + client->SetBlockNotSent(blockpos); + else + client->ResendBlockIfOnWire(blockpos); + + return; } // action == INTERACT_DIGGING_COMPLETED - /* - 3: place block or right-click object - */ - else if (action == INTERACT_PLACE) { + // Place block or right-click object + case INTERACT_PLACE: { ItemStack selected_item; playersao->getWieldedItem(&selected_item, nullptr); @@ -1264,59 +1254,54 @@ void Server::handleCommand_Interact(NetworkPacket *pkt) } pointed_object->rightClick(playersao); - } else if (m_script->item_OnPlace( - selected_item, playersao, pointed)) { + } else if (m_script->item_OnPlace(selected_item, playersao, pointed)) { // Placement was handled in lua // Apply returned ItemStack - if (playersao->setWieldedItem(selected_item)) { + if (playersao->setWieldedItem(selected_item)) SendInventory(playersao, true); - } } + if (pointed.type != POINTEDTHING_NODE) + return; + // If item has node placement prediction, always send the // blocks to make sure the client knows what exactly happened RemoteClient *client = getClient(peer_id); - v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_above, BS)); - v3s16 blockpos2 = getNodeBlockPos(floatToInt(pointed_pos_under, BS)); - if (!selected_item.getDefinition(m_itemdef).node_placement_prediction.empty()) { + v3s16 blockpos = getNodeBlockPos(pointed.node_abovesurface); + v3s16 blockpos2 = getNodeBlockPos(pointed.node_undersurface); + if (!selected_item.getDefinition(m_itemdef + ).node_placement_prediction.empty()) { client->SetBlockNotSent(blockpos); - if (blockpos2 != blockpos) { + if (blockpos2 != blockpos) client->SetBlockNotSent(blockpos2); - } - } - else { + } else { client->ResendBlockIfOnWire(blockpos); - if (blockpos2 != blockpos) { + if (blockpos2 != blockpos) client->ResendBlockIfOnWire(blockpos2); - } } + + return; } // action == INTERACT_PLACE - /* - 4: use - */ - else if (action == INTERACT_USE) { + case INTERACT_USE: { ItemStack selected_item; playersao->getWieldedItem(&selected_item, nullptr); actionstream << player->getName() << " uses " << selected_item.name << ", pointing at " << pointed.dump() << std::endl; - if (m_script->item_OnUse( - selected_item, playersao, pointed)) { + if (m_script->item_OnUse(selected_item, playersao, pointed)) { // Apply returned ItemStack - if (playersao->setWieldedItem(selected_item)) { + if (playersao->setWieldedItem(selected_item)) SendInventory(playersao, true); - } } - } // action == INTERACT_USE + return; + } - /* - 5: rightclick air - */ - else if (action == INTERACT_ACTIVATE) { + // Rightclick air + case INTERACT_ACTIVATE: { ItemStack selected_item; playersao->getWieldedItem(&selected_item, nullptr); @@ -1325,21 +1310,17 @@ void Server::handleCommand_Interact(NetworkPacket *pkt) pointed.type = POINTEDTHING_NOTHING; // can only ever be NOTHING - if (m_script->item_OnSecondaryUse( - selected_item, playersao, pointed)) { - if (playersao->setWieldedItem(selected_item)) { + if (m_script->item_OnSecondaryUse(selected_item, playersao, pointed)) { + if (playersao->setWieldedItem(selected_item)) SendInventory(playersao, true); - } } - } // action == INTERACT_ACTIVATE + return; + } + + default: + warningstream << "Server: Invalid action " << action << std::endl; - /* - Catch invalid actions - */ - else { - warningstream << "Server: Invalid action " - << action << std::endl; } } -- cgit v1.2.3 From 74e22b72e1fc577d05ea703aed4bfa8c1e1f0599 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Tue, 1 Sep 2020 20:18:32 +0200 Subject: Change default ambient occlusion gamma to 1.8 (#10185) --- src/defaultsettings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index c93af9506..d2115c959 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -230,7 +230,7 @@ void set_default_settings(Settings *settings) settings->setDefault("show_entity_selectionbox", "false"); settings->setDefault("texture_clean_transparent", "false"); settings->setDefault("texture_min_size", "64"); - settings->setDefault("ambient_occlusion_gamma", "2.2"); + settings->setDefault("ambient_occlusion_gamma", "1.8"); #if ENABLE_GLES settings->setDefault("enable_shaders", "false"); #else -- cgit v1.2.3 From 4ba5046308d6bdf7b38394770c6f82b6927393f2 Mon Sep 17 00:00:00 2001 From: Paramat Date: Thu, 3 Sep 2020 01:28:40 +0100 Subject: Add 'ores' global mapgen flag (#10276) --- builtin/settingtypes.txt | 2 +- src/mapgen/mapgen.cpp | 3 ++- src/mapgen/mapgen.h | 1 + src/mapgen/mapgen_carpathian.cpp | 3 ++- src/mapgen/mapgen_flat.cpp | 3 ++- src/mapgen/mapgen_fractal.cpp | 3 ++- src/mapgen/mapgen_v5.cpp | 3 ++- src/mapgen/mapgen_v6.cpp | 3 ++- src/mapgen/mapgen_v7.cpp | 3 ++- src/mapgen/mapgen_valleys.cpp | 3 ++- 10 files changed, 18 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index ef56f99bf..39cc22d62 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -1475,7 +1475,7 @@ mapgen_limit (Map generation limit) int 31000 0 31000 # Global map generation attributes. # In Mapgen v6 the 'decorations' flag controls all decorations except trees # and junglegrass, in all other mapgens this flag controls all decorations. -mg_flags (Mapgen flags) flags caves,dungeons,light,decorations,biomes caves,dungeons,light,decorations,biomes,nocaves,nodungeons,nolight,nodecorations,nobiomes +mg_flags (Mapgen flags) flags caves,dungeons,light,decorations,biomes,ores caves,dungeons,light,decorations,biomes,ores,nocaves,nodungeons,nolight,nodecorations,nobiomes,noores [*Biome API temperature and humidity noise parameters] diff --git a/src/mapgen/mapgen.cpp b/src/mapgen/mapgen.cpp index f57529082..52ef64e7e 100644 --- a/src/mapgen/mapgen.cpp +++ b/src/mapgen/mapgen.cpp @@ -58,6 +58,7 @@ FlagDesc flagdesc_mapgen[] = { {"light", MG_LIGHT}, {"decorations", MG_DECORATIONS}, {"biomes", MG_BIOMES}, + {"ores", MG_ORES}, {NULL, 0} }; @@ -217,7 +218,7 @@ void Mapgen::getMapgenNames(std::vector *mgnames, bool include_hid void Mapgen::setDefaultSettings(Settings *settings) { settings->setDefault("mg_flags", flagdesc_mapgen, - MG_CAVES | MG_DUNGEONS | MG_LIGHT | MG_DECORATIONS | MG_BIOMES); + MG_CAVES | MG_DUNGEONS | MG_LIGHT | MG_DECORATIONS | MG_BIOMES | MG_ORES); for (int i = 0; i < (int)MAPGEN_INVALID; ++i) { MapgenParams *params = createMapgenParams((MapgenType)i); diff --git a/src/mapgen/mapgen.h b/src/mapgen/mapgen.h index a92b3b0d0..0f2977c4c 100644 --- a/src/mapgen/mapgen.h +++ b/src/mapgen/mapgen.h @@ -37,6 +37,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #define MG_LIGHT 0x10 #define MG_DECORATIONS 0x20 #define MG_BIOMES 0x40 +#define MG_ORES 0x80 typedef u16 biome_t; // copy from mg_biome.h to avoid an unnecessary include diff --git a/src/mapgen/mapgen_carpathian.cpp b/src/mapgen/mapgen_carpathian.cpp index feb9b428c..74ed263ba 100644 --- a/src/mapgen/mapgen_carpathian.cpp +++ b/src/mapgen/mapgen_carpathian.cpp @@ -315,7 +315,8 @@ void MapgenCarpathian::makeChunk(BlockMakeData *data) } // Generate the registered ores - m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max); + if (flags & MG_ORES) + m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max); // Generate dungeons if (flags & MG_DUNGEONS) diff --git a/src/mapgen/mapgen_flat.cpp b/src/mapgen/mapgen_flat.cpp index df6469ad9..d62548014 100644 --- a/src/mapgen/mapgen_flat.cpp +++ b/src/mapgen/mapgen_flat.cpp @@ -264,7 +264,8 @@ void MapgenFlat::makeChunk(BlockMakeData *data) } // Generate the registered ores - m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max); + if (flags & MG_ORES) + m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max); if (flags & MG_DUNGEONS) generateDungeons(stone_surface_max_y); diff --git a/src/mapgen/mapgen_fractal.cpp b/src/mapgen/mapgen_fractal.cpp index cb55bc288..3b6bbd6c1 100644 --- a/src/mapgen/mapgen_fractal.cpp +++ b/src/mapgen/mapgen_fractal.cpp @@ -250,7 +250,8 @@ void MapgenFractal::makeChunk(BlockMakeData *data) } // Generate the registered ores - m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max); + if (flags & MG_ORES) + m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max); // Generate dungeons if (flags & MG_DUNGEONS) diff --git a/src/mapgen/mapgen_v5.cpp b/src/mapgen/mapgen_v5.cpp index 124667e5d..0f6a19fa1 100644 --- a/src/mapgen/mapgen_v5.cpp +++ b/src/mapgen/mapgen_v5.cpp @@ -257,7 +257,8 @@ void MapgenV5::makeChunk(BlockMakeData *data) } // Generate the registered ores - m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max); + if (flags & MG_ORES) + m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max); // Generate dungeons and desert temples if (flags & MG_DUNGEONS) diff --git a/src/mapgen/mapgen_v6.cpp b/src/mapgen/mapgen_v6.cpp index e9692246c..8bea5eb69 100644 --- a/src/mapgen/mapgen_v6.cpp +++ b/src/mapgen/mapgen_v6.cpp @@ -652,7 +652,8 @@ void MapgenV6::makeChunk(BlockMakeData *data) m_emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max); // Generate the registered ores - m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max); + if (flags & MG_ORES) + m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max); // Calculate lighting if (flags & MG_LIGHT) diff --git a/src/mapgen/mapgen_v7.cpp b/src/mapgen/mapgen_v7.cpp index e93dc9140..a1fe25ab6 100644 --- a/src/mapgen/mapgen_v7.cpp +++ b/src/mapgen/mapgen_v7.cpp @@ -377,7 +377,8 @@ void MapgenV7::makeChunk(BlockMakeData *data) } // Generate the registered ores - m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max); + if (flags & MG_ORES) + m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max); // Generate dungeons if (flags & MG_DUNGEONS) diff --git a/src/mapgen/mapgen_valleys.cpp b/src/mapgen/mapgen_valleys.cpp index efcc8ee85..d7b6f738f 100644 --- a/src/mapgen/mapgen_valleys.cpp +++ b/src/mapgen/mapgen_valleys.cpp @@ -268,7 +268,8 @@ void MapgenValleys::makeChunk(BlockMakeData *data) } // Generate the registered ores - m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max); + if (flags & MG_ORES) + m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max); // Dungeon creation if (flags & MG_DUNGEONS) -- cgit v1.2.3 From 050964bed6005f8d816ddf362b9fc8675581d190 Mon Sep 17 00:00:00 2001 From: Lars Müller <34514239+appgurueu@users.noreply.github.com> Date: Fri, 4 Sep 2020 20:49:07 +0200 Subject: Fix inventory swapping not calling all callbacks (#9923) "Predicts" whether something will be swapped for allow callbacks, then calls callbacks a second time with swapped properties. Co-authored-by: SmallJoker --- doc/lua_api.txt | 25 ++++ src/inventory.cpp | 9 +- src/inventorymanager.cpp | 303 ++++++++++++++++++++++++++--------------------- src/inventorymanager.h | 12 ++ 4 files changed, 210 insertions(+), 139 deletions(-) (limited to 'src') diff --git a/doc/lua_api.txt b/doc/lua_api.txt index cc4af970c..86627c19e 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -5888,6 +5888,31 @@ An `InvRef` is a reference to an inventory. `minetest.get_inventory(location)`. * returns `{type="undefined"}` in case location is not known +### Callbacks + +Detached & nodemeta inventories provide the following callbacks for move actions: + +#### Before + +The `allow_*` callbacks return how many items can be moved. + +* `allow_move`/`allow_metadata_inventory_move`: Moving items in the inventory +* `allow_take`/`allow_metadata_inventory_take`: Taking items from the inventory +* `allow_put`/`allow_metadata_inventory_put`: Putting items to the inventory + +#### After + +The `on_*` callbacks are called after the items have been placed in the inventories. + +* `on_move`/`on_metadata_inventory_move`: Moving items in the inventory +* `on_take`/`on_metadata_inventory_take`: Taking items from the inventory +* `on_put`/`on_metadata_inventory_put`: Putting items to the inventory + +#### Swapping + +When a player tries to put an item to a place where another item is, the items are *swapped*. +This means that all callbacks will be called twice (once for each action). + `ItemStack` ----------- diff --git a/src/inventory.cpp b/src/inventory.cpp index 349ee503d..cf72cb005 100644 --- a/src/inventory.cpp +++ b/src/inventory.cpp @@ -732,17 +732,17 @@ void InventoryList::moveItemSomewhere(u32 i, InventoryList *dest, u32 count) u32 InventoryList::moveItem(u32 i, InventoryList *dest, u32 dest_i, u32 count, bool swap_if_needed, bool *did_swap) { - if(this == dest && i == dest_i) + if (this == dest && i == dest_i) return count; // Take item from source list ItemStack item1; - if(count == 0) + if (count == 0) item1 = changeItem(i, ItemStack()); else item1 = takeItem(i, count); - if(item1.empty()) + if (item1.empty()) return 0; // Try to add the item to destination list @@ -750,8 +750,7 @@ u32 InventoryList::moveItem(u32 i, InventoryList *dest, u32 dest_i, item1 = dest->addItem(dest_i, item1); // If something is returned, the item was not fully added - if(!item1.empty()) - { + if (!item1.empty()) { // If olditem is returned, nothing was added. bool nothing_added = (item1.count == oldcount); diff --git a/src/inventorymanager.cpp b/src/inventorymanager.cpp index b6f464901..635bd2e4b 100644 --- a/src/inventorymanager.cpp +++ b/src/inventorymanager.cpp @@ -154,6 +154,93 @@ IMoveAction::IMoveAction(std::istream &is, bool somewhere) : } } +void IMoveAction::swapDirections() +{ + std::swap(from_inv, to_inv); + std::swap(from_list, to_list); + std::swap(from_i, to_i); +} + +void IMoveAction::onPutAndOnTake(const ItemStack &src_item, ServerActiveObject *player) const +{ + ServerScripting *sa = PLAYER_TO_SA(player); + if (to_inv.type == InventoryLocation::DETACHED) + sa->detached_inventory_OnPut(*this, src_item, player); + else if (to_inv.type == InventoryLocation::NODEMETA) + sa->nodemeta_inventory_OnPut(*this, src_item, player); + else if (to_inv.type == InventoryLocation::PLAYER) + sa->player_inventory_OnPut(*this, src_item, player); + else + assert(false); + + if (from_inv.type == InventoryLocation::DETACHED) + sa->detached_inventory_OnTake(*this, src_item, player); + else if (from_inv.type == InventoryLocation::NODEMETA) + sa->nodemeta_inventory_OnTake(*this, src_item, player); + else if (from_inv.type == InventoryLocation::PLAYER) + sa->player_inventory_OnTake(*this, src_item, player); + else + assert(false); +} + +void IMoveAction::onMove(int count, ServerActiveObject *player) const +{ + ServerScripting *sa = PLAYER_TO_SA(player); + if (from_inv.type == InventoryLocation::DETACHED) + sa->detached_inventory_OnMove(*this, count, player); + else if (from_inv.type == InventoryLocation::NODEMETA) + sa->nodemeta_inventory_OnMove(*this, count, player); + else if (from_inv.type == InventoryLocation::PLAYER) + sa->player_inventory_OnMove(*this, count, player); + else + assert(false); +} + +int IMoveAction::allowPut(const ItemStack &dst_item, ServerActiveObject *player) const +{ + ServerScripting *sa = PLAYER_TO_SA(player); + int dst_can_put_count = 0xffff; + if (to_inv.type == InventoryLocation::DETACHED) + dst_can_put_count = sa->detached_inventory_AllowPut(*this, dst_item, player); + else if (to_inv.type == InventoryLocation::NODEMETA) + dst_can_put_count = sa->nodemeta_inventory_AllowPut(*this, dst_item, player); + else if (to_inv.type == InventoryLocation::PLAYER) + dst_can_put_count = sa->player_inventory_AllowPut(*this, dst_item, player); + else + assert(false); + return dst_can_put_count; +} + +int IMoveAction::allowTake(const ItemStack &src_item, ServerActiveObject *player) const +{ + ServerScripting *sa = PLAYER_TO_SA(player); + int src_can_take_count = 0xffff; + if (from_inv.type == InventoryLocation::DETACHED) + src_can_take_count = sa->detached_inventory_AllowTake(*this, src_item, player); + else if (from_inv.type == InventoryLocation::NODEMETA) + src_can_take_count = sa->nodemeta_inventory_AllowTake(*this, src_item, player); + else if (from_inv.type == InventoryLocation::PLAYER) + src_can_take_count = sa->player_inventory_AllowTake(*this, src_item, player); + else + assert(false); + return src_can_take_count; +} + +int IMoveAction::allowMove(int try_take_count, ServerActiveObject *player) const +{ + ServerScripting *sa = PLAYER_TO_SA(player); + int src_can_take_count = 0xffff; + if (from_inv.type == InventoryLocation::DETACHED) + src_can_take_count = sa->detached_inventory_AllowMove(*this, try_take_count, player); + else if (from_inv.type == InventoryLocation::NODEMETA) + src_can_take_count = sa->nodemeta_inventory_AllowMove(*this, try_take_count, player); + else if (from_inv.type == InventoryLocation::PLAYER) + src_can_take_count = sa->player_inventory_AllowMove(*this, try_take_count, player); + else + assert(false); + return src_can_take_count; +} + void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGameDef *gamedef) { Inventory *inv_from = mgr->getInventory(from_inv); @@ -251,93 +338,80 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame Collect information of endpoints */ - int try_take_count = count; - if (try_take_count == 0) - try_take_count = list_from->getItem(from_i).count; + ItemStack src_item = list_from->getItem(from_i); + if (count > 0) + src_item.count = count; + if (src_item.empty()) + return; int src_can_take_count = 0xffff; int dst_can_put_count = 0xffff; - /* Query detached inventories */ + // this is needed for swapping items inside one inventory to work + ItemStack restitem; + bool allow_swap = !list_to->itemFits(to_i, src_item, &restitem) + && restitem.count == src_item.count + && !caused_by_move_somewhere; - // Move occurs in the same detached inventory - if (from_inv.type == InventoryLocation::DETACHED && - from_inv == to_inv) { - src_can_take_count = PLAYER_TO_SA(player)->detached_inventory_AllowMove( - *this, try_take_count, player); - dst_can_put_count = src_can_take_count; - } else { - // Destination is detached - if (to_inv.type == InventoryLocation::DETACHED) { - ItemStack src_item = list_from->getItem(from_i); - src_item.count = try_take_count; - dst_can_put_count = PLAYER_TO_SA(player)->detached_inventory_AllowPut( - *this, src_item, player); - } - // Source is detached - if (from_inv.type == InventoryLocation::DETACHED) { - ItemStack src_item = list_from->getItem(from_i); - src_item.count = try_take_count; - src_can_take_count = PLAYER_TO_SA(player)->detached_inventory_AllowTake( - *this, src_item, player); - } - } - - /* Query node metadata inventories */ + // Shift-click: Cannot fill this stack, proceed with next slot + if (caused_by_move_somewhere && restitem.count == src_item.count) + return; - // Both endpoints are nodemeta - // Move occurs in the same nodemeta inventory - if (from_inv.type == InventoryLocation::NODEMETA && - from_inv == to_inv) { - src_can_take_count = PLAYER_TO_SA(player)->nodemeta_inventory_AllowMove( - *this, try_take_count, player); - dst_can_put_count = src_can_take_count; - } else { - // Destination is nodemeta - if (to_inv.type == InventoryLocation::NODEMETA) { - ItemStack src_item = list_from->getItem(from_i); - src_item.count = try_take_count; - dst_can_put_count = PLAYER_TO_SA(player)->nodemeta_inventory_AllowPut( - *this, src_item, player); + if (allow_swap) { + // Swap will affect the entire stack if it can performed. + src_item = list_from->getItem(from_i); + count = src_item.count; + } + + if (from_inv == to_inv) { + // Move action within the same inventory + src_can_take_count = allowMove(src_item.count, player); + + bool swap_expected = allow_swap; + allow_swap = allow_swap + && (src_can_take_count == -1 || src_can_take_count >= src_item.count); + if (allow_swap) { + int try_put_count = list_to->getItem(to_i).count; + swapDirections(); + dst_can_put_count = allowMove(try_put_count, player); + allow_swap = allow_swap + && (dst_can_put_count == -1 || dst_can_put_count >= try_put_count); + swapDirections(); + } else { + dst_can_put_count = src_can_take_count; } - // Source is nodemeta - if (from_inv.type == InventoryLocation::NODEMETA) { - ItemStack src_item = list_from->getItem(from_i); - src_item.count = try_take_count; - src_can_take_count = PLAYER_TO_SA(player)->nodemeta_inventory_AllowTake( - *this, src_item, player); - } - } - - // Query player inventories - - // Move occurs in the same player inventory - if (from_inv.type == InventoryLocation::PLAYER && - from_inv == to_inv) { - src_can_take_count = PLAYER_TO_SA(player)->player_inventory_AllowMove( - *this, try_take_count, player); - dst_can_put_count = src_can_take_count; + if (swap_expected != allow_swap) + src_can_take_count = dst_can_put_count = 0; } else { - // Destination is a player - if (to_inv.type == InventoryLocation::PLAYER) { - ItemStack src_item = list_from->getItem(from_i); - src_item.count = try_take_count; - dst_can_put_count = PLAYER_TO_SA(player)->player_inventory_AllowPut( - *this, src_item, player); - } - // Source is a player - if (from_inv.type == InventoryLocation::PLAYER) { - ItemStack src_item = list_from->getItem(from_i); - src_item.count = try_take_count; - src_can_take_count = PLAYER_TO_SA(player)->player_inventory_AllowTake( - *this, src_item, player); + // Take from one inventory, put into another + dst_can_put_count = allowPut(src_item, player); + src_can_take_count = allowTake(src_item, player); + + bool swap_expected = allow_swap; + allow_swap = allow_swap + && (src_can_take_count == -1 || src_can_take_count >= src_item.count) + && (dst_can_put_count == -1 || dst_can_put_count >= src_item.count); + // A swap is expected, which means that we have to + // run the "allow" callbacks a second time with swapped inventories + if (allow_swap) { + ItemStack dst_item = list_to->getItem(to_i); + swapDirections(); + + int src_can_take = allowPut(dst_item, player); + int dst_can_put = allowTake(dst_item, player); + allow_swap = allow_swap + && (src_can_take == -1 || src_can_take >= dst_item.count) + && (dst_can_put == -1 || dst_can_put >= dst_item.count); + swapDirections(); } + if (swap_expected != allow_swap) + src_can_take_count = dst_can_put_count = 0; } int old_count = count; /* Modify count according to collected data */ - count = try_take_count; + count = src_item.count; if (src_can_take_count != -1 && count > src_can_take_count) count = src_can_take_count; if (dst_can_put_count != -1 && count > dst_can_put_count) @@ -367,7 +441,7 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame return; } - ItemStack src_item = list_from->getItem(from_i); + src_item = list_from->getItem(from_i); src_item.count = count; ItemStack from_stack_was = list_from->getItem(from_i); ItemStack to_stack_was = list_to->getItem(to_i); @@ -380,7 +454,8 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame */ bool did_swap = false; move_count = list_from->moveItem(from_i, - list_to, to_i, count, !caused_by_move_somewhere, &did_swap); + list_to, to_i, count, allow_swap, &did_swap); + assert(allow_swap == did_swap); // If source is infinite, reset it's stack if (src_can_take_count == -1) { @@ -471,69 +546,29 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame Report move to endpoints */ - /* Detached inventories */ - - // Both endpoints are same detached - if (from_inv.type == InventoryLocation::DETACHED && - from_inv == to_inv) { - PLAYER_TO_SA(player)->detached_inventory_OnMove( - *this, count, player); - } else { - // Destination is detached - if (to_inv.type == InventoryLocation::DETACHED) { - PLAYER_TO_SA(player)->detached_inventory_OnPut( - *this, src_item, player); - } - // Source is detached - if (from_inv.type == InventoryLocation::DETACHED) { - PLAYER_TO_SA(player)->detached_inventory_OnTake( - *this, src_item, player); + // Source = destination => move + if (from_inv == to_inv) { + onMove(count, player); + if (did_swap) { + // Item is now placed in source list + src_item = list_from->getItem(from_i); + swapDirections(); + onMove(src_item.count, player); + swapDirections(); } - } - - /* Node metadata inventories */ - - // Both endpoints are same nodemeta - if (from_inv.type == InventoryLocation::NODEMETA && - from_inv == to_inv) { - PLAYER_TO_SA(player)->nodemeta_inventory_OnMove( - *this, count, player); - } else { - // Destination is nodemeta - if (to_inv.type == InventoryLocation::NODEMETA) { - PLAYER_TO_SA(player)->nodemeta_inventory_OnPut( - *this, src_item, player); - } - // Source is nodemeta - if (from_inv.type == InventoryLocation::NODEMETA) { - PLAYER_TO_SA(player)->nodemeta_inventory_OnTake( - *this, src_item, player); - } - } - - // Player inventories - - // Both endpoints are same player inventory - if (from_inv.type == InventoryLocation::PLAYER && - from_inv == to_inv) { - PLAYER_TO_SA(player)->player_inventory_OnMove( - *this, count, player); + mgr->setInventoryModified(from_inv); } else { - // Destination is player inventory - if (to_inv.type == InventoryLocation::PLAYER) { - PLAYER_TO_SA(player)->player_inventory_OnPut( - *this, src_item, player); + onPutAndOnTake(src_item, player); + if (did_swap) { + // Item is now placed in source list + src_item = list_from->getItem(from_i); + swapDirections(); + onPutAndOnTake(src_item, player); + swapDirections(); } - // Source is player inventory - if (from_inv.type == InventoryLocation::PLAYER) { - PLAYER_TO_SA(player)->player_inventory_OnTake( - *this, src_item, player); - } - } - - mgr->setInventoryModified(from_inv); - if (inv_from != inv_to) mgr->setInventoryModified(to_inv); + mgr->setInventoryModified(from_inv); + } } void IMoveAction::clientApply(InventoryManager *mgr, IGameDef *gamedef) diff --git a/src/inventorymanager.h b/src/inventorymanager.h index 69bf30169..4ad5d3f49 100644 --- a/src/inventorymanager.h +++ b/src/inventorymanager.h @@ -183,6 +183,18 @@ struct IMoveAction : public InventoryAction, public MoveAction void apply(InventoryManager *mgr, ServerActiveObject *player, IGameDef *gamedef); void clientApply(InventoryManager *mgr, IGameDef *gamedef); + + void swapDirections(); + + void onPutAndOnTake(const ItemStack &src_item, ServerActiveObject *player) const; + + void onMove(int count, ServerActiveObject *player) const; + + int allowPut(const ItemStack &dst_item, ServerActiveObject *player) const; + + int allowTake(const ItemStack &src_item, ServerActiveObject *player) const; + + int allowMove(int try_take_count, ServerActiveObject *player) const; }; struct IDropAction : public InventoryAction, public MoveAction -- cgit v1.2.3 From b3ace8f19746b53f839e7b0bdff0843c83866f64 Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Fri, 4 Sep 2020 20:49:50 +0200 Subject: Scale inventory image for scaled allfaces nodes (#10225) The inventory image size of the inventory image of nodes with drawtype allfaces (and related) is scaled as well if visual_scale is set (previously, the inventory image size was always the same) --- games/devtest/mods/testnodes/drawtypes.lua | 9 +++++++++ src/client/wieldmesh.cpp | 2 ++ 2 files changed, 11 insertions(+) (limited to 'src') diff --git a/games/devtest/mods/testnodes/drawtypes.lua b/games/devtest/mods/testnodes/drawtypes.lua index 6bf57fa37..82d862819 100644 --- a/games/devtest/mods/testnodes/drawtypes.lua +++ b/games/devtest/mods/testnodes/drawtypes.lua @@ -514,6 +514,15 @@ local scale = function(subname, desc_double, desc_half) minetest.register_node("testnodes:"..subname.."_half", def) end +scale("allfaces", + S("Double-sized Allfaces Drawtype Test Node"), + S("Half-sized Allfaces Drawtype Test Node")) +scale("allfaces_optional", + S("Double-sized Allfaces Optional Drawtype Test Node"), + S("Half-sized Allfaces Optional Drawtype Test Node")) +scale("allfaces_optional_waving", + S("Double-sized Waving Allfaces Optional Drawtype Test Node"), + S("Half-sized Waving Allfaces Optional Drawtype Test Node")) scale("plantlike", S("Double-sized Plantlike Drawtype Test Node"), S("Half-sized Plantlike Drawtype Test Node")) diff --git a/src/client/wieldmesh.cpp b/src/client/wieldmesh.cpp index a268895ed..285cc38e5 100644 --- a/src/client/wieldmesh.cpp +++ b/src/client/wieldmesh.cpp @@ -562,6 +562,8 @@ void getItemMesh(Client *client, const ItemStack &item, ItemMesh *result) // add overlays postProcessNodeMesh(mesh, f, false, false, nullptr, &result->buffer_colors, true); + if (f.drawtype == NDT_ALLFACES) + scaleMesh(mesh, v3f(f.visual_scale)); break; } case NDT_PLANTLIKE: { -- cgit v1.2.3 From 6dcc9e63318f815a3de8c9db2ee7b845066e0135 Mon Sep 17 00:00:00 2001 From: Lejo Date: Fri, 4 Sep 2020 20:50:33 +0200 Subject: Prevent interacting with items out of the hotbar (#10359) --- src/network/serverpackethandler.cpp | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/network/serverpackethandler.cpp b/src/network/serverpackethandler.cpp index d133b4ff9..fe70d376e 100644 --- a/src/network/serverpackethandler.cpp +++ b/src/network/serverpackethandler.cpp @@ -636,7 +636,7 @@ void Server::handleCommand_InventoryAction(NetworkPacket* pkt) return; from_inv_is_current_player = true; } - + bool to_inv_is_current_player = false; if (ma->to_inv.type == InventoryLocation::PLAYER) { if (ma->to_inv.name != player->getName()) @@ -869,6 +869,15 @@ void Server::handleCommand_PlayerItem(NetworkPacket* pkt) *pkt >> item; + if (item >= player->getHotbarItemcount()) { + actionstream << "Player: " << player->getName() + << " tried to access item=" << item + << " out of hotbar_itemcount=" + << player->getHotbarItemcount() + << "; ignoring." << std::endl; + return; + } + playersao->getPlayer()->setWieldIndex(item); } @@ -984,6 +993,16 @@ void Server::handleCommand_Interact(NetworkPacket *pkt) v3f player_pos = playersao->getLastGoodPosition(); // Update wielded item + + if (item_i >= player->getHotbarItemcount()) { + actionstream << "Player: " << player->getName() + << " tried to access item=" << item_i + << " out of hotbar_itemcount=" + << player->getHotbarItemcount() + << "; ignoring." << std::endl; + return; + } + playersao->getPlayer()->setWieldIndex(item_i); // Get pointed to object (NULL if not POINTEDTYPE_OBJECT) -- cgit v1.2.3 From 0d128ab344e3d04d2b30dbd5e047f4ac700013b7 Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Mon, 7 Sep 2020 21:19:38 +0200 Subject: Inventory: Protect Craft and Drop actions (#10353) Change dangerous pointer to unique_ptr for automated deletion. --- src/network/serverpackethandler.cpp | 79 ++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 44 deletions(-) (limited to 'src') diff --git a/src/network/serverpackethandler.cpp b/src/network/serverpackethandler.cpp index fe70d376e..0bd09e637 100644 --- a/src/network/serverpackethandler.cpp +++ b/src/network/serverpackethandler.cpp @@ -600,7 +600,7 @@ void Server::handleCommand_InventoryAction(NetworkPacket* pkt) << std::endl; std::istringstream is(datastring, std::ios_base::binary); // Create an action - InventoryAction *a = InventoryAction::deSerialize(is); + std::unique_ptr a(InventoryAction::deSerialize(is)); if (!a) { infostream << "TOSERVER_INVENTORY_ACTION: " << "InventoryAction::deSerialize() returned NULL" @@ -617,11 +617,30 @@ void Server::handleCommand_InventoryAction(NetworkPacket* pkt) where the client made a bad prediction. */ + const bool player_has_interact = checkPriv(player->getName(), "interact"); + + auto check_inv_access = [player, player_has_interact] ( + const InventoryLocation &loc) -> bool { + if (loc.type == InventoryLocation::CURRENT_PLAYER) + return false; // Only used internally on the client, never sent + if (loc.type == InventoryLocation::PLAYER) { + // Allow access to own inventory in all cases + return loc.name == player->getName(); + } + + if (!player_has_interact) { + infostream << "Cannot modify foreign inventory: " + << "No interact privilege" << std::endl; + return false; + } + return true; + }; + /* Handle restrictions and special cases of the move action */ if (a->getType() == IAction::Move) { - IMoveAction *ma = (IMoveAction*)a; + IMoveAction *ma = (IMoveAction*)a.get(); ma->from_inv.applyCurrentPlayer(player->getName()); ma->to_inv.applyCurrentPlayer(player->getName()); @@ -630,21 +649,11 @@ void Server::handleCommand_InventoryAction(NetworkPacket* pkt) if (ma->from_inv != ma->to_inv) m_inventory_mgr->setInventoryModified(ma->to_inv); - bool from_inv_is_current_player = false; - if (ma->from_inv.type == InventoryLocation::PLAYER) { - if (ma->from_inv.name != player->getName()) - return; - from_inv_is_current_player = true; - } - - bool to_inv_is_current_player = false; - if (ma->to_inv.type == InventoryLocation::PLAYER) { - if (ma->to_inv.name != player->getName()) - return; - to_inv_is_current_player = true; - } + if (!check_inv_access(ma->from_inv) || + !check_inv_access(ma->to_inv)) + return; - InventoryLocation *remote = from_inv_is_current_player ? + InventoryLocation *remote = ma->from_inv.type == InventoryLocation::PLAYER ? &ma->to_inv : &ma->from_inv; // Check for out-of-range interaction @@ -664,7 +673,6 @@ void Server::handleCommand_InventoryAction(NetworkPacket* pkt) << (ma->from_inv.dump()) << ":" << ma->from_list << " to " << (ma->to_inv.dump()) << ":" << ma->to_list << " because src is " << ma->from_list << std::endl; - delete a; return; } @@ -676,18 +684,6 @@ void Server::handleCommand_InventoryAction(NetworkPacket* pkt) << (ma->from_inv.dump()) << ":" << ma->from_list << " to " << (ma->to_inv.dump()) << ":" << ma->to_list << " because dst is " << ma->to_list << std::endl; - delete a; - return; - } - - // Disallow moving items in elsewhere than player's inventory - // if not allowed to interact - if (!checkPriv(player->getName(), "interact") && - (!from_inv_is_current_player || - !to_inv_is_current_player)) { - infostream << "Cannot move outside of player's inventory: " - << "No interact privilege" << std::endl; - delete a; return; } } @@ -695,7 +691,7 @@ void Server::handleCommand_InventoryAction(NetworkPacket* pkt) Handle restrictions and special cases of the drop action */ else if (a->getType() == IAction::Drop) { - IDropAction *da = (IDropAction*)a; + IDropAction *da = (IDropAction*)a.get(); da->from_inv.applyCurrentPlayer(player->getName()); @@ -708,22 +704,18 @@ void Server::handleCommand_InventoryAction(NetworkPacket* pkt) infostream << "Ignoring IDropAction from " << (da->from_inv.dump()) << ":" << da->from_list << " because src is " << da->from_list << std::endl; - delete a; return; } // Disallow dropping items if not allowed to interact - if (!checkPriv(player->getName(), "interact")) { - delete a; + if (!player_has_interact || !check_inv_access(da->from_inv)) return; - } // Disallow dropping items if dead if (playersao->isDead()) { infostream << "Ignoring IDropAction from " << (da->from_inv.dump()) << ":" << da->from_list << " because player is dead." << std::endl; - delete a; return; } } @@ -731,29 +723,28 @@ void Server::handleCommand_InventoryAction(NetworkPacket* pkt) Handle restrictions and special cases of the craft action */ else if (a->getType() == IAction::Craft) { - ICraftAction *ca = (ICraftAction*)a; + ICraftAction *ca = (ICraftAction*)a.get(); ca->craft_inv.applyCurrentPlayer(player->getName()); m_inventory_mgr->setInventoryModified(ca->craft_inv); - //bool craft_inv_is_current_player = - // (ca->craft_inv.type == InventoryLocation::PLAYER) && - // (ca->craft_inv.name == player->getName()); - // Disallow crafting if not allowed to interact - if (!checkPriv(player->getName(), "interact")) { + if (!player_has_interact) { infostream << "Cannot craft: " << "No interact privilege" << std::endl; - delete a; return; } + + if (!check_inv_access(ca->craft_inv)) + return; + } else { + // Unknown action. Ignored. + return; } // Do the action a->apply(m_inventory_mgr.get(), playersao, this); - // Eat the action - delete a; } void Server::handleCommand_ChatMessage(NetworkPacket* pkt) -- cgit v1.2.3 From 62913b872ea1b21a5aada55ed323476fbcea61dc Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Wed, 9 Sep 2020 18:12:03 +0100 Subject: Darwin platform build fix (#10376) the event header seemingly being generic with libevent thus renaming it. openal and opengl are deprecated on newer mac os releases thus suppressing the build warnings. --- src/client/camera.cpp | 2 +- src/client/clientenvironment.cpp | 2 +- src/client/event_manager.h | 2 +- src/client/localplayer.cpp | 2 +- src/client/shader.cpp | 5 +++ src/client/sound_openal.cpp | 1 + src/event.h | 71 ---------------------------------------- src/mtevent.h | 71 ++++++++++++++++++++++++++++++++++++++++ 8 files changed, 81 insertions(+), 75 deletions(-) delete mode 100644 src/event.h create mode 100644 src/mtevent.h (limited to 'src') diff --git a/src/client/camera.cpp b/src/client/camera.cpp index abc55e4b7..11f8a1c90 100644 --- a/src/client/camera.cpp +++ b/src/client/camera.cpp @@ -30,7 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "wieldmesh.h" #include "noise.h" // easeCurve #include "sound.h" -#include "event.h" +#include "mtevent.h" #include "nodedef.h" #include "util/numeric.h" #include "constants.h" diff --git a/src/client/clientenvironment.cpp b/src/client/clientenvironment.cpp index 895b0193c..0b7e92325 100644 --- a/src/client/clientenvironment.cpp +++ b/src/client/clientenvironment.cpp @@ -25,7 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "clientmap.h" #include "scripting_client.h" #include "mapblock_mesh.h" -#include "event.h" +#include "mtevent.h" #include "collision.h" #include "nodedef.h" #include "profiler.h" diff --git a/src/client/event_manager.h b/src/client/event_manager.h index 3762e89bf..16f7bcf07 100644 --- a/src/client/event_manager.h +++ b/src/client/event_manager.h @@ -19,7 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #pragma once -#include "event.h" +#include "mtevent.h" #include #include diff --git a/src/client/localplayer.cpp b/src/client/localplayer.cpp index 1e7040d57..f3eb1a2dd 100644 --- a/src/client/localplayer.cpp +++ b/src/client/localplayer.cpp @@ -19,7 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "localplayer.h" #include -#include "event.h" +#include "mtevent.h" #include "collision.h" #include "nodedef.h" #include "settings.h" diff --git a/src/client/shader.cpp b/src/client/shader.cpp index 0aba7b118..fc0a72319 100644 --- a/src/client/shader.cpp +++ b/src/client/shader.cpp @@ -45,7 +45,12 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #endif #else +#ifndef __APPLE__ #include +#else +#define GL_SILENCE_DEPRECATION +#include +#endif #endif /* diff --git a/src/client/sound_openal.cpp b/src/client/sound_openal.cpp index c1c916e68..f4e61f93e 100644 --- a/src/client/sound_openal.cpp +++ b/src/client/sound_openal.cpp @@ -28,6 +28,7 @@ with this program; ifnot, write to the Free Software Foundation, Inc., #include //#include #elif defined(__APPLE__) + #define OPENAL_DEPRECATED #include #include //#include diff --git a/src/event.h b/src/event.h deleted file mode 100644 index 149f7eecd..000000000 --- a/src/event.h +++ /dev/null @@ -1,71 +0,0 @@ -/* -Minetest -Copyright (C) 2013 celeron55, Perttu Ahola - -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 "irrlichttypes.h" - -class MtEvent -{ -public: - enum Type : u8 - { - VIEW_BOBBING_STEP = 0, - CAMERA_PUNCH_LEFT, - CAMERA_PUNCH_RIGHT, - PLAYER_FALLING_DAMAGE, - PLAYER_DAMAGE, - NODE_DUG, - PLAYER_JUMP, - PLAYER_REGAIN_GROUND, - TYPE_MAX, - }; - - virtual ~MtEvent() = default; - virtual Type getType() const = 0; -}; - -// An event with no parameters and customizable name -class SimpleTriggerEvent : public MtEvent -{ - Type type; - -public: - SimpleTriggerEvent(Type type) : type(type) {} - Type getType() const override { return type; } -}; - -class MtEventReceiver -{ -public: - virtual ~MtEventReceiver() = default; - virtual void onEvent(MtEvent *e) = 0; -}; - -typedef void (*event_receive_func)(MtEvent *e, void *data); - -class MtEventManager -{ -public: - virtual ~MtEventManager() = default; - virtual void put(MtEvent *e) = 0; - virtual void reg(MtEvent::Type type, event_receive_func f, void *data) = 0; - // If data==NULL, every occurence of f is deregistered. - virtual void dereg(MtEvent::Type type, event_receive_func f, void *data) = 0; -}; diff --git a/src/mtevent.h b/src/mtevent.h new file mode 100644 index 000000000..149f7eecd --- /dev/null +++ b/src/mtevent.h @@ -0,0 +1,71 @@ +/* +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola + +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 "irrlichttypes.h" + +class MtEvent +{ +public: + enum Type : u8 + { + VIEW_BOBBING_STEP = 0, + CAMERA_PUNCH_LEFT, + CAMERA_PUNCH_RIGHT, + PLAYER_FALLING_DAMAGE, + PLAYER_DAMAGE, + NODE_DUG, + PLAYER_JUMP, + PLAYER_REGAIN_GROUND, + TYPE_MAX, + }; + + virtual ~MtEvent() = default; + virtual Type getType() const = 0; +}; + +// An event with no parameters and customizable name +class SimpleTriggerEvent : public MtEvent +{ + Type type; + +public: + SimpleTriggerEvent(Type type) : type(type) {} + Type getType() const override { return type; } +}; + +class MtEventReceiver +{ +public: + virtual ~MtEventReceiver() = default; + virtual void onEvent(MtEvent *e) = 0; +}; + +typedef void (*event_receive_func)(MtEvent *e, void *data); + +class MtEventManager +{ +public: + virtual ~MtEventManager() = default; + virtual void put(MtEvent *e) = 0; + virtual void reg(MtEvent::Type type, event_receive_func f, void *data) = 0; + // If data==NULL, every occurence of f is deregistered. + virtual void dereg(MtEvent::Type type, event_receive_func f, void *data) = 0; +}; -- cgit v1.2.3 From 0683bea283d456253de343f37720789382ece6b2 Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Wed, 9 Sep 2020 18:12:58 +0100 Subject: Add NetBSD cpu affinity support code (#10378) --- src/threading/thread.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src') diff --git a/src/threading/thread.cpp b/src/threading/thread.cpp index eb51516c6..e19e6ae60 100644 --- a/src/threading/thread.cpp +++ b/src/threading/thread.cpp @@ -33,6 +33,8 @@ DEALINGS IN THE SOFTWARE. #include #elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) #include +#elif defined(__NetBSD__) + #include #elif defined(_MSC_VER) struct THREADNAME_INFO { DWORD dwType; // Must be 0x1000 @@ -285,7 +287,14 @@ bool Thread::bindToProcessor(unsigned int proc_number) CPU_SET(proc_number, &cpuset); return pthread_setaffinity_np(getThreadHandle(), sizeof(cpuset), &cpuset) == 0; +#elif defined(__NetBSD__) + cpuset_t *cpuset = cpuset_create(); + if (cpuset == NULL) + return false; + int r = pthread_setaffinity_np(getThreadHandle(), cpuset_size(cpuset), cpuset); + cpuset_destroy(cpuset); + return r == 0; #elif defined(__sun) || defined(sun) return processor_bind(P_LWPID, P_MYID, proc_number, NULL) == 0 -- cgit v1.2.3 From 3fb1f45301880a3aa901b752af1ecc912efe5915 Mon Sep 17 00:00:00 2001 From: Sebastien Marie Date: Thu, 10 Sep 2020 12:19:18 +0200 Subject: Remove Thread::kill() and related unittest (#10317) Closes: #6065 --- src/threading/thread.cpp | 54 +++++++++++++++++------------------------ src/threading/thread.h | 8 ------ src/unittest/test_threading.cpp | 25 ------------------- 3 files changed, 22 insertions(+), 65 deletions(-) (limited to 'src') diff --git a/src/threading/thread.cpp b/src/threading/thread.cpp index e19e6ae60..5cfc60995 100644 --- a/src/threading/thread.cpp +++ b/src/threading/thread.cpp @@ -73,7 +73,28 @@ Thread::Thread(const std::string &name) : Thread::~Thread() { - kill(); + // kill the thread if running + if (!m_running) { + wait(); + } else { + + m_running = false; + +#if defined(_WIN32) + // See https://msdn.microsoft.com/en-us/library/hh920601.aspx#thread__native_handle_method + TerminateThread((HANDLE) m_thread_obj->native_handle(), 0); + CloseHandle((HANDLE) m_thread_obj->native_handle()); +#else + // We need to pthread_kill instead on Android since NDKv5's pthread + // implementation is incomplete. +# ifdef __ANDROID__ + pthread_kill(getThreadHandle(), SIGKILL); +# else + pthread_cancel(getThreadHandle()); +# endif + wait(); +#endif + } // Make sure start finished mutex is unlocked before it's destroyed if (m_start_finished_mutex.try_lock()) @@ -138,37 +159,6 @@ bool Thread::wait() } -bool Thread::kill() -{ - if (!m_running) { - wait(); - return false; - } - - m_running = false; - -#if defined(_WIN32) - // See https://msdn.microsoft.com/en-us/library/hh920601.aspx#thread__native_handle_method - TerminateThread((HANDLE) m_thread_obj->native_handle(), 0); - CloseHandle((HANDLE) m_thread_obj->native_handle()); -#else - // We need to pthread_kill instead on Android since NDKv5's pthread - // implementation is incomplete. -# ifdef __ANDROID__ - pthread_kill(getThreadHandle(), SIGKILL); -# else - pthread_cancel(getThreadHandle()); -# endif - wait(); -#endif - - m_retval = nullptr; - m_joinable = false; - m_request_stop = false; - - return true; -} - bool Thread::getReturnValue(void **ret) { diff --git a/src/threading/thread.h b/src/threading/thread.h index 3946335f5..45fb171da 100644 --- a/src/threading/thread.h +++ b/src/threading/thread.h @@ -74,14 +74,6 @@ public: */ bool stop(); - /* - * Immediately terminates the thread. - * This should be used with extreme caution, as the thread will not have - * any opportunity to release resources it may be holding (such as memory - * or locks). - */ - bool kill(); - /* * Waits for thread to finish. * Note: This does not stop a thread, you have to do this on your own. diff --git a/src/unittest/test_threading.cpp b/src/unittest/test_threading.cpp index 8d4d814fd..65ef7c02d 100644 --- a/src/unittest/test_threading.cpp +++ b/src/unittest/test_threading.cpp @@ -31,7 +31,6 @@ public: void runTests(IGameDef *gamedef); void testStartStopWait(); - void testThreadKill(); void testAtomicSemaphoreThread(); }; @@ -40,7 +39,6 @@ static TestThreading g_test_instance; void TestThreading::runTests(IGameDef *gamedef) { TEST(testStartStopWait); - TEST(testThreadKill); TEST(testAtomicSemaphoreThread); } @@ -111,29 +109,6 @@ void TestThreading::testStartStopWait() } -void TestThreading::testThreadKill() -{ - SimpleTestThread *thread = new SimpleTestThread(300); - - UASSERT(thread->start() == true); - - // kill()ing is quite violent, so let's make sure our victim is sleeping - // before we do this... so we don't corrupt the rest of the program's state - sleep_ms(100); - UASSERT(thread->kill() == true); - - // The state of the thread object should be reset if all went well - UASSERT(thread->isRunning() == false); - UASSERT(thread->start() == true); - UASSERT(thread->stop() == true); - UASSERT(thread->wait() == true); - - // kill() after already waiting should fail. - UASSERT(thread->kill() == false); - - delete thread; -} - class AtomicTestThread : public Thread { public: -- cgit v1.2.3 From fcff9f291103411af6d8f946fbb275b6fa0583b9 Mon Sep 17 00:00:00 2001 From: hecks <42101236+hecktest@users.noreply.github.com> Date: Mon, 14 Sep 2020 19:27:25 +0200 Subject: Remove "generate normal maps" feature (#10313) Erase all traces of normal "generation" from fragment shaders Remove the "feature" from the engine and default config Remove any leftover documentation of it --- builtin/mainmenu/tab_settings.lua | 22 ++++------- builtin/settingtypes.txt | 14 +------ client/shaders/nodes_shader/opengl_fragment.glsl | 47 +---------------------- client/shaders/object_shader/opengl_fragment.glsl | 31 --------------- minetest.conf.example | 17 +------- src/client/shader.cpp | 28 -------------- src/defaultsettings.cpp | 3 -- src/settings_translation_file.cpp | 8 +--- 8 files changed, 12 insertions(+), 158 deletions(-) (limited to 'src') diff --git a/builtin/mainmenu/tab_settings.lua b/builtin/mainmenu/tab_settings.lua index 02b15c81b..510346f8d 100644 --- a/builtin/mainmenu/tab_settings.lua +++ b/builtin/mainmenu/tab_settings.lua @@ -191,15 +191,13 @@ local function formspec(tabview, name, tabdata) .. dump(core.settings:get_bool("enable_bumpmapping")) .. "]" .. "checkbox[8.25,1;cb_tonemapping;" .. fgettext("Tone Mapping") .. ";" .. dump(core.settings:get_bool("tone_mapping")) .. "]" .. - "checkbox[8.25,1.5;cb_generate_normalmaps;" .. fgettext("Generate Normal Maps") .. ";" - .. dump(core.settings:get_bool("generate_normalmaps")) .. "]" .. - "checkbox[8.25,2;cb_parallax;" .. fgettext("Parallax Occlusion") .. ";" + "checkbox[8.25,1.5;cb_parallax;" .. fgettext("Parallax Occlusion") .. ";" .. dump(core.settings:get_bool("enable_parallax_occlusion")) .. "]" .. - "checkbox[8.25,2.5;cb_waving_water;" .. fgettext("Waving Liquids") .. ";" + "checkbox[8.25,2;cb_waving_water;" .. fgettext("Waving Liquids") .. ";" .. dump(core.settings:get_bool("enable_waving_water")) .. "]" .. - "checkbox[8.25,3;cb_waving_leaves;" .. fgettext("Waving Leaves") .. ";" + "checkbox[8.25,2.5;cb_waving_leaves;" .. fgettext("Waving Leaves") .. ";" .. dump(core.settings:get_bool("enable_waving_leaves")) .. "]" .. - "checkbox[8.25,3.5;cb_waving_plants;" .. fgettext("Waving Plants") .. ";" + "checkbox[8.25,3;cb_waving_plants;" .. fgettext("Waving Plants") .. ";" .. dump(core.settings:get_bool("enable_waving_plants")) .. "]" else tab_string = tab_string .. @@ -208,14 +206,12 @@ local function formspec(tabview, name, tabdata) "label[8.38,1.2;" .. core.colorize("#888888", fgettext("Tone Mapping")) .. "]" .. "label[8.38,1.7;" .. core.colorize("#888888", - fgettext("Generate Normal Maps")) .. "]" .. - "label[8.38,2.2;" .. core.colorize("#888888", fgettext("Parallax Occlusion")) .. "]" .. - "label[8.38,2.7;" .. core.colorize("#888888", + "label[8.38,2.2;" .. core.colorize("#888888", fgettext("Waving Liquids")) .. "]" .. - "label[8.38,3.2;" .. core.colorize("#888888", + "label[8.38,2.7;" .. core.colorize("#888888", fgettext("Waving Leaves")) .. "]" .. - "label[8.38,3.7;" .. core.colorize("#888888", + "label[8.38,3.2;" .. core.colorize("#888888", fgettext("Waving Plants")) .. "]" end @@ -275,10 +271,6 @@ local function handle_settings_buttons(this, fields, tabname, tabdata) core.settings:set("tone_mapping", fields["cb_tonemapping"]) return true end - if fields["cb_generate_normalmaps"] then - core.settings:set("generate_normalmaps", fields["cb_generate_normalmaps"]) - return true - end if fields["cb_parallax"] then core.settings:set("enable_parallax_occlusion", fields["cb_parallax"]) return true diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index 39cc22d62..6d9c6f573 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -543,22 +543,10 @@ tone_mapping (Filmic tone mapping) bool false [***Bumpmapping] -# Enables bumpmapping for textures. Normalmaps need to be supplied by the texture pack -# or need to be auto-generated. +# Enables bumpmapping for textures. Normalmaps need to be supplied by the texture pack. # Requires shaders to be enabled. enable_bumpmapping (Bumpmapping) bool false -# Enables on the fly normalmap generation (Emboss effect). -# Requires bumpmapping to be enabled. -generate_normalmaps (Generate normalmaps) bool false - -# Strength of generated normalmaps. -normalmaps_strength (Normalmaps strength) float 0.6 - -# Defines sampling step of texture. -# A higher value results in smoother normal maps. -normalmaps_smooth (Normalmaps sampling) int 0 0 2 - [***Parallax Occlusion] # Enables parallax occlusion mapping. diff --git a/client/shaders/nodes_shader/opengl_fragment.glsl b/client/shaders/nodes_shader/opengl_fragment.glsl index 7213612bd..437b325d3 100644 --- a/client/shaders/nodes_shader/opengl_fragment.glsl +++ b/client/shaders/nodes_shader/opengl_fragment.glsl @@ -71,16 +71,6 @@ void get_texture_flags() } } -float intensity(vec3 color) -{ - return (color.r + color.g + color.b) / 3.0; -} - -float get_rgb_height(vec2 uv) -{ - return intensity(texture2D(baseTexture, uv).rgb); -} - vec4 get_normal_map(vec2 uv) { vec4 bump = texture2D(normalTexture, uv).rgba; @@ -115,19 +105,6 @@ float find_intersection(vec2 dp, vec2 ds) return best_depth; } -float find_intersectionRGB(vec2 dp, vec2 ds) -{ - const float depth_step = 1.0 / 24.0; - float depth = 1.0; - for (int i = 0 ; i < 24 ; i++) { - float h = get_rgb_height(dp + ds * depth); - if (h >= depth) - break; - depth -= depth_step; - } - return depth; -} - void main(void) { vec3 color; @@ -149,21 +126,17 @@ void main(void) float h = normal.a * scale - bias; uv += h * normal.z * eyeRay; } + } #endif - #if PARALLAX_OCCLUSION_MODE == 1 // Relief mapping if (normalTexturePresent && area_enable_parallax > 0.0) { vec2 ds = eyeRay * PARALLAX_OCCLUSION_SCALE; float dist = find_intersection(uv, ds); uv += dist * ds; -#endif - } else if (GENERATE_NORMALMAPS == 1 && area_enable_parallax > 0.0) { - vec2 ds = eyeRay * PARALLAX_OCCLUSION_SCALE; - float dist = find_intersectionRGB(uv, ds); - uv += dist * ds; } #endif +#endif #if USE_NORMALMAPS == 1 if (normalTexturePresent) { @@ -172,22 +145,6 @@ void main(void) } #endif -#if GENERATE_NORMALMAPS == 1 - if (normalTexturePresent == false) { - float tl = get_rgb_height(vec2(uv.x - SAMPLE_STEP, uv.y + SAMPLE_STEP)); - float t = get_rgb_height(vec2(uv.x - SAMPLE_STEP, uv.y - SAMPLE_STEP)); - float tr = get_rgb_height(vec2(uv.x + SAMPLE_STEP, uv.y + SAMPLE_STEP)); - float r = get_rgb_height(vec2(uv.x + SAMPLE_STEP, uv.y)); - float br = get_rgb_height(vec2(uv.x + SAMPLE_STEP, uv.y - SAMPLE_STEP)); - float b = get_rgb_height(vec2(uv.x, uv.y - SAMPLE_STEP)); - float bl = get_rgb_height(vec2(uv.x -SAMPLE_STEP, uv.y - SAMPLE_STEP)); - float l = get_rgb_height(vec2(uv.x - SAMPLE_STEP, uv.y)); - float dX = (tr + 2.0 * r + br) - (tl + 2.0 * l + bl); - float dY = (bl + 2.0 * b + br) - (tl + 2.0 * t + tr); - bump = vec4(normalize(vec3 (dX, dY, NORMALMAPS_STRENGTH)), 1.0); - use_normalmap = true; - } -#endif vec4 base = texture2D(baseTexture, uv).rgba; #ifdef USE_DISCARD diff --git a/client/shaders/object_shader/opengl_fragment.glsl b/client/shaders/object_shader/opengl_fragment.glsl index 2d33ca439..a8a43e1e2 100644 --- a/client/shaders/object_shader/opengl_fragment.glsl +++ b/client/shaders/object_shader/opengl_fragment.glsl @@ -74,20 +74,6 @@ void get_texture_flags() } } -float intensity(vec3 color) -{ - return (color.r + color.g + color.b) / 3.0; -} - -float get_rgb_height(vec2 uv) -{ - if (texSeamless) { - return intensity(texture2D(baseTexture, uv).rgb); - } else { - return intensity(texture2D(baseTexture, clamp(uv, 0.0, 0.999)).rgb); - } -} - vec4 get_normal_map(vec2 uv) { vec4 bump = texture2D(normalTexture, uv).rgba; @@ -110,23 +96,6 @@ void main(void) } #endif -#if GENERATE_NORMALMAPS == 1 - if (normalTexturePresent == false) { - float tl = get_rgb_height(vec2(uv.x - SAMPLE_STEP, uv.y + SAMPLE_STEP)); - float t = get_rgb_height(vec2(uv.x - SAMPLE_STEP, uv.y - SAMPLE_STEP)); - float tr = get_rgb_height(vec2(uv.x + SAMPLE_STEP, uv.y + SAMPLE_STEP)); - float r = get_rgb_height(vec2(uv.x + SAMPLE_STEP, uv.y)); - float br = get_rgb_height(vec2(uv.x + SAMPLE_STEP, uv.y - SAMPLE_STEP)); - float b = get_rgb_height(vec2(uv.x, uv.y - SAMPLE_STEP)); - float bl = get_rgb_height(vec2(uv.x -SAMPLE_STEP, uv.y - SAMPLE_STEP)); - float l = get_rgb_height(vec2(uv.x - SAMPLE_STEP, uv.y)); - float dX = (tr + 2.0 * r + br) - (tl + 2.0 * l + bl); - float dY = (bl + 2.0 * b + br) - (tl + 2.0 * t + tr); - bump = vec4(normalize(vec3 (dX, dY, NORMALMAPS_STRENGTH)), 1.0); - use_normalmap = true; - } -#endif - vec4 base = texture2D(baseTexture, uv).rgba; #ifdef USE_DISCARD diff --git a/minetest.conf.example b/minetest.conf.example index 520125713..6b315b6ea 100644 --- a/minetest.conf.example +++ b/minetest.conf.example @@ -604,26 +604,11 @@ #### Bumpmapping -# Enables bumpmapping for textures. Normalmaps need to be supplied by the texture pack -# or need to be auto-generated. +# Enables bumpmapping for textures. Normalmaps need to be supplied by the texture pack. # Requires shaders to be enabled. # type: bool # enable_bumpmapping = false -# Enables on the fly normalmap generation (Emboss effect). -# Requires bumpmapping to be enabled. -# type: bool -# generate_normalmaps = false - -# Strength of generated normalmaps. -# type: float -# normalmaps_strength = 0.6 - -# Defines sampling step of texture. -# A higher value results in smoother normal maps. -# type: int min: 0 max: 2 -# normalmaps_smooth = 0 - #### Parallax Occlusion # Enables parallax occlusion mapping. diff --git a/src/client/shader.cpp b/src/client/shader.cpp index fc0a72319..c5fe5dfe0 100644 --- a/src/client/shader.cpp +++ b/src/client/shader.cpp @@ -688,34 +688,6 @@ ShaderInfo generate_shader(const std::string &name, u8 material_type, u8 drawtyp shaders_header += itos(drawtype); shaders_header += "\n"; - if (g_settings->getBool("generate_normalmaps")) { - shaders_header += "#define GENERATE_NORMALMAPS 1\n"; - } else { - shaders_header += "#define GENERATE_NORMALMAPS 0\n"; - } - shaders_header += "#define NORMALMAPS_STRENGTH "; - shaders_header += ftos(g_settings->getFloat("normalmaps_strength")); - shaders_header += "\n"; - float sample_step; - int smooth = (int)g_settings->getFloat("normalmaps_smooth"); - switch (smooth){ - case 0: - sample_step = 0.0078125; // 1.0 / 128.0 - break; - case 1: - sample_step = 0.00390625; // 1.0 / 256.0 - break; - case 2: - sample_step = 0.001953125; // 1.0 / 512.0 - break; - default: - sample_step = 0.0078125; - break; - } - shaders_header += "#define SAMPLE_STEP "; - shaders_header += ftos(sample_step); - shaders_header += "\n"; - if (g_settings->getBool("enable_bumpmapping")) shaders_header += "#define ENABLE_BUMPMAPPING\n"; diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index d2115c959..3a0b88dc2 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -253,9 +253,6 @@ void set_default_settings(Settings *settings) settings->setDefault("tone_mapping", "false"); settings->setDefault("enable_bumpmapping", "false"); settings->setDefault("enable_parallax_occlusion", "false"); - settings->setDefault("generate_normalmaps", "false"); - settings->setDefault("normalmaps_strength", "0.6"); - settings->setDefault("normalmaps_smooth", "1"); settings->setDefault("parallax_occlusion_mode", "1"); settings->setDefault("parallax_occlusion_iterations", "4"); settings->setDefault("parallax_occlusion_scale", "0.08"); diff --git a/src/settings_translation_file.cpp b/src/settings_translation_file.cpp index febfbb9d3..0cd772337 100644 --- a/src/settings_translation_file.cpp +++ b/src/settings_translation_file.cpp @@ -242,13 +242,7 @@ fake_function() { gettext("Enables Hable's 'Uncharted 2' filmic tone mapping.\nSimulates the tone curve of photographic film and how this approximates the\nappearance of high dynamic range images. Mid-range contrast is slightly\nenhanced, highlights and shadows are gradually compressed."); gettext("Bumpmapping"); gettext("Bumpmapping"); - gettext("Enables bumpmapping for textures. Normalmaps need to be supplied by the texture pack\nor need to be auto-generated.\nRequires shaders to be enabled."); - gettext("Generate normalmaps"); - gettext("Enables on the fly normalmap generation (Emboss effect).\nRequires bumpmapping to be enabled."); - gettext("Normalmaps strength"); - gettext("Strength of generated normalmaps."); - gettext("Normalmaps sampling"); - gettext("Defines sampling step of texture.\nA higher value results in smoother normal maps."); + gettext("Enables bumpmapping for textures. Normalmaps need to be supplied by the texture pack.\nRequires shaders to be enabled."); gettext("Parallax Occlusion"); gettext("Parallax occlusion"); gettext("Enables parallax occlusion mapping.\nRequires shaders to be enabled."); -- cgit v1.2.3 From 9ec75d77651c333eca3c5b46a3a56c8353fed464 Mon Sep 17 00:00:00 2001 From: rubenwardy Date: Wed, 16 Sep 2020 14:51:11 +0100 Subject: Clean up server-side translations, remove global variable (#10075) --- src/client/client.cpp | 9 ++------ src/filesys.cpp | 15 +++++++++++++ src/filesys.h | 2 ++ src/script/lua_api/l_env.cpp | 6 ++--- src/server.cpp | 53 ++++++++++++++++++-------------------------- src/server.h | 7 ++++-- src/serverlist.cpp | 10 +-------- src/translation.cpp | 8 ------- src/translation.h | 5 ----- 9 files changed, 50 insertions(+), 65 deletions(-) (limited to 'src') diff --git a/src/client/client.cpp b/src/client/client.cpp index 745cce900..d6e529c40 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -238,18 +238,13 @@ void Client::scanModSubfolder(const std::string &mod_name, const std::string &mo infostream << "Client::scanModSubfolder(): Loading \"" << real_path << "\" as \"" << vfs_path << "\"." << std::endl; - std::ifstream is(real_path, std::ios::binary | std::ios::ate); - if(!is.good()) { + std::string contents; + if (!fs::ReadFile(real_path, contents)) { errorstream << "Client::scanModSubfolder(): Can't read file \"" << real_path << "\"." << std::endl; continue; } - auto size = is.tellg(); - std::string contents(size, '\0'); - is.seekg(0); - is.read(&contents[0], size); - infostream << " size: " << size << " bytes" << std::endl; m_mod_vfs.emplace(vfs_path, contents); } } diff --git a/src/filesys.cpp b/src/filesys.cpp index 0bc351669..2470b1b64 100644 --- a/src/filesys.cpp +++ b/src/filesys.cpp @@ -750,6 +750,21 @@ bool safeWriteToFile(const std::string &path, const std::string &content) return true; } +bool ReadFile(const std::string &path, std::string &out) +{ + std::ifstream is(path, std::ios::binary | std::ios::ate); + if (!is.good()) { + return false; + } + + auto size = is.tellg(); + out.resize(size); + is.seekg(0); + is.read(&out[0], size); + + return true; +} + bool Rename(const std::string &from, const std::string &to) { return rename(from.c_str(), to.c_str()) == 0; diff --git a/src/filesys.h b/src/filesys.h index 09f129aa3..b2c800c55 100644 --- a/src/filesys.h +++ b/src/filesys.h @@ -128,6 +128,8 @@ const char *GetFilenameFromPath(const char *path); bool safeWriteToFile(const std::string &path, const std::string &content); +bool ReadFile(const std::string &path, std::string &out); + bool Rename(const std::string &from, const std::string &to); } // namespace fs diff --git a/src/script/lua_api/l_env.cpp b/src/script/lua_api/l_env.cpp index b2bc8c5f6..138e88ae8 100644 --- a/src/script/lua_api/l_env.cpp +++ b/src/script/lua_api/l_env.cpp @@ -1340,9 +1340,9 @@ int ModApiEnvMod::l_get_translated_string(lua_State * L) GET_ENV_PTR; std::string lang_code = luaL_checkstring(L, 1); std::string string = luaL_checkstring(L, 2); - getServer(L)->loadTranslationLanguage(lang_code); - string = wide_to_utf8(translate_string(utf8_to_wide(string), - &(*g_server_translations)[lang_code])); + + auto *translations = getServer(L)->getTranslationLanguage(lang_code); + string = wide_to_utf8(translate_string(utf8_to_wide(string), translations)); lua_pushstring(L, string.c_str()); return 1; } diff --git a/src/server.cpp b/src/server.cpp index 7b3978462..b8a99f6ae 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -2451,31 +2451,14 @@ bool Server::addMediaFile(const std::string &filename, // Ok, attempt to load the file and add to cache // Read data - std::ifstream fis(filepath.c_str(), std::ios_base::binary); - if (!fis.good()) { - errorstream << "Server::addMediaFile(): Could not open \"" - << filename << "\" for reading" << std::endl; - return false; - } std::string filedata; - bool bad = false; - for (;;) { - char buf[1024]; - fis.read(buf, sizeof(buf)); - std::streamsize len = fis.gcount(); - filedata.append(buf, len); - if (fis.eof()) - break; - if (!fis.good()) { - bad = true; - break; - } - } - if (bad) { - errorstream << "Server::addMediaFile(): Failed to read \"" - << filename << "\"" << std::endl; + if (!fs::ReadFile(filepath, filedata)) { + errorstream << "Server::addMediaFile(): Failed to open \"" + << filename << "\" for reading" << std::endl; return false; - } else if (filedata.empty()) { + } + + if (filedata.empty()) { errorstream << "Server::addMediaFile(): Empty file \"" << filepath << "\"" << std::endl; return false; @@ -3890,19 +3873,27 @@ void Server::broadcastModChannelMessage(const std::string &channel, } } -void Server::loadTranslationLanguage(const std::string &lang_code) +Translations *Server::getTranslationLanguage(const std::string &lang_code) { - if (g_server_translations->count(lang_code)) - return; // Already loaded + if (lang_code.empty()) + return nullptr; + + auto it = server_translations.find(lang_code); + if (it != server_translations.end()) + return &it->second; // Already loaded + + // [] will create an entry + auto *translations = &server_translations[lang_code]; std::string suffix = "." + lang_code + ".tr"; for (const auto &i : m_media) { if (str_ends_with(i.first, suffix)) { - std::ifstream t(i.second.path); - std::string data((std::istreambuf_iterator(t)), - std::istreambuf_iterator()); - - (*g_server_translations)[lang_code].loadTranslation(data); + std::string data; + if (fs::ReadFile(i.second.path, data)) { + translations->loadTranslation(data); + } } } + + return translations; } diff --git a/src/server.h b/src/server.h index be6f60abc..258d75eaf 100644 --- a/src/server.h +++ b/src/server.h @@ -38,6 +38,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "serverenvironment.h" #include "clientiface.h" #include "chatmessage.h" +#include "translation.h" #include #include #include @@ -343,8 +344,8 @@ public: // Send block to specific player only bool SendBlock(session_t peer_id, const v3s16 &blockpos); - // Load translations for a language - void loadTranslationLanguage(const std::string &lang_code); + // Get or load translations for a language + Translations *getTranslationLanguage(const std::string &lang_code); // Bind address Address m_bind_addr; @@ -557,6 +558,8 @@ private: // Mods std::unique_ptr m_modmgr; + std::unordered_map server_translations; + /* Threads */ diff --git a/src/serverlist.cpp b/src/serverlist.cpp index 2f6ab2e61..c7fe2d888 100644 --- a/src/serverlist.cpp +++ b/src/serverlist.cpp @@ -52,15 +52,7 @@ std::vector getLocal() { std::string path = ServerList::getFilePath(); std::string liststring; - if (fs::PathExists(path)) { - std::ifstream istream(path.c_str()); - if (istream.is_open()) { - std::ostringstream ostream; - ostream << istream.rdbuf(); - liststring = ostream.str(); - istream.close(); - } - } + fs::ReadFile(path, liststring); return deSerialize(liststring); } diff --git a/src/translation.cpp b/src/translation.cpp index 8bbaee0a3..82e813a5d 100644 --- a/src/translation.cpp +++ b/src/translation.cpp @@ -29,14 +29,6 @@ Translations client_translations; Translations *g_client_translations = &client_translations; #endif -// Per language server translations -std::unordered_map server_translations; -std::unordered_map *g_server_translations = &server_translations; - -Translations::~Translations() -{ - clear(); -} void Translations::clear() { diff --git a/src/translation.h b/src/translation.h index 71423b15e..f1a336fca 100644 --- a/src/translation.h +++ b/src/translation.h @@ -23,7 +23,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include class Translations; -extern std::unordered_map *g_server_translations; #ifndef SERVER extern Translations *g_client_translations; #endif @@ -31,10 +30,6 @@ extern Translations *g_client_translations; class Translations { public: - Translations() = default; - - ~Translations(); - void loadTranslation(const std::string &data); void clear(); const std::wstring &getTranslation( -- cgit v1.2.3 From 49117de47658cd6c885f88010c9328f8ce3e6e93 Mon Sep 17 00:00:00 2001 From: Lars Date: Sun, 20 Sep 2020 12:51:12 -0700 Subject: Record player existence in dymmy database. --- src/database/database-dummy.cpp | 23 +++++++++++++++++++++++ src/database/database-dummy.h | 9 +++++---- 2 files changed, 28 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/database/database-dummy.cpp b/src/database/database-dummy.cpp index a3d8cd579..b56f341c5 100644 --- a/src/database/database-dummy.cpp +++ b/src/database/database-dummy.cpp @@ -22,6 +22,7 @@ Dummy database class */ #include "database-dummy.h" +#include "remoteplayer.h" bool Database_Dummy::saveBlock(const v3s16 &pos, const std::string &data) @@ -57,3 +58,25 @@ void Database_Dummy::listAllLoadableBlocks(std::vector &dst) } } +void Database_Dummy::savePlayer(RemotePlayer *player) +{ + m_player_database.insert(player->getName()); +} + +bool Database_Dummy::loadPlayer(RemotePlayer *player, PlayerSAO *sao) +{ + return m_player_database.find(player->getName()) != m_player_database.end(); +} + +bool Database_Dummy::removePlayer(const std::string &name) +{ + m_player_database.erase(name); + return true; +} + +void Database_Dummy::listPlayers(std::vector &res) +{ + for (const auto &player : m_player_database) { + res.emplace_back(player); + } +} diff --git a/src/database/database-dummy.h b/src/database/database-dummy.h index 2d87d58f6..b69919f84 100644 --- a/src/database/database-dummy.h +++ b/src/database/database-dummy.h @@ -32,14 +32,15 @@ public: bool deleteBlock(const v3s16 &pos); void listAllLoadableBlocks(std::vector &dst); - void savePlayer(RemotePlayer *player) {} - bool loadPlayer(RemotePlayer *player, PlayerSAO *sao) { return true; } - bool removePlayer(const std::string &name) { return true; } - void listPlayers(std::vector &res) {} + void savePlayer(RemotePlayer *player); + bool loadPlayer(RemotePlayer *player, PlayerSAO *sao); + bool removePlayer(const std::string &name); + void listPlayers(std::vector &res); void beginSave() {} void endSave() {} private: std::map m_database; + std::set m_player_database; }; -- cgit v1.2.3 From e7f33ee2f1c57b2b5c48d1a54a5f9e4c72a3275c Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Mon, 21 Sep 2020 19:10:44 +0200 Subject: Settings: Fix crash on exit due to group double-free --- src/settings.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/settings.cpp b/src/settings.cpp index 55404319e..473a216bf 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -824,13 +824,21 @@ bool Settings::setDefault(const std::string &name, const std::string &value) bool Settings::setGroup(const std::string &name, Settings *group) { - return setEntry(name, &group, true, false); + // Settings must own the group pointer + // avoid double-free by copying the source + Settings *copy = new Settings(); + *copy = *group; + return setEntry(name, ©, true, false); } bool Settings::setGroupDefault(const std::string &name, Settings *group) { - return setEntry(name, &group, true, true); + // Settings must own the group pointer + // avoid double-free by copying the source + Settings *copy = new Settings(); + *copy = *group; + return setEntry(name, ©, true, true); } -- cgit v1.2.3 From 55e2dd911b16a70ee976e067cf34a48922db9dcb Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Tue, 22 Sep 2020 18:38:33 +0200 Subject: Fix chat/infotext overlap if many chat lines (#10399) Moves the infotext depending on the value of the recent_chat_messages value + 2 additional lines to account for the 2 debug mode lines + 1 additional line as "buffer" for better readability if chat is full. --- src/client/gameui.cpp | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/client/gameui.cpp b/src/client/gameui.cpp index 81c268e44..75e7d15b9 100644 --- a/src/client/gameui.cpp +++ b/src/client/gameui.cpp @@ -61,17 +61,6 @@ void GameUI::init() m_guitext2 = gui::StaticText::add(guienv, L"", core::rect(0, 0, 0, 0), false, false, guiroot); - // At the middle of the screen - // Object infos are shown in this - m_guitext_info = gui::StaticText::add(guienv, L"", - core::rect(0, 0, 400, g_fontengine->getTextHeight() * 5 + 5) - + v2s32(100, 200), false, true, guiroot); - - // Status text (displays info when showing and hiding GUI stuff, etc.) - m_guitext_status = gui::StaticText::add(guienv, L"", - core::rect(0, 0, 0, 0), false, false, guiroot); - m_guitext_status->setVisible(false); - // Chat text m_guitext_chat = gui::StaticText::add(guienv, L"", core::rect(0, 0, 0, 0), //false, false); // Disable word wrap as of now @@ -82,6 +71,20 @@ void GameUI::init() chat_font_size, FM_Unspecified)); } + // At the middle of the screen + // Object infos are shown in this + u32 chat_font_height = m_guitext_chat->getActiveFont()->getDimension(L"Ay").Height; + m_guitext_info = gui::StaticText::add(guienv, L"", + core::rect(0, 0, 400, g_fontengine->getTextHeight() * 5 + 5) + + v2s32(100, chat_font_height * + (g_settings->getU16("recent_chat_messages") + 3)), + false, true, guiroot); + + // Status text (displays info when showing and hiding GUI stuff, etc.) + m_guitext_status = gui::StaticText::add(guienv, L"", + core::rect(0, 0, 0, 0), false, false, guiroot); + m_guitext_status->setVisible(false); + // Profiler text (size is updated when text is updated) m_guitext_profiler = gui::StaticText::add(guienv, L"", core::rect(0, 0, 0, 0), false, false, guiroot); -- cgit v1.2.3 From add68369a59af90f8b4203b53695521c6d657d6b Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Tue, 22 Sep 2020 18:40:34 +0200 Subject: Settings: Fix unittest memory leak, change input types --- src/settings.cpp | 10 +++++----- src/settings.h | 4 ++-- src/unittest/test_settings.cpp | 18 +++++++++--------- 3 files changed, 16 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/settings.cpp b/src/settings.cpp index 473a216bf..28b72c4e3 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -822,22 +822,22 @@ bool Settings::setDefault(const std::string &name, const std::string &value) } -bool Settings::setGroup(const std::string &name, Settings *group) +bool Settings::setGroup(const std::string &name, const Settings &group) { // Settings must own the group pointer // avoid double-free by copying the source Settings *copy = new Settings(); - *copy = *group; + *copy = group; return setEntry(name, ©, true, false); } -bool Settings::setGroupDefault(const std::string &name, Settings *group) +bool Settings::setGroupDefault(const std::string &name, const Settings &group) { // Settings must own the group pointer // avoid double-free by copying the source Settings *copy = new Settings(); - *copy = *group; + *copy = group; return setEntry(name, ©, true, true); } @@ -1060,7 +1060,7 @@ void Settings::overrideDefaults(Settings *other) { for (const auto &setting : other->m_settings) { if (setting.second.is_group) { - setGroupDefault(setting.first, setting.second.group); + setGroupDefault(setting.first, *setting.second.group); continue; } const FlagDesc *flagdesc = getFlagDescFallback(setting.first); diff --git a/src/settings.h b/src/settings.h index 0c9a155db..ccc252049 100644 --- a/src/settings.h +++ b/src/settings.h @@ -192,8 +192,8 @@ public: bool set_group, bool set_default); bool set(const std::string &name, const std::string &value); bool setDefault(const std::string &name, const std::string &value); - bool setGroup(const std::string &name, Settings *group); - bool setGroupDefault(const std::string &name, Settings *group); + bool setGroup(const std::string &name, const Settings &group); + bool setGroupDefault(const std::string &name, const Settings &group); bool setBool(const std::string &name, bool value); bool setS16(const std::string &name, s16 value); bool setU16(const std::string &name, u16 value); diff --git a/src/unittest/test_settings.cpp b/src/unittest/test_settings.cpp index aa56f3e06..f91ba5b67 100644 --- a/src/unittest/test_settings.cpp +++ b/src/unittest/test_settings.cpp @@ -149,15 +149,15 @@ void TestSettings::testAllSettings() UASSERT(group->getS16("a") == 5); UASSERT(fabs(group->getFloat("bb") - 2.5) < 0.001); - Settings *group3 = new Settings; - group3->set("cat", "meow"); - group3->set("dog", "woof"); - - Settings *group2 = new Settings; - group2->setS16("num_apples", 4); - group2->setS16("num_oranges", 53); - group2->setGroup("animals", group3); - group2->set("animals", "cute"); //destroys group 3 + Settings group3; + group3.set("cat", "meow"); + group3.set("dog", "woof"); + + Settings group2; + group2.setS16("num_apples", 4); + group2.setS16("num_oranges", 53); + group2.setGroup("animals", group3); + group2.set("animals", "cute"); //destroys group 3 s.setGroup("groupy_thing", group2); // Test set failure conditions -- cgit v1.2.3 From 787561b29afdbc78769f68c2f5c4f2cff1b32340 Mon Sep 17 00:00:00 2001 From: Vincent Robinson Date: Wed, 23 Sep 2020 10:12:20 -0700 Subject: Replace MyEventReceiver KeyList with std::unordered_set (#10419) --- src/client/inputhandler.cpp | 48 +++++++++++--------- src/client/inputhandler.h | 108 ++++++++------------------------------------ src/client/keycode.h | 19 ++++++++ 3 files changed, 64 insertions(+), 111 deletions(-) (limited to 'src') diff --git a/src/client/inputhandler.cpp b/src/client/inputhandler.cpp index 608a405a8..ee3e37ae9 100644 --- a/src/client/inputhandler.cpp +++ b/src/client/inputhandler.cpp @@ -112,7 +112,7 @@ bool MyEventReceiver::OnEvent(const SEvent &event) // Remember whether each key is down or up if (event.EventType == irr::EET_KEY_INPUT_EVENT) { const KeyPress &keyCode = event.KeyInput; - if (keysListenedFor[keyCode]) { + if (keysListenedFor.count(keyCode)) { // If the key is being held down then the OS may // send a continuous stream of keydown events. // In this case, we don't want to let this @@ -120,15 +120,15 @@ bool MyEventReceiver::OnEvent(const SEvent &event) // certain actions to repeat constantly. if (event.KeyInput.PressedDown) { if (!IsKeyDown(keyCode)) { - keyWasDown.set(keyCode); - keyWasPressed.set(keyCode); + keyWasDown.insert(keyCode); + keyWasPressed.insert(keyCode); } - keyIsDown.set(keyCode); + keyIsDown.insert(keyCode); } else { if (IsKeyDown(keyCode)) - keyWasReleased.set(keyCode); + keyWasReleased.insert(keyCode); - keyIsDown.unset(keyCode); + keyIsDown.erase(keyCode); } return true; @@ -153,36 +153,36 @@ bool MyEventReceiver::OnEvent(const SEvent &event) switch (event.MouseInput.Event) { case EMIE_LMOUSE_PRESSED_DOWN: key = "KEY_LBUTTON"; - keyIsDown.set(key); - keyWasDown.set(key); - keyWasPressed.set(key); + keyIsDown.insert(key); + keyWasDown.insert(key); + keyWasPressed.insert(key); break; case EMIE_MMOUSE_PRESSED_DOWN: key = "KEY_MBUTTON"; - keyIsDown.set(key); - keyWasDown.set(key); - keyWasPressed.set(key); + keyIsDown.insert(key); + keyWasDown.insert(key); + keyWasPressed.insert(key); break; case EMIE_RMOUSE_PRESSED_DOWN: key = "KEY_RBUTTON"; - keyIsDown.set(key); - keyWasDown.set(key); - keyWasPressed.set(key); + keyIsDown.insert(key); + keyWasDown.insert(key); + keyWasPressed.insert(key); break; case EMIE_LMOUSE_LEFT_UP: key = "KEY_LBUTTON"; - keyIsDown.unset(key); - keyWasReleased.set(key); + keyIsDown.erase(key); + keyWasReleased.insert(key); break; case EMIE_MMOUSE_LEFT_UP: key = "KEY_MBUTTON"; - keyIsDown.unset(key); - keyWasReleased.set(key); + keyIsDown.erase(key); + keyWasReleased.insert(key); break; case EMIE_RMOUSE_LEFT_UP: key = "KEY_RBUTTON"; - keyIsDown.unset(key); - keyWasReleased.set(key); + keyIsDown.erase(key); + keyWasReleased.insert(key); break; case EMIE_MOUSE_WHEEL: mouse_wheel += event.MouseInput.Wheel; @@ -235,7 +235,11 @@ void RandomInputHandler::step(float dtime) i.counter -= dtime; if (i.counter < 0.0) { i.counter = 0.1 * Rand(1, i.time_max); - keydown.toggle(getKeySetting(i.key.c_str())); + KeyPress k = getKeySetting(i.key.c_str()); + if (keydown.count(k)) + keydown.erase(k); + else + keydown.insert(k); } } { diff --git a/src/client/inputhandler.h b/src/client/inputhandler.h index def147a82..885f34e05 100644 --- a/src/client/inputhandler.h +++ b/src/client/inputhandler.h @@ -21,9 +21,9 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "irrlichttypes_extrabloated.h" #include "joystick_controller.h" -#include #include "keycode.h" #include "renderingengine.h" +#include #ifdef HAVE_TOUCHSCREENGUI #include "gui/touchscreengui.h" @@ -61,98 +61,32 @@ struct KeyCache InputHandler *handler; }; -class KeyList : private std::list -{ - typedef std::list super; - typedef super::iterator iterator; - typedef super::const_iterator const_iterator; - - virtual const_iterator find(const KeyPress &key) const - { - const_iterator f(begin()); - const_iterator e(end()); - - while (f != e) { - if (*f == key) - return f; - - ++f; - } - - return e; - } - - virtual iterator find(const KeyPress &key) - { - iterator f(begin()); - iterator e(end()); - - while (f != e) { - if (*f == key) - return f; - - ++f; - } - - return e; - } - -public: - void clear() { super::clear(); } - - void set(const KeyPress &key) - { - if (find(key) == end()) - push_back(key); - } - - void unset(const KeyPress &key) - { - iterator p(find(key)); - - if (p != end()) - erase(p); - } - - void toggle(const KeyPress &key) - { - iterator p(this->find(key)); - - if (p != end()) - erase(p); - else - push_back(key); - } - - bool operator[](const KeyPress &key) const { return find(key) != end(); } -}; - class MyEventReceiver : public IEventReceiver { public: // This is the one method that we have to implement virtual bool OnEvent(const SEvent &event); - bool IsKeyDown(const KeyPress &keyCode) const { return keyIsDown[keyCode]; } + bool IsKeyDown(const KeyPress &keyCode) const { return keyIsDown.count(keyCode); } // Checks whether a key was down and resets the state bool WasKeyDown(const KeyPress &keyCode) { - bool b = keyWasDown[keyCode]; + bool b = keyWasDown.count(keyCode); if (b) - keyWasDown.unset(keyCode); + keyWasDown.erase(keyCode); return b; } // Checks whether a key was just pressed. State will be cleared // in the subsequent iteration of Game::processPlayerInteraction - bool WasKeyPressed(const KeyPress &keycode) const { return keyWasPressed[keycode]; } + bool WasKeyPressed(const KeyPress &keycode) const { return keyWasPressed.count(keycode); } // Checks whether a key was just released. State will be cleared // in the subsequent iteration of Game::processPlayerInteraction - bool WasKeyReleased(const KeyPress &keycode) const { return keyWasReleased[keycode]; } + bool WasKeyReleased(const KeyPress &keycode) const { return keyWasReleased.count(keycode); } - void listenForKey(const KeyPress &keyCode) { keysListenedFor.set(keyCode); } + void listenForKey(const KeyPress &keyCode) { keysListenedFor.insert(keyCode); } void dontListenForKeys() { keysListenedFor.clear(); } s32 getMouseWheel() @@ -198,24 +132,20 @@ public: #endif private: - // The current state of keys - KeyList keyIsDown; + //! The current state of keys + std::unordered_set keyIsDown; - // Whether a key was down - KeyList keyWasDown; + //! Whether a key was down + std::unordered_set keyWasDown; - // Whether a key has just been pressed - KeyList keyWasPressed; + //! Whether a key has just been pressed + std::unordered_set keyWasPressed; - // Whether a key has just been released - KeyList keyWasReleased; + //! Whether a key has just been released + std::unordered_set keyWasReleased; - // List of keys we listen for - // TODO perhaps the type of this is not really - // performant as KeyList is designed for few but - // often changing keys, and keysListenedFor is expected - // to change seldomly but contain lots of keys. - KeyList keysListenedFor; + //! List of keys we listen for + std::unordered_set keysListenedFor; }; class InputHandler @@ -347,7 +277,7 @@ public: return true; } - virtual bool isKeyDown(GameKeyType k) { return keydown[keycache.key[k]]; } + virtual bool isKeyDown(GameKeyType k) { return keydown.count(keycache.key[k]); } virtual bool wasKeyDown(GameKeyType k) { return false; } virtual bool wasKeyPressed(GameKeyType k) { return false; } virtual bool wasKeyReleased(GameKeyType k) { return false; } @@ -362,7 +292,7 @@ public: s32 Rand(s32 min, s32 max); private: - KeyList keydown; + std::unordered_set keydown; v2s32 mousepos; v2s32 mousespeed; }; diff --git a/src/client/keycode.h b/src/client/keycode.h index 7036705d1..263b722c7 100644 --- a/src/client/keycode.h +++ b/src/client/keycode.h @@ -24,12 +24,20 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include +class KeyPress; +namespace std +{ + template <> struct hash; +} + /* A key press, consisting of either an Irrlicht keycode or an actual char */ class KeyPress { public: + friend struct std::hash; + KeyPress() = default; KeyPress(const char *name); @@ -55,6 +63,17 @@ protected: std::string m_name = ""; }; +namespace std +{ + template <> struct hash + { + size_t operator()(const KeyPress &key) const + { + return key.Key; + } + }; +} + extern const KeyPress EscapeKey; extern const KeyPress CancelKey; -- cgit v1.2.3 From 9bff154cba14686f5a3b56f4cba405824b88c402 Mon Sep 17 00:00:00 2001 From: Paramat Date: Thu, 24 Sep 2020 00:10:50 +0100 Subject: Fix horizontal/vertical merging bug of hardware-colored framed glass (#10417) Previously, the param2-controlled horizontal/vertical merge feature (which was undocumented and forgotten) was always active, causing uses of param2 other than "glasslikeliquidlevel" to affect H/V merging. Only respect H/V merge bits when paramtype2 = "glasslikeliquidlevel". H/V merge bits and liquid level bits are designed to be used simultaneously. --- src/client/content_mapblock.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/content_mapblock.cpp b/src/client/content_mapblock.cpp index 65a85709b..df2748212 100644 --- a/src/client/content_mapblock.cpp +++ b/src/client/content_mapblock.cpp @@ -723,7 +723,8 @@ void MapblockMeshGenerator::drawGlasslikeFramedNode() for (auto &glass_tile : glass_tiles) glass_tile = tiles[4]; - u8 param2 = n.getParam2(); + // Only respect H/V merge bits when paramtype2 = "glasslikeliquidlevel" (liquid tank) + u8 param2 = (f->param_type_2 == CPT2_GLASSLIKE_LIQUID_LEVEL) ? n.getParam2() : 0; bool H_merge = !(param2 & 128); bool V_merge = !(param2 & 64); param2 &= 63; -- cgit v1.2.3 From c6e3050357e8378ad15e7fa7a9aa80f3936fbc2d Mon Sep 17 00:00:00 2001 From: Buckaroo Banzai <39065740+BuckarooBanzay@users.noreply.github.com> Date: Fri, 25 Sep 2020 18:52:42 +0200 Subject: Correct erroneous reported max lag with prometheus (#10427) Co-authored-by: BuckarooBanzay --- src/server.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/server.cpp b/src/server.cpp index b8a99f6ae..456edfeb8 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -653,7 +653,12 @@ void Server::AsyncRunStep(bool initial_step) } m_clients.step(dtime); - m_lag_gauge->increment((m_lag_gauge->get() > dtime ? -1 : 1) * dtime/100); + // increase/decrease lag gauge gradually + if (m_lag_gauge->get() > dtime) { + m_lag_gauge->decrement(dtime/100); + } else { + m_lag_gauge->increment(dtime/100); + } #if USE_CURL // send masterserver announce { -- cgit v1.2.3 From 09af0c5946c7082fc82563faf0ad9ef144fb9a06 Mon Sep 17 00:00:00 2001 From: luk3yx Date: Sun, 27 Sep 2020 01:31:54 +1200 Subject: Remove null bytes from TOCLIENT_BLOCKDATA (#10433) --- src/server.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/server.cpp b/src/server.cpp index 456edfeb8..d40ff259f 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -2338,7 +2338,7 @@ void Server::SendBlockNoLock(session_t peer_id, MapBlock *block, u8 ver, block->serializeNetworkSpecific(os); std::string s = os.str(); - NetworkPacket pkt(TOCLIENT_BLOCKDATA, 2 + 2 + 2 + 2 + s.size(), peer_id); + NetworkPacket pkt(TOCLIENT_BLOCKDATA, 2 + 2 + 2 + s.size(), peer_id); pkt << block->getPos(); pkt.putRawString(s.c_str(), s.size()); -- cgit v1.2.3 From 917e357bcaf5b7ebb77afe16b8c8fbe53b827e79 Mon Sep 17 00:00:00 2001 From: Tyler Schwend Date: Sat, 26 Sep 2020 12:41:16 -0400 Subject: Log server announce on updates and deletes too (#10177) --- src/serverlist.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/serverlist.cpp b/src/serverlist.cpp index c7fe2d888..80a8c2f1a 100644 --- a/src/serverlist.cpp +++ b/src/serverlist.cpp @@ -245,12 +245,19 @@ void sendAnnounce(AnnounceAction action, for (const ModSpec &mod : mods) { server["mods"].append(mod.name); } - actionstream << "Announcing to " << g_settings->get("serverlist_url") << std::endl; } else if (action == AA_UPDATE) { if (lag) server["lag"] = lag; } + if (action == AA_START) { + actionstream << "Announcing " << aa_names[action] << " to " << + g_settings->get("serverlist_url") << std::endl; + } else { + infostream << "Announcing " << aa_names[action] << " to " << + g_settings->get("serverlist_url") << std::endl; + } + HTTPFetchRequest fetch_request; fetch_request.url = g_settings->get("serverlist_url") + std::string("/announce"); fetch_request.method = HTTP_POST; -- cgit v1.2.3 From 65c15e137fe584edb38edea21c49873be00d554c Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein <54945686+EliasFleckenstein03@users.noreply.github.com> Date: Sat, 26 Sep 2020 18:41:44 +0200 Subject: Patch fast/teleport vulnerability when attached to an entity (#10340) --- src/server/player_sao.cpp | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/server/player_sao.cpp b/src/server/player_sao.cpp index 67efed210..e5b239bba 100644 --- a/src/server/player_sao.cpp +++ b/src/server/player_sao.cpp @@ -558,11 +558,34 @@ void PlayerSAO::setMaxSpeedOverride(const v3f &vel) bool PlayerSAO::checkMovementCheat() { - if (isAttached() || m_is_singleplayer || + if (m_is_singleplayer || g_settings->getBool("disable_anticheat")) { m_last_good_position = m_base_position; return false; } + if (UnitSAO *parent = dynamic_cast(getParent())) { + v3f attachment_pos; + { + int parent_id; + std::string bone; + v3f attachment_rot; + getAttachment(&parent_id, &bone, &attachment_pos, &attachment_rot); + } + + v3f parent_pos = parent->getBasePosition(); + f32 diff = m_base_position.getDistanceFromSQ(parent_pos) - attachment_pos.getLengthSQ(); + const f32 maxdiff = 4.0f * BS; // fair trade-off value for various latencies + + if (diff > maxdiff * maxdiff) { + setBasePosition(parent_pos); + actionstream << "Server: " << m_player->getName() + << " moved away from parent; diff=" << sqrtf(diff) / BS + << " resetting position." << std::endl; + return true; + } + // Player movement is locked to the entity. Skip further checks + return false; + } bool cheated = false; /* -- cgit v1.2.3 From 995d4052610b98821e1dcaf5031477de6f202bef Mon Sep 17 00:00:00 2001 From: "k.h.lai" Date: Wed, 30 Sep 2020 01:39:53 +0800 Subject: Improve MSVC cmake and update vcpkg instruction (#10407) Remove unnecessary compiler flag for clang-cl Update vcpkg instruction in README.md --- README.md | 5 +++-- src/CMakeLists.txt | 26 ++++++++++++++++---------- 2 files changed, 19 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/README.md b/README.md index 6a3c11f40..a06c3e257 100644 --- a/README.md +++ b/README.md @@ -314,13 +314,14 @@ It is highly recommended to use vcpkg as package manager. After you successfully built vcpkg you can easily install the required libraries: ```powershell -vcpkg install irrlicht zlib curl[winssl] openal-soft libvorbis libogg sqlite3 freetype luajit --triplet x64-windows +vcpkg install irrlicht zlib curl[winssl] openal-soft libvorbis libogg sqlite3 freetype luajit gmp jsoncpp --triplet x64-windows ``` - `curl` is optional, but required to read the serverlist, `curl[winssl]` is required to use the content store. - `openal-soft`, `libvorbis` and `libogg` are optional, but required to use sound. - `freetype` is optional, it allows true-type font rendering. - `luajit` is optional, it replaces the integrated Lua interpreter with a faster just-in-time interpreter. +- `gmp` and `jsoncpp` are optional, otherwise the bundled versions will be compiled There are other optional libraries, but they are not tested if they can build and link correctly. @@ -353,7 +354,7 @@ This is outdated and not recommended. Follow the instructions on https://dev.min Run the following script in PowerShell: ```powershell -cmake . -G"Visual Studio 15 2017 Win64" -DCMAKE_TOOLCHAIN_FILE=D:/vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_BUILD_TYPE=Release -DENABLE_GETTEXT=0 -DENABLE_CURSES=0 +cmake . -G"Visual Studio 15 2017 Win64" -DCMAKE_TOOLCHAIN_FILE=D:/vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_BUILD_TYPE=Release -DENABLE_GETTEXT=OFF -DENABLE_CURSES=OFF -DENABLE_SYSTEM_JSONCPP=ON cmake --build . --config Release ``` Make sure that the right compiler is selected and the path to the vcpkg toolchain is correct. diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7e1d0bd39..b5d4fae0e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -701,21 +701,14 @@ include(CheckCSourceCompiles) if(MSVC) # Visual Studio - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D WIN32_LEAN_AND_MEAN /MP") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D WIN32_LEAN_AND_MEAN") # EHa enables SEH exceptions (used for catching segfaults) - set(CMAKE_CXX_FLAGS_RELEASE "/EHa /Ox /GL /FD /MD /GS- /Zi /fp:fast /D NDEBUG /D _HAS_ITERATOR_DEBUGGING=0 /TP") + set(CMAKE_CXX_FLAGS_RELEASE "/EHa /Ox /MD /GS- /Zi /fp:fast /D NDEBUG /D _HAS_ITERATOR_DEBUGGING=0") if(CMAKE_SIZEOF_VOID_P EQUAL 4) set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /arch:SSE") endif() - - if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") - set(CMAKE_EXE_LINKER_FLAGS_RELEASE "/INCREMENTAL:NO /DEBUG /OPT:REF /OPT:ICF") - else() - set(CMAKE_EXE_LINKER_FLAGS_RELEASE "/LTCG /INCREMENTAL:NO /DEBUG /OPT:REF /OPT:ICF") - endif() - - set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup") + set(CMAKE_EXE_LINKER_FLAGS_RELEASE "/INCREMENTAL:NO /DEBUG /OPT:REF /OPT:ICF /SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup") set(CMAKE_CXX_FLAGS_SEMIDEBUG "/MDd /Zi /Ob0 /O1 /RTC1") @@ -726,6 +719,19 @@ if(MSVC) # Flags for C files (sqlite) # /MD = dynamically link to MSVCRxxx.dll set(CMAKE_C_FLAGS_RELEASE "/O2 /Ob2 /MD") + + # Flags that cannot be shared between cl and clang-cl + # https://clang.llvm.org/docs/UsersManual.html#clang-cl + if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fuse-ld=lld") + + # Disable pragma-pack warning + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Wno-pragma-pack") + else() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /TP /FD /GL") + set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LTCG") + endif() else() # GCC or compatible compilers such as Clang set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") -- cgit v1.2.3 From 79414aa3e5591fdaffa0956a08610a2228042941 Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Sun, 20 Sep 2020 12:52:35 +0200 Subject: Settings: Remove unused functions Make Settings-internal functions private --- src/settings.cpp | 87 ++++++-------------------------------------------------- src/settings.h | 49 +++++++++++++++---------------- 2 files changed, 33 insertions(+), 103 deletions(-) (limited to 'src') diff --git a/src/settings.cpp b/src/settings.cpp index 28b72c4e3..56ab9e12b 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -45,7 +45,13 @@ Settings::~Settings() Settings & Settings::operator += (const Settings &other) { - update(other); + if (&other == this) + return *this; + + MutexAutoLock lock(m_mutex); + MutexAutoLock lock2(other.m_mutex); + + updateNoLock(other); return *this; } @@ -512,25 +518,6 @@ u32 Settings::getFlagStr(const std::string &name, const FlagDesc *flagdesc, return flags; } -// N.B. if getStruct() is used to read a non-POD aggregate type, -// the behavior is undefined. -bool Settings::getStruct(const std::string &name, const std::string &format, - void *out, size_t olen) const -{ - std::string valstr; - - try { - valstr = get(name); - } catch (SettingNotFoundException &e) { - return false; - } - - if (!deSerializeStringToStruct(valstr, format, out, olen)) - return false; - - return true; -} - bool Settings::getNoiseParams(const std::string &name, NoiseParams &np) const { @@ -546,6 +533,7 @@ bool Settings::getNoiseParamsFromValue(const std::string &name, if (!getNoEx(name, value)) return false; + // Format: f32,f32,(f32,f32,f32),s32,s32,f32[,f32] Strfnd f(value); np.offset = stof(f.next(",")); @@ -615,28 +603,6 @@ std::vector Settings::getNames() const * Getters that don't throw exceptions * ***************************************/ -bool Settings::getEntryNoEx(const std::string &name, SettingsEntry &val) const -{ - try { - val = getEntry(name); - return true; - } catch (SettingNotFoundException &e) { - return false; - } -} - - -bool Settings::getEntryDefaultNoEx(const std::string &name, SettingsEntry &val) const -{ - try { - val = getEntryDefault(name); - return true; - } catch (SettingNotFoundException &e) { - return false; - } -} - - bool Settings::getGroupNoEx(const std::string &name, Settings *&val) const { try { @@ -908,17 +874,6 @@ bool Settings::setFlagStr(const std::string &name, u32 flags, } -bool Settings::setStruct(const std::string &name, const std::string &format, - void *value) -{ - std::string structstr; - if (!serializeStructToString(&structstr, format, value)) - return false; - - return set(name, structstr); -} - - bool Settings::setNoiseParams(const std::string &name, const NoiseParams &np, bool set_default) { @@ -969,32 +924,6 @@ void Settings::clearDefaults() clearDefaultsNoLock(); } -void Settings::updateValue(const Settings &other, const std::string &name) -{ - if (&other == this) - return; - - MutexAutoLock lock(m_mutex); - - try { - m_settings[name] = other.get(name); - } catch (SettingNotFoundException &e) { - } -} - - -void Settings::update(const Settings &other) -{ - if (&other == this) - return; - - MutexAutoLock lock(m_mutex); - MutexAutoLock lock2(other.m_mutex); - - updateNoLock(other); -} - - SettingsParseEvent Settings::parseConfigObject(const std::string &line, const std::string &end, std::string &name, std::string &value) { diff --git a/src/settings.h b/src/settings.h index ccc252049..7db5539b2 100644 --- a/src/settings.h +++ b/src/settings.h @@ -113,23 +113,10 @@ public: bool parseConfigLines(std::istream &is, const std::string &end = ""); void writeLines(std::ostream &os, u32 tab_depth=0) const; - SettingsParseEvent parseConfigObject(const std::string &line, - const std::string &end, std::string &name, std::string &value); - bool updateConfigObject(std::istream &is, std::ostream &os, - const std::string &end, u32 tab_depth=0); - - static bool checkNameValid(const std::string &name); - static bool checkValueValid(const std::string &value); - static std::string getMultiline(std::istream &is, size_t *num_lines=NULL); - static void printEntry(std::ostream &os, const std::string &name, - const SettingsEntry &entry, u32 tab_depth=0); - /*********** * Getters * ***********/ - const SettingsEntry &getEntry(const std::string &name) const; - const SettingsEntry &getEntryDefault(const std::string &name) const; Settings *getGroup(const std::string &name) const; const std::string &get(const std::string &name) const; const std::string &getDefault(const std::string &name) const; @@ -144,10 +131,6 @@ public: v3f getV3F(const std::string &name) const; u32 getFlagStr(const std::string &name, const FlagDesc *flagdesc, u32 *flagmask) const; - // N.B. if getStruct() is used to read a non-POD aggregate type, - // the behavior is undefined. - bool getStruct(const std::string &name, const std::string &format, - void *out, size_t olen) const; bool getNoiseParams(const std::string &name, NoiseParams &np) const; bool getNoiseParamsFromValue(const std::string &name, NoiseParams &np) const; bool getNoiseParamsFromGroup(const std::string &name, NoiseParams &np) const; @@ -161,8 +144,6 @@ public: * Getters that don't throw exceptions * ***************************************/ - bool getEntryNoEx(const std::string &name, SettingsEntry &val) const; - bool getEntryDefaultNoEx(const std::string &name, SettingsEntry &val) const; bool getGroupNoEx(const std::string &name, Settings *&val) const; bool getNoEx(const std::string &name, std::string &val) const; bool getDefaultNoEx(const std::string &name, std::string &val) const; @@ -206,16 +187,11 @@ public: const FlagDesc *flagdesc = nullptr, u32 flagmask = U32_MAX); bool setNoiseParams(const std::string &name, const NoiseParams &np, bool set_default=false); - // N.B. if setStruct() is used to write a non-POD aggregate type, - // the behavior is undefined. - bool setStruct(const std::string &name, const std::string &format, void *value); // remove a setting bool remove(const std::string &name); void clear(); void clearDefaults(); - void updateValue(const Settings &other, const std::string &name); - void update(const Settings &other); /************** * Miscellany * @@ -232,6 +208,31 @@ public: SettingsChangedCallback cbf, void *userdata = NULL); private: + /*********************** + * Reading and writing * + ***********************/ + + SettingsParseEvent parseConfigObject(const std::string &line, + const std::string &end, std::string &name, std::string &value); + bool updateConfigObject(std::istream &is, std::ostream &os, + const std::string &end, u32 tab_depth=0); + + static bool checkNameValid(const std::string &name); + static bool checkValueValid(const std::string &value); + static std::string getMultiline(std::istream &is, size_t *num_lines=NULL); + static void printEntry(std::ostream &os, const std::string &name, + const SettingsEntry &entry, u32 tab_depth=0); + + /*********** + * Getters * + ***********/ + + const SettingsEntry &getEntry(const std::string &name) const; + const SettingsEntry &getEntryDefault(const std::string &name) const; + + // Allow TestSettings to run sanity checks using private functions. + friend class TestSettings; + void updateNoLock(const Settings &other); void clearNoLock(); void clearDefaultsNoLock(); -- cgit v1.2.3 From ca5c2dbefab3676514e48b445b36de50993de9f1 Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Sun, 20 Sep 2020 13:04:01 +0200 Subject: Clean up serialization This reverts 1a5b4b3 and further functions in serialize.cpp that are unused The intend for a sane NetworkPacket/stream replacement was good, but a wrapper class around i/ostream might be more versatile than introducing a new vector-based serialization class. --- src/unittest/test_serialization.cpp | 324 --------------------------------- src/util/serialize.cpp | 349 ------------------------------------ src/util/serialize.h | 242 ------------------------- 3 files changed, 915 deletions(-) (limited to 'src') diff --git a/src/unittest/test_serialization.cpp b/src/unittest/test_serialization.cpp index 51e28f144..d72bf0d4c 100644 --- a/src/unittest/test_serialization.cpp +++ b/src/unittest/test_serialization.cpp @@ -32,18 +32,12 @@ public: void buildTestStrings(); void testSerializeString(); - void testSerializeWideString(); void testSerializeLongString(); void testSerializeJsonString(); - void testSerializeHex(); void testDeSerializeString(); - void testDeSerializeWideString(); void testDeSerializeLongString(); void testStreamRead(); void testStreamWrite(); - void testVecPut(); - void testStringLengthLimits(); - void testBufReader(); void testFloatFormat(); std::string teststring2; @@ -61,17 +55,11 @@ void TestSerialization::runTests(IGameDef *gamedef) TEST(testSerializeString); TEST(testDeSerializeString); - TEST(testSerializeWideString); - TEST(testDeSerializeWideString); TEST(testSerializeLongString); TEST(testDeSerializeLongString); TEST(testSerializeJsonString); - TEST(testSerializeHex); TEST(testStreamRead); TEST(testStreamWrite); - TEST(testVecPut); - TEST(testStringLengthLimits); - TEST(testBufReader); TEST(testFloatFormat); } @@ -136,50 +124,6 @@ void TestSerialization::testDeSerializeString() } } -void TestSerialization::testSerializeWideString() -{ - // Test blank string - UASSERT(serializeWideString(L"") == mkstr("\0\0")); - - // Test basic string - UASSERT(serializeWideString(utf8_to_wide("Hello world!")) == - mkstr("\0\14\0H\0e\0l\0l\0o\0 \0w\0o\0r\0l\0d\0!")); - - // Test character range - UASSERT(serializeWideString(teststring2_w) == - mkstr("\1\0") + teststring2_w_encoded); -} - -void TestSerialization::testDeSerializeWideString() -{ - // Test deserialize - { - std::istringstream is(serializeWideString(teststring2_w), std::ios::binary); - UASSERT(deSerializeWideString(is) == teststring2_w); - UASSERT(!is.eof()); - is.get(); - UASSERT(is.eof()); - } - - // Test deserialize an incomplete length specifier - { - std::istringstream is(mkstr("\x53"), std::ios::binary); - EXCEPTION_CHECK(SerializationError, deSerializeWideString(is)); - } - - // Test deserialize a string with an incomplete character - { - std::istringstream is(mkstr("\x00\x07\0a\0b\0c\0d\0e\0f\0"), std::ios::binary); - EXCEPTION_CHECK(SerializationError, deSerializeWideString(is)); - } - - // Test deserialize a string with incomplete data - { - std::istringstream is(mkstr("\x00\x08\0a\0b\0c\0d\0e\0f"), std::ios::binary); - EXCEPTION_CHECK(SerializationError, deSerializeWideString(is)); - } -} - void TestSerialization::testSerializeLongString() { // Test blank string @@ -268,25 +212,6 @@ void TestSerialization::testSerializeJsonString() UASSERT(is.eof()); } -void TestSerialization::testSerializeHex() -{ - // Test blank string - UASSERT(serializeHexString("") == ""); - UASSERT(serializeHexString("", true) == ""); - - // Test basic string - UASSERT(serializeHexString("Hello world!") == - "48656c6c6f20776f726c6421"); - UASSERT(serializeHexString("Hello world!", true) == - "48 65 6c 6c 6f 20 77 6f 72 6c 64 21"); - - // Test binary string - UASSERT(serializeHexString(mkstr("\x00\x0a\xb0\x63\x1f\x00\xff")) == - "000ab0631f00ff"); - UASSERT(serializeHexString(mkstr("\x00\x0a\xb0\x63\x1f\x00\xff"), true) == - "00 0a b0 63 1f 00 ff"); -} - void TestSerialization::testStreamRead() { @@ -376,255 +301,6 @@ void TestSerialization::testStreamWrite() } -void TestSerialization::testVecPut() -{ - std::vector buf; - - putU8(&buf, 0x11); - putU16(&buf, 0x2233); - putU32(&buf, 0x44556677); - putU64(&buf, 0x8899AABBCCDDEEFFLL); - - putS8(&buf, -128); - putS16(&buf, 30000); - putS32(&buf, -6); - putS64(&buf, -43); - - putF1000(&buf, 53.53467f); - putF1000(&buf, -300000.32f); - putF1000(&buf, F1000_MIN); - putF1000(&buf, F1000_MAX); - - putString(&buf, "foobar!"); - - putV2S16(&buf, v2s16(500, 500)); - putV3S16(&buf, v3s16(4207, 604, -30)); - putV2S32(&buf, v2s32(1920, 1080)); - putV3S32(&buf, v3s32(-400, 6400054, 290549855)); - - putWideString(&buf, L"\x02~woof~\x5455"); - - putV3F1000(&buf, v3f(500, 10024.2f, -192.54f)); - putARGB8(&buf, video::SColor(255, 128, 50, 128)); - - putLongString(&buf, "some longer string here"); - - putU16(&buf, 0xF00D); - - UASSERT(buf.size() == sizeof(test_serialized_data)); - UASSERT(!memcmp(&buf[0], test_serialized_data, sizeof(test_serialized_data))); -} - - -void TestSerialization::testStringLengthLimits() -{ - std::vector buf; - std::string too_long(STRING_MAX_LEN + 1, 'A'); - std::string way_too_large(LONG_STRING_MAX_LEN + 1, 'B'); - std::wstring too_long_wide(WIDE_STRING_MAX_LEN + 1, L'C'); - - EXCEPTION_CHECK(SerializationError, putString(&buf, too_long)); - - putLongString(&buf, too_long); - too_long.resize(too_long.size() - 1); - putString(&buf, too_long); - - EXCEPTION_CHECK(SerializationError, putWideString(&buf, too_long_wide)); - too_long_wide.resize(too_long_wide.size() - 1); - putWideString(&buf, too_long_wide); -} - - -void TestSerialization::testBufReader() -{ - u8 u8_data; - u16 u16_data; - u32 u32_data; - u64 u64_data; - s8 s8_data; - s16 s16_data; - s32 s32_data; - s64 s64_data; - f32 f32_data, f32_data2, f32_data3, f32_data4; - video::SColor scolor_data; - v2s16 v2s16_data; - v3s16 v3s16_data; - v2s32 v2s32_data; - v3s32 v3s32_data; - v3f v3f_data; - std::string string_data; - std::wstring widestring_data; - std::string longstring_data; - u8 raw_data[10] = {0}; - - BufReader buf(test_serialized_data, sizeof(test_serialized_data)); - - // Try reading data like normal - UASSERT(buf.getU8() == 0x11); - UASSERT(buf.getU16() == 0x2233); - UASSERT(buf.getU32() == 0x44556677); - UASSERT(buf.getU64() == 0x8899AABBCCDDEEFFLL); - UASSERT(buf.getS8() == -128); - UASSERT(buf.getS16() == 30000); - UASSERT(buf.getS32() == -6); - UASSERT(buf.getS64() == -43); - UASSERT(buf.getF1000() == 53.534f); - UASSERT(buf.getF1000() == -300000.32f); - UASSERT(buf.getF1000() == F1000_MIN); - UASSERT(buf.getF1000() == F1000_MAX); - UASSERT(buf.getString() == "foobar!"); - UASSERT(buf.getV2S16() == v2s16(500, 500)); - UASSERT(buf.getV3S16() == v3s16(4207, 604, -30)); - UASSERT(buf.getV2S32() == v2s32(1920, 1080)); - UASSERT(buf.getV3S32() == v3s32(-400, 6400054, 290549855)); - UASSERT(buf.getWideString() == L"\x02~woof~\x5455"); - UASSERT(buf.getV3F1000() == v3f(500, 10024.2f, -192.54f)); - UASSERT(buf.getARGB8() == video::SColor(255, 128, 50, 128)); - UASSERT(buf.getLongString() == "some longer string here"); - - // Verify the offset and data is unchanged after a failed read - size_t orig_pos = buf.pos; - u32_data = 0; - UASSERT(buf.getU32NoEx(&u32_data) == false); - UASSERT(buf.pos == orig_pos); - UASSERT(u32_data == 0); - - // Now try the same for a failed string read - UASSERT(buf.getStringNoEx(&string_data) == false); - UASSERT(buf.pos == orig_pos); - UASSERT(string_data == ""); - - // Now try the same for a failed string read - UASSERT(buf.getWideStringNoEx(&widestring_data) == false); - UASSERT(buf.pos == orig_pos); - UASSERT(widestring_data == L""); - - UASSERT(buf.getU16() == 0xF00D); - - UASSERT(buf.remaining() == 0); - - // Check to make sure these each blow exceptions as they're supposed to - EXCEPTION_CHECK(SerializationError, buf.getU8()); - EXCEPTION_CHECK(SerializationError, buf.getU16()); - EXCEPTION_CHECK(SerializationError, buf.getU32()); - EXCEPTION_CHECK(SerializationError, buf.getU64()); - - EXCEPTION_CHECK(SerializationError, buf.getS8()); - EXCEPTION_CHECK(SerializationError, buf.getS16()); - EXCEPTION_CHECK(SerializationError, buf.getS32()); - EXCEPTION_CHECK(SerializationError, buf.getS64()); - - EXCEPTION_CHECK(SerializationError, buf.getF1000()); - EXCEPTION_CHECK(SerializationError, buf.getARGB8()); - - EXCEPTION_CHECK(SerializationError, buf.getV2S16()); - EXCEPTION_CHECK(SerializationError, buf.getV3S16()); - EXCEPTION_CHECK(SerializationError, buf.getV2S32()); - EXCEPTION_CHECK(SerializationError, buf.getV3S32()); - EXCEPTION_CHECK(SerializationError, buf.getV3F1000()); - - EXCEPTION_CHECK(SerializationError, buf.getString()); - EXCEPTION_CHECK(SerializationError, buf.getWideString()); - EXCEPTION_CHECK(SerializationError, buf.getLongString()); - EXCEPTION_CHECK(SerializationError, - buf.getRawData(raw_data, sizeof(raw_data))); - - // See if we can skip backwards - buf.pos = 5; - UASSERT(buf.getRawDataNoEx(raw_data, 3) == true); - UASSERT(raw_data[0] == 0x66); - UASSERT(raw_data[1] == 0x77); - UASSERT(raw_data[2] == 0x88); - - UASSERT(buf.getU32() == 0x99AABBCC); - UASSERT(buf.pos == 12); - - // Now let's try it all over again using the NoEx variants - buf.pos = 0; - - UASSERT(buf.getU8NoEx(&u8_data)); - UASSERT(buf.getU16NoEx(&u16_data)); - UASSERT(buf.getU32NoEx(&u32_data)); - UASSERT(buf.getU64NoEx(&u64_data)); - - UASSERT(buf.getS8NoEx(&s8_data)); - UASSERT(buf.getS16NoEx(&s16_data)); - UASSERT(buf.getS32NoEx(&s32_data)); - UASSERT(buf.getS64NoEx(&s64_data)); - - UASSERT(buf.getF1000NoEx(&f32_data)); - UASSERT(buf.getF1000NoEx(&f32_data2)); - UASSERT(buf.getF1000NoEx(&f32_data3)); - UASSERT(buf.getF1000NoEx(&f32_data4)); - - UASSERT(buf.getStringNoEx(&string_data)); - UASSERT(buf.getV2S16NoEx(&v2s16_data)); - UASSERT(buf.getV3S16NoEx(&v3s16_data)); - UASSERT(buf.getV2S32NoEx(&v2s32_data)); - UASSERT(buf.getV3S32NoEx(&v3s32_data)); - UASSERT(buf.getWideStringNoEx(&widestring_data)); - UASSERT(buf.getV3F1000NoEx(&v3f_data)); - UASSERT(buf.getARGB8NoEx(&scolor_data)); - - UASSERT(buf.getLongStringNoEx(&longstring_data)); - - // and make sure we got the correct data - UASSERT(u8_data == 0x11); - UASSERT(u16_data == 0x2233); - UASSERT(u32_data == 0x44556677); - UASSERT(u64_data == 0x8899AABBCCDDEEFFLL); - UASSERT(s8_data == -128); - UASSERT(s16_data == 30000); - UASSERT(s32_data == -6); - UASSERT(s64_data == -43); - UASSERT(f32_data == 53.534f); - UASSERT(f32_data2 == -300000.32f); - UASSERT(f32_data3 == F1000_MIN); - UASSERT(f32_data4 == F1000_MAX); - UASSERT(string_data == "foobar!"); - UASSERT(v2s16_data == v2s16(500, 500)); - UASSERT(v3s16_data == v3s16(4207, 604, -30)); - UASSERT(v2s32_data == v2s32(1920, 1080)); - UASSERT(v3s32_data == v3s32(-400, 6400054, 290549855)); - UASSERT(widestring_data == L"\x02~woof~\x5455"); - UASSERT(v3f_data == v3f(500, 10024.2f, -192.54f)); - UASSERT(scolor_data == video::SColor(255, 128, 50, 128)); - UASSERT(longstring_data == "some longer string here"); - - UASSERT(buf.remaining() == 2); - UASSERT(buf.getRawDataNoEx(raw_data, 3) == false); - UASSERT(buf.remaining() == 2); - UASSERT(buf.getRawDataNoEx(raw_data, 2) == true); - UASSERT(raw_data[0] == 0xF0); - UASSERT(raw_data[1] == 0x0D); - UASSERT(buf.remaining() == 0); - - // Make sure no more available data causes a failure - UASSERT(!buf.getU8NoEx(&u8_data)); - UASSERT(!buf.getU16NoEx(&u16_data)); - UASSERT(!buf.getU32NoEx(&u32_data)); - UASSERT(!buf.getU64NoEx(&u64_data)); - - UASSERT(!buf.getS8NoEx(&s8_data)); - UASSERT(!buf.getS16NoEx(&s16_data)); - UASSERT(!buf.getS32NoEx(&s32_data)); - UASSERT(!buf.getS64NoEx(&s64_data)); - - UASSERT(!buf.getF1000NoEx(&f32_data)); - UASSERT(!buf.getARGB8NoEx(&scolor_data)); - - UASSERT(!buf.getV2S16NoEx(&v2s16_data)); - UASSERT(!buf.getV3S16NoEx(&v3s16_data)); - UASSERT(!buf.getV2S32NoEx(&v2s32_data)); - UASSERT(!buf.getV3S32NoEx(&v3s32_data)); - UASSERT(!buf.getV3F1000NoEx(&v3f_data)); - - UASSERT(!buf.getStringNoEx(&string_data)); - UASSERT(!buf.getWideStringNoEx(&widestring_data)); - UASSERT(!buf.getLongStringNoEx(&longstring_data)); - UASSERT(!buf.getRawDataNoEx(raw_data, sizeof(raw_data))); -} - void TestSerialization::testFloatFormat() { FloatType type = getFloatSerializationType(); diff --git a/src/util/serialize.cpp b/src/util/serialize.cpp index 5b276668d..fd5cbda21 100644 --- a/src/util/serialize.cpp +++ b/src/util/serialize.cpp @@ -30,74 +30,6 @@ with this program; if not, write to the Free Software Foundation, Inc., FloatType g_serialize_f32_type = FLOATTYPE_UNKNOWN; -//// -//// BufReader -//// - -bool BufReader::getStringNoEx(std::string *val) -{ - u16 num_chars; - if (!getU16NoEx(&num_chars)) - return false; - - if (pos + num_chars > size) { - pos -= sizeof(num_chars); - return false; - } - - val->assign((const char *)data + pos, num_chars); - pos += num_chars; - - return true; -} - -bool BufReader::getWideStringNoEx(std::wstring *val) -{ - u16 num_chars; - if (!getU16NoEx(&num_chars)) - return false; - - if (pos + num_chars * 2 > size) { - pos -= sizeof(num_chars); - return false; - } - - for (size_t i = 0; i != num_chars; i++) { - val->push_back(readU16(data + pos)); - pos += 2; - } - - return true; -} - -bool BufReader::getLongStringNoEx(std::string *val) -{ - u32 num_chars; - if (!getU32NoEx(&num_chars)) - return false; - - if (pos + num_chars > size) { - pos -= sizeof(num_chars); - return false; - } - - val->assign((const char *)data + pos, num_chars); - pos += num_chars; - - return true; -} - -bool BufReader::getRawDataNoEx(void *val, size_t len) -{ - if (pos + len > size) - return false; - - memcpy(val, data + pos, len); - pos += len; - - return true; -} - //// //// String @@ -404,284 +336,3 @@ std::string deSerializeJsonStringIfNeeded(std::istream &is) return tmp_os.str(); } -//// -//// String/Struct conversions -//// - -bool deSerializeStringToStruct(std::string valstr, - std::string format, void *out, size_t olen) -{ - size_t len = olen; - std::vector strs_alloced; - std::string *str; - char *f, *snext; - size_t pos; - - char *s = &valstr[0]; - char *buf = new char[len]; - char *bufpos = buf; - - char *fmtpos, *fmt = &format[0]; - while ((f = strtok_r(fmt, ",", &fmtpos)) && s) { - fmt = nullptr; - - bool is_unsigned = false; - int width = 0; - char valtype = *f; - - width = (int)strtol(f + 1, &f, 10); - if (width && valtype == 's') - valtype = 'i'; - - switch (valtype) { - case 'u': - is_unsigned = true; - /* FALLTHROUGH */ - case 'i': - if (width == 16) { - bufpos += PADDING(bufpos, u16); - if ((bufpos - buf) + sizeof(u16) <= len) { - if (is_unsigned) - *(u16 *)bufpos = (u16)strtoul(s, &s, 10); - else - *(s16 *)bufpos = (s16)strtol(s, &s, 10); - } - bufpos += sizeof(u16); - } else if (width == 32) { - bufpos += PADDING(bufpos, u32); - if ((bufpos - buf) + sizeof(u32) <= len) { - if (is_unsigned) - *(u32 *)bufpos = (u32)strtoul(s, &s, 10); - else - *(s32 *)bufpos = (s32)strtol(s, &s, 10); - } - bufpos += sizeof(u32); - } else if (width == 64) { - bufpos += PADDING(bufpos, u64); - if ((bufpos - buf) + sizeof(u64) <= len) { - if (is_unsigned) - *(u64 *)bufpos = (u64)strtoull(s, &s, 10); - else - *(s64 *)bufpos = (s64)strtoll(s, &s, 10); - } - bufpos += sizeof(u64); - } - s = strchr(s, ','); - break; - case 'b': - snext = strchr(s, ','); - if (snext) - *snext++ = 0; - - bufpos += PADDING(bufpos, bool); - if ((bufpos - buf) + sizeof(bool) <= len) - *(bool *)bufpos = is_yes(std::string(s)); - bufpos += sizeof(bool); - - s = snext; - break; - case 'f': - bufpos += PADDING(bufpos, float); - if ((bufpos - buf) + sizeof(float) <= len) - *(float *)bufpos = strtof(s, &s); - bufpos += sizeof(float); - - s = strchr(s, ','); - break; - case 's': - while (*s == ' ' || *s == '\t') - s++; - if (*s++ != '"') //error, expected string - goto fail; - snext = s; - - while (snext[0] && !(snext[-1] != '\\' && snext[0] == '"')) - snext++; - *snext++ = 0; - - bufpos += PADDING(bufpos, std::string *); - - str = new std::string(s); - pos = 0; - while ((pos = str->find("\\\"", pos)) != std::string::npos) - str->erase(pos, 1); - - if ((bufpos - buf) + sizeof(std::string *) <= len) - *(std::string **)bufpos = str; - bufpos += sizeof(std::string *); - strs_alloced.push_back(str); - - s = *snext ? snext + 1 : nullptr; - break; - case 'v': - while (*s == ' ' || *s == '\t') - s++; - if (*s++ != '(') //error, expected vector - goto fail; - - if (width == 2) { - bufpos += PADDING(bufpos, v2f); - - if ((bufpos - buf) + sizeof(v2f) <= len) { - v2f *v = (v2f *)bufpos; - v->X = strtof(s, &s); - s++; - v->Y = strtof(s, &s); - } - - bufpos += sizeof(v2f); - } else if (width == 3) { - bufpos += PADDING(bufpos, v3f); - if ((bufpos - buf) + sizeof(v3f) <= len) { - v3f *v = (v3f *)bufpos; - v->X = strtof(s, &s); - s++; - v->Y = strtof(s, &s); - s++; - v->Z = strtof(s, &s); - } - - bufpos += sizeof(v3f); - } - s = strchr(s, ','); - break; - default: //error, invalid format specifier - goto fail; - } - - if (s && *s == ',') - s++; - - if ((size_t)(bufpos - buf) > len) //error, buffer too small - goto fail; - } - - if (f && *f) { //error, mismatched number of fields and values -fail: - for (size_t i = 0; i != strs_alloced.size(); i++) - delete strs_alloced[i]; - delete[] buf; - return false; - } - - memcpy(out, buf, olen); - delete[] buf; - return true; -} - -// Casts *buf to a signed or unsigned fixed-width integer of 'w' width -#define SIGN_CAST(w, buf) (is_unsigned ? *((u##w *) buf) : *((s##w *) buf)) - -bool serializeStructToString(std::string *out, - std::string format, void *value) -{ - std::ostringstream os; - std::string str; - char *f; - size_t strpos; - - char *bufpos = (char *) value; - char *fmtpos, *fmt = &format[0]; - while ((f = strtok_r(fmt, ",", &fmtpos))) { - fmt = nullptr; - bool is_unsigned = false; - int width = 0; - char valtype = *f; - - width = (int)strtol(f + 1, &f, 10); - if (width && valtype == 's') - valtype = 'i'; - - switch (valtype) { - case 'u': - is_unsigned = true; - /* FALLTHROUGH */ - case 'i': - if (width == 16) { - bufpos += PADDING(bufpos, u16); - os << SIGN_CAST(16, bufpos); - bufpos += sizeof(u16); - } else if (width == 32) { - bufpos += PADDING(bufpos, u32); - os << SIGN_CAST(32, bufpos); - bufpos += sizeof(u32); - } else if (width == 64) { - bufpos += PADDING(bufpos, u64); - os << SIGN_CAST(64, bufpos); - bufpos += sizeof(u64); - } - break; - case 'b': - bufpos += PADDING(bufpos, bool); - os << std::boolalpha << *((bool *) bufpos); - bufpos += sizeof(bool); - break; - case 'f': - bufpos += PADDING(bufpos, float); - os << *((float *) bufpos); - bufpos += sizeof(float); - break; - case 's': - bufpos += PADDING(bufpos, std::string *); - str = **((std::string **) bufpos); - - strpos = 0; - while ((strpos = str.find('"', strpos)) != std::string::npos) { - str.insert(strpos, 1, '\\'); - strpos += 2; - } - - os << str; - bufpos += sizeof(std::string *); - break; - case 'v': - if (width == 2) { - bufpos += PADDING(bufpos, v2f); - v2f *v = (v2f *) bufpos; - os << '(' << v->X << ", " << v->Y << ')'; - bufpos += sizeof(v2f); - } else { - bufpos += PADDING(bufpos, v3f); - v3f *v = (v3f *) bufpos; - os << '(' << v->X << ", " << v->Y << ", " << v->Z << ')'; - bufpos += sizeof(v3f); - } - break; - default: - return false; - } - os << ", "; - } - *out = os.str(); - - // Trim off the trailing comma and space - if (out->size() >= 2) - out->resize(out->size() - 2); - - return true; -} - -#undef SIGN_CAST - -//// -//// Other -//// - -std::string serializeHexString(const std::string &data, bool insert_spaces) -{ - std::string result; - result.reserve(data.size() * (2 + insert_spaces)); - - static const char hex_chars[] = "0123456789abcdef"; - - const size_t len = data.size(); - for (size_t i = 0; i != len; i++) { - u8 byte = data[i]; - result.push_back(hex_chars[(byte >> 4) & 0x0F]); - result.push_back(hex_chars[(byte >> 0) & 0x0F]); - if (insert_spaces && i != len - 1) - result.push_back(' '); - } - - return result; -} diff --git a/src/util/serialize.h b/src/util/serialize.h index a4b5a234a..a988a8f78 100644 --- a/src/util/serialize.h +++ b/src/util/serialize.h @@ -442,15 +442,9 @@ MAKE_STREAM_WRITE_FXN(video::SColor, ARGB8, 4); // Creates a string with the length as the first two bytes std::string serializeString(const std::string &plain); -// Creates a string with the length as the first two bytes from wide string -std::string serializeWideString(const std::wstring &plain); - // Reads a string with the length as the first two bytes std::string deSerializeString(std::istream &is); -// Reads a wide string with the length as the first two bytes -std::wstring deSerializeWideString(std::istream &is); - // Creates a string with the length as the first four bytes std::string serializeLongString(const std::string &plain); @@ -469,239 +463,3 @@ std::string serializeJsonStringIfNeeded(const std::string &s); // Parses a string serialized by serializeJsonStringIfNeeded. std::string deSerializeJsonStringIfNeeded(std::istream &is); - -// Creates a string consisting of the hexadecimal representation of `data` -std::string serializeHexString(const std::string &data, bool insert_spaces=false); - -// Creates a string containing comma delimited values of a struct whose layout is -// described by the parameter format -bool serializeStructToString(std::string *out, - std::string format, void *value); - -// Reads a comma delimited string of values into a struct whose layout is -// decribed by the parameter format -bool deSerializeStringToStruct(std::string valstr, - std::string format, void *out, size_t olen); - -//// -//// BufReader -//// - -#define MAKE_BUFREADER_GETNOEX_FXN(T, N, S) \ - inline bool get ## N ## NoEx(T *val) \ - { \ - if (pos + S > size) \ - return false; \ - *val = read ## N(data + pos); \ - pos += S; \ - return true; \ - } - -#define MAKE_BUFREADER_GET_FXN(T, N) \ - inline T get ## N() \ - { \ - T val; \ - if (!get ## N ## NoEx(&val)) \ - throw SerializationError("Attempted read past end of data"); \ - return val; \ - } - -class BufReader { -public: - BufReader(const u8 *data_, size_t size_) : - data(data_), - size(size_) - { - } - - MAKE_BUFREADER_GETNOEX_FXN(u8, U8, 1); - MAKE_BUFREADER_GETNOEX_FXN(u16, U16, 2); - MAKE_BUFREADER_GETNOEX_FXN(u32, U32, 4); - MAKE_BUFREADER_GETNOEX_FXN(u64, U64, 8); - MAKE_BUFREADER_GETNOEX_FXN(s8, S8, 1); - MAKE_BUFREADER_GETNOEX_FXN(s16, S16, 2); - MAKE_BUFREADER_GETNOEX_FXN(s32, S32, 4); - MAKE_BUFREADER_GETNOEX_FXN(s64, S64, 8); - MAKE_BUFREADER_GETNOEX_FXN(f32, F1000, 4); - MAKE_BUFREADER_GETNOEX_FXN(v2s16, V2S16, 4); - MAKE_BUFREADER_GETNOEX_FXN(v3s16, V3S16, 6); - MAKE_BUFREADER_GETNOEX_FXN(v2s32, V2S32, 8); - MAKE_BUFREADER_GETNOEX_FXN(v3s32, V3S32, 12); - MAKE_BUFREADER_GETNOEX_FXN(v3f, V3F1000, 12); - MAKE_BUFREADER_GETNOEX_FXN(video::SColor, ARGB8, 4); - - bool getStringNoEx(std::string *val); - bool getWideStringNoEx(std::wstring *val); - bool getLongStringNoEx(std::string *val); - bool getRawDataNoEx(void *data, size_t len); - - MAKE_BUFREADER_GET_FXN(u8, U8); - MAKE_BUFREADER_GET_FXN(u16, U16); - MAKE_BUFREADER_GET_FXN(u32, U32); - MAKE_BUFREADER_GET_FXN(u64, U64); - MAKE_BUFREADER_GET_FXN(s8, S8); - MAKE_BUFREADER_GET_FXN(s16, S16); - MAKE_BUFREADER_GET_FXN(s32, S32); - MAKE_BUFREADER_GET_FXN(s64, S64); - MAKE_BUFREADER_GET_FXN(f32, F1000); - MAKE_BUFREADER_GET_FXN(v2s16, V2S16); - MAKE_BUFREADER_GET_FXN(v3s16, V3S16); - MAKE_BUFREADER_GET_FXN(v2s32, V2S32); - MAKE_BUFREADER_GET_FXN(v3s32, V3S32); - MAKE_BUFREADER_GET_FXN(v3f, V3F1000); - MAKE_BUFREADER_GET_FXN(video::SColor, ARGB8); - MAKE_BUFREADER_GET_FXN(std::string, String); - MAKE_BUFREADER_GET_FXN(std::wstring, WideString); - MAKE_BUFREADER_GET_FXN(std::string, LongString); - - inline void getRawData(void *val, size_t len) - { - if (!getRawDataNoEx(val, len)) - throw SerializationError("Attempted read past end of data"); - } - - inline size_t remaining() - { - assert(pos <= size); - return size - pos; - } - - const u8 *data; - size_t size; - size_t pos = 0; -}; - -#undef MAKE_BUFREADER_GET_FXN -#undef MAKE_BUFREADER_GETNOEX_FXN - - -//// -//// Vector-based write routines -//// - -inline void putU8(std::vector *dest, u8 val) -{ - dest->push_back((val >> 0) & 0xFF); -} - -inline void putU16(std::vector *dest, u16 val) -{ - dest->push_back((val >> 8) & 0xFF); - dest->push_back((val >> 0) & 0xFF); -} - -inline void putU32(std::vector *dest, u32 val) -{ - dest->push_back((val >> 24) & 0xFF); - dest->push_back((val >> 16) & 0xFF); - dest->push_back((val >> 8) & 0xFF); - dest->push_back((val >> 0) & 0xFF); -} - -inline void putU64(std::vector *dest, u64 val) -{ - dest->push_back((val >> 56) & 0xFF); - dest->push_back((val >> 48) & 0xFF); - dest->push_back((val >> 40) & 0xFF); - dest->push_back((val >> 32) & 0xFF); - dest->push_back((val >> 24) & 0xFF); - dest->push_back((val >> 16) & 0xFF); - dest->push_back((val >> 8) & 0xFF); - dest->push_back((val >> 0) & 0xFF); -} - -inline void putS8(std::vector *dest, s8 val) -{ - putU8(dest, val); -} - -inline void putS16(std::vector *dest, s16 val) -{ - putU16(dest, val); -} - -inline void putS32(std::vector *dest, s32 val) -{ - putU32(dest, val); -} - -inline void putS64(std::vector *dest, s64 val) -{ - putU64(dest, val); -} - -inline void putF1000(std::vector *dest, f32 val) -{ - putS32(dest, val * FIXEDPOINT_FACTOR); -} - -inline void putV2S16(std::vector *dest, v2s16 val) -{ - putS16(dest, val.X); - putS16(dest, val.Y); -} - -inline void putV3S16(std::vector *dest, v3s16 val) -{ - putS16(dest, val.X); - putS16(dest, val.Y); - putS16(dest, val.Z); -} - -inline void putV2S32(std::vector *dest, v2s32 val) -{ - putS32(dest, val.X); - putS32(dest, val.Y); -} - -inline void putV3S32(std::vector *dest, v3s32 val) -{ - putS32(dest, val.X); - putS32(dest, val.Y); - putS32(dest, val.Z); -} - -inline void putV3F1000(std::vector *dest, v3f val) -{ - putF1000(dest, val.X); - putF1000(dest, val.Y); - putF1000(dest, val.Z); -} - -inline void putARGB8(std::vector *dest, video::SColor val) -{ - putU32(dest, val.color); -} - -inline void putString(std::vector *dest, const std::string &val) -{ - if (val.size() > STRING_MAX_LEN) - throw SerializationError("String too long"); - - putU16(dest, val.size()); - dest->insert(dest->end(), val.begin(), val.end()); -} - -inline void putWideString(std::vector *dest, const std::wstring &val) -{ - if (val.size() > WIDE_STRING_MAX_LEN) - throw SerializationError("String too long"); - - putU16(dest, val.size()); - for (size_t i = 0; i != val.size(); i++) - putU16(dest, val[i]); -} - -inline void putLongString(std::vector *dest, const std::string &val) -{ - if (val.size() > LONG_STRING_MAX_LEN) - throw SerializationError("String too long"); - - putU32(dest, val.size()); - dest->insert(dest->end(), val.begin(), val.end()); -} - -inline void putRawData(std::vector *dest, const void *src, size_t len) -{ - dest->insert(dest->end(), (u8 *)src, (u8 *)src + len); -} -- cgit v1.2.3 From 947466ab28129fd69e6630974c6c4e901f2bebc6 Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Sun, 20 Sep 2020 13:12:55 +0200 Subject: (se)SerializeString: Include max length in the name This commit clarifies the maximal length of the serialized strings. It will avoid accidental use of serializeString() when a larger string can be expected. Removes unused Wide String serialization functions --- src/client/content_cao.cpp | 12 +++---- src/content_nodemeta.cpp | 18 +++++------ src/database/database-leveldb.cpp | 16 +++++----- src/itemdef.cpp | 52 +++++++++++++++--------------- src/mapblock.cpp | 4 +-- src/mapgen/mg_schematic.cpp | 4 +-- src/nameidmapping.cpp | 4 +-- src/network/clientpackethandler.cpp | 8 ++--- src/nodedef.cpp | 40 +++++++++++------------ src/nodemetadata.cpp | 8 ++--- src/object_properties.cpp | 28 ++++++++--------- src/particles.cpp | 4 +-- src/server.cpp | 4 +-- src/server/luaentity_sao.cpp | 28 ++++++++--------- src/server/player_sao.cpp | 16 +++++----- src/server/serveractiveobject.cpp | 2 +- src/server/unit_sao.cpp | 6 ++-- src/sound.h | 4 +-- src/staticobject.cpp | 4 +-- src/tool.cpp | 8 ++--- src/unittest/test_serialization.cpp | 50 +++++++++++++---------------- src/util/serialize.cpp | 63 +++++-------------------------------- src/util/serialize.h | 8 ++--- 23 files changed, 168 insertions(+), 223 deletions(-) (limited to 'src') diff --git a/src/client/content_cao.cpp b/src/client/content_cao.cpp index 599139aa3..71a9d4b54 100644 --- a/src/client/content_cao.cpp +++ b/src/client/content_cao.cpp @@ -371,7 +371,7 @@ void GenericCAO::processInitData(const std::string &data) } // PROTOCOL_VERSION >= 37 - m_name = deSerializeString(is); + m_name = deSerializeString16(is); m_is_player = readU8(is); m_id = readU16(is); m_position = readV3F32(is); @@ -381,7 +381,7 @@ void GenericCAO::processInitData(const std::string &data) const u8 num_messages = readU8(is); for (int i = 0; i < num_messages; i++) { - std::string message = deSerializeLongString(is); + std::string message = deSerializeString32(is); processMessage(message); } @@ -1657,7 +1657,7 @@ void GenericCAO::processMessage(const std::string &data) rot_translator.update(m_rotation, false, update_interval); updateNodePos(); } else if (cmd == AO_CMD_SET_TEXTURE_MOD) { - std::string mod = deSerializeString(is); + std::string mod = deSerializeString16(is); // immediately reset a engine issued texture modifier if a mod sends a different one if (m_reset_textures_timer > 0) { @@ -1735,7 +1735,7 @@ void GenericCAO::processMessage(const std::string &data) m_animation_speed = readF32(is); updateAnimationSpeed(); } else if (cmd == AO_CMD_SET_BONE_POSITION) { - std::string bone = deSerializeString(is); + std::string bone = deSerializeString16(is); v3f position = readV3F32(is); v3f rotation = readV3F32(is); m_bone_position[bone] = core::vector2d(position, rotation); @@ -1743,7 +1743,7 @@ void GenericCAO::processMessage(const std::string &data) // updateBonePosition(); now called every step } else if (cmd == AO_CMD_ATTACH_TO) { u16 parent_id = readS16(is); - std::string bone = deSerializeString(is); + std::string bone = deSerializeString16(is); v3f position = readV3F32(is); v3f rotation = readV3F32(is); @@ -1793,7 +1793,7 @@ void GenericCAO::processMessage(const std::string &data) int armor_groups_size = readU16(is); for(int i=0; igetInventory()->deSerialize(is); - deSerializeLongString(is); // m_text - deSerializeString(is); // m_owner + deSerializeString32(is); // m_text + deSerializeString16(is); // m_owner - meta->setString("infotext",deSerializeString(is)); - meta->setString("formspec",deSerializeString(is)); + meta->setString("infotext",deSerializeString16(is)); + meta->setString("formspec",deSerializeString16(is)); readU8(is); // m_allow_text_input readU8(is); // m_allow_removal readU8(is); // m_enforce_owner int num_vars = readU32(is); for(int i=0; isetString(name, var); } return false; } else if(id == NODEMETA_SIGN) // SignNodeMetadata { - meta->setString("text", deSerializeString(is)); + meta->setString("text", deSerializeString16(is)); //meta->setString("infotext","\"${text}\""); meta->setString("infotext", std::string("\"") + meta->getString("text") + "\""); @@ -87,7 +87,7 @@ static bool content_nodemeta_deserialize_legacy_body( } else if(id == NODEMETA_LOCKABLE_CHEST) // LockingChestNodeMetadata { - meta->setString("owner", deSerializeString(is)); + meta->setString("owner", deSerializeString16(is)); meta->getInventory()->deSerialize(is); // Rename inventory list "0" to "main" @@ -138,7 +138,7 @@ static bool content_nodemeta_deserialize_legacy_meta( s16 id = readS16(is); // Read data - std::string data = deSerializeString(is); + std::string data = deSerializeString16(is); std::istringstream tmp_is(data, std::ios::binary); return content_nodemeta_deserialize_legacy_body(tmp_is, id, meta); } diff --git a/src/database/database-leveldb.cpp b/src/database/database-leveldb.cpp index 1976ae13d..73cd63f6d 100644 --- a/src/database/database-leveldb.cpp +++ b/src/database/database-leveldb.cpp @@ -145,8 +145,8 @@ void PlayerDatabaseLevelDB::savePlayer(RemotePlayer *player) StringMap stringvars = sao->getMeta().getStrings(); writeU32(os, stringvars.size()); for (const auto &it : stringvars) { - os << serializeString(it.first); - os << serializeLongString(it.second); + os << serializeString16(it.first); + os << serializeString32(it.second); } player->inventory.serialize(os); @@ -183,8 +183,8 @@ bool PlayerDatabaseLevelDB::loadPlayer(RemotePlayer *player, PlayerSAO *sao) u32 attribute_count = readU32(is); for (u32 i = 0; i < attribute_count; i++) { - std::string name = deSerializeString(is); - std::string value = deSerializeLongString(is); + std::string name = deSerializeString16(is); + std::string value = deSerializeString32(is); sao->getMeta().setString(name, value); } sao->getMeta().setModified(false); @@ -247,13 +247,13 @@ bool AuthDatabaseLevelDB::getAuth(const std::string &name, AuthEntry &res) res.id = 1; res.name = name; - res.password = deSerializeString(is); + res.password = deSerializeString16(is); u16 privilege_count = readU16(is); res.privileges.clear(); res.privileges.reserve(privilege_count); for (u16 i = 0; i < privilege_count; i++) { - res.privileges.push_back(deSerializeString(is)); + res.privileges.push_back(deSerializeString16(is)); } res.last_login = readS64(is); @@ -264,14 +264,14 @@ bool AuthDatabaseLevelDB::saveAuth(const AuthEntry &authEntry) { std::ostringstream os; writeU8(os, 1); - os << serializeString(authEntry.password); + os << serializeString16(authEntry.password); size_t privilege_count = authEntry.privileges.size(); FATAL_ERROR_IF(privilege_count > U16_MAX, "Unsupported number of privileges"); writeU16(os, privilege_count); for (const std::string &privilege : authEntry.privileges) { - os << serializeString(privilege); + os << serializeString16(privilege); } writeS64(os, authEntry.last_login); diff --git a/src/itemdef.cpp b/src/itemdef.cpp index 8e0492827..df20bdf15 100644 --- a/src/itemdef.cpp +++ b/src/itemdef.cpp @@ -128,10 +128,10 @@ void ItemDefinition::serialize(std::ostream &os, u16 protocol_version) const u8 version = 6; writeU8(os, version); writeU8(os, type); - os << serializeString(name); - os << serializeString(description); - os << serializeString(inventory_image); - os << serializeString(wield_image); + os << serializeString16(name); + os << serializeString16(description); + os << serializeString16(inventory_image); + os << serializeString16(wield_image); writeV3F32(os, wield_scale); writeS16(os, stack_max); writeU8(os, usable); @@ -143,25 +143,25 @@ void ItemDefinition::serialize(std::ostream &os, u16 protocol_version) const tool_capabilities->serialize(tmp_os, protocol_version); tool_capabilities_s = tmp_os.str(); } - os << serializeString(tool_capabilities_s); + os << serializeString16(tool_capabilities_s); writeU16(os, groups.size()); for (const auto &group : groups) { - os << serializeString(group.first); + os << serializeString16(group.first); writeS16(os, group.second); } - os << serializeString(node_placement_prediction); + os << serializeString16(node_placement_prediction); // Version from ContentFeatures::serialize to keep in sync sound_place.serialize(os, CONTENTFEATURES_VERSION); sound_place_failed.serialize(os, CONTENTFEATURES_VERSION); writeF32(os, range); - os << serializeString(palette_image); + os << serializeString16(palette_image); writeARGB8(os, color); - os << serializeString(inventory_overlay); - os << serializeString(wield_overlay); + os << serializeString16(inventory_overlay); + os << serializeString16(wield_overlay); } void ItemDefinition::deSerialize(std::istream &is) @@ -175,16 +175,16 @@ void ItemDefinition::deSerialize(std::istream &is) throw SerializationError("unsupported ItemDefinition version"); type = (enum ItemType)readU8(is); - name = deSerializeString(is); - description = deSerializeString(is); - inventory_image = deSerializeString(is); - wield_image = deSerializeString(is); + name = deSerializeString16(is); + description = deSerializeString16(is); + inventory_image = deSerializeString16(is); + wield_image = deSerializeString16(is); wield_scale = readV3F32(is); stack_max = readS16(is); usable = readU8(is); liquids_pointable = readU8(is); - std::string tool_capabilities_s = deSerializeString(is); + std::string tool_capabilities_s = deSerializeString16(is); if (!tool_capabilities_s.empty()) { std::istringstream tmp_is(tool_capabilities_s, std::ios::binary); tool_capabilities = new ToolCapabilities; @@ -194,22 +194,22 @@ void ItemDefinition::deSerialize(std::istream &is) groups.clear(); u32 groups_size = readU16(is); for(u32 i=0; iserialize(tmp_os, protocol_version); - os << serializeString(tmp_os.str()); + os << serializeString16(tmp_os.str()); } writeU16(os, m_aliases.size()); for (const auto &it : m_aliases) { - os << serializeString(it.first); - os << serializeString(it.second); + os << serializeString16(it.first); + os << serializeString16(it.second); } } void deSerialize(std::istream &is) @@ -543,7 +543,7 @@ public: for(u16 i=0; iidef()); } else { - //std::string data = deSerializeLongString(is); + //std::string data = deSerializeString32(is); std::ostringstream oss(std::ios_base::binary); decompressZlib(is, oss); std::istringstream iss(oss.str(), std::ios_base::binary); diff --git a/src/mapgen/mg_schematic.cpp b/src/mapgen/mg_schematic.cpp index ba102d997..dfd414709 100644 --- a/src/mapgen/mg_schematic.cpp +++ b/src/mapgen/mg_schematic.cpp @@ -314,7 +314,7 @@ bool Schematic::deserializeFromMts(std::istream *is, //// Read node names u16 nidmapcount = readU16(ss); for (int i = 0; i != nidmapcount; i++) { - std::string name = deSerializeString(ss); + std::string name = deSerializeString16(ss); // Instances of "ignore" from v1 are converted to air (and instances // are fixed to have MTSCHEM_PROB_NEVER later on). @@ -372,7 +372,7 @@ bool Schematic::serializeToMts(std::ostream *os, writeU16(ss, names.size()); // name count for (size_t i = 0; i != names.size(); i++) - ss << serializeString(names[i]); // node names + ss << serializeString16(names[i]); // node names // compressed bulk node data MapNode::serializeBulk(ss, SER_FMT_VER_HIGHEST_WRITE, diff --git a/src/nameidmapping.cpp b/src/nameidmapping.cpp index bd5bb1fc8..05cfae069 100644 --- a/src/nameidmapping.cpp +++ b/src/nameidmapping.cpp @@ -27,7 +27,7 @@ void NameIdMapping::serialize(std::ostream &os) const writeU16(os, m_id_to_name.size()); for (const auto &i : m_id_to_name) { writeU16(os, i.first); - os << serializeString(i.second); + os << serializeString16(i.second); } } @@ -41,7 +41,7 @@ void NameIdMapping::deSerialize(std::istream &is) m_name_to_id.clear(); for (u32 i = 0; i < count; i++) { u16 id = readU16(is); - std::string name = deSerializeString(is); + std::string name = deSerializeString16(is); m_id_to_name[id] = name; m_name_to_id[name] = id; } diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp index 8d87ff8f2..5683564a0 100644 --- a/src/network/clientpackethandler.cpp +++ b/src/network/clientpackethandler.cpp @@ -497,7 +497,7 @@ void Client::handleCommand_ActiveObjectMessages(NetworkPacket* pkt) if (!is.good()) break; - std::string message = deSerializeString(is); + std::string message = deSerializeString16(is); // Pass on to the environment m_env.processActiveObjectMessage(id, message); @@ -994,7 +994,7 @@ void Client::handleCommand_AddParticleSpawner(NetworkPacket* pkt) p.minsize = readF32(is); p.maxsize = readF32(is); p.collisiondetection = readU8(is); - p.texture = deSerializeLongString(is); + p.texture = deSerializeString32(is); server_id = readU32(is); @@ -1207,11 +1207,11 @@ void Client::handleCommand_HudSetSky(NetworkPacket* pkt) SkyboxParams skybox; skybox.bgcolor = video::SColor(readARGB8(is)); - skybox.type = std::string(deSerializeString(is)); + skybox.type = std::string(deSerializeString16(is)); u16 count = readU16(is); for (size_t i = 0; i < count; i++) - skybox.textures.emplace_back(deSerializeString(is)); + skybox.textures.emplace_back(deSerializeString16(is)); skybox.clouds = true; try { diff --git a/src/nodedef.cpp b/src/nodedef.cpp index 392f5eb98..3a5934cf3 100644 --- a/src/nodedef.cpp +++ b/src/nodedef.cpp @@ -207,7 +207,7 @@ void TileDef::serialize(std::ostream &os, u16 protocol_version) const u8 version = 6; writeU8(os, version); - os << serializeString(name); + os << serializeString16(name); animation.serialize(os, version); bool has_scale = scale > 0; u16 flags = 0; @@ -241,7 +241,7 @@ void TileDef::deSerialize(std::istream &is, u8 contentfeatures_version, int version = readU8(is); if (version < 6) throw SerializationError("unsupported TileDef version"); - name = deSerializeString(is); + name = deSerializeString16(is); animation.deSerialize(is, version); u16 flags = readU16(is); backface_culling = flags & TILE_FLAG_BACKFACE_CULLING; @@ -416,10 +416,10 @@ void ContentFeatures::serialize(std::ostream &os, u16 protocol_version) const writeU8(os, version); // general - os << serializeString(name); + os << serializeString16(name); writeU16(os, groups.size()); for (const auto &group : groups) { - os << serializeString(group.first); + os << serializeString16(group.first); writeS16(os, group.second); } writeU8(os, param_type); @@ -427,7 +427,7 @@ void ContentFeatures::serialize(std::ostream &os, u16 protocol_version) const // visual writeU8(os, drawtype); - os << serializeString(mesh); + os << serializeString16(mesh); writeF32(os, visual_scale); writeU8(os, 6); for (const TileDef &td : tiledef) @@ -442,7 +442,7 @@ void ContentFeatures::serialize(std::ostream &os, u16 protocol_version) const writeU8(os, color.getRed()); writeU8(os, color.getGreen()); writeU8(os, color.getBlue()); - os << serializeString(palette_name); + os << serializeString16(palette_name); writeU8(os, waving); writeU8(os, connect_sides); writeU16(os, connects_to_ids.size()); @@ -470,8 +470,8 @@ void ContentFeatures::serialize(std::ostream &os, u16 protocol_version) const // liquid writeU8(os, liquid_type); - os << serializeString(liquid_alternative_flowing); - os << serializeString(liquid_alternative_source); + os << serializeString16(liquid_alternative_flowing); + os << serializeString16(liquid_alternative_source); writeU8(os, liquid_viscosity); writeU8(os, liquid_renewable); writeU8(os, liquid_range); @@ -492,7 +492,7 @@ void ContentFeatures::serialize(std::ostream &os, u16 protocol_version) const writeU8(os, legacy_facedir_simple); writeU8(os, legacy_wallmounted); - os << serializeString(node_dig_prediction); + os << serializeString16(node_dig_prediction); writeU8(os, leveled_max); } @@ -519,11 +519,11 @@ void ContentFeatures::deSerialize(std::istream &is) throw SerializationError("unsupported ContentFeatures version"); // general - name = deSerializeString(is); + name = deSerializeString16(is); groups.clear(); u32 groups_size = readU16(is); for (u32 i = 0; i < groups_size; i++) { - std::string name = deSerializeString(is); + std::string name = deSerializeString16(is); int value = readS16(is); groups[name] = value; } @@ -532,7 +532,7 @@ void ContentFeatures::deSerialize(std::istream &is) // visual drawtype = (enum NodeDrawType) readU8(is); - mesh = deSerializeString(is); + mesh = deSerializeString16(is); visual_scale = readF32(is); if (readU8(is) != 6) throw SerializationError("unsupported tile count"); @@ -548,7 +548,7 @@ void ContentFeatures::deSerialize(std::istream &is) color.setRed(readU8(is)); color.setGreen(readU8(is)); color.setBlue(readU8(is)); - palette_name = deSerializeString(is); + palette_name = deSerializeString16(is); waving = readU8(is); connect_sides = readU8(is); u16 connects_to_size = readU16(is); @@ -578,8 +578,8 @@ void ContentFeatures::deSerialize(std::istream &is) // liquid liquid_type = (enum LiquidType) readU8(is); - liquid_alternative_flowing = deSerializeString(is); - liquid_alternative_source = deSerializeString(is); + liquid_alternative_flowing = deSerializeString16(is); + liquid_alternative_source = deSerializeString16(is); liquid_viscosity = readU8(is); liquid_renewable = readU8(is); liquid_range = readU8(is); @@ -601,7 +601,7 @@ void ContentFeatures::deSerialize(std::istream &is) legacy_wallmounted = readU8(is); try { - node_dig_prediction = deSerializeString(is); + node_dig_prediction = deSerializeString16(is); u8 tmp_leveled_max = readU8(is); if (is.eof()) /* readU8 doesn't throw exceptions so we have to do this */ throw SerializationError(""); @@ -1472,7 +1472,7 @@ void NodeDefManager::serialize(std::ostream &os, u16 protocol_version) const // strict version incompatibilities std::ostringstream wrapper_os(std::ios::binary); f->serialize(wrapper_os, protocol_version); - os2<= 2) writeU8(os, (priv) ? 1 : 0); } @@ -63,8 +63,8 @@ void NodeMetadata::deSerialize(std::istream &is, u8 version) clear(); int num_vars = readU32(is); for(int i=0; i= 2) { if (readU8(is) == 1) diff --git a/src/object_properties.cpp b/src/object_properties.cpp index 8d51bcbfa..c31c667e7 100644 --- a/src/object_properties.cpp +++ b/src/object_properties.cpp @@ -84,11 +84,11 @@ void ObjectProperties::serialize(std::ostream &os) const writeV3F32(os, selectionbox.MinEdge); writeV3F32(os, selectionbox.MaxEdge); writeU8(os, pointable); - os << serializeString(visual); + os << serializeString16(visual); writeV3F32(os, visual_size); writeU16(os, textures.size()); for (const std::string &texture : textures) { - os << serializeString(texture); + os << serializeString16(texture); } writeV2S16(os, spritediv); writeV2S16(os, initial_sprite_basepos); @@ -96,7 +96,7 @@ void ObjectProperties::serialize(std::ostream &os) const writeU8(os, makes_footstep_sound); writeF32(os, automatic_rotate); // Added in protocol version 14 - os << serializeString(mesh); + os << serializeString16(mesh); writeU16(os, colors.size()); for (video::SColor color : colors) { writeARGB8(os, color); @@ -106,17 +106,17 @@ void ObjectProperties::serialize(std::ostream &os) const writeU8(os, automatic_face_movement_dir); writeF32(os, automatic_face_movement_dir_offset); writeU8(os, backface_culling); - os << serializeString(nametag); + os << serializeString16(nametag); writeARGB8(os, nametag_color); writeF32(os, automatic_face_movement_max_rotation_per_sec); - os << serializeString(infotext); - os << serializeString(wield_item); + os << serializeString16(infotext); + os << serializeString16(wield_item); writeS8(os, glow); writeU16(os, breath_max); writeF32(os, eye_height); writeF32(os, zoom_fov); writeU8(os, use_texture_alpha); - os << serializeString(damage_texture_modifier); + os << serializeString16(damage_texture_modifier); writeU8(os, shaded); // Add stuff only at the bottom. @@ -137,19 +137,19 @@ void ObjectProperties::deSerialize(std::istream &is) selectionbox.MinEdge = readV3F32(is); selectionbox.MaxEdge = readV3F32(is); pointable = readU8(is); - visual = deSerializeString(is); + visual = deSerializeString16(is); visual_size = readV3F32(is); textures.clear(); u32 texture_count = readU16(is); for (u32 i = 0; i < texture_count; i++){ - textures.push_back(deSerializeString(is)); + textures.push_back(deSerializeString16(is)); } spritediv = readV2S16(is); initial_sprite_basepos = readV2S16(is); is_visible = readU8(is); makes_footstep_sound = readU8(is); automatic_rotate = readF32(is); - mesh = deSerializeString(is); + mesh = deSerializeString16(is); colors.clear(); u32 color_count = readU16(is); for (u32 i = 0; i < color_count; i++){ @@ -160,18 +160,18 @@ void ObjectProperties::deSerialize(std::istream &is) automatic_face_movement_dir = readU8(is); automatic_face_movement_dir_offset = readF32(is); backface_culling = readU8(is); - nametag = deSerializeString(is); + nametag = deSerializeString16(is); nametag_color = readARGB8(is); automatic_face_movement_max_rotation_per_sec = readF32(is); - infotext = deSerializeString(is); - wield_item = deSerializeString(is); + infotext = deSerializeString16(is); + wield_item = deSerializeString16(is); glow = readS8(is); breath_max = readU16(is); eye_height = readF32(is); zoom_fov = readF32(is); use_texture_alpha = readU8(is); try { - damage_texture_modifier = deSerializeString(is); + damage_texture_modifier = deSerializeString16(is); u8 tmp = readU8(is); if (is.eof()) throw SerializationError(""); diff --git a/src/particles.cpp b/src/particles.cpp index fd81238dc..14c987958 100644 --- a/src/particles.cpp +++ b/src/particles.cpp @@ -28,7 +28,7 @@ void ParticleParameters::serialize(std::ostream &os, u16 protocol_ver) const writeF32(os, expirationtime); writeF32(os, size); writeU8(os, collisiondetection); - os << serializeLongString(texture); + os << serializeString32(texture); writeU8(os, vertical); writeU8(os, collision_removal); animation.serialize(os, 6); /* NOT the protocol ver */ @@ -47,7 +47,7 @@ void ParticleParameters::deSerialize(std::istream &is, u16 protocol_ver) expirationtime = readF32(is); size = readF32(is); collisiondetection = readU8(is); - texture = deSerializeLongString(is); + texture = deSerializeString32(is); vertical = readU8(is); collision_removal = readU8(is); animation.deSerialize(is, 6); /* NOT the protocol ver */ diff --git a/src/server.cpp b/src/server.cpp index d40ff259f..982f904f4 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -802,7 +802,7 @@ void Server::AsyncRunStep(bool initial_step) // u16 id // std::string data buffer.append(idbuf, sizeof(idbuf)); - buffer.append(serializeString(aom.datastring)); + buffer.append(serializeString16(aom.datastring)); } } /* @@ -1993,7 +1993,7 @@ void Server::SendActiveObjectRemoveAdd(RemoteClient *client, PlayerSAO *playersa writeU8((u8*)buf, type); data.append(buf, 1); - data.append(serializeLongString( + data.append(serializeString32( obj->getClientInitializationData(client->net_proto_version))); // Add to known objects diff --git a/src/server/luaentity_sao.cpp b/src/server/luaentity_sao.cpp index d504c42ca..f20914f7f 100644 --- a/src/server/luaentity_sao.cpp +++ b/src/server/luaentity_sao.cpp @@ -42,8 +42,8 @@ LuaEntitySAO::LuaEntitySAO(ServerEnvironment *env, v3f pos, const std::string &d u8 version2 = 0; u8 version = readU8(is); - name = deSerializeString(is); - state = deSerializeLongString(is); + name = deSerializeString16(is); + state = deSerializeString32(is); if (version < 1) break; @@ -225,7 +225,7 @@ std::string LuaEntitySAO::getClientInitializationData(u16 protocol_version) // PROTOCOL_VERSION >= 37 writeU8(os, 1); // version - os << serializeString(""); // name + os << serializeString16(""); // name writeU8(os, 0); // is_player writeU16(os, getId()); //id writeV3F32(os, m_base_position); @@ -233,26 +233,26 @@ std::string LuaEntitySAO::getClientInitializationData(u16 protocol_version) writeU16(os, m_hp); std::ostringstream msg_os(std::ios::binary); - msg_os << serializeLongString(getPropertyPacket()); // message 1 - msg_os << serializeLongString(generateUpdateArmorGroupsCommand()); // 2 - msg_os << serializeLongString(generateUpdateAnimationCommand()); // 3 + msg_os << serializeString32(getPropertyPacket()); // message 1 + msg_os << serializeString32(generateUpdateArmorGroupsCommand()); // 2 + msg_os << serializeString32(generateUpdateAnimationCommand()); // 3 for (const auto &bone_pos : m_bone_position) { - msg_os << serializeLongString(generateUpdateBonePositionCommand( + msg_os << serializeString32(generateUpdateBonePositionCommand( bone_pos.first, bone_pos.second.X, bone_pos.second.Y)); // m_bone_position.size } - msg_os << serializeLongString(generateUpdateAttachmentCommand()); // 4 + msg_os << serializeString32(generateUpdateAttachmentCommand()); // 4 int message_count = 4 + m_bone_position.size(); for (const auto &id : getAttachmentChildIds()) { if (ServerActiveObject *obj = m_env->getActiveObject(id)) { message_count++; - msg_os << serializeLongString(obj->generateUpdateInfantCommand( + msg_os << serializeString32(obj->generateUpdateInfantCommand( id, protocol_version)); } } - msg_os << serializeLongString(generateSetTextureModCommand()); + msg_os << serializeString32(generateSetTextureModCommand()); message_count++; writeU8(os, message_count); @@ -270,14 +270,14 @@ void LuaEntitySAO::getStaticData(std::string *result) const // version must be 1 to keep backwards-compatibility. See version2 writeU8(os, 1); // name - os<getScriptIface()-> luaentity_GetStaticdata(m_id); - os<= 15 writeU8(os, 1); // version - os << serializeString(m_player->getName()); // name + os << serializeString16(m_player->getName()); // name writeU8(os, 1); // is_player writeS16(os, getId()); // id writeV3F32(os, m_base_position); @@ -117,22 +117,22 @@ std::string PlayerSAO::getClientInitializationData(u16 protocol_version) writeU16(os, getHP()); std::ostringstream msg_os(std::ios::binary); - msg_os << serializeLongString(getPropertyPacket()); // message 1 - msg_os << serializeLongString(generateUpdateArmorGroupsCommand()); // 2 - msg_os << serializeLongString(generateUpdateAnimationCommand()); // 3 + msg_os << serializeString32(getPropertyPacket()); // message 1 + msg_os << serializeString32(generateUpdateArmorGroupsCommand()); // 2 + msg_os << serializeString32(generateUpdateAnimationCommand()); // 3 for (const auto &bone_pos : m_bone_position) { - msg_os << serializeLongString(generateUpdateBonePositionCommand( + msg_os << serializeString32(generateUpdateBonePositionCommand( bone_pos.first, bone_pos.second.X, bone_pos.second.Y)); // m_bone_position.size } - msg_os << serializeLongString(generateUpdateAttachmentCommand()); // 4 - msg_os << serializeLongString(generateUpdatePhysicsOverrideCommand()); // 5 + msg_os << serializeString32(generateUpdateAttachmentCommand()); // 4 + msg_os << serializeString32(generateUpdatePhysicsOverrideCommand()); // 5 int message_count = 5 + m_bone_position.size(); for (const auto &id : getAttachmentChildIds()) { if (ServerActiveObject *obj = m_env->getActiveObject(id)) { message_count++; - msg_os << serializeLongString(obj->generateUpdateInfantCommand( + msg_os << serializeString32(obj->generateUpdateInfantCommand( id, protocol_version)); } } diff --git a/src/server/serveractiveobject.cpp b/src/server/serveractiveobject.cpp index 3341dc008..8cb59b2d6 100644 --- a/src/server/serveractiveobject.cpp +++ b/src/server/serveractiveobject.cpp @@ -61,7 +61,7 @@ std::string ServerActiveObject::generateUpdateInfantCommand(u16 infant_id, u16 p // Clients since 4aa9a66 so no longer need this data // Version 38 is the first bump after that commit. // See also: ClientEnvironment::addActiveObject - os << serializeLongString(getClientInitializationData(protocol_version)); + os << serializeString32(getClientInitializationData(protocol_version)); } return os.str(); } diff --git a/src/server/unit_sao.cpp b/src/server/unit_sao.cpp index ef0e87f2c..d906e885e 100644 --- a/src/server/unit_sao.cpp +++ b/src/server/unit_sao.cpp @@ -242,7 +242,7 @@ std::string UnitSAO::generateUpdateAttachmentCommand() const writeU8(os, AO_CMD_ATTACH_TO); // parameters writeS16(os, m_attachment_parent_id); - os << serializeString(m_attachment_bone); + os << serializeString16(m_attachment_bone); writeV3F32(os, m_attachment_position); writeV3F32(os, m_attachment_rotation); return os.str(); @@ -255,7 +255,7 @@ std::string UnitSAO::generateUpdateBonePositionCommand( // command writeU8(os, AO_CMD_SET_BONE_POSITION); // parameters - os << serializeString(bone); + os << serializeString16(bone); writeV3F32(os, position); writeV3F32(os, rotation); return os.str(); @@ -291,7 +291,7 @@ std::string UnitSAO::generateUpdateArmorGroupsCommand() const writeU8(os, AO_CMD_UPDATE_ARMOR_GROUPS); writeU16(os, m_armor_groups.size()); for (const auto &armor_group : m_armor_groups) { - os << serializeString(armor_group.first); + os << serializeString16(armor_group.first); writeS16(os, armor_group.second); } return os.str(); diff --git a/src/sound.h b/src/sound.h index 6cbd55e8f..6f7b0a1af 100644 --- a/src/sound.h +++ b/src/sound.h @@ -39,7 +39,7 @@ struct SimpleSoundSpec // keep in sync with item definitions void serialize(std::ostream &os, u8 cf_version) const { - os << serializeString(name); + os << serializeString16(name); writeF32(os, gain); writeF32(os, pitch); writeF32(os, fade); @@ -49,7 +49,7 @@ struct SimpleSoundSpec void deSerialize(std::istream &is, u8 cf_version) { - name = deSerializeString(is); + name = deSerializeString16(is); gain = readF32(is); pitch = readF32(is); fade = readF32(is); diff --git a/src/staticobject.cpp b/src/staticobject.cpp index 5ccb7baf5..86e455b9f 100644 --- a/src/staticobject.cpp +++ b/src/staticobject.cpp @@ -35,7 +35,7 @@ void StaticObject::serialize(std::ostream &os) // pos writeV3F1000(os, pos); // data - os<uses); writeS16(os, cap->maxlevel); writeU32(os, cap->times.size()); @@ -79,7 +79,7 @@ void ToolCapabilities::serialize(std::ostream &os, u16 protocol_version) const writeU32(os, damageGroups.size()); for (const auto &damageGroup : damageGroups) { - os << serializeString(damageGroup.first); + os << serializeString16(damageGroup.first); writeS16(os, damageGroup.second); } @@ -98,7 +98,7 @@ void ToolCapabilities::deSerialize(std::istream &is) groupcaps.clear(); u32 groupcaps_size = readU32(is); for (u32 i = 0; i < groupcaps_size; i++) { - std::string name = deSerializeString(is); + std::string name = deSerializeString16(is); ToolGroupCap cap; cap.uses = readS16(is); cap.maxlevel = readS16(is); @@ -113,7 +113,7 @@ void ToolCapabilities::deSerialize(std::istream &is) u32 damage_groups_size = readU32(is); for (u32 i = 0; i < damage_groups_size; i++) { - std::string name = deSerializeString(is); + std::string name = deSerializeString16(is); s16 rating = readS16(is); damageGroups[name] = rating; } diff --git a/src/unittest/test_serialization.cpp b/src/unittest/test_serialization.cpp index d72bf0d4c..660d77d02 100644 --- a/src/unittest/test_serialization.cpp +++ b/src/unittest/test_serialization.cpp @@ -44,7 +44,7 @@ public: std::wstring teststring2_w; std::string teststring2_w_encoded; - static const u8 test_serialized_data[12 * 13 - 8]; + static const u8 test_serialized_data[12 * 11 - 2]; }; static TestSerialization g_test_instance; @@ -91,21 +91,21 @@ void TestSerialization::buildTestStrings() void TestSerialization::testSerializeString() { // Test blank string - UASSERT(serializeString("") == mkstr("\0\0")); + UASSERT(serializeString16("") == mkstr("\0\0")); // Test basic string - UASSERT(serializeString("Hello world!") == mkstr("\0\14Hello world!")); + UASSERT(serializeString16("Hello world!") == mkstr("\0\14Hello world!")); // Test character range - UASSERT(serializeString(teststring2) == mkstr("\1\0") + teststring2); + UASSERT(serializeString16(teststring2) == mkstr("\1\0") + teststring2); } void TestSerialization::testDeSerializeString() { // Test deserialize { - std::istringstream is(serializeString(teststring2), std::ios::binary); - UASSERT(deSerializeString(is) == teststring2); + std::istringstream is(serializeString16(teststring2), std::ios::binary); + UASSERT(deSerializeString16(is) == teststring2); UASSERT(!is.eof()); is.get(); UASSERT(is.eof()); @@ -114,34 +114,34 @@ void TestSerialization::testDeSerializeString() // Test deserialize an incomplete length specifier { std::istringstream is(mkstr("\x53"), std::ios::binary); - EXCEPTION_CHECK(SerializationError, deSerializeString(is)); + EXCEPTION_CHECK(SerializationError, deSerializeString16(is)); } // Test deserialize a string with incomplete data { std::istringstream is(mkstr("\x00\x55 abcdefg"), std::ios::binary); - EXCEPTION_CHECK(SerializationError, deSerializeString(is)); + EXCEPTION_CHECK(SerializationError, deSerializeString16(is)); } } void TestSerialization::testSerializeLongString() { // Test blank string - UASSERT(serializeLongString("") == mkstr("\0\0\0\0")); + UASSERT(serializeString32("") == mkstr("\0\0\0\0")); // Test basic string - UASSERT(serializeLongString("Hello world!") == mkstr("\0\0\0\14Hello world!")); + UASSERT(serializeString32("Hello world!") == mkstr("\0\0\0\14Hello world!")); // Test character range - UASSERT(serializeLongString(teststring2) == mkstr("\0\0\1\0") + teststring2); + UASSERT(serializeString32(teststring2) == mkstr("\0\0\1\0") + teststring2); } void TestSerialization::testDeSerializeLongString() { // Test deserialize { - std::istringstream is(serializeLongString(teststring2), std::ios::binary); - UASSERT(deSerializeLongString(is) == teststring2); + std::istringstream is(serializeString32(teststring2), std::ios::binary); + UASSERT(deSerializeString32(is) == teststring2); UASSERT(!is.eof()); is.get(); UASSERT(is.eof()); @@ -150,19 +150,19 @@ void TestSerialization::testDeSerializeLongString() // Test deserialize an incomplete length specifier { std::istringstream is(mkstr("\x53"), std::ios::binary); - EXCEPTION_CHECK(SerializationError, deSerializeLongString(is)); + EXCEPTION_CHECK(SerializationError, deSerializeString32(is)); } // Test deserialize a string with incomplete data { std::istringstream is(mkstr("\x00\x00\x00\x05 abc"), std::ios::binary); - EXCEPTION_CHECK(SerializationError, deSerializeLongString(is)); + EXCEPTION_CHECK(SerializationError, deSerializeString32(is)); } // Test deserialize a string with a length too large { std::istringstream is(mkstr("\xFF\xFF\xFF\xFF blah"), std::ios::binary); - EXCEPTION_CHECK(SerializationError, deSerializeLongString(is)); + EXCEPTION_CHECK(SerializationError, deSerializeString32(is)); } } @@ -235,19 +235,17 @@ void TestSerialization::testStreamRead() UASSERT(readF1000(is) == F1000_MIN); UASSERT(readF1000(is) == F1000_MAX); - UASSERT(deSerializeString(is) == "foobar!"); + UASSERT(deSerializeString16(is) == "foobar!"); UASSERT(readV2S16(is) == v2s16(500, 500)); UASSERT(readV3S16(is) == v3s16(4207, 604, -30)); UASSERT(readV2S32(is) == v2s32(1920, 1080)); UASSERT(readV3S32(is) == v3s32(-400, 6400054, 290549855)); - UASSERT(deSerializeWideString(is) == L"\x02~woof~\x5455"); - UASSERT(readV3F1000(is) == v3f(500, 10024.2f, -192.54f)); UASSERT(readARGB8(is) == video::SColor(255, 128, 50, 128)); - UASSERT(deSerializeLongString(is) == "some longer string here"); + UASSERT(deSerializeString32(is) == "some longer string here"); UASSERT(is.rdbuf()->in_avail() == 2); UASSERT(readU16(is) == 0xF00D); @@ -275,7 +273,7 @@ void TestSerialization::testStreamWrite() writeF1000(os, F1000_MIN); writeF1000(os, F1000_MAX); - os << serializeString("foobar!"); + os << serializeString16("foobar!"); data = os.str(); UASSERT(data.size() < sizeof(test_serialized_data)); @@ -286,12 +284,10 @@ void TestSerialization::testStreamWrite() writeV2S32(os, v2s32(1920, 1080)); writeV3S32(os, v3s32(-400, 6400054, 290549855)); - os << serializeWideString(L"\x02~woof~\x5455"); - writeV3F1000(os, v3f(500, 10024.2f, -192.54f)); writeARGB8(os, video::SColor(255, 128, 50, 128)); - os << serializeLongString("some longer string here"); + os << serializeString32("some longer string here"); writeU16(os, 0xF00D); @@ -384,7 +380,7 @@ void TestSerialization::testFloatFormat() UASSERT(test_single(i)); } -const u8 TestSerialization::test_serialized_data[12 * 13 - 8] = { +const u8 TestSerialization::test_serialized_data[12 * 11 - 2] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x80, 0x75, 0x30, 0xff, 0xff, 0xff, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd5, 0x00, 0x00, 0xd1, 0x1e, 0xee, 0x1e, @@ -392,9 +388,7 @@ const u8 TestSerialization::test_serialized_data[12 * 13 - 8] = { 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72, 0x21, 0x01, 0xf4, 0x01, 0xf4, 0x10, 0x6f, 0x02, 0x5c, 0xff, 0xe2, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x04, 0x38, 0xff, 0xff, 0xfe, 0x70, 0x00, 0x61, 0xa8, 0x36, 0x11, 0x51, 0x70, - 0x5f, 0x00, 0x08, 0x00, - 0x02, 0x00, 0x7e, 0x00, 'w', 0x00, 'o', 0x00, 'o', 0x00, 'f', 0x00, // \x02~woof~\x5455 - 0x7e, 0x54, 0x55, 0x00, 0x07, 0xa1, 0x20, 0x00, 0x98, 0xf5, 0x08, 0xff, + 0x5f, 0x00, 0x07, 0xa1, 0x20, 0x00, 0x98, 0xf5, 0x08, 0xff, 0xfd, 0x0f, 0xe4, 0xff, 0x80, 0x32, 0x80, 0x00, 0x00, 0x00, 0x17, 0x73, 0x6f, 0x6d, 0x65, 0x20, 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x68, 0x65, 0x72, 0x65, 0xF0, 0x0D, diff --git a/src/util/serialize.cpp b/src/util/serialize.cpp index fd5cbda21..d770101f2 100644 --- a/src/util/serialize.cpp +++ b/src/util/serialize.cpp @@ -35,13 +35,13 @@ FloatType g_serialize_f32_type = FLOATTYPE_UNKNOWN; //// String //// -std::string serializeString(const std::string &plain) +std::string serializeString16(const std::string &plain) { std::string s; char buf[2]; if (plain.size() > STRING_MAX_LEN) - throw SerializationError("String too long for serializeString"); + throw SerializationError("String too long for serializeString16"); s.reserve(2 + plain.size()); writeU16((u8 *)&buf[0], plain.size()); @@ -51,14 +51,14 @@ std::string serializeString(const std::string &plain) return s; } -std::string deSerializeString(std::istream &is) +std::string deSerializeString16(std::istream &is) { std::string s; char buf[2]; is.read(buf, 2); if (is.gcount() != 2) - throw SerializationError("deSerializeString: size not read"); + throw SerializationError("deSerializeString16: size not read"); u16 s_size = readU16((u8 *)buf); if (s_size == 0) @@ -67,66 +67,17 @@ std::string deSerializeString(std::istream &is) s.resize(s_size); is.read(&s[0], s_size); if (is.gcount() != s_size) - throw SerializationError("deSerializeString: couldn't read all chars"); + throw SerializationError("deSerializeString16: couldn't read all chars"); return s; } -//// -//// Wide String -//// - -std::string serializeWideString(const std::wstring &plain) -{ - std::string s; - char buf[2]; - - if (plain.size() > WIDE_STRING_MAX_LEN) - throw SerializationError("String too long for serializeWideString"); - s.reserve(2 + 2 * plain.size()); - - writeU16((u8 *)buf, plain.size()); - s.append(buf, 2); - - for (wchar_t i : plain) { - writeU16((u8 *)buf, i); - s.append(buf, 2); - } - return s; -} - -std::wstring deSerializeWideString(std::istream &is) -{ - std::wstring s; - char buf[2]; - - is.read(buf, 2); - if (is.gcount() != 2) - throw SerializationError("deSerializeWideString: size not read"); - - u16 s_size = readU16((u8 *)buf); - if (s_size == 0) - return s; - - s.reserve(s_size); - for (u32 i = 0; i < s_size; i++) { - is.read(&buf[0], 2); - if (is.gcount() != 2) { - throw SerializationError( - "deSerializeWideString: couldn't read all chars"); - } - - wchar_t c16 = readU16((u8 *)buf); - s.append(&c16, 1); - } - return s; -} //// //// Long String //// -std::string serializeLongString(const std::string &plain) +std::string serializeString32(const std::string &plain) { std::string s; char buf[4]; @@ -141,7 +92,7 @@ std::string serializeLongString(const std::string &plain) return s; } -std::string deSerializeLongString(std::istream &is) +std::string deSerializeString32(std::istream &is) { std::string s; char buf[4]; diff --git a/src/util/serialize.h b/src/util/serialize.h index a988a8f78..b3ec28eab 100644 --- a/src/util/serialize.h +++ b/src/util/serialize.h @@ -440,16 +440,16 @@ MAKE_STREAM_WRITE_FXN(video::SColor, ARGB8, 4); //// // Creates a string with the length as the first two bytes -std::string serializeString(const std::string &plain); +std::string serializeString16(const std::string &plain); // Reads a string with the length as the first two bytes -std::string deSerializeString(std::istream &is); +std::string deSerializeString16(std::istream &is); // Creates a string with the length as the first four bytes -std::string serializeLongString(const std::string &plain); +std::string serializeString32(const std::string &plain); // Reads a string with the length as the first four bytes -std::string deSerializeLongString(std::istream &is); +std::string deSerializeString32(std::istream &is); // Creates a string encoded in JSON format (almost equivalent to a C string literal) std::string serializeJsonString(const std::string &plain); -- cgit v1.2.3 From 9dc29a75b416c6dab27ce93d0129383309cbf2c2 Mon Sep 17 00:00:00 2001 From: HybridDog <3192173+HybridDog@users.noreply.github.com> Date: Sat, 3 Oct 2020 18:33:51 +0200 Subject: Reduce the FPS when the window is unfocused (#8837) --- builtin/settingtypes.txt | 4 ++-- src/client/game.cpp | 7 ++++--- src/defaultsettings.cpp | 4 ++-- src/gui/guiEngine.cpp | 17 +++++++++-------- src/gui/guiEngine.h | 2 +- 5 files changed, 18 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index 6d9c6f573..7f2d12be5 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -606,8 +606,8 @@ arm_inertia (Arm inertia) bool true # to not waste CPU power for no benefit. fps_max (Maximum FPS) int 60 1 -# Maximum FPS when game is paused. -pause_fps_max (FPS in pause menu) int 20 1 +# Maximum FPS when the window is not focused, or when the game is paused. +fps_max_unfocused (FPS when unfocused or paused) int 20 1 # Open the pause menu when the window's focus is lost. Does not pause if a formspec is # open. diff --git a/src/client/game.cpp b/src/client/game.cpp index 920383aaf..8f9d51417 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -3996,9 +3996,10 @@ inline void Game::limitFps(FpsControl *fps_timings, f32 *dtime) else fps_timings->busy_time = 0; - u32 frametime_min = 1000 / (g_menumgr.pausesGame() - ? g_settings->getFloat("pause_fps_max") - : g_settings->getFloat("fps_max")); + u32 frametime_min = 1000 / ( + device->isWindowFocused() && !g_menumgr.pausesGame() + ? g_settings->getFloat("fps_max") + : g_settings->getFloat("fps_max_unfocused")); if (fps_timings->busy_time < frametime_min) { fps_timings->sleep_time = frametime_min - fps_timings->busy_time; diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 3a0b88dc2..8f5ed3e17 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -165,7 +165,7 @@ void set_default_settings(Settings *settings) settings->setDefault("tooltip_show_delay", "400"); settings->setDefault("tooltip_append_itemname", "false"); settings->setDefault("fps_max", "60"); - settings->setDefault("pause_fps_max", "20"); + settings->setDefault("fps_max_unfocused", "20"); settings->setDefault("viewing_range", "100"); #if ENABLE_GLES settings->setDefault("near_plane", "0.1"); @@ -477,7 +477,7 @@ void set_default_settings(Settings *settings) settings->setDefault("max_block_generate_distance", "5"); settings->setDefault("enable_3d_clouds", "false"); settings->setDefault("fps_max", "30"); - settings->setDefault("pause_fps_max", "10"); + settings->setDefault("fps_max_unfocused", "10"); settings->setDefault("max_objects_per_block", "20"); settings->setDefault("sqlite_synchronous", "1"); settings->setDefault("server_map_save_interval", "15"); diff --git a/src/gui/guiEngine.cpp b/src/gui/guiEngine.cpp index b40707d01..4a13f0b11 100644 --- a/src/gui/guiEngine.cpp +++ b/src/gui/guiEngine.cpp @@ -297,10 +297,14 @@ void GUIEngine::run() driver->endScene(); + IrrlichtDevice *device = RenderingEngine::get_raw_device(); + u32 frametime_min = 1000 / (device->isWindowFocused() + ? g_settings->getFloat("fps_max") + : g_settings->getFloat("fps_max_unfocused")); if (m_clouds_enabled) - cloudPostProcess(); + cloudPostProcess(frametime_min, device); else - sleep_ms(25); + sleep_ms(frametime_min); m_script->step(); @@ -367,9 +371,8 @@ void GUIEngine::cloudPreProcess() } /******************************************************************************/ -void GUIEngine::cloudPostProcess() +void GUIEngine::cloudPostProcess(u32 frametime_min, IrrlichtDevice *device) { - float fps_max = g_settings->getFloat("pause_fps_max"); // Time of frame without fps limit u32 busytime_u32; @@ -380,12 +383,10 @@ void GUIEngine::cloudPostProcess() else busytime_u32 = 0; - // FPS limiter - u32 frametime_min = 1000./fps_max; - + // FPS limit if (busytime_u32 < frametime_min) { u32 sleeptime = frametime_min - busytime_u32; - RenderingEngine::get_raw_device()->sleep(sleeptime); + device->sleep(sleeptime); } } diff --git a/src/gui/guiEngine.h b/src/gui/guiEngine.h index f9ad0fb0a..e5b3edce7 100644 --- a/src/gui/guiEngine.h +++ b/src/gui/guiEngine.h @@ -277,7 +277,7 @@ private: /** do preprocessing for cloud subsystem */ void cloudPreProcess(); /** do postprocessing for cloud subsystem */ - void cloudPostProcess(); + void cloudPostProcess(u32 frametime_min, IrrlichtDevice *device); /** internam data required for drawing clouds */ struct clouddata { -- cgit v1.2.3 From 07500479191ed927ab661b3758ffcd2fd43158c5 Mon Sep 17 00:00:00 2001 From: random-geek <35757396+random-geek@users.noreply.github.com> Date: Sat, 3 Oct 2020 09:34:34 -0700 Subject: Fix scroll bar overlapping text (again) (#9058) --- src/gui/guiEditBoxWithScrollbar.cpp | 4 +--- src/gui/intlGUIEditBox.cpp | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/gui/guiEditBoxWithScrollbar.cpp b/src/gui/guiEditBoxWithScrollbar.cpp index 442406688..169425a9a 100644 --- a/src/gui/guiEditBoxWithScrollbar.cpp +++ b/src/gui/guiEditBoxWithScrollbar.cpp @@ -1028,7 +1028,7 @@ void GUIEditBoxWithScrollBar::breakText() s32 last_line_start = 0; s32 size = Text.size(); s32 length = 0; - s32 el_width = RelativeRect.getWidth() - 6; + s32 el_width = RelativeRect.getWidth() - m_scrollbar_width - 10; wchar_t c; for (s32 i = 0; i < size; ++i) { @@ -1399,8 +1399,6 @@ void GUIEditBoxWithScrollBar::createVScrollBar() m_scrollbar_width = skin ? skin->getSize(gui::EGDS_SCROLLBAR_SIZE) : 16; - RelativeRect.LowerRightCorner.X -= m_scrollbar_width + 4; - irr::core::rect scrollbarrect = m_frame_rect; scrollbarrect.UpperLeftCorner.X += m_frame_rect.getWidth() - m_scrollbar_width; m_vscrollbar = new GUIScrollBar(Environment, getParent(), -1, diff --git a/src/gui/intlGUIEditBox.cpp b/src/gui/intlGUIEditBox.cpp index 10395423c..8be63fd6f 100644 --- a/src/gui/intlGUIEditBox.cpp +++ b/src/gui/intlGUIEditBox.cpp @@ -1165,7 +1165,7 @@ void intlGUIEditBox::breakText() s32 lastLineStart = 0; s32 size = Text.size(); s32 length = 0; - s32 elWidth = RelativeRect.getWidth() - 6; + s32 elWidth = RelativeRect.getWidth() - m_scrollbar_width - 10; wchar_t c; for (s32 i=0; i scrollbarrect = FrameRect; scrollbarrect.UpperLeftCorner.X += FrameRect.getWidth() - m_scrollbar_width; m_vscrollbar = new GUIScrollBar(Environment, getParent(), -1, -- cgit v1.2.3 From 3250b37e32f264db04c1ca449d9feefc22fd38b7 Mon Sep 17 00:00:00 2001 From: rubenwardy Date: Sun, 4 Oct 2020 00:33:45 +0100 Subject: Deprecate get_player_velocity and add_player_velocity (#10173) --- builtin/game/features.lua | 1 + doc/lua_api.txt | 31 +++++++++------- src/script/lua_api/l_base.cpp | 5 ++- src/script/lua_api/l_object.cpp | 82 +++++++++++++++++++---------------------- src/script/lua_api/l_object.h | 6 --- 5 files changed, 58 insertions(+), 67 deletions(-) (limited to 'src') diff --git a/builtin/game/features.lua b/builtin/game/features.lua index a15475333..4d3c90ff0 100644 --- a/builtin/game/features.lua +++ b/builtin/game/features.lua @@ -17,6 +17,7 @@ core.features = { area_store_persistent_ids = true, pathfinder_works = true, object_step_has_moveresult = true, + direct_velocity_on_players = true, } function core.has_feature(arg) diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 5d5e4b93a..c21da1871 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -4340,6 +4340,8 @@ Utilities pathfinder_works = true, -- Whether Collision info is available to an objects' on_step (5.3.0) object_step_has_moveresult = true, + -- Whether get_velocity() and add_velocity() can be used on players (5.4.0) + direct_velocity_on_players = true, } * `minetest.has_feature(arg)`: returns `boolean, missing_features` @@ -6118,6 +6120,19 @@ object you are working with still exists. * `get_pos()`: returns `{x=num, y=num, z=num}` * `set_pos(pos)`: `pos`=`{x=num, y=num, z=num}` +* `get_velocity()`: returns the velocity, a vector. +* `add_velocity(vel)` + * `vel` is a vector, e.g. `{x=0.0, y=2.3, z=1.0}` + * In comparison to using get_velocity, adding the velocity and then using + set_velocity, add_velocity is supposed to avoid synchronization problems. + Additionally, players also do not support set_velocity. + * If a player: + * Does not apply during free_move. + * Note that since the player speed is normalized at each move step, + increasing e.g. Y velocity beyond what would usually be achieved + (see: physics overrides) will cause existing X/Z velocity to be reduced. + * Example: `add_velocity({x=0, y=6.5, z=0})` is equivalent to + pressing the jump key (assuming default settings) * `move_to(pos, continuous=false)` * Does an interpolated move for Lua entities for visually smooth transitions. * If `continuous` is true, the Lua entity will not be moved to the current @@ -6189,11 +6204,6 @@ object you are working with still exists. no effect and returning `nil`. * `set_velocity(vel)` * `vel` is a vector, e.g. `{x=0.0, y=2.3, z=1.0}` -* `add_velocity(vel)` - * `vel` is a vector, e.g. `{x=0.0, y=2.3, z=1.0}` - * In comparison to using get_velocity, adding the velocity and then using - set_velocity, add_velocity is supposed to avoid synchronization problems. -* `get_velocity()`: returns the velocity, a vector * `set_acceleration(acc)` * `acc` is a vector * `get_acceleration()`: returns the acceleration, a vector @@ -6229,16 +6239,9 @@ object you are working with still exists. #### Player only (no-op for other objects) * `get_player_name()`: returns `""` if is not a player -* `get_player_velocity()`: returns `nil` if is not a player, otherwise a +* `get_player_velocity()`: **DEPRECATED**, use get_velocity() instead. table {x, y, z} representing the player's instantaneous velocity in nodes/s -* `add_player_velocity(vel)` - * Adds to player velocity, this happens client-side and only once. - * Does not apply during free_move. - * Note that since the player speed is normalized at each move step, - increasing e.g. Y velocity beyond what would usually be achieved - (see: physics overrides) will cause existing X/Z velocity to be reduced. - * Example: `add_player_velocity({x=0, y=6.5, z=0})` is equivalent to - pressing the jump key (assuming default settings) +* `add_player_velocity(vel)`: **DEPRECATED**, use add_velocity(vel) instead. * `get_look_dir()`: get camera direction as a unit vector * `get_look_vertical()`: pitch in radians * Angle ranges between -pi/2 and pi/2, which are straight up and down diff --git a/src/script/lua_api/l_base.cpp b/src/script/lua_api/l_base.cpp index 2bee09436..03ef5447a 100644 --- a/src/script/lua_api/l_base.cpp +++ b/src/script/lua_api/l_base.cpp @@ -170,10 +170,11 @@ void ModApiBase::markAliasDeprecated(luaL_Reg *reg) m_deprecated_wrappers.emplace( std::pair(reg->name, original_reg)); reg->func = l_deprecated_function; + } else { + last_func = reg->func; + last_name = reg->name; } - last_func = reg->func; - last_name = reg->name; ++reg; } } diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index 24667e769..303b1175b 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -863,12 +863,21 @@ int ObjectRef::l_add_velocity(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); - LuaEntitySAO *co = getluaobject(ref); - if (!co) + v3f vel = checkFloatPos(L, 2); + + ServerActiveObject *obj = getobject(ref); + if (obj == nullptr) return 0; - v3f pos = checkFloatPos(L, 2); - // Do it - co->addVelocity(pos); + + if (obj->getType() == ACTIVEOBJECT_TYPE_LUAENTITY) { + LuaEntitySAO *co = dynamic_cast(obj); + co->addVelocity(vel); + } else if (obj->getType() == ACTIVEOBJECT_TYPE_PLAYER) { + PlayerSAO *player = dynamic_cast(obj); + player->setMaxSpeedOverride(vel); + getServer(L)->SendPlayerSpeed(player->getPeerID(), vel); + } + return 0; } @@ -877,11 +886,23 @@ int ObjectRef::l_get_velocity(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); - LuaEntitySAO *co = getluaobject(ref); - if (co == NULL) return 0; - // Do it - v3f v = co->getVelocity(); - pushFloatPos(L, v); + + ServerActiveObject *obj = getobject(ref); + if (obj == nullptr) + return 0; + + if (obj->getType() == ACTIVEOBJECT_TYPE_LUAENTITY) { + LuaEntitySAO *co = dynamic_cast(obj); + v3f v = co->getVelocity(); + pushFloatPos(L, v); + return 1; + } else if (obj->getType() == ACTIVEOBJECT_TYPE_PLAYER) { + RemotePlayer *player = dynamic_cast(obj)->getPlayer(); + push_v3f(L, player->getSpeed() / BS); + return 1; + } + + lua_pushnil(L); return 1; } @@ -1082,38 +1103,6 @@ int ObjectRef::l_get_player_name(lua_State *L) return 1; } -// get_player_velocity(self) -int ObjectRef::l_get_player_velocity(lua_State *L) -{ - NO_MAP_LOCK_REQUIRED; - ObjectRef *ref = checkobject(L, 1); - RemotePlayer *player = getplayer(ref); - if (player == NULL) { - lua_pushnil(L); - return 1; - } - // Do it - push_v3f(L, player->getSpeed() / BS); - return 1; -} - -// add_player_velocity(self, {x=num, y=num, z=num}) -int ObjectRef::l_add_player_velocity(lua_State *L) -{ - NO_MAP_LOCK_REQUIRED; - ObjectRef *ref = checkobject(L, 1); - v3f vel = checkFloatPos(L, 2); - - PlayerSAO *co = getplayersao(ref); - if (!co) - return 0; - - // Do it - co->setMaxSpeedOverride(vel); - getServer(L)->SendPlayerSpeed(co->getPeerID(), vel); - return 0; -} - // get_look_dir(self) int ObjectRef::l_get_look_dir(lua_State *L) { @@ -2288,10 +2277,14 @@ luaL_Reg ObjectRef::methods[] = { luamethod(ObjectRef, get_properties), luamethod(ObjectRef, set_nametag_attributes), luamethod(ObjectRef, get_nametag_attributes), - // LuaEntitySAO-only + luamethod_aliased(ObjectRef, set_velocity, setvelocity), luamethod(ObjectRef, add_velocity), + {"add_player_velocity", ObjectRef::l_add_velocity}, luamethod_aliased(ObjectRef, get_velocity, getvelocity), + {"get_player_velocity", ObjectRef::l_get_velocity}, + + // LuaEntitySAO-only luamethod_aliased(ObjectRef, set_acceleration, setacceleration), luamethod_aliased(ObjectRef, get_acceleration, getacceleration), luamethod_aliased(ObjectRef, set_yaw, setyaw), @@ -2307,8 +2300,7 @@ luaL_Reg ObjectRef::methods[] = { luamethod(ObjectRef, is_player), luamethod(ObjectRef, is_player_connected), luamethod(ObjectRef, get_player_name), - luamethod(ObjectRef, get_player_velocity), - luamethod(ObjectRef, add_player_velocity), + luamethod(ObjectRef, get_look_dir), luamethod(ObjectRef, get_look_pitch), luamethod(ObjectRef, get_look_yaw), diff --git a/src/script/lua_api/l_object.h b/src/script/lua_api/l_object.h index a75c59fd9..126719b1f 100644 --- a/src/script/lua_api/l_object.h +++ b/src/script/lua_api/l_object.h @@ -209,12 +209,6 @@ private: // get_player_name(self) static int l_get_player_name(lua_State *L); - // get_player_velocity(self) - static int l_get_player_velocity(lua_State *L); - - // add_player_velocity(self, {x=num, y=num, z=num}) - static int l_add_player_velocity(lua_State *L); - // get_fov(self) static int l_get_fov(lua_State *L); -- cgit v1.2.3 From 0f98b54aa4b2361575002d92b29fe222703ba557 Mon Sep 17 00:00:00 2001 From: Lars Müller <34514239+appgurueu@users.noreply.github.com> Date: Sun, 4 Oct 2020 15:09:12 +0200 Subject: Fix short 180 degree rotation when using set_bone_position (#10405) --- src/client/content_cao.cpp | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/client/content_cao.cpp b/src/client/content_cao.cpp index 71a9d4b54..c1715a289 100644 --- a/src/client/content_cao.cpp +++ b/src/client/content_cao.cpp @@ -1460,24 +1460,17 @@ void GenericCAO::updateBonePosition() if (!bone) continue; - //If bone is manually positioned there is no need to perform the bug check - bool skip = false; - for (auto &it : m_bone_position) { - if (it.first == bone->getName()) { - skip = true; - break; - } - } - if (skip) - continue; - // Workaround for Irrlicht bug // We check each bone to see if it has been rotated ~180deg from its expected position due to a bug in Irricht // when using EJUOR_CONTROL joint control. If the bug is detected we update the bone to the proper position // and update the bones transformation. v3f bone_rot = bone->getRelativeTransformation().getRotationDegrees(); - float offset = fabsf(bone_rot.X - bone->getRotation().X); - if (offset > 179.9f && offset < 180.1f) { + float offset_X = fabsf(bone_rot.X - bone->getRotation().X); + float offset_Y = fabsf(bone_rot.Y - bone->getRotation().Y); + float offset_Z = fabsf(bone_rot.Z - bone->getRotation().Z); + if ((offset_X > 179.9f && offset_X < 180.1f) + || (offset_Y > 179.9f && offset_Y < 180.1f) + || (offset_Z > 179.9f && offset_Z < 180.1f)) { bone->setRotation(bone_rot); bone->updateAbsolutePosition(); } -- cgit v1.2.3 From 3068853e8a58ccc7370a5ce977c08223601c497a Mon Sep 17 00:00:00 2001 From: Jordan Snelling Date: Sun, 4 Oct 2020 14:10:34 +0100 Subject: Add First Person Attachments (#10360) Fixes some other third person camera specific attachments. Implements a single new flag for entities to be forced visible in first person mode. Old mods do not need to be updated to use the new flag and are fully backwards compatible. --- doc/lua_api.txt | 8 +++--- src/activeobject.h | 4 +-- src/client/content_cao.cpp | 56 ++++++++++++++++++++++++++++++++++++----- src/client/content_cao.h | 8 ++++++ src/client/game.cpp | 3 ++- src/clientiface.cpp | 5 ++-- src/script/lua_api/l_camera.cpp | 3 ++- src/script/lua_api/l_object.cpp | 14 +++++++---- src/server/luaentity_sao.cpp | 4 +-- src/server/player_sao.cpp | 9 ++++--- src/server/unit_sao.cpp | 17 +++++++------ src/server/unit_sao.h | 5 ++-- 12 files changed, 101 insertions(+), 35 deletions(-) (limited to 'src') diff --git a/doc/lua_api.txt b/doc/lua_api.txt index c21da1871..77fb4a654 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -6167,12 +6167,14 @@ object you are working with still exists. `frame_loop`. * `set_animation_frame_speed(frame_speed)` * `frame_speed`: number, default: `15.0` -* `set_attach(parent, bone, position, rotation)` +* `set_attach(parent, bone, position, rotation, forced_visible)` * `bone`: string * `position`: `{x=num, y=num, z=num}` (relative) * `rotation`: `{x=num, y=num, z=num}` = Rotation on each axis, in degrees -* `get_attach()`: returns parent, bone, position, rotation or nil if it isn't - attached. + * `forced_visible`: Boolean to control whether the attached entity + should appear in first person. +* `get_attach()`: returns parent, bone, position, rotation, forced_visible, + or nil if it isn't attached. * `set_detach()` * `set_bone_position(bone, position, rotation)` * `bone`: string diff --git a/src/activeobject.h b/src/activeobject.h index 85e160d10..0829858ad 100644 --- a/src/activeobject.h +++ b/src/activeobject.h @@ -120,9 +120,9 @@ public: virtual void setAttachment(int parent_id, const std::string &bone, v3f position, - v3f rotation) {} + v3f rotation, bool force_visible) {} virtual void getAttachment(int *parent_id, std::string *bone, v3f *position, - v3f *rotation) const {} + v3f *rotation, bool *force_visible) const {} virtual void clearChildAttachments() {} virtual void clearParentAttachment() {} virtual void addAttachmentChild(int child_id) {} diff --git a/src/client/content_cao.cpp b/src/client/content_cao.cpp index c1715a289..fae06554a 100644 --- a/src/client/content_cao.cpp +++ b/src/client/content_cao.cpp @@ -456,7 +456,8 @@ void GenericCAO::setChildrenVisible(bool toset) for (u16 cao_id : m_attachment_child_ids) { GenericCAO *obj = m_env->getGenericCAO(cao_id); if (obj) { - obj->setVisible(toset); + // Check if the entity is forced to appear in first person. + obj->setVisible(obj->isForcedVisible() ? true : toset); } } } @@ -477,8 +478,6 @@ void GenericCAO::setAttachment(int parent_id, const std::string &bone, v3f posit if (parent) parent->addAttachmentChild(m_id); } - - updateAttachments(); } @@ -498,7 +497,7 @@ void GenericCAO::clearChildAttachments() int child_id = *m_attachment_child_ids.begin(); if (ClientActiveObject *child = m_env->getActiveObject(child_id)) - child->setAttachment(0, "", v3f(), v3f()); + child->setAttachment(0, "", v3f(), v3f(), false); removeAttachmentChild(child_id); } @@ -800,6 +799,7 @@ void GenericCAO::addToScene(ITextureSource *tsrc) updateBonePosition(); updateAttachments(); setNodeLight(m_last_light); + updateMeshCulling(); } void GenericCAO::updateLight(u32 day_night_ratio) @@ -1411,6 +1411,9 @@ void GenericCAO::updateTextures(std::string mod) setMeshColor(mesh, m_prop.colors[0]); } } + // Prevent showing the player after changing texture + if (m_is_local_player) + updateMeshCulling(); } void GenericCAO::updateAnimation() @@ -1739,12 +1742,25 @@ void GenericCAO::processMessage(const std::string &data) std::string bone = deSerializeString16(is); v3f position = readV3F32(is); v3f rotation = readV3F32(is); + m_force_visible = readU8(is); // Returns false for EOF setAttachment(parent_id, bone, position, rotation); + // Forcibly show attachments if required by set_attach + if (m_force_visible) + m_is_visible = true; // localplayer itself can't be attached to localplayer - if (!m_is_local_player) - m_is_visible = !m_attached_to_local; + else if (!m_is_local_player) { + // Objects attached to the local player should be hidden in first + // person provided the forced boolean isn't set. + m_is_visible = !m_attached_to_local || + m_client->getCamera()->getCameraMode() != CAMERA_MODE_FIRST; + m_force_visible = false; + } else { + // Local players need to have this set, + // otherwise first person attachments fail. + m_is_visible = true; + } } else if (cmd == AO_CMD_PUNCHED) { u16 result_hp = readU16(is); @@ -1858,5 +1874,33 @@ std::string GenericCAO::debugInfoText() return os.str(); } +void GenericCAO::updateMeshCulling() +{ + if (!m_is_local_player) + return; + + // Grab the active player scene node so we know there's + // at least a mesh to occlude from the camera. + irr::scene::ISceneNode *node = getSceneNode(); + if (!node) + return; + + if (m_client->getCamera()->getCameraMode() == CAMERA_MODE_FIRST) { + // Hide the mesh by culling both front and + // back faces. Serious hackyness but it works for our + // purposes. This also preserves the skeletal armature. + node->setMaterialFlag(video::EMF_BACK_FACE_CULLING, + true); + node->setMaterialFlag(video::EMF_FRONT_FACE_CULLING, + true); + } else { + // Restore mesh visibility. + node->setMaterialFlag(video::EMF_BACK_FACE_CULLING, + m_prop.backface_culling); + node->setMaterialFlag(video::EMF_FRONT_FACE_CULLING, + false); + } +} + // Prototype GenericCAO proto_GenericCAO(NULL, NULL); diff --git a/src/client/content_cao.h b/src/client/content_cao.h index 974ff9a1e..daf697767 100644 --- a/src/client/content_cao.h +++ b/src/client/content_cao.h @@ -124,6 +124,7 @@ private: float m_step_distance_counter = 0.0f; u8 m_last_light = 255; bool m_is_visible = false; + bool m_force_visible = false; s8 m_glow = 0; // Material video::E_MATERIAL_TYPE m_material_type; @@ -215,6 +216,11 @@ public: m_is_visible = toset; } + inline bool isForcedVisible() const + { + return m_force_visible; + } + void setChildrenVisible(bool toset); void setAttachment(int parent_id, const std::string &bone, v3f position, v3f rotation); void getAttachment(int *parent_id, std::string *bone, v3f *position, @@ -275,4 +281,6 @@ public: { return m_prop.infotext; } + + void updateMeshCulling(); }; diff --git a/src/client/game.cpp b/src/client/game.cpp index 8f9d51417..366464467 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -2950,7 +2950,8 @@ void Game::updateCamera(u32 busy_time, f32 dtime) camera->toggleCameraMode(); - playercao->setVisible(camera->getCameraMode() > CAMERA_MODE_FIRST); + // Make the player visible depending on camera mode. + playercao->updateMeshCulling(); playercao->setChildrenVisible(camera->getCameraMode() > CAMERA_MODE_FIRST); } diff --git a/src/clientiface.cpp b/src/clientiface.cpp index 602a44c90..28a0ee770 100644 --- a/src/clientiface.cpp +++ b/src/clientiface.cpp @@ -80,10 +80,11 @@ LuaEntitySAO *getAttachedObject(PlayerSAO *sao, ServerEnvironment *env) int id; std::string bone; v3f dummy; - sao->getAttachment(&id, &bone, &dummy, &dummy); + bool force_visible; + sao->getAttachment(&id, &bone, &dummy, &dummy, &force_visible); ServerActiveObject *ao = env->getActiveObject(id); while (id && ao) { - ao->getAttachment(&id, &bone, &dummy, &dummy); + ao->getAttachment(&id, &bone, &dummy, &dummy, &force_visible); if (id) ao = env->getActiveObject(id); } diff --git a/src/script/lua_api/l_camera.cpp b/src/script/lua_api/l_camera.cpp index bfa60be67..40251154c 100644 --- a/src/script/lua_api/l_camera.cpp +++ b/src/script/lua_api/l_camera.cpp @@ -63,7 +63,8 @@ int LuaCamera::l_set_camera_mode(lua_State *L) return 0; camera->setCameraMode((CameraMode)((int)lua_tonumber(L, 2))); - playercao->setVisible(camera->getCameraMode() > CAMERA_MODE_FIRST); + // Make the player visible depending on camera mode. + playercao->updateMeshCulling(); playercao->setChildrenVisible(camera->getCameraMode() > CAMERA_MODE_FIRST); return 0; } diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index 303b1175b..fead4e849 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -664,7 +664,7 @@ int ObjectRef::l_get_bone_position(lua_State *L) return 2; } -// set_attach(self, parent, bone, position, rotation) +// set_attach(self, parent, bone, position, rotation, force_visible) int ObjectRef::l_set_attach(lua_State *L) { GET_ENV_PTR; @@ -687,7 +687,8 @@ int ObjectRef::l_set_attach(lua_State *L) std::string bone; v3f position = v3f(0, 0, 0); v3f rotation = v3f(0, 0, 0); - co->getAttachment(&parent_id, &bone, &position, &rotation); + bool force_visible; + co->getAttachment(&parent_id, &bone, &position, &rotation, &force_visible); if (parent_id) { ServerActiveObject *old_parent = env->getActiveObject(parent_id); old_parent->removeAttachmentChild(co->getId()); @@ -702,7 +703,8 @@ int ObjectRef::l_set_attach(lua_State *L) rotation = v3f(0, 0, 0); if (!lua_isnil(L, 5)) rotation = read_v3f(L, 5); - co->setAttachment(parent->getId(), bone, position, rotation); + force_visible = readParam(L, 6, false); + co->setAttachment(parent->getId(), bone, position, rotation, force_visible); parent->addAttachmentChild(co->getId()); return 0; } @@ -722,7 +724,8 @@ int ObjectRef::l_get_attach(lua_State *L) std::string bone; v3f position = v3f(0, 0, 0); v3f rotation = v3f(0, 0, 0); - co->getAttachment(&parent_id, &bone, &position, &rotation); + bool force_visible; + co->getAttachment(&parent_id, &bone, &position, &rotation, &force_visible); if (!parent_id) return 0; ServerActiveObject *parent = env->getActiveObject(parent_id); @@ -731,7 +734,8 @@ int ObjectRef::l_get_attach(lua_State *L) lua_pushlstring(L, bone.c_str(), bone.size()); push_v3f(L, position); push_v3f(L, rotation); - return 4; + lua_pushboolean(L, force_visible); + return 5; } // set_detach(self) diff --git a/src/server/luaentity_sao.cpp b/src/server/luaentity_sao.cpp index f20914f7f..b39797531 100644 --- a/src/server/luaentity_sao.cpp +++ b/src/server/luaentity_sao.cpp @@ -238,9 +238,9 @@ std::string LuaEntitySAO::getClientInitializationData(u16 protocol_version) msg_os << serializeString32(generateUpdateAnimationCommand()); // 3 for (const auto &bone_pos : m_bone_position) { msg_os << serializeString32(generateUpdateBonePositionCommand( - bone_pos.first, bone_pos.second.X, bone_pos.second.Y)); // m_bone_position.size + bone_pos.first, bone_pos.second.X, bone_pos.second.Y)); // 3 + N } - msg_os << serializeString32(generateUpdateAttachmentCommand()); // 4 + msg_os << serializeString32(generateUpdateAttachmentCommand()); // 4 + m_bone_position.size int message_count = 4 + m_bone_position.size(); diff --git a/src/server/player_sao.cpp b/src/server/player_sao.cpp index 8d4938c3c..344d18a20 100644 --- a/src/server/player_sao.cpp +++ b/src/server/player_sao.cpp @@ -122,10 +122,10 @@ std::string PlayerSAO::getClientInitializationData(u16 protocol_version) msg_os << serializeString32(generateUpdateAnimationCommand()); // 3 for (const auto &bone_pos : m_bone_position) { msg_os << serializeString32(generateUpdateBonePositionCommand( - bone_pos.first, bone_pos.second.X, bone_pos.second.Y)); // m_bone_position.size + bone_pos.first, bone_pos.second.X, bone_pos.second.Y)); // 3 + N } - msg_os << serializeString32(generateUpdateAttachmentCommand()); // 4 - msg_os << serializeString32(generateUpdatePhysicsOverrideCommand()); // 5 + msg_os << serializeString32(generateUpdateAttachmentCommand()); // 4 + m_bone_position.size + msg_os << serializeString32(generateUpdatePhysicsOverrideCommand()); // 5 + m_bone_position.size int message_count = 5 + m_bone_position.size(); @@ -569,7 +569,8 @@ bool PlayerSAO::checkMovementCheat() int parent_id; std::string bone; v3f attachment_rot; - getAttachment(&parent_id, &bone, &attachment_pos, &attachment_rot); + bool force_visible; + getAttachment(&parent_id, &bone, &attachment_pos, &attachment_rot, &force_visible); } v3f parent_pos = parent->getBasePosition(); diff --git a/src/server/unit_sao.cpp b/src/server/unit_sao.cpp index d906e885e..2371640ca 100644 --- a/src/server/unit_sao.cpp +++ b/src/server/unit_sao.cpp @@ -121,8 +121,8 @@ void UnitSAO::sendOutdatedData() } // clang-format on -void UnitSAO::setAttachment( - int parent_id, const std::string &bone, v3f position, v3f rotation) +void UnitSAO::setAttachment(int parent_id, const std::string &bone, v3f position, + v3f rotation, bool force_visible) { // Attachments need to be handled on both the server and client. // If we just attach on the server, we can only copy the position of the parent. @@ -137,6 +137,7 @@ void UnitSAO::setAttachment( m_attachment_bone = bone; m_attachment_position = position; m_attachment_rotation = rotation; + m_force_visible = force_visible; m_attachment_sent = false; if (parent_id != old_parent) { @@ -145,13 +146,14 @@ void UnitSAO::setAttachment( } } -void UnitSAO::getAttachment( - int *parent_id, std::string *bone, v3f *position, v3f *rotation) const +void UnitSAO::getAttachment(int *parent_id, std::string *bone, v3f *position, + v3f *rotation, bool *force_visible) const { *parent_id = m_attachment_parent_id; *bone = m_attachment_bone; *position = m_attachment_position; *rotation = m_attachment_rotation; + *force_visible = m_force_visible; } void UnitSAO::clearChildAttachments() @@ -159,7 +161,7 @@ void UnitSAO::clearChildAttachments() for (int child_id : m_attachment_child_ids) { // Child can be NULL if it was deleted earlier if (ServerActiveObject *child = m_env->getActiveObject(child_id)) - child->setAttachment(0, "", v3f(0, 0, 0), v3f(0, 0, 0)); + child->setAttachment(0, "", v3f(0, 0, 0), v3f(0, 0, 0), false); } m_attachment_child_ids.clear(); } @@ -169,9 +171,9 @@ void UnitSAO::clearParentAttachment() ServerActiveObject *parent = nullptr; if (m_attachment_parent_id) { parent = m_env->getActiveObject(m_attachment_parent_id); - setAttachment(0, "", m_attachment_position, m_attachment_rotation); + setAttachment(0, "", m_attachment_position, m_attachment_rotation, false); } else { - setAttachment(0, "", v3f(0, 0, 0), v3f(0, 0, 0)); + setAttachment(0, "", v3f(0, 0, 0), v3f(0, 0, 0), false); } // Do it if (parent) @@ -245,6 +247,7 @@ std::string UnitSAO::generateUpdateAttachmentCommand() const os << serializeString16(m_attachment_bone); writeV3F32(os, m_attachment_position); writeV3F32(os, m_attachment_rotation); + writeU8(os, m_force_visible); return os.str(); } diff --git a/src/server/unit_sao.h b/src/server/unit_sao.h index 3cb7f0ad5..a21e055c5 100644 --- a/src/server/unit_sao.h +++ b/src/server/unit_sao.h @@ -64,9 +64,9 @@ public: ServerActiveObject *getParent() const; inline bool isAttached() const { return getParent(); } void setAttachment(int parent_id, const std::string &bone, v3f position, - v3f rotation); + v3f rotation, bool force_visible); void getAttachment(int *parent_id, std::string *bone, v3f *position, - v3f *rotation) const; + v3f *rotation, bool *force_visible) const; void clearChildAttachments(); void clearParentAttachment(); void addAttachmentChild(int child_id); @@ -133,4 +133,5 @@ private: v3f m_attachment_position; v3f m_attachment_rotation; bool m_attachment_sent = false; + bool m_force_visible = false; }; -- cgit v1.2.3 From 81c66d6efb9fb0ab8a03b40e2bc22aa49eff9a04 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Rollo Date: Sun, 4 Oct 2020 15:24:29 +0200 Subject: Minimap as HUD element with API control Features: * Define Minimap available modes (surface/radar, scale) from Lua, using player:set_minimap_modes() * New HUD elements for displaying minimap with custom size and placing * New minimap mode for displaying a texture instead of the map --- doc/lua_api.txt | 33 ++++- src/client/client.cpp | 1 + src/client/client.h | 1 + src/client/game.cpp | 75 +++++------- src/client/hud.cpp | 30 ++++- src/client/hud.h | 2 + src/client/mapblock_mesh.cpp | 2 +- src/client/minimap.cpp | 237 +++++++++++++++++++++++++++--------- src/client/minimap.h | 41 ++++--- src/hud.cpp | 1 + src/hud.h | 13 +- src/network/clientopcodes.cpp | 1 + src/network/clientpackethandler.cpp | 46 ++++++- src/network/networkprotocol.h | 14 ++- src/network/serveropcodes.cpp | 1 + src/script/lua_api/l_minimap.cpp | 24 ++-- src/script/lua_api/l_object.cpp | 62 ++++++++++ src/script/lua_api/l_object.h | 3 + src/server.cpp | 17 +++ src/server.h | 12 ++ 20 files changed, 471 insertions(+), 145 deletions(-) (limited to 'src') diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 77fb4a654..9e9af20da 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -1484,6 +1484,15 @@ Displays an image oriented or translated according to current heading direction. If translation is chosen, texture is repeated horizontally to fill the whole element. +### `minimap` + +Displays a minimap on the HUD. + +* `size`: Size of the minimap to display. Minimap should be a square to avoid + distortion. +* `alignment`: The alignment of the minimap. +* `offset`: offset in pixels from position. + Representations of simple things ================================ @@ -6366,6 +6375,27 @@ object you are working with still exists. * `hud_set_hotbar_selected_image(texturename)` * sets image for selected item of hotbar * `hud_get_hotbar_selected_image`: returns texturename +* `set_minimap_modes({mode, mode, ...}, selected_mode)` + * Overrides the available minimap modes (and toggle order), and changes the + selected mode. + * `mode` is a table consisting of up to four fields: + * `type`: Available type: + * `off`: Minimap off + * `surface`: Minimap in surface mode + * `radar`: Minimap in radar mode + * `texture`: Texture to be displayed instead of terrain map + (texture is centered around 0,0 and can be scaled). + Texture size is limited to 512 x 512 pixel. + * `label`: Optional label to display on minimap mode toggle + The translation must be handled within the mod. + * `size`: Sidelength or diameter, in number of nodes, of the terrain + displayed in minimap + * `texture`: Only for texture type, name of the texture to display + * `scale`: Only for texture type, scale of the texture map in nodes per + pixel (for example a `scale` of 2 means each pixel represents a 2x2 + nodes square) + * `selected_mode` is the mode index to be selected after modes have been changed + (0 is the first mode). * `set_sky(parameters)` * `parameters` is a table with the following optional fields: * `base_color`: ColorSpec, changes fog in "skybox" and "plain". @@ -8047,7 +8077,8 @@ Used by `Player:hud_add`. Returned by `Player:hud_get`. { hud_elem_type = "image", -- See HUD element types - -- Type of element, can be "image", "text", "statbar", "inventory" or "compass" + -- Type of element, can be "image", "text", "statbar", "inventory", + -- "compass" or "minimap" position = {x=0.5, y=0.5}, -- Left corner position of element diff --git a/src/client/client.cpp b/src/client/client.cpp index d6e529c40..7fafe0da9 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -129,6 +129,7 @@ Client::Client( if (g_settings->getBool("enable_minimap")) { m_minimap = new Minimap(this); } + m_cache_save_interval = g_settings->getU16("server_map_save_interval"); } diff --git a/src/client/client.h b/src/client/client.h index 733634db1..8f4aac6e3 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -223,6 +223,7 @@ public: void handleCommand_CSMRestrictionFlags(NetworkPacket *pkt); void handleCommand_PlayerSpeed(NetworkPacket *pkt); void handleCommand_MediaPush(NetworkPacket *pkt); + void handleCommand_MinimapModes(NetworkPacket *pkt); void ProcessData(NetworkPacket *pkt); diff --git a/src/client/game.cpp b/src/client/game.cpp index 366464467..54e0c9f20 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -1416,11 +1416,9 @@ bool Game::createClient(const GameStartData &start_data) } mapper = client->getMinimap(); - if (mapper) { - mapper->setMinimapMode(MINIMAP_MODE_OFF); - if (client->modsLoaded()) - client->getScript()->on_minimap_ready(mapper); - } + + if (mapper && client->modsLoaded()) + client->getScript()->on_minimap_ready(mapper); return true; } @@ -2222,52 +2220,37 @@ void Game::toggleMinimap(bool shift_pressed) if (!mapper || !m_game_ui->m_flags.show_hud || !g_settings->getBool("enable_minimap")) return; - if (shift_pressed) { + if (shift_pressed) mapper->toggleMinimapShape(); - return; - } + else + mapper->nextMode(); + + // TODO: When legacy minimap is deprecated, keep only HUD minimap stuff here + // Not so satisying code to keep compatibility with old fixed mode system + // --> u32 hud_flags = client->getEnv().getLocalPlayer()->hud_flags; - MinimapMode mode = MINIMAP_MODE_OFF; - if (hud_flags & HUD_FLAG_MINIMAP_VISIBLE) { - mode = mapper->getMinimapMode(); - mode = (MinimapMode)((int)mode + 1); - // If radar is disabled and in, or switching to, radar mode - if (!(hud_flags & HUD_FLAG_MINIMAP_RADAR_VISIBLE) && mode > 3) - mode = MINIMAP_MODE_OFF; - } + if (!(hud_flags & HUD_FLAG_MINIMAP_VISIBLE)) { + m_game_ui->m_flags.show_minimap = false; + } else { - m_game_ui->m_flags.show_minimap = true; - switch (mode) { - case MINIMAP_MODE_SURFACEx1: - m_game_ui->showTranslatedStatusText("Minimap in surface mode, Zoom x1"); - break; - case MINIMAP_MODE_SURFACEx2: - m_game_ui->showTranslatedStatusText("Minimap in surface mode, Zoom x2"); - break; - case MINIMAP_MODE_SURFACEx4: - m_game_ui->showTranslatedStatusText("Minimap in surface mode, Zoom x4"); - break; - case MINIMAP_MODE_RADARx1: - m_game_ui->showTranslatedStatusText("Minimap in radar mode, Zoom x1"); - break; - case MINIMAP_MODE_RADARx2: - m_game_ui->showTranslatedStatusText("Minimap in radar mode, Zoom x2"); - break; - case MINIMAP_MODE_RADARx4: - m_game_ui->showTranslatedStatusText("Minimap in radar mode, Zoom x4"); - break; - default: - mode = MINIMAP_MODE_OFF; - m_game_ui->m_flags.show_minimap = false; - if (hud_flags & HUD_FLAG_MINIMAP_VISIBLE) - m_game_ui->showTranslatedStatusText("Minimap hidden"); - else - m_game_ui->showTranslatedStatusText("Minimap currently disabled by game or mod"); - } + // If radar is disabled, try to find a non radar mode or fall back to 0 + if (!(hud_flags & HUD_FLAG_MINIMAP_RADAR_VISIBLE)) + while (mapper->getModeIndex() && + mapper->getModeDef().type == MINIMAP_TYPE_RADAR) + mapper->nextMode(); - mapper->setMinimapMode(mode); + m_game_ui->m_flags.show_minimap = mapper->getModeDef().type != + MINIMAP_TYPE_OFF; + } + // <-- + // End of 'not so satifying code' + if ((hud_flags & HUD_FLAG_MINIMAP_VISIBLE) || + (hud && hud->hasElementOfType(HUD_ELEM_MINIMAP))) + m_game_ui->showStatusText(utf8_to_wide(mapper->getModeDef().label)); + else + m_game_ui->showTranslatedStatusText("Minimap currently disabled by game or mod"); } void Game::toggleFog() @@ -3954,7 +3937,7 @@ void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime, /* Update minimap pos and rotation */ - if (mapper && m_game_ui->m_flags.show_minimap && m_game_ui->m_flags.show_hud) { + if (mapper && m_game_ui->m_flags.show_hud) { mapper->setPos(floatToInt(player->getPosition(), BS)); mapper->setAngle(player->getYaw()); } diff --git a/src/client/hud.cpp b/src/client/hud.cpp index d3038230c..f6497fe25 100644 --- a/src/client/hud.cpp +++ b/src/client/hud.cpp @@ -36,6 +36,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "mesh.h" #include "wieldmesh.h" #include "client/renderingengine.h" +#include "client/minimap.h" #ifdef HAVE_TOUCHSCREENGUI #include "gui/touchscreengui.h" @@ -297,6 +298,18 @@ void Hud::drawItems(v2s32 upperleftpos, v2s32 screen_offset, s32 itemcount, } } +bool Hud::hasElementOfType(HudElementType type) +{ + for (size_t i = 0; i != player->maxHudId(); i++) { + HudElement *e = player->getHud(i); + if (!e) + continue; + if (e->type == type) + return true; + } + return false; +} + // Calculates screen position of waypoint. Returns true if waypoint is visible (in front of the player), else false. bool Hud::calculateScreenPos(const v3s16 &camera_offset, HudElement *e, v2s32 *pos) { @@ -491,7 +504,22 @@ void Hud::drawLuaElements(const v3s16 &camera_offset) default: break; } - + break; } + case HUD_ELEM_MINIMAP: { + if (e->size.X <= 0 || e->size.Y <= 0) + break; + if (!client->getMinimap()) + break; + // Draw a minimap of size "size" + v2s32 dstsize(e->size.X * m_scale_factor, + e->size.Y * m_scale_factor); + // (no percent size as minimap would likely be anamorphosed) + v2s32 offset((e->align.X - 1.0) * dstsize.X / 2, + (e->align.Y - 1.0) * dstsize.Y / 2); + core::rect rect(0, 0, dstsize.X, dstsize.Y); + rect += pos + offset + v2s32(e->offset.X * m_scale_factor, + e->offset.Y * m_scale_factor); + client->getMinimap()->drawMinimap(rect); break; } default: infostream << "Hud::drawLuaElements: ignoring drawform " << e->type << diff --git a/src/client/hud.h b/src/client/hud.h index cf83cb16e..d46545d71 100644 --- a/src/client/hud.h +++ b/src/client/hud.h @@ -81,6 +81,8 @@ public: m_selected_face_normal = face_normal; } + bool hasElementOfType(HudElementType type); + void drawLuaElements(const v3s16 &camera_offset); private: diff --git a/src/client/mapblock_mesh.cpp b/src/client/mapblock_mesh.cpp index 2f96ca61f..b59679523 100644 --- a/src/client/mapblock_mesh.cpp +++ b/src/client/mapblock_mesh.cpp @@ -1044,7 +1044,7 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset): m_use_tangent_vertices = data->m_use_tangent_vertices; m_enable_vbo = g_settings->getBool("enable_vbo"); - if (g_settings->getBool("enable_minimap")) { + if (data->m_client->getMinimap()) { m_minimap_mapblock = new MinimapMapblock; m_minimap_mapblock->getMinimapNodes( &data->m_vmanip, data->m_blockpos * MAP_BLOCKSIZE); diff --git a/src/client/minimap.cpp b/src/client/minimap.cpp index 68770ec19..6bae408b4 100644 --- a/src/client/minimap.cpp +++ b/src/client/minimap.cpp @@ -25,7 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "shader.h" #include "mapblock.h" #include "client/renderingengine.h" - +#include "gettext.h" //// //// MinimapUpdateThread @@ -108,8 +108,11 @@ void MinimapUpdateThread::doUpdate() } } - if (data->map_invalidated && data->mode != MINIMAP_MODE_OFF) { - getMap(data->pos, data->map_size, data->scan_height); + + if (data->map_invalidated && ( + data->mode.type == MINIMAP_TYPE_RADAR || + data->mode.type == MINIMAP_TYPE_SURFACE)) { + getMap(data->pos, data->mode.map_size, data->mode.scan_height); data->map_invalidated = false; } } @@ -181,19 +184,26 @@ Minimap::Minimap(Client *client) this->m_ndef = client->getNodeDefManager(); m_angle = 0.f; + m_current_mode_index = 0; // Initialize static settings m_enable_shaders = g_settings->getBool("enable_shaders"); m_surface_mode_scan_height = g_settings->getBool("minimap_double_scan_height") ? 256 : 128; + // Initialize minimap modes + addMode(MINIMAP_TYPE_OFF); + addMode(MINIMAP_TYPE_SURFACE, 256); + addMode(MINIMAP_TYPE_SURFACE, 128); + addMode(MINIMAP_TYPE_SURFACE, 64); + addMode(MINIMAP_TYPE_RADAR, 512); + addMode(MINIMAP_TYPE_RADAR, 256); + addMode(MINIMAP_TYPE_RADAR, 128); + // Initialize minimap data data = new MinimapData; - data->mode = MINIMAP_MODE_OFF; - data->is_radar = false; - data->map_invalidated = true; - data->texture = NULL; - data->heightmap_texture = NULL; + data->map_invalidated = true; + data->minimap_shape_round = g_settings->getBool("minimap_shape_round"); // Get round minimap textures @@ -215,6 +225,8 @@ Minimap::Minimap(Client *client) // Create object marker texture data->object_marker_red = m_tsrc->getTexture("object_marker_red.png"); + setModeIndex(0); + // Create mesh buffer for minimap m_meshbuffer = getMinimapMeshBuffer(); @@ -280,29 +292,101 @@ MinimapShape Minimap::getMinimapShape() return MINIMAP_SHAPE_SQUARE; } -void Minimap::setMinimapMode(MinimapMode mode) +void Minimap::setModeIndex(size_t index) { - static const MinimapModeDef modedefs[MINIMAP_MODE_COUNT] = { - {false, 0, 0}, - {false, m_surface_mode_scan_height, 256}, - {false, m_surface_mode_scan_height, 128}, - {false, m_surface_mode_scan_height, 64}, - {true, 32, 128}, - {true, 32, 64}, - {true, 32, 32} - }; - - if (mode >= MINIMAP_MODE_COUNT) - return; - MutexAutoLock lock(m_mutex); - data->is_radar = modedefs[mode].is_radar; - data->scan_height = modedefs[mode].scan_height; - data->map_size = modedefs[mode].map_size; - data->mode = mode; + if (index < m_modes.size()) { + data->mode = m_modes[index]; + m_current_mode_index = index; + } else { + data->mode = MinimapModeDef{MINIMAP_TYPE_OFF, N_("Minimap hidden"), 0, 0, ""}; + m_current_mode_index = 0; + } + + data->map_invalidated = true; - m_minimap_update_thread->deferUpdate(); + if (m_minimap_update_thread) + m_minimap_update_thread->deferUpdate(); +} + +void Minimap::addMode(MinimapModeDef mode) +{ + // Check validity + if (mode.type == MINIMAP_TYPE_TEXTURE) { + if (mode.texture.empty()) + return; + if (mode.scale < 1) + mode.scale = 1; + } + + int zoom = -1; + + // Build a default standard label + if (mode.label == "") { + switch (mode.type) { + case MINIMAP_TYPE_OFF: + mode.label = N_("Minimap hidden"); + break; + case MINIMAP_TYPE_SURFACE: + mode.label = N_("Minimap in surface mode, Zoom x%d"); + if (mode.map_size > 0) + zoom = 256 / mode.map_size; + break; + case MINIMAP_TYPE_RADAR: + mode.label = N_("Minimap in radar mode, Zoom x%d"); + if (mode.map_size > 0) + zoom = 512 / mode.map_size; + break; + case MINIMAP_TYPE_TEXTURE: + mode.label = N_("Minimap in texture mode"); + break; + default: + break; + } + } + + if (zoom >= 0) { + char label_buf[1024]; + porting::mt_snprintf(label_buf, sizeof(label_buf), + mode.label.c_str(), zoom); + mode.label = label_buf; + } + + m_modes.push_back(mode); +} + +void Minimap::addMode(MinimapType type, u16 size, std::string label, + std::string texture, u16 scale) +{ + MinimapModeDef mode; + mode.type = type; + mode.label = label; + mode.map_size = size; + mode.texture = texture; + mode.scale = scale; + switch (type) { + case MINIMAP_TYPE_SURFACE: + mode.scan_height = m_surface_mode_scan_height; + break; + case MINIMAP_TYPE_RADAR: + mode.scan_height = 32; + break; + default: + mode.scan_height = 0; + } + addMode(mode); +} + +void Minimap::nextMode() +{ + if (m_modes.empty()) + return; + m_current_mode_index++; + if (m_current_mode_index >= m_modes.size()) + m_current_mode_index = 0; + + setModeIndex(m_current_mode_index); } void Minimap::setPos(v3s16 pos) @@ -331,16 +415,16 @@ void Minimap::setAngle(f32 angle) void Minimap::blitMinimapPixelsToImageRadar(video::IImage *map_image) { video::SColor c(240, 0, 0, 0); - for (s16 x = 0; x < data->map_size; x++) - for (s16 z = 0; z < data->map_size; z++) { - MinimapPixel *mmpixel = &data->minimap_scan[x + z * data->map_size]; + for (s16 x = 0; x < data->mode.map_size; x++) + for (s16 z = 0; z < data->mode.map_size; z++) { + MinimapPixel *mmpixel = &data->minimap_scan[x + z * data->mode.map_size]; if (mmpixel->air_count > 0) c.setGreen(core::clamp(core::round32(32 + mmpixel->air_count * 8), 0, 255)); else c.setGreen(0); - map_image->setPixel(x, data->map_size - z - 1, c); + map_image->setPixel(x, data->mode.map_size - z - 1, c); } } @@ -349,9 +433,9 @@ void Minimap::blitMinimapPixelsToImageSurface( { // This variable creation/destruction has a 1% cost on rendering minimap video::SColor tilecolor; - for (s16 x = 0; x < data->map_size; x++) - for (s16 z = 0; z < data->map_size; z++) { - MinimapPixel *mmpixel = &data->minimap_scan[x + z * data->map_size]; + for (s16 x = 0; x < data->mode.map_size; x++) + for (s16 z = 0; z < data->mode.map_size; z++) { + MinimapPixel *mmpixel = &data->minimap_scan[x + z * data->mode.map_size]; const ContentFeatures &f = m_ndef->get(mmpixel->n); const TileDef *tile = &f.tiledef[0]; @@ -367,10 +451,10 @@ void Minimap::blitMinimapPixelsToImageSurface( tilecolor.setBlue(tilecolor.getBlue() * f.minimap_color.getBlue() / 255); tilecolor.setAlpha(240); - map_image->setPixel(x, data->map_size - z - 1, tilecolor); + map_image->setPixel(x, data->mode.map_size - z - 1, tilecolor); u32 h = mmpixel->height; - heightmap_image->setPixel(x,data->map_size - z - 1, + heightmap_image->setPixel(x,data->mode.map_size - z - 1, video::SColor(255, h, h, h)); } } @@ -378,21 +462,46 @@ void Minimap::blitMinimapPixelsToImageSurface( video::ITexture *Minimap::getMinimapTexture() { // update minimap textures when new scan is ready - if (data->map_invalidated) + if (data->map_invalidated && data->mode.type != MINIMAP_TYPE_TEXTURE) return data->texture; // create minimap and heightmap images in memory - core::dimension2d dim(data->map_size, data->map_size); + core::dimension2d dim(data->mode.map_size, data->mode.map_size); video::IImage *map_image = driver->createImage(video::ECF_A8R8G8B8, dim); video::IImage *heightmap_image = driver->createImage(video::ECF_A8R8G8B8, dim); video::IImage *minimap_image = driver->createImage(video::ECF_A8R8G8B8, core::dimension2d(MINIMAP_MAX_SX, MINIMAP_MAX_SY)); // Blit MinimapPixels to images - if (data->is_radar) - blitMinimapPixelsToImageRadar(map_image); - else + switch(data->mode.type) { + case MINIMAP_TYPE_OFF: + break; + case MINIMAP_TYPE_SURFACE: blitMinimapPixelsToImageSurface(map_image, heightmap_image); + break; + case MINIMAP_TYPE_RADAR: + blitMinimapPixelsToImageRadar(map_image); + break; + case MINIMAP_TYPE_TEXTURE: + // Want to use texture source, to : 1 find texture, 2 cache it + video::ITexture* texture = m_tsrc->getTexture(data->mode.texture); + video::IImage* image = driver->createImageFromData( + texture->getColorFormat(), texture->getSize(), texture->lock(), true, false); + texture->unlock(); + + auto dim = image->getDimension(); + + map_image->fill(video::SColor(255, 0, 0, 0)); + + image->copyTo(map_image, + irr::core::vector2d { + ((data->mode.map_size - (static_cast(dim.Width))) >> 1) + - data->pos.X / data->mode.scale, + ((data->mode.map_size - (static_cast(dim.Height))) >> 1) + + data->pos.Z / data->mode.scale + }); + image->drop(); + } map_image->copyToScaling(minimap_image); map_image->drop(); @@ -461,21 +570,31 @@ scene::SMeshBuffer *Minimap::getMinimapMeshBuffer() void Minimap::drawMinimap() { + // Non hud managed minimap drawing (legacy minimap) + v2u32 screensize = RenderingEngine::get_instance()->getWindowSize(); + const u32 size = 0.25 * screensize.Y; + + drawMinimap(core::rect( + screensize.X - size - 10, 10, + screensize.X - 10, size + 10)); +} + +void Minimap::drawMinimap(core::rect rect) { + video::ITexture *minimap_texture = getMinimapTexture(); if (!minimap_texture) return; + if (data->mode.type == MINIMAP_TYPE_OFF) + return; + updateActiveMarkers(); - v2u32 screensize = RenderingEngine::get_instance()->getWindowSize(); - const u32 size = 0.25 * screensize.Y; core::rect oldViewPort = driver->getViewPort(); core::matrix4 oldProjMat = driver->getTransform(video::ETS_PROJECTION); core::matrix4 oldViewMat = driver->getTransform(video::ETS_VIEW); - driver->setViewPort(core::rect( - screensize.X - size - 10, 10, - screensize.X - 10, size + 10)); + driver->setViewPort(rect); driver->setTransform(video::ETS_PROJECTION, core::matrix4()); driver->setTransform(video::ETS_VIEW, core::matrix4()); @@ -488,7 +607,7 @@ void Minimap::drawMinimap() material.TextureLayer[0].Texture = minimap_texture; material.TextureLayer[1].Texture = data->heightmap_texture; - if (m_enable_shaders && !data->is_radar) { + if (m_enable_shaders && data->mode.type == MINIMAP_TYPE_SURFACE) { u16 sid = m_shdrsrc->getShader("minimap_shader", 1, 1); material.MaterialType = m_shdrsrc->getShaderInfo(sid).material; } else { @@ -529,14 +648,14 @@ void Minimap::drawMinimap() driver->setViewPort(oldViewPort); // Draw player markers - v2s32 s_pos(screensize.X - size - 10, 10); + v2s32 s_pos(rect.UpperLeftCorner.X, rect.UpperLeftCorner.Y); core::dimension2di imgsize(data->object_marker_red->getOriginalSize()); core::rect img_rect(0, 0, imgsize.Width, imgsize.Height); static const video::SColor col(255, 255, 255, 255); static const video::SColor c[4] = {col, col, col, col}; f32 sin_angle = std::sin(m_angle * core::DEGTORAD); f32 cos_angle = std::cos(m_angle * core::DEGTORAD); - s32 marker_size2 = 0.025 * (float)size; + s32 marker_size2 = 0.025 * (float)rect.getWidth();; for (std::list::const_iterator i = m_active_markers.begin(); i != m_active_markers.end(); ++i) { @@ -547,8 +666,8 @@ void Minimap::drawMinimap() posf.X = t1; posf.Y = t2; } - posf.X = (posf.X + 0.5) * (float)size; - posf.Y = (posf.Y + 0.5) * (float)size; + posf.X = (posf.X + 0.5) * (float)rect.getWidth(); + posf.Y = (posf.Y + 0.5) * (float)rect.getHeight(); core::rect dest_rect( s_pos.X + posf.X - marker_size2, s_pos.Y + posf.Y - marker_size2, @@ -571,16 +690,16 @@ void Minimap::updateActiveMarkers() for (Nametag *nametag : nametags) { v3s16 pos = floatToInt(nametag->parent_node->getAbsolutePosition() + intToFloat(client->getCamera()->getOffset(), BS), BS); - pos -= data->pos - v3s16(data->map_size / 2, - data->scan_height / 2, - data->map_size / 2); - if (pos.X < 0 || pos.X > data->map_size || - pos.Y < 0 || pos.Y > data->scan_height || - pos.Z < 0 || pos.Z > data->map_size) { + pos -= data->pos - v3s16(data->mode.map_size / 2, + data->mode.scan_height / 2, + data->mode.map_size / 2); + if (pos.X < 0 || pos.X > data->mode.map_size || + pos.Y < 0 || pos.Y > data->mode.scan_height || + pos.Z < 0 || pos.Z > data->mode.map_size) { continue; } - pos.X = ((float)pos.X / data->map_size) * MINIMAP_MAX_SX; - pos.Z = ((float)pos.Z / data->map_size) * MINIMAP_MAX_SY; + pos.X = ((float)pos.X / data->mode.map_size) * MINIMAP_MAX_SX; + pos.Z = ((float)pos.Z / data->mode.map_size) * MINIMAP_MAX_SY; const video::SColor &mask_col = minimap_mask->getPixel(pos.X, pos.Z); if (!mask_col.getAlpha()) { continue; diff --git a/src/client/minimap.h b/src/client/minimap.h index 258d5330d..11374b116 100644 --- a/src/client/minimap.h +++ b/src/client/minimap.h @@ -19,6 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #pragma once +#include "../hud.h" #include "irrlichttypes_extrabloated.h" #include "util/thread.h" #include "voxel.h" @@ -33,26 +34,18 @@ class IShaderSource; #define MINIMAP_MAX_SX 512 #define MINIMAP_MAX_SY 512 -enum MinimapMode { - MINIMAP_MODE_OFF, - MINIMAP_MODE_SURFACEx1, - MINIMAP_MODE_SURFACEx2, - MINIMAP_MODE_SURFACEx4, - MINIMAP_MODE_RADARx1, - MINIMAP_MODE_RADARx2, - MINIMAP_MODE_RADARx4, - MINIMAP_MODE_COUNT, -}; - enum MinimapShape { MINIMAP_SHAPE_SQUARE, MINIMAP_SHAPE_ROUND, }; struct MinimapModeDef { - bool is_radar; + MinimapType type; + std::string label; u16 scan_height; u16 map_size; + std::string texture; + u16 scale; }; struct MinimapPixel { @@ -69,12 +62,9 @@ struct MinimapMapblock { }; struct MinimapData { - bool is_radar; - MinimapMode mode; + MinimapModeDef mode; v3s16 pos; v3s16 old_pos; - u16 scan_height; - u16 map_size; MinimapPixel minimap_scan[MINIMAP_MAX_SX * MINIMAP_MAX_SY]; bool map_invalidated; bool minimap_shape_round; @@ -127,12 +117,22 @@ public: v3s16 getPos() const { return data->pos; } void setAngle(f32 angle); f32 getAngle() const { return m_angle; } - void setMinimapMode(MinimapMode mode); - MinimapMode getMinimapMode() const { return data->mode; } void toggleMinimapShape(); void setMinimapShape(MinimapShape shape); MinimapShape getMinimapShape(); + void clearModes() { m_modes.clear(); }; + void addMode(MinimapModeDef mode); + void addMode(MinimapType type, u16 size = 0, std::string label = "", + std::string texture = "", u16 scale = 1); + + void setModeIndex(size_t index); + size_t getModeIndex() const { return m_current_mode_index; }; + size_t getMaxModeIndex() const { return m_modes.size() - 1; }; + void nextMode(); + + void setModesFromString(std::string modes_string); + MinimapModeDef getModeDef() const { return data->mode; } video::ITexture *getMinimapTexture(); @@ -144,6 +144,7 @@ public: void updateActiveMarkers(); void drawMinimap(); + void drawMinimap(core::rect rect); video::IVideoDriver *driver; Client* client; @@ -153,9 +154,11 @@ private: ITextureSource *m_tsrc; IShaderSource *m_shdrsrc; const NodeDefManager *m_ndef; - MinimapUpdateThread *m_minimap_update_thread; + MinimapUpdateThread *m_minimap_update_thread = nullptr; scene::SMeshBuffer *m_meshbuffer; bool m_enable_shaders; + std::vector m_modes; + size_t m_current_mode_index; u16 m_surface_mode_scan_height; f32 m_angle; std::mutex m_mutex; diff --git a/src/hud.cpp b/src/hud.cpp index 175701342..1791e04df 100644 --- a/src/hud.cpp +++ b/src/hud.cpp @@ -29,6 +29,7 @@ const struct EnumString es_HudElementType[] = {HUD_ELEM_WAYPOINT, "waypoint"}, {HUD_ELEM_IMAGE_WAYPOINT, "image_waypoint"}, {HUD_ELEM_COMPASS, "compass"}, + {HUD_ELEM_MINIMAP, "minimap"}, {0, NULL}, }; diff --git a/src/hud.h b/src/hud.h index 0a6993c1b..a0613ae98 100644 --- a/src/hud.h +++ b/src/hud.h @@ -51,7 +51,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #define HUD_HOTBAR_ITEMCOUNT_DEFAULT 8 #define HUD_HOTBAR_ITEMCOUNT_MAX 32 - #define HOTBAR_IMAGE_SIZE 48 enum HudElementType { @@ -61,7 +60,8 @@ enum HudElementType { HUD_ELEM_INVENTORY = 3, HUD_ELEM_WAYPOINT = 4, HUD_ELEM_IMAGE_WAYPOINT = 5, - HUD_ELEM_COMPASS = 6 + HUD_ELEM_COMPASS = 6, + HUD_ELEM_MINIMAP = 7 }; enum HudElementStat { @@ -108,3 +108,12 @@ extern const EnumString es_HudElementType[]; extern const EnumString es_HudElementStat[]; extern const EnumString es_HudBuiltinElement[]; +// Minimap stuff + +enum MinimapType { + MINIMAP_TYPE_OFF, + MINIMAP_TYPE_SURFACE, + MINIMAP_TYPE_RADAR, + MINIMAP_TYPE_TEXTURE, +}; + diff --git a/src/network/clientopcodes.cpp b/src/network/clientopcodes.cpp index f812a08a1..55cfdd4dc 100644 --- a/src/network/clientopcodes.cpp +++ b/src/network/clientopcodes.cpp @@ -122,6 +122,7 @@ const ToClientCommandHandler toClientCommandTable[TOCLIENT_NUM_MSG_TYPES] = null_command_handler, { "TOCLIENT_SRP_BYTES_S_B", TOCLIENT_STATE_NOT_CONNECTED, &Client::handleCommand_SrpBytesSandB }, // 0x60 { "TOCLIENT_FORMSPEC_PREPEND", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_FormspecPrepend }, // 0x61, + { "TOCLIENT_MINIMAP_MODES", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_MinimapModes }, // 0x62, }; const static ServerCommandFactory null_command_factory = { "TOSERVER_NULL", 0, false }; diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp index 5683564a0..65db02300 100644 --- a/src/network/clientpackethandler.cpp +++ b/src/network/clientpackethandler.cpp @@ -1164,15 +1164,24 @@ void Client::handleCommand_HudSetFlags(NetworkPacket* pkt) m_minimap_disabled_by_server = !(player->hud_flags & HUD_FLAG_MINIMAP_VISIBLE); bool m_minimap_radar_disabled_by_server = !(player->hud_flags & HUD_FLAG_MINIMAP_RADAR_VISIBLE); + // Not so satisying code to keep compatibility with old fixed mode system + // --> + // Hide minimap if it has been disabled by the server if (m_minimap && m_minimap_disabled_by_server && was_minimap_visible) // defers a minimap update, therefore only call it if really // needed, by checking that minimap was visible before - m_minimap->setMinimapMode(MINIMAP_MODE_OFF); - - // Switch to surface mode if radar disabled by server - if (m_minimap && m_minimap_radar_disabled_by_server && was_minimap_radar_visible) - m_minimap->setMinimapMode(MINIMAP_MODE_SURFACEx1); + m_minimap->setModeIndex(0); + + // If radar has been disabled, try to find a non radar mode or fall back to 0 + if (m_minimap && m_minimap_radar_disabled_by_server + && was_minimap_radar_visible) { + while (m_minimap->getModeIndex() > 0 && + m_minimap->getModeDef().type == MINIMAP_TYPE_RADAR) + m_minimap->nextMode(); + } + // <-- + // End of 'not so satifying code' } void Client::handleCommand_HudSetParam(NetworkPacket* pkt) @@ -1611,3 +1620,30 @@ void Client::handleCommand_ModChannelSignal(NetworkPacket *pkt) if (valid_signal) m_script->on_modchannel_signal(channel, signal); } + +void Client::handleCommand_MinimapModes(NetworkPacket *pkt) +{ + u16 count; // modes + u16 mode; // wanted current mode index after change + + *pkt >> count >> mode; + + if (m_minimap) + m_minimap->clearModes(); + + for (size_t index = 0; index < count; index++) { + u16 type; + std::string label; + u16 size; + std::string texture; + u16 scale; + + *pkt >> type >> label >> size >> texture >> scale; + + if (m_minimap) + m_minimap->addMode(MinimapType(type), size, label, texture, scale); + } + + if (m_minimap) + m_minimap->setModeIndex(mode); +} diff --git a/src/network/networkprotocol.h b/src/network/networkprotocol.h index 05600cda9..666e75e45 100644 --- a/src/network/networkprotocol.h +++ b/src/network/networkprotocol.h @@ -204,6 +204,7 @@ with this program; if not, write to the Free Software Foundation, Inc., PROTOCOL VERSION 39: Updated set_sky packet Adds new sun, moon and stars packets + Minimap modes */ #define LATEST_PROTOCOL_VERSION 39 @@ -764,7 +765,18 @@ enum ToClientCommand u8[len] formspec */ - TOCLIENT_NUM_MSG_TYPES = 0x62, + TOCLIENT_MINIMAP_MODES = 0x62, + /* + u16 count // modes + u16 mode // wanted current mode index after change + for each mode + u16 type + std::string label + u16 size + std::string extra + */ + + TOCLIENT_NUM_MSG_TYPES = 0x63, }; enum ToServerCommand diff --git a/src/network/serveropcodes.cpp b/src/network/serveropcodes.cpp index 2fc3197c2..aea5d7174 100644 --- a/src/network/serveropcodes.cpp +++ b/src/network/serveropcodes.cpp @@ -221,4 +221,5 @@ const ClientCommandFactory clientCommandFactoryTable[TOCLIENT_NUM_MSG_TYPES] = null_command_factory, // 0x5f { "TOSERVER_SRP_BYTES_S_B", 0, true }, // 0x60 { "TOCLIENT_FORMSPEC_PREPEND", 0, true }, // 0x61 + { "TOCLIENT_MINIMAP_MODES", 0, true }, // 0x62 }; diff --git a/src/script/lua_api/l_minimap.cpp b/src/script/lua_api/l_minimap.cpp index 5fba76eb8..3bbb6e5e3 100644 --- a/src/script/lua_api/l_minimap.cpp +++ b/src/script/lua_api/l_minimap.cpp @@ -89,7 +89,7 @@ int LuaMinimap::l_get_mode(lua_State *L) LuaMinimap *ref = checkobject(L, 1); Minimap *m = getobject(ref); - lua_pushinteger(L, m->getMinimapMode()); + lua_pushinteger(L, m->getModeIndex()); return 1; } @@ -98,13 +98,11 @@ int LuaMinimap::l_set_mode(lua_State *L) LuaMinimap *ref = checkobject(L, 1); Minimap *m = getobject(ref); - s32 mode = lua_tointeger(L, 2); - if (mode < MINIMAP_MODE_OFF || - mode >= MINIMAP_MODE_COUNT) { + u32 mode = lua_tointeger(L, 2); + if (mode >= m->getMaxModeIndex()) return 0; - } - m->setMinimapMode((MinimapMode) mode); + m->setModeIndex(mode); return 1; } @@ -140,8 +138,11 @@ int LuaMinimap::l_show(lua_State *L) LuaMinimap *ref = checkobject(L, 1); Minimap *m = getobject(ref); - if (m->getMinimapMode() == MINIMAP_MODE_OFF) - m->setMinimapMode(MINIMAP_MODE_SURFACEx1); + // This is not very adapted to new minimap mode management. Btw, tried + // to do something compatible. + + if (m->getModeIndex() == 0 && m->getMaxModeIndex() > 0) + m->setModeIndex(1); client->showMinimap(true); return 1; @@ -155,8 +156,11 @@ int LuaMinimap::l_hide(lua_State *L) LuaMinimap *ref = checkobject(L, 1); Minimap *m = getobject(ref); - if (m->getMinimapMode() != MINIMAP_MODE_OFF) - m->setMinimapMode(MINIMAP_MODE_OFF); + // This is not very adapted to new minimap mode management. Btw, tried + // to do something compatible. + + if (m->getModeIndex() != 0) + m->setModeIndex(0); client->showMinimap(false); return 1; diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index fead4e849..57ed7e2cd 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -2199,6 +2199,67 @@ int ObjectRef::l_get_day_night_ratio(lua_State *L) return 1; } +// set_minimap_modes(self, modes, modeindex) +int ObjectRef::l_set_minimap_modes(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + + // Arg 1 should be a player + ObjectRef *ref = checkobject(L, 1); + RemotePlayer *player = getplayer(ref); + if (player == NULL) + return 0; + + // Arg 2 should be a table (of tables) + if (!lua_istable(L, 2)) { + return 0; + } + + // Arg 3 should be a number + s16 wantedmode = lua_tonumber(L, 3); + + std::vector modes; + + lua_pushnil(L); + while (lua_next(L, 2) != 0) { + /* key is at index -2, value is at index -1 */ + if (lua_istable(L, -1)) { + bool ok = true; + MinimapMode mode; + std::string type = getstringfield_default(L, -1, "type", ""); + if (type == "off") + mode.type = MINIMAP_TYPE_OFF; + else if (type == "surface") + mode.type = MINIMAP_TYPE_SURFACE; + else if (type == "radar") + mode.type = MINIMAP_TYPE_RADAR; + else if (type == "texture") { + mode.type = MINIMAP_TYPE_TEXTURE; + mode.texture = getstringfield_default(L, -1, "texture", ""); + mode.scale = getintfield_default(L, -1, "scale", 1); + } else { + warningstream << "Minimap mode of unknown type \"" << type.c_str() + << "\" ignored.\n" << std::endl; + ok = false; + } + + if (ok) { + mode.label = getstringfield_default(L, -1, "label", ""); + // Size is limited to 512. Performance gets poor if size too large, and + // segfaults have been experienced. + mode.size = rangelim(getintfield_default(L, -1, "size", 0), 1, 512); + modes.push_back(mode); + } + } + /* removes 'value'; keeps 'key' for next iteration */ + lua_pop(L, 1); + } + lua_pop(L, 1); // Remove key + + getServer(L)->SendMinimapModes(player->getPeerId(), modes, wantedmode); + return 0; +} + ObjectRef::ObjectRef(ServerActiveObject *object): m_object(object) { @@ -2359,5 +2420,6 @@ luaL_Reg ObjectRef::methods[] = { luamethod(ObjectRef, set_eye_offset), luamethod(ObjectRef, get_eye_offset), luamethod(ObjectRef, send_mapblock), + luamethod(ObjectRef, set_minimap_modes), {0,0} }; diff --git a/src/script/lua_api/l_object.h b/src/script/lua_api/l_object.h index 126719b1f..ca03dfa2e 100644 --- a/src/script/lua_api/l_object.h +++ b/src/script/lua_api/l_object.h @@ -377,4 +377,7 @@ private: // send_mapblock(pos) static int l_send_mapblock(lua_State *L); + + // set_minimap_modes(self, modes, wanted_mode) + static int l_set_minimap_modes(lua_State *L); }; diff --git a/src/server.cpp b/src/server.cpp index 982f904f4..8f6257afe 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -2662,6 +2662,23 @@ void Server::sendRequestedMedia(session_t peer_id, } } +void Server::SendMinimapModes(session_t peer_id, + std::vector &modes, size_t wanted_mode) +{ + RemotePlayer *player = m_env->getPlayer(peer_id); + assert(player); + if (player->getPeerId() == PEER_ID_INEXISTENT) + return; + + NetworkPacket pkt(TOCLIENT_MINIMAP_MODES, 0, peer_id); + pkt << (u16)modes.size() << (u16)wanted_mode; + + for (auto &mode : modes) + pkt << (u16)mode.type << mode.label << mode.size << mode.texture << mode.scale; + + Send(&pkt); +} + void Server::sendDetachedInventory(Inventory *inventory, const std::string &name, session_t peer_id) { NetworkPacket pkt(TOCLIENT_DETACHED_INVENTORY, 0, peer_id); diff --git a/src/server.h b/src/server.h index 258d75eaf..4b3ac5cf7 100644 --- a/src/server.h +++ b/src/server.h @@ -118,6 +118,14 @@ struct ServerPlayingSound std::unordered_set clients; // peer ids }; +struct MinimapMode { + MinimapType type = MINIMAP_TYPE_OFF; + std::string label; + u16 size = 0; + std::string texture; + u16 scale = 1; +}; + class Server : public con::PeerHandler, public MapEventReceiver, public IGameDef { @@ -331,6 +339,10 @@ public: void SendPlayerSpeed(session_t peer_id, const v3f &added_vel); void SendPlayerFov(session_t peer_id); + void SendMinimapModes(session_t peer_id, + std::vector &modes, + size_t wanted_mode); + void sendDetachedInventories(session_t peer_id, bool incremental); virtual bool registerModStorage(ModMetadata *storage); -- cgit v1.2.3 From f46509d5e2c681b6da2abdeb27779be3c36a6916 Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Mon, 5 Oct 2020 09:07:33 +0200 Subject: Remove unused functions reported by cppcheck (#10463) Run unused functions reported by cppcheck This change removes a few (but not all) unused functions. Some unused helper functions were not removed due to their complexity and potential of future use. --- src/chat.cpp | 13 ++---- src/chat.h | 2 - src/client/client.cpp | 5 --- src/client/client.h | 1 - src/client/clientenvironment.cpp | 15 ------- src/client/clientmap.cpp | 2 +- src/client/mapblock_mesh.cpp | 27 ------------ src/client/mapblock_mesh.h | 5 --- src/content/CMakeLists.txt | 1 - src/content/packages.cpp | 69 ------------------------------ src/content/packages.h | 52 ---------------------- src/gui/guiChatConsole.cpp | 5 --- src/gui/guiChatConsole.h | 4 -- src/log.cpp | 11 +---- src/log.h | 10 ----- src/map.cpp | 63 +-------------------------- src/map.h | 21 +-------- src/mapgen/mapgen.cpp | 33 -------------- src/mapgen/mapgen.h | 7 +-- src/mapgen/mapgen_v6.cpp | 6 --- src/mapgen/mapgen_v6.h | 1 - src/mapgen/treegen.cpp | 13 ------ src/mapgen/treegen.h | 2 - src/network/networkpacket.cpp | 7 --- src/network/networkpacket.h | 1 - src/script/common/c_converter.cpp | 45 ------------------- src/script/common/c_converter.h | 2 - src/script/lua_api/l_mainmenu.cpp | 1 - src/unittest/test_map_settings_manager.cpp | 28 +----------- 29 files changed, 13 insertions(+), 439 deletions(-) delete mode 100644 src/content/packages.cpp delete mode 100644 src/content/packages.h (limited to 'src') diff --git a/src/chat.cpp b/src/chat.cpp index c3ed59804..2f65e68b3 100644 --- a/src/chat.cpp +++ b/src/chat.cpp @@ -123,14 +123,14 @@ void ChatBuffer::deleteByAge(f32 maxAge) deleteOldest(count); } -u32 ChatBuffer::getColumns() const +u32 ChatBuffer::getRows() const { - return m_cols; + return m_rows; } -u32 ChatBuffer::getRows() const +void ChatBuffer::scrollTop() { - return m_rows; + m_scroll = getTopScrollPos(); } void ChatBuffer::reformat(u32 cols, u32 rows) @@ -220,11 +220,6 @@ void ChatBuffer::scrollBottom() m_scroll = getBottomScrollPos(); } -void ChatBuffer::scrollTop() -{ - m_scroll = getTopScrollPos(); -} - u32 ChatBuffer::formatChatLine(const ChatLine& line, u32 cols, std::vector& destination) const { diff --git a/src/chat.h b/src/chat.h index f84ece206..0b98e4d3c 100644 --- a/src/chat.h +++ b/src/chat.h @@ -94,8 +94,6 @@ public: // Delete lines older than maxAge. void deleteByAge(f32 maxAge); - // Get number of columns, 0 if reformat has not been called yet. - u32 getColumns() const; // Get number of rows, 0 if reformat has not been called yet. u32 getRows() const; // Update console size and reformat all formatted lines. diff --git a/src/client/client.cpp b/src/client/client.cpp index 7fafe0da9..0bd98b256 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -1665,11 +1665,6 @@ ClientEvent *Client::getClientEvent() return event; } -bool Client::connectedToServer() -{ - return m_con->Connected(); -} - const Address Client::getServerAddress() { return m_con->GetPeerAddress(PEER_ID_SERVER); diff --git a/src/client/client.h b/src/client/client.h index 8f4aac6e3..bffdc7ec6 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -338,7 +338,6 @@ public: u16 getProtoVersion() { return m_proto_ver; } - bool connectedToServer(); void confirmRegistration(); bool m_is_registration_confirmation_state = false; bool m_simple_singleplayer_mode; diff --git a/src/client/clientenvironment.cpp b/src/client/clientenvironment.cpp index 0b7e92325..f831978a8 100644 --- a/src/client/clientenvironment.cpp +++ b/src/client/clientenvironment.cpp @@ -368,21 +368,6 @@ bool isFreeClientActiveObjectId(const u16 id, } -u16 getFreeClientActiveObjectId(ClientActiveObjectMap &objects) -{ - // try to reuse id's as late as possible - static u16 last_used_id = 0; - u16 startid = last_used_id; - for(;;) { - last_used_id ++; - if (isFreeClientActiveObjectId(last_used_id, objects)) - return last_used_id; - - if (last_used_id == startid) - return 0; - } -} - u16 ClientEnvironment::addActiveObject(ClientActiveObject *object) { // Register object. If failed return zero id diff --git a/src/client/clientmap.cpp b/src/client/clientmap.cpp index 3e4ab2e94..3124313e7 100644 --- a/src/client/clientmap.cpp +++ b/src/client/clientmap.cpp @@ -36,7 +36,7 @@ ClientMap::ClientMap( MapDrawControl &control, s32 id ): - Map(dout_client, client), + Map(client), scene::ISceneNode(RenderingEngine::get_scene_manager()->getRootSceneNode(), RenderingEngine::get_scene_manager(), id), m_client(client), diff --git a/src/client/mapblock_mesh.cpp b/src/client/mapblock_mesh.cpp index b59679523..f9332e399 100644 --- a/src/client/mapblock_mesh.cpp +++ b/src/client/mapblock_mesh.cpp @@ -81,33 +81,6 @@ void MeshMakeData::fill(MapBlock *block) } } -void MeshMakeData::fillSingleNode(MapNode *node) -{ - m_blockpos = v3s16(0,0,0); - - v3s16 blockpos_nodes = v3s16(0,0,0); - VoxelArea area(blockpos_nodes-v3s16(1,1,1)*MAP_BLOCKSIZE, - blockpos_nodes+v3s16(1,1,1)*MAP_BLOCKSIZE*2-v3s16(1,1,1)); - s32 volume = area.getVolume(); - s32 our_node_index = area.index(1,1,1); - - // Allocate this block + neighbors - m_vmanip.clear(); - m_vmanip.addArea(area); - - // Fill in data - MapNode *data = new MapNode[volume]; - for(s32 i = 0; i < volume; i++) - { - if (i == our_node_index) - data[i] = *node; - else - data[i] = MapNode(CONTENT_AIR, LIGHT_MAX, 0); - } - m_vmanip.copyFrom(data, area, area.MinEdge, area.MinEdge, area.getExtent()); - delete[] data; -} - void MeshMakeData::setCrack(int crack_level, v3s16 crack_pos) { if (crack_level >= 0) diff --git a/src/client/mapblock_mesh.h b/src/client/mapblock_mesh.h index 6af23a656..f8aed40dc 100644 --- a/src/client/mapblock_mesh.h +++ b/src/client/mapblock_mesh.h @@ -62,11 +62,6 @@ struct MeshMakeData */ void fill(MapBlock *block); - /* - Set up with only a single node at (1,1,1) - */ - void fillSingleNode(MapNode *node); - /* Set the (node) position of a crack */ diff --git a/src/content/CMakeLists.txt b/src/content/CMakeLists.txt index 5adcf6b1e..6dd049418 100644 --- a/src/content/CMakeLists.txt +++ b/src/content/CMakeLists.txt @@ -1,6 +1,5 @@ set(content_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/content.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/packages.cpp ${CMAKE_CURRENT_SOURCE_DIR}/mods.cpp ${CMAKE_CURRENT_SOURCE_DIR}/subgames.cpp PARENT_SCOPE diff --git a/src/content/packages.cpp b/src/content/packages.cpp deleted file mode 100644 index 2d488eb76..000000000 --- a/src/content/packages.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* -Minetest -Copyright (C) 2018 rubenwardy - -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 "content/packages.h" -#include "log.h" -#include "filesys.h" -#include "porting.h" -#include "settings.h" -#include "content/mods.h" -#include "content/subgames.h" - -std::string Package::getDownloadURL(const std::string &baseURL) const -{ - return baseURL + "/packages/" + author + "/" + name + "/releases/" + - std::to_string(release) + "/download/"; -} - -#if USE_CURL -std::vector getPackagesFromURL(const std::string &url) -{ - std::vector extra_headers; - extra_headers.emplace_back("Accept: application/json"); - - Json::Value json = fetchJsonValue(url, &extra_headers); - if (!json.isArray()) { - errorstream << "Invalid JSON download " << std::endl; - return std::vector(); - } - - std::vector packages; - - // Note: `unsigned int` is required to index JSON - for (unsigned int i = 0; i < json.size(); ++i) { - Package package; - - package.author = json[i]["author"].asString(); - package.name = json[i]["name"].asString(); - package.title = json[i]["title"].asString(); - package.type = json[i]["type"].asString(); - package.shortDesc = json[i]["shortDesc"].asString(); - package.release = json[i]["release"].asInt(); - if (json[i].isMember("thumbnail")) - package.thumbnail = json[i]["thumbnail"].asString(); - - if (package.valid()) - packages.push_back(package); - else - errorstream << "Invalid package at " << i << std::endl; - } - - return packages; -} -#endif diff --git a/src/content/packages.h b/src/content/packages.h deleted file mode 100644 index 9029475ef..000000000 --- a/src/content/packages.h +++ /dev/null @@ -1,52 +0,0 @@ -/* -Minetest -Copyright (C) 2018 rubenwardy - -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 "config.h" -#include "convert_json.h" -#include "irrlichttypes.h" - -struct Package -{ - std::string author; - std::string name; // Technical name - std::string title; - std::string type; // One of "mod", "game", or "txp" - - std::string shortDesc; - u32 release; - std::string thumbnail; - - bool valid() const - { - return !(author.empty() || name.empty() || title.empty() || - type.empty() || release <= 0); - } - - std::string getDownloadURL(const std::string &baseURL) const; -}; - -#if USE_CURL -std::vector getPackagesFromURL(const std::string &url); -#else -inline std::vector getPackagesFromURL(const std::string &url) -{ - return std::vector(); -} -#endif diff --git a/src/gui/guiChatConsole.cpp b/src/gui/guiChatConsole.cpp index 575c6ab25..ef471106d 100644 --- a/src/gui/guiChatConsole.cpp +++ b/src/gui/guiChatConsole.cpp @@ -136,11 +136,6 @@ void GUIChatConsole::closeConsoleAtOnce() recalculateConsolePosition(); } -f32 GUIChatConsole::getDesiredHeight() const -{ - return m_desired_height_fraction; -} - void GUIChatConsole::replaceAndAddToHistory(const std::wstring &line) { ChatPrompt& prompt = m_chat_backend->getPrompt(); diff --git a/src/gui/guiChatConsole.h b/src/gui/guiChatConsole.h index 7be40e27c..204f9f9cc 100644 --- a/src/gui/guiChatConsole.h +++ b/src/gui/guiChatConsole.h @@ -55,10 +55,6 @@ public: // Set whether to close the console after the user presses enter. void setCloseOnEnter(bool close) { m_close_on_enter = close; } - // Return the desired height (fraction of screen size) - // Zero if the console is closed or getting closed - f32 getDesiredHeight() const; - // Replace actual line when adding the actual to the history (if there is any) void replaceAndAddToHistory(const std::wstring &line); diff --git a/src/log.cpp b/src/log.cpp index 54442c39b..3c61414e9 100644 --- a/src/log.cpp +++ b/src/log.cpp @@ -97,16 +97,7 @@ LogBuffer verbose_buf(g_logger, LL_VERBOSE); std::ostream *dout_con_ptr = &null_stream; std::ostream *derr_con_ptr = &verbosestream; -// Server -std::ostream *dout_server_ptr = &infostream; -std::ostream *derr_server_ptr = &errorstream; - -#ifndef SERVER -// Client -std::ostream *dout_client_ptr = &infostream; -std::ostream *derr_client_ptr = &errorstream; -#endif - +// Common streams std::ostream rawstream(&raw_buf); std::ostream dstream(&none_buf); std::ostream errorstream(&error_buf); diff --git a/src/log.h b/src/log.h index 856d3479b..6ed6b1fb7 100644 --- a/src/log.h +++ b/src/log.h @@ -192,14 +192,8 @@ extern std::ostream null_stream; extern std::ostream *dout_con_ptr; extern std::ostream *derr_con_ptr; -extern std::ostream *dout_server_ptr; extern std::ostream *derr_server_ptr; -#ifndef SERVER -extern std::ostream *dout_client_ptr; -extern std::ostream *derr_client_ptr; -#endif - extern Logger g_logger; // Writes directly to all LL_NONE log outputs for g_logger with no prefix. @@ -222,8 +216,4 @@ extern std::ostream dstream; #define dout_con (*dout_con_ptr) #define derr_con (*derr_con_ptr) -#define dout_server (*dout_server_ptr) -#ifndef SERVER - #define dout_client (*dout_client_ptr) -#endif diff --git a/src/map.cpp b/src/map.cpp index b9ab7c066..ef7eddb39 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -62,8 +62,7 @@ with this program; if not, write to the Free Software Foundation, Inc., Map */ -Map::Map(std::ostream &dout, IGameDef *gamedef): - m_dout(dout), +Map::Map(IGameDef *gamedef): m_gamedef(gamedef), m_nodedef(gamedef->ndef()) { @@ -1201,7 +1200,7 @@ bool Map::isBlockOccluded(MapBlock *block, v3s16 cam_pos_nodes) */ ServerMap::ServerMap(const std::string &savedir, IGameDef *gamedef, EmergeManager *emerge, MetricsBackend *mb): - Map(dout_server, gamedef), + Map(gamedef), settings_mgr(g_settings, savedir + DIR_DELIM + "map_meta.txt"), m_emerge(emerge) { @@ -1327,11 +1326,6 @@ u64 ServerMap::getSeed() return getMapgenParams()->seed; } -s16 ServerMap::getWaterLevel() -{ - return getMapgenParams()->water_level; -} - bool ServerMap::blockpos_over_mapgen_limit(v3s16 p) { const s16 mapgen_limit_bp = rangelim( @@ -1732,59 +1726,6 @@ void ServerMap::updateVManip(v3s16 pos) vm->m_is_dirty = true; } -s16 ServerMap::findGroundLevel(v2s16 p2d) -{ -#if 0 - /* - Uh, just do something random... - */ - // Find existing map from top to down - s16 max=63; - s16 min=-64; - v3s16 p(p2d.X, max, p2d.Y); - for(; p.Y>min; p.Y--) - { - MapNode n = getNodeNoEx(p); - if(n.getContent() != CONTENT_IGNORE) - break; - } - if(p.Y == min) - goto plan_b; - // If this node is not air, go to plan b - if(getNodeNoEx(p).getContent() != CONTENT_AIR) - goto plan_b; - // Search existing walkable and return it - for(; p.Y>min; p.Y--) - { - MapNode n = getNodeNoEx(p); - if(content_walkable(n.d) && n.getContent() != CONTENT_IGNORE) - return p.Y; - } - - // Move to plan b -plan_b: -#endif - - /* - Determine from map generator noise functions - */ - - s16 level = m_emerge->getGroundLevelAtPoint(p2d); - return level; - - //double level = base_rock_level_2d(m_seed, p2d) + AVERAGE_MUD_AMOUNT; - //return (s16)level; -} - -void ServerMap::createDirs(const std::string &path) -{ - if (!fs::CreateAllDirs(path)) { - m_dout<<"ServerMap: Failed to create directory " - <<"\""< *getSectorsPtr(){return &m_sectors;} - /* Variables */ @@ -283,8 +276,6 @@ public: protected: friend class LuaVoxelManip; - std::ostream &m_dout; // A bit deprecated, could be removed - IGameDef *m_gamedef; std::set m_event_receivers; @@ -374,15 +365,6 @@ public: */ MapBlock *getBlockOrEmerge(v3s16 p3d); - // Helper for placing objects on ground level - s16 findGroundLevel(v2s16 p2d); - - /* - Misc. helper functions for fiddling with directory and file - names when saving - */ - void createDirs(const std::string &path); - /* Database functions */ @@ -414,7 +396,6 @@ public: bool isSavingEnabled(){ return m_map_saving_enabled; } u64 getSeed(); - s16 getWaterLevel(); /*! * Fixes lighting in one map block. diff --git a/src/mapgen/mapgen.cpp b/src/mapgen/mapgen.cpp index 52ef64e7e..e0dfd2d71 100644 --- a/src/mapgen/mapgen.cpp +++ b/src/mapgen/mapgen.cpp @@ -244,26 +244,6 @@ u32 Mapgen::getBlockSeed2(v3s16 p, s32 seed) } -// Returns Y one under area minimum if not found -s16 Mapgen::findGroundLevelFull(v2s16 p2d) -{ - const v3s16 &em = vm->m_area.getExtent(); - s16 y_nodes_max = vm->m_area.MaxEdge.Y; - s16 y_nodes_min = vm->m_area.MinEdge.Y; - u32 i = vm->m_area.index(p2d.X, y_nodes_max, p2d.Y); - s16 y; - - for (y = y_nodes_max; y >= y_nodes_min; y--) { - MapNode &n = vm->m_data[i]; - if (ndef->get(n).walkable) - break; - - VoxelArea::add_y(em, i, -1); - } - return (y >= y_nodes_min) ? y : y_nodes_min - 1; -} - - // Returns -MAX_MAP_GENERATION_LIMIT if not found s16 Mapgen::findGroundLevel(v2s16 p2d, s16 ymin, s16 ymax) { @@ -984,19 +964,6 @@ GenerateNotifier::GenerateNotifier(u32 notify_on, } -void GenerateNotifier::setNotifyOn(u32 notify_on) -{ - m_notify_on = notify_on; -} - - -void GenerateNotifier::setNotifyOnDecoIds( - const std::set *notify_on_deco_ids) -{ - m_notify_on_deco_ids = notify_on_deco_ids; -} - - bool GenerateNotifier::addEvent(GenNotifyType type, v3s16 pos, u32 id) { if (!(m_notify_on & (1 << type))) diff --git a/src/mapgen/mapgen.h b/src/mapgen/mapgen.h index 0f2977c4c..1487731e2 100644 --- a/src/mapgen/mapgen.h +++ b/src/mapgen/mapgen.h @@ -88,19 +88,17 @@ struct GenNotifyEvent { class GenerateNotifier { public: + // Use only for temporary Mapgen objects with no map generation! GenerateNotifier() = default; GenerateNotifier(u32 notify_on, const std::set *notify_on_deco_ids); - void setNotifyOn(u32 notify_on); - void setNotifyOnDecoIds(const std::set *notify_on_deco_ids); - bool addEvent(GenNotifyType type, v3s16 pos, u32 id=0); void getEvents(std::map > &event_map); void clearEvents(); private: u32 m_notify_on = 0; - const std::set *m_notify_on_deco_ids; + const std::set *m_notify_on_deco_ids = nullptr; std::list m_notify_events; }; @@ -186,7 +184,6 @@ public: static u32 getBlockSeed(v3s16 p, s32 seed); static u32 getBlockSeed2(v3s16 p, s32 seed); - s16 findGroundLevelFull(v2s16 p2d); s16 findGroundLevel(v2s16 p2d, s16 ymin, s16 ymax); s16 findLiquidSurface(v2s16 p2d, s16 ymin, s16 ymax); void updateHeightmap(v3s16 nmin, v3s16 nmax); diff --git a/src/mapgen/mapgen_v6.cpp b/src/mapgen/mapgen_v6.cpp index 8bea5eb69..90a52e031 100644 --- a/src/mapgen/mapgen_v6.cpp +++ b/src/mapgen/mapgen_v6.cpp @@ -341,12 +341,6 @@ float MapgenV6::baseTerrainLevelFromMap(int index) } -s16 MapgenV6::find_ground_level_from_noise(u64 seed, v2s16 p2d, s16 precision) -{ - return baseTerrainLevelFromNoise(p2d) + MGV6_AVERAGE_MUD_AMOUNT; -} - - int MapgenV6::getGroundLevelAtPoint(v2s16 p) { return baseTerrainLevelFromNoise(p) + MGV6_AVERAGE_MUD_AMOUNT; diff --git a/src/mapgen/mapgen_v6.h b/src/mapgen/mapgen_v6.h index ff565edec..a6e6da8c6 100644 --- a/src/mapgen/mapgen_v6.h +++ b/src/mapgen/mapgen_v6.h @@ -150,7 +150,6 @@ public: s16 find_stone_level(v2s16 p2d); bool block_is_underground(u64 seed, v3s16 blockpos); - s16 find_ground_level_from_noise(u64 seed, v2s16 p2d, s16 precision); float getHumidity(v2s16 p); float getTreeAmount(v2s16 p); diff --git a/src/mapgen/treegen.cpp b/src/mapgen/treegen.cpp index e7e30c880..e633d800a 100644 --- a/src/mapgen/treegen.cpp +++ b/src/mapgen/treegen.cpp @@ -527,19 +527,6 @@ treegen::error make_ltree(MMVManip &vmanip, v3s16 p0, } -void tree_node_placement(MMVManip &vmanip, v3f p0, MapNode node) -{ - v3s16 p1 = v3s16(myround(p0.X), myround(p0.Y), myround(p0.Z)); - if (!vmanip.m_area.contains(p1)) - return; - u32 vi = vmanip.m_area.index(p1); - if (vmanip.m_data[vi].getContent() != CONTENT_AIR - && vmanip.m_data[vi].getContent() != CONTENT_IGNORE) - return; - vmanip.m_data[vmanip.m_area.index(p1)] = node; -} - - void tree_trunk_placement(MMVManip &vmanip, v3f p0, TreeDef &tree_definition) { v3s16 p1 = v3s16(myround(p0.X), myround(p0.Y), myround(p0.Z)); diff --git a/src/mapgen/treegen.h b/src/mapgen/treegen.h index 447baabb3..59a418824 100644 --- a/src/mapgen/treegen.h +++ b/src/mapgen/treegen.h @@ -76,8 +76,6 @@ namespace treegen { const NodeDefManager *ndef, const TreeDef &tree_definition); // L-System tree gen helper functions - void tree_node_placement(MMVManip &vmanip, v3f p0, - MapNode node); void tree_trunk_placement(MMVManip &vmanip, v3f p0, TreeDef &tree_definition); void tree_leaves_placement(MMVManip &vmanip, v3f p0, diff --git a/src/network/networkpacket.cpp b/src/network/networkpacket.cpp index 4d531b611..6d0abb12c 100644 --- a/src/network/networkpacket.cpp +++ b/src/network/networkpacket.cpp @@ -223,13 +223,6 @@ NetworkPacket& NetworkPacket::operator>>(char& dst) return *this; } -char NetworkPacket::getChar(u32 offset) -{ - checkReadOffset(offset, 1); - - return readU8(&m_data[offset]); -} - NetworkPacket& NetworkPacket::operator<<(char src) { checkDataSize(1); diff --git a/src/network/networkpacket.h b/src/network/networkpacket.h index fc8617651..e77bfb744 100644 --- a/src/network/networkpacket.h +++ b/src/network/networkpacket.h @@ -64,7 +64,6 @@ public: std::string readLongString(); - char getChar(u32 offset); NetworkPacket &operator>>(char &dst); NetworkPacket &operator<<(char src); diff --git a/src/script/common/c_converter.cpp b/src/script/common/c_converter.cpp index eb6ab5331..c00401b58 100644 --- a/src/script/common/c_converter.cpp +++ b/src/script/common/c_converter.cpp @@ -679,48 +679,3 @@ size_t write_array_slice_float( return elem_index - 1; } - - -size_t write_array_slice_u16( - lua_State *L, - int table_index, - u16 *data, - v3u16 data_size, - v3u16 slice_offset, - v3u16 slice_size) -{ - v3u16 pmin, pmax(data_size); - - if (slice_offset.X > 0) { - slice_offset.X--; - pmin.X = slice_offset.X; - pmax.X = MYMIN(slice_offset.X + slice_size.X, data_size.X); - } - - if (slice_offset.Y > 0) { - slice_offset.Y--; - pmin.Y = slice_offset.Y; - pmax.Y = MYMIN(slice_offset.Y + slice_size.Y, data_size.Y); - } - - if (slice_offset.Z > 0) { - slice_offset.Z--; - pmin.Z = slice_offset.Z; - pmax.Z = MYMIN(slice_offset.Z + slice_size.Z, data_size.Z); - } - - const u32 ystride = data_size.X; - const u32 zstride = data_size.X * data_size.Y; - - u32 elem_index = 1; - for (u32 z = pmin.Z; z != pmax.Z; z++) - for (u32 y = pmin.Y; y != pmax.Y; y++) - for (u32 x = pmin.X; x != pmax.X; x++) { - u32 i = z * zstride + y * ystride + x; - lua_pushinteger(L, data[i]); - lua_rawseti(L, table_index, elem_index); - elem_index++; - } - - return elem_index - 1; -} diff --git a/src/script/common/c_converter.h b/src/script/common/c_converter.h index a4a7079fd..6ad6f3212 100644 --- a/src/script/common/c_converter.h +++ b/src/script/common/c_converter.h @@ -136,5 +136,3 @@ void warn_if_field_exists(lua_State *L, int table, size_t write_array_slice_float(lua_State *L, int table_index, float *data, v3u16 data_size, v3u16 slice_offset, v3u16 slice_size); -size_t write_array_slice_u16(lua_State *L, int table_index, u16 *data, - v3u16 data_size, v3u16 slice_offset, v3u16 slice_size); diff --git a/src/script/lua_api/l_mainmenu.cpp b/src/script/lua_api/l_mainmenu.cpp index e49ec4052..0aa2760e9 100644 --- a/src/script/lua_api/l_mainmenu.cpp +++ b/src/script/lua_api/l_mainmenu.cpp @@ -29,7 +29,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "porting.h" #include "filesys.h" #include "convert_json.h" -#include "content/packages.h" #include "content/content.h" #include "content/subgames.h" #include "serverlist.h" diff --git a/src/unittest/test_map_settings_manager.cpp b/src/unittest/test_map_settings_manager.cpp index 0a5c971b9..3d642a9b4 100644 --- a/src/unittest/test_map_settings_manager.cpp +++ b/src/unittest/test_map_settings_manager.cpp @@ -65,31 +65,6 @@ void check_noise_params(const NoiseParams *np1, const NoiseParams *np2) } -std::string read_file_to_string(const std::string &filepath) -{ - std::string buf; - FILE *f = fopen(filepath.c_str(), "rb"); - if (!f) - return ""; - - fseek(f, 0, SEEK_END); - - long filesize = ftell(f); - if (filesize == -1) { - fclose(f); - return ""; - } - rewind(f); - - buf.resize(filesize); - - UASSERTEQ(size_t, fread(&buf[0], 1, filesize, f), 1); - - fclose(f); - return buf; -} - - void TestMapSettingsManager::makeUserConfig(Settings *conf) { conf->set("mg_name", "v7"); @@ -199,7 +174,8 @@ void TestMapSettingsManager::testMapSettingsManager() }; SHA1 ctx; - std::string metafile_contents = read_file_to_string(test_mapmeta_path); + std::string metafile_contents; + UASSERT(fs::ReadFile(test_mapmeta_path, metafile_contents)); ctx.addBytes(&metafile_contents[0], metafile_contents.size()); unsigned char *sha1_result = ctx.getDigest(); int resultdiff = memcmp(sha1_result, expected_contents_hash, 20); -- cgit v1.2.3 From e80fc22dd996e5b0efd8c4f67700c0920e323e46 Mon Sep 17 00:00:00 2001 From: rubenwardy Date: Tue, 6 Oct 2020 12:10:37 +0100 Subject: Prevent games from setting secure settings (#10460) --- src/content/subgames.cpp | 8 ++++++++ src/content/subgames.h | 3 --- src/settings.cpp | 13 +++++++++++++ src/settings.h | 2 ++ 4 files changed, 23 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/content/subgames.cpp b/src/content/subgames.cpp index 695ba431f..c6350f2dd 100644 --- a/src/content/subgames.cpp +++ b/src/content/subgames.cpp @@ -34,12 +34,17 @@ with this program; if not, write to the Free Software Foundation, Inc., // The maximum number of identical world names allowed #define MAX_WORLD_NAMES 100 +namespace +{ + bool getGameMinetestConfig(const std::string &game_path, Settings &conf) { std::string conf_path = game_path + DIR_DELIM + "minetest.conf"; return conf.readConfigFile(conf_path.c_str()); } +} + struct GameFindPath { std::string path; @@ -330,8 +335,11 @@ void loadGameConfAndInitWorld(const std::string &path, const std::string &name, // files that were loaded before. g_settings->clearDefaults(); set_default_settings(g_settings); + Settings game_defaults; getGameMinetestConfig(gamespec.path, game_defaults); + game_defaults.removeSecureSettings(); + g_settings->overrideDefaults(&game_defaults); infostream << "Initializing world at " << final_path << std::endl; diff --git a/src/content/subgames.h b/src/content/subgames.h index 35b619aaf..60392639b 100644 --- a/src/content/subgames.h +++ b/src/content/subgames.h @@ -53,9 +53,6 @@ struct SubgameSpec bool isValid() const { return (!id.empty() && !path.empty()); } }; -// minetest.conf -bool getGameMinetestConfig(const std::string &game_path, Settings &conf); - SubgameSpec findSubgame(const std::string &id); SubgameSpec findWorldSubgame(const std::string &world_path); diff --git a/src/settings.cpp b/src/settings.cpp index 56ab9e12b..f30ef34e9 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -1039,6 +1039,19 @@ void Settings::deregisterChangedCallback(const std::string &name, } } +void Settings::removeSecureSettings() +{ + for (const auto &name : getNames()) { + if (name.compare(0, 7, "secure.") != 0) + continue; + + errorstream << "Secure setting " << name + << " isn't allowed, so was ignored." + << std::endl; + remove(name); + } +} + void Settings::doCallbacks(const std::string &name) const { MutexAutoLock lock(m_callback_mutex); diff --git a/src/settings.h b/src/settings.h index 7db5539b2..6db2f9481 100644 --- a/src/settings.h +++ b/src/settings.h @@ -207,6 +207,8 @@ public: void deregisterChangedCallback(const std::string &name, SettingsChangedCallback cbf, void *userdata = NULL); + void removeSecureSettings(); + private: /*********************** * Reading and writing * -- cgit v1.2.3 From 2f4037752b023f87ca1f8859a8dce4f833353967 Mon Sep 17 00:00:00 2001 From: HybridDog <3192173+HybridDog@users.noreply.github.com> Date: Tue, 6 Oct 2020 20:49:46 +0200 Subject: Add minetest.get_artificial_light and minetest.get_natural_light (#5680) Add more detailed light detection functions, a function to get the artificial light (torches) and a function to get the sunlight as seen by the player (you can specify timeofday). Co-authored-by: rubenwardy --- builtin/game/misc.lua | 6 ++ doc/lua_api.txt | 16 ++++ games/devtest/mods/testtools/init.lua | 2 + games/devtest/mods/testtools/light.lua | 22 ++++++ .../testtools/textures/testtools_lighttool.png | Bin 0 -> 1659 bytes src/script/lua_api/l_env.cpp | 41 ++++++++++ src/script/lua_api/l_env.h | 5 ++ src/serverenvironment.cpp | 85 +++++++++++++++++++++ src/serverenvironment.h | 3 + 9 files changed, 180 insertions(+) create mode 100644 games/devtest/mods/testtools/light.lua create mode 100644 games/devtest/mods/testtools/textures/testtools_lighttool.png (limited to 'src') diff --git a/builtin/game/misc.lua b/builtin/game/misc.lua index 341e613c2..96a0a2dda 100644 --- a/builtin/game/misc.lua +++ b/builtin/game/misc.lua @@ -151,6 +151,12 @@ function core.setting_get_pos(name) end +-- See l_env.cpp for the other functions +function core.get_artificial_light(param1) + return math.floor(param1 / 16) +end + + -- To be overriden by protection mods function core.is_protected(pos, name) diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 9e9af20da..c4eb56374 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -4824,6 +4824,22 @@ Environment access * `pos`: The position where to measure the light. * `timeofday`: `nil` for current time, `0` for night, `0.5` for day * Returns a number between `0` and `15` or `nil` + * `nil` is returned e.g. when the map isn't loaded at `pos` +* `minetest.get_natural_light(pos[, timeofday])` + * Figures out the sunlight (or moonlight) value at pos at the given time of + day. + * `pos`: The position of the node + * `timeofday`: `nil` for current time, `0` for night, `0.5` for day + * Returns a number between `0` and `15` or `nil` + * This function tests 203 nodes in the worst case, which happens very + unlikely +* `minetest.get_artificial_light(param1)` + * Calculates the artificial light (light from e.g. torches) value from the + `param1` value. + * `param1`: The param1 value of a `paramtype = "light"` node. + * Returns a number between `0` and `15` + * Currently it's the same as `math.floor(param1 / 16)`, except that it + ensures compatibility. * `minetest.place_node(pos, node)` * Place node with the same effects that a player would cause * `minetest.dig_node(pos)` diff --git a/games/devtest/mods/testtools/init.lua b/games/devtest/mods/testtools/init.lua index df5bc8e55..d578b264a 100644 --- a/games/devtest/mods/testtools/init.lua +++ b/games/devtest/mods/testtools/init.lua @@ -1,6 +1,8 @@ local S = minetest.get_translator("testtools") local F = minetest.formspec_escape +dofile(minetest.get_modpath("testtools") .. "/light.lua") + -- TODO: Add a Node Metadata tool minetest.register_tool("testtools:param2tool", { diff --git a/games/devtest/mods/testtools/light.lua b/games/devtest/mods/testtools/light.lua new file mode 100644 index 000000000..a9458ca6b --- /dev/null +++ b/games/devtest/mods/testtools/light.lua @@ -0,0 +1,22 @@ + +local S = minetest.get_translator("testtools") + +minetest.register_tool("testtools:lighttool", { + description = S("Light tool"), + inventory_image = "testtools_lighttool.png", + groups = { testtool = 1, disable_repair = 1 }, + on_use = function(itemstack, user, pointed_thing) + local pos = pointed_thing.above + if pointed_thing.type ~= "node" or not pos then + return + end + + local node = minetest.get_node(pos) + local time = minetest.get_timeofday() + local sunlight = minetest.get_natural_light(pos) + local artificial = minetest.get_artificial_light(node.param1) + local message = ("param1 0x%02x | time %.5f | sunlight %d | artificial %d") + :format(node.param1, time, sunlight, artificial) + minetest.chat_send_player(user:get_player_name(), message) + end +}) diff --git a/games/devtest/mods/testtools/textures/testtools_lighttool.png b/games/devtest/mods/testtools/textures/testtools_lighttool.png new file mode 100644 index 000000000..6f744b7fa Binary files /dev/null and b/games/devtest/mods/testtools/textures/testtools_lighttool.png differ diff --git a/src/script/lua_api/l_env.cpp b/src/script/lua_api/l_env.cpp index 138e88ae8..8d50d664d 100644 --- a/src/script/lua_api/l_env.cpp +++ b/src/script/lua_api/l_env.cpp @@ -407,6 +407,46 @@ int ModApiEnvMod::l_get_node_light(lua_State *L) return 1; } + +// get_natural_light(pos, timeofday) +// pos = {x=num, y=num, z=num} +// timeofday: nil = current time, 0 = night, 0.5 = day +int ModApiEnvMod::l_get_natural_light(lua_State *L) +{ + GET_ENV_PTR; + + v3s16 pos = read_v3s16(L, 1); + + bool is_position_ok; + MapNode n = env->getMap().getNode(pos, &is_position_ok); + if (!is_position_ok) + return 0; + + // If the daylight is 0, nothing needs to be calculated + u8 daylight = n.param1 & 0x0f; + if (daylight == 0) { + lua_pushinteger(L, 0); + return 1; + } + + u32 time_of_day; + if (lua_isnumber(L, 2)) { + time_of_day = 24000.0 * lua_tonumber(L, 2); + time_of_day %= 24000; + } else { + time_of_day = env->getTimeOfDay(); + } + u32 dnr = time_to_daynight_ratio(time_of_day, true); + + // If it's the same as the artificial light, the sunlight needs to be + // searched for because the value may not emanate from the sun + if (daylight == n.param1 >> 4) + daylight = env->findSunlight(pos); + + lua_pushinteger(L, dnr * daylight / 1000); + return 1; +} + // place_node(pos, node) // pos = {x=num, y=num, z=num} int ModApiEnvMod::l_place_node(lua_State *L) @@ -1358,6 +1398,7 @@ void ModApiEnvMod::Initialize(lua_State *L, int top) API_FCT(get_node); API_FCT(get_node_or_nil); API_FCT(get_node_light); + API_FCT(get_natural_light); API_FCT(place_node); API_FCT(dig_node); API_FCT(punch_node); diff --git a/src/script/lua_api/l_env.h b/src/script/lua_api/l_env.h index 07d4d2438..7f212b5fc 100644 --- a/src/script/lua_api/l_env.h +++ b/src/script/lua_api/l_env.h @@ -56,6 +56,11 @@ private: // timeofday: nil = current time, 0 = night, 0.5 = day static int l_get_node_light(lua_State *L); + // get_natural_light(pos, timeofday) + // pos = {x=num, y=num, z=num} + // timeofday: nil = current time, 0 = night, 0.5 = day + static int l_get_natural_light(lua_State *L); + // place_node(pos, node) // pos = {x=num, y=num, z=num} static int l_place_node(lua_State *L); diff --git a/src/serverenvironment.cpp b/src/serverenvironment.cpp index 320042e19..6ef56efc8 100644 --- a/src/serverenvironment.cpp +++ b/src/serverenvironment.cpp @@ -1066,6 +1066,91 @@ bool ServerEnvironment::swapNode(v3s16 p, const MapNode &n) return true; } +u8 ServerEnvironment::findSunlight(v3s16 pos) const +{ + // Directions for neighbouring nodes with specified order + static const v3s16 dirs[] = { + v3s16(-1, 0, 0), v3s16(1, 0, 0), v3s16(0, 0, -1), v3s16(0, 0, 1), + v3s16(0, -1, 0), v3s16(0, 1, 0) + }; + + const NodeDefManager *ndef = m_server->ndef(); + + // found_light remembers the highest known sunlight value at pos + u8 found_light = 0; + + struct stack_entry { + v3s16 pos; + s16 dist; + }; + std::stack stack; + stack.push({pos, 0}); + + std::unordered_map dists; + dists[MapDatabase::getBlockAsInteger(pos)] = 0; + + while (!stack.empty()) { + struct stack_entry e = stack.top(); + stack.pop(); + + v3s16 currentPos = e.pos; + s8 dist = e.dist + 1; + + for (const v3s16& off : dirs) { + v3s16 neighborPos = currentPos + off; + s64 neighborHash = MapDatabase::getBlockAsInteger(neighborPos); + + // Do not walk neighborPos multiple times unless the distance to the start + // position is shorter + auto it = dists.find(neighborHash); + if (it != dists.end() && dist >= it->second) + continue; + + // Position to walk + bool is_position_ok; + MapNode node = m_map->getNode(neighborPos, &is_position_ok); + if (!is_position_ok) { + // This happens very rarely because the map at currentPos is loaded + m_map->emergeBlock(neighborPos, false); + node = m_map->getNode(neighborPos, &is_position_ok); + if (!is_position_ok) + continue; // not generated + } + + const ContentFeatures &def = ndef->get(node); + if (!def.sunlight_propagates) { + // Do not test propagation here again + dists[neighborHash] = -1; + continue; + } + + // Sunlight could have come from here + dists[neighborHash] = dist; + u8 daylight = node.param1 & 0x0f; + + // In the special case where sunlight shines from above and thus + // does not decrease with upwards distance, daylight is always + // bigger than nightlight, which never reaches 15 + int possible_finlight = daylight - dist; + if (possible_finlight <= found_light) { + // Light from here cannot make a brighter light at currentPos than + // found_light + continue; + } + + u8 nightlight = node.param1 >> 4; + if (daylight > nightlight) { + // Found a valid daylight + found_light = possible_finlight; + } else { + // Sunlight may be darker, so walk the neighbours + stack.push({neighborPos, dist}); + } + } + } + return found_light; +} + void ServerEnvironment::clearObjects(ClearObjectsMode mode) { infostream << "ServerEnvironment::clearObjects(): " diff --git a/src/serverenvironment.h b/src/serverenvironment.h index af742e290..cfd5b8f3e 100644 --- a/src/serverenvironment.h +++ b/src/serverenvironment.h @@ -322,6 +322,9 @@ public: bool removeNode(v3s16 p); bool swapNode(v3s16 p, const MapNode &n); + // Find the daylight value at pos with a Depth First Search + u8 findSunlight(v3s16 pos) const; + // Find all active objects inside a radius around a point void getObjectsInsideRadius(std::vector &objects, const v3f &pos, float radius, std::function include_obj_cb) -- cgit v1.2.3 From a37e96eefc646f01f34d0c6d8948d4a9c4062cae Mon Sep 17 00:00:00 2001 From: Zughy <63455151+Zughy@users.noreply.github.com> Date: Tue, 6 Oct 2020 20:51:27 +0200 Subject: -Wmem-access only called when GCC > 7 (#10453) --- src/client/mapblock_mesh.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/client/mapblock_mesh.cpp b/src/client/mapblock_mesh.cpp index f9332e399..c7790f1e4 100644 --- a/src/client/mapblock_mesh.cpp +++ b/src/client/mapblock_mesh.cpp @@ -394,7 +394,9 @@ static void getNodeVertexDirs(const v3s16 &dir, v3s16 *vertex_dirs) #if defined(__GNUC__) && !defined(__clang__) #pragma GCC diagnostic push +#if __GNUC__ > 7 #pragma GCC diagnostic ignored "-Wclass-memaccess" +#endif #endif memcpy(vertex_dirs, &vertex_dirs_table[idx], 4 * sizeof(v3s16)); #if defined(__GNUC__) && !defined(__clang__) -- cgit v1.2.3 From b2f3f663858e6d2a2174066e425bb6f2edea910b Mon Sep 17 00:00:00 2001 From: DS Date: Thu, 8 Oct 2020 19:44:47 +0200 Subject: Fix box[]es not being clipped (#10473) Fixes a regression of #8676. --- src/gui/guiBox.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/gui/guiBox.cpp b/src/gui/guiBox.cpp index 99a115daf..443f1064f 100644 --- a/src/gui/guiBox.cpp +++ b/src/gui/guiBox.cpp @@ -107,10 +107,11 @@ void GUIBox::draw() video::IVideoDriver *driver = Environment->getVideoDriver(); driver->draw2DRectangle(main_rect, m_colors[0], m_colors[1], m_colors[3], - m_colors[2], nullptr); + m_colors[2], &AbsoluteClippingRect); for (size_t i = 0; i <= 3; i++) - driver->draw2DRectangle(m_bordercolors[i], border_rects[i], nullptr); + driver->draw2DRectangle(m_bordercolors[i], border_rects[i], + &AbsoluteClippingRect); IGUIElement::draw(); } -- cgit v1.2.3 From f3ae45b2b245dd0aeb4a7d9b76afaf078871104c Mon Sep 17 00:00:00 2001 From: DS Date: Fri, 9 Oct 2020 20:11:21 +0200 Subject: Add a short_description to be used by mods (#8980) --- builtin/game/register.lua | 6 ++++ doc/lua_api.txt | 10 ++++++ games/devtest/mods/unittests/init.lua | 2 ++ games/devtest/mods/unittests/itemdescription.lua | 44 ++++++++++++++++++++++++ src/inventory.cpp | 14 ++++++++ src/inventory.h | 1 + src/itemdef.cpp | 9 +++-- src/itemdef.h | 1 + src/script/common/c_content.cpp | 3 ++ src/script/lua_api/l_item.cpp | 11 ++++++ src/script/lua_api/l_item.h | 3 ++ 11 files changed, 102 insertions(+), 2 deletions(-) create mode 100644 games/devtest/mods/unittests/itemdescription.lua (limited to 'src') diff --git a/builtin/game/register.lua b/builtin/game/register.lua index 3de67c04b..f00b76494 100644 --- a/builtin/game/register.lua +++ b/builtin/game/register.lua @@ -118,6 +118,12 @@ function core.register_item(name, itemdef) end itemdef.name = name + -- default description to item name + itemdef.description = itemdef.description or name + -- default short_description to first line of description + itemdef.short_description = itemdef.short_description or + itemdef.description:gsub("\n.*","") + -- Apply defaults and add to registered_* table if itemdef.type == "node" then -- Use the nodebox as selection box if it's not set manually diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 60fea3817..c8b294149 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -2054,6 +2054,8 @@ Some of the values in the key-value store are handled specially: * `description`: Set the item stack's description. Defaults to `idef.description`. +* `short_description`: Set the item stack's short description. Defaults + to `idef.short_description`. * `color`: A `ColorString`, which sets the stack's color. * `palette_index`: If the item has a palette, this is used to get the current color from the palette. @@ -5994,6 +5996,8 @@ an itemstring, a table or `nil`. stack). * `set_metadata(metadata)`: (DEPRECATED) Returns true. * `get_description()`: returns the description shown in inventory list tooltips. +* `get_short_description()`: returns the short description. + * Unlike the description, this does not include new lines. * `clear()`: removes all items from the stack, making it empty. * `replace(item)`: replace the contents of this stack. * `item` can also be an itemstring or table. @@ -7096,6 +7100,12 @@ Used by `minetest.register_node`, `minetest.register_craftitem`, and { description = "Steel Axe", + -- Can contain new lines. "\n" has to be used as new line character. + -- Defaults to the item's name. + + short_description = "Steel Axe", + -- Must not contain new lines. + -- Defaults to the first line of description. groups = {}, -- key = name, value = rating; rating = 1..3. diff --git a/games/devtest/mods/unittests/init.lua b/games/devtest/mods/unittests/init.lua index 6c1728420..12c67f78b 100644 --- a/games/devtest/mods/unittests/init.lua +++ b/games/devtest/mods/unittests/init.lua @@ -5,10 +5,12 @@ dofile(modpath .. "/random.lua") dofile(modpath .. "/player.lua") dofile(modpath .. "/crafting_prepare.lua") dofile(modpath .. "/crafting.lua") +dofile(modpath .. "/itemdescription.lua") if minetest.settings:get_bool("devtest_unittests_autostart", false) then unittests.test_random() unittests.test_crafting() + unittests.test_short_desc() minetest.register_on_joinplayer(function(player) unittests.test_player(player) end) diff --git a/games/devtest/mods/unittests/itemdescription.lua b/games/devtest/mods/unittests/itemdescription.lua new file mode 100644 index 000000000..1d0826545 --- /dev/null +++ b/games/devtest/mods/unittests/itemdescription.lua @@ -0,0 +1,44 @@ +local full_description = "Colorful Pickaxe\nThe best pick." +minetest.register_tool("unittests:colorful_pick", { + description = full_description, + inventory_image = "basetools_mesepick.png", + tool_capabilities = { + full_punch_interval = 1.0, + max_drop_level=3, + groupcaps={ + cracky={times={[1]=2.0, [2]=1.0, [3]=0.5}, uses=20, maxlevel=3}, + crumbly={times={[1]=2.0, [2]=1.0, [3]=0.5}, uses=20, maxlevel=3}, + snappy={times={[1]=2.0, [2]=1.0, [3]=0.5}, uses=20, maxlevel=3} + }, + damage_groups = {fleshy=4}, + }, +}) + +minetest.register_chatcommand("item_description", { + param = "", + description = "Show the short and full description of the wielded item.", + func = function(name) + local player = minetest.get_player_by_name(name) + local item = player:get_wielded_item() + return true, string.format("short_description: %s\ndescription: %s", + item:get_short_description(), item:get_description()) + end +}) + +function unittests.test_short_desc() + local stack = ItemStack("unittests:colorful_pick") + assert(stack:get_short_description() == "Colorful Pickaxe") + assert(stack:get_short_description() == minetest.registered_items["unittests:colorful_pick"].short_description) + assert(stack:get_description() == full_description) + assert(stack:get_description() == minetest.registered_items["unittests:colorful_pick"].description) + + stack:get_meta():set_string("description", "Hello World") + assert(stack:get_short_description() == "Colorful Pickaxe") + assert(stack:get_description() == "Hello World") + + stack:get_meta():set_string("short_description", "Foo Bar") + assert(stack:get_short_description() == "Foo Bar") + assert(stack:get_description() == "Hello World") + + return true +end diff --git a/src/inventory.cpp b/src/inventory.cpp index cf72cb005..1ef9b13cd 100644 --- a/src/inventory.cpp +++ b/src/inventory.cpp @@ -258,6 +258,20 @@ std::string ItemStack::getDescription(IItemDefManager *itemdef) const return desc.empty() ? name : desc; } +std::string ItemStack::getShortDescription(IItemDefManager *itemdef) const +{ + std::string desc = metadata.getString("short_description"); + if (desc.empty()) + desc = getDefinition(itemdef).short_description; + if (!desc.empty()) + return desc; + // no short_description because of old server version or modified builtin + // return first line of description + std::stringstream sstr(getDescription(itemdef)); + std::getline(sstr, desc, '\n'); + return desc; +} + ItemStack ItemStack::addItem(ItemStack newitem, IItemDefManager *itemdef) { diff --git a/src/inventory.h b/src/inventory.h index 67a7859ed..f36bc57cf 100644 --- a/src/inventory.h +++ b/src/inventory.h @@ -49,6 +49,7 @@ struct ItemStack std::string getItemString(bool include_meta = true) const; // Returns the tooltip std::string getDescription(IItemDefManager *itemdef) const; + std::string getShortDescription(IItemDefManager *itemdef) const; /* Quantity methods diff --git a/src/itemdef.cpp b/src/itemdef.cpp index df20bdf15..5fb1e4c47 100644 --- a/src/itemdef.cpp +++ b/src/itemdef.cpp @@ -62,6 +62,7 @@ ItemDefinition& ItemDefinition::operator=(const ItemDefinition &def) type = def.type; name = def.name; description = def.description; + short_description = def.short_description; inventory_image = def.inventory_image; inventory_overlay = def.inventory_overlay; wield_image = def.wield_image; @@ -102,6 +103,7 @@ void ItemDefinition::reset() type = ITEM_NONE; name = ""; description = ""; + short_description = ""; inventory_image = ""; inventory_overlay = ""; wield_image = ""; @@ -162,6 +164,8 @@ void ItemDefinition::serialize(std::ostream &os, u16 protocol_version) const writeARGB8(os, color); os << serializeString16(inventory_overlay); os << serializeString16(wield_overlay); + + os << serializeString16(short_description); } void ItemDefinition::deSerialize(std::istream &is) @@ -213,8 +217,9 @@ void ItemDefinition::deSerialize(std::istream &is) // If you add anything here, insert it primarily inside the try-catch // block to not need to increase the version. - //try { - //} catch(SerializationError &e) {}; + try { + short_description = deSerializeString16(is); + } catch(SerializationError &e) {}; } diff --git a/src/itemdef.h b/src/itemdef.h index f47e6cbe7..ebf0d3527 100644 --- a/src/itemdef.h +++ b/src/itemdef.h @@ -56,6 +56,7 @@ struct ItemDefinition ItemType type; std::string name; // "" = hand std::string description; // Shown in tooltip. + std::string short_description; /* Visual properties diff --git a/src/script/common/c_content.cpp b/src/script/common/c_content.cpp index 774b6a326..147f6e3ed 100644 --- a/src/script/common/c_content.cpp +++ b/src/script/common/c_content.cpp @@ -56,6 +56,7 @@ void read_item_definition(lua_State* L, int index, es_ItemType, ITEM_NONE); getstringfield(L, index, "name", def.name); getstringfield(L, index, "description", def.description); + getstringfield(L, index, "short_description", def.short_description); getstringfield(L, index, "inventory_image", def.inventory_image); getstringfield(L, index, "inventory_overlay", def.inventory_overlay); getstringfield(L, index, "wield_image", def.wield_image); @@ -142,6 +143,8 @@ void push_item_definition_full(lua_State *L, const ItemDefinition &i) lua_setfield(L, -2, "name"); lua_pushstring(L, i.description.c_str()); lua_setfield(L, -2, "description"); + lua_pushstring(L, i.short_description.c_str()); + lua_setfield(L, -2, "short_description"); lua_pushstring(L, type.c_str()); lua_setfield(L, -2, "type"); lua_pushstring(L, i.inventory_image.c_str()); diff --git a/src/script/lua_api/l_item.cpp b/src/script/lua_api/l_item.cpp index d67cab76f..2d1124a4d 100644 --- a/src/script/lua_api/l_item.cpp +++ b/src/script/lua_api/l_item.cpp @@ -193,6 +193,16 @@ int LuaItemStack::l_get_description(lua_State *L) return 1; } +// get_short_description(self) +int LuaItemStack::l_get_short_description(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + LuaItemStack *o = checkobject(L, 1); + std::string desc = o->m_stack.getShortDescription(getGameDef(L)->idef()); + lua_pushstring(L, desc.c_str()); + return 1; +} + // clear(self) -> true int LuaItemStack::l_clear(lua_State *L) { @@ -493,6 +503,7 @@ const luaL_Reg LuaItemStack::methods[] = { luamethod(LuaItemStack, get_metadata), luamethod(LuaItemStack, set_metadata), luamethod(LuaItemStack, get_description), + luamethod(LuaItemStack, get_short_description), luamethod(LuaItemStack, clear), luamethod(LuaItemStack, replace), luamethod(LuaItemStack, to_string), diff --git a/src/script/lua_api/l_item.h b/src/script/lua_api/l_item.h index 98744c071..16878c101 100644 --- a/src/script/lua_api/l_item.h +++ b/src/script/lua_api/l_item.h @@ -72,6 +72,9 @@ private: // get_description(self) static int l_get_description(lua_State *L); + // get_short_description(self) + static int l_get_short_description(lua_State *L); + // clear(self) -> true static int l_clear(lua_State *L); -- cgit v1.2.3 From 272b72361acc70dbc047a90a98dbf7d2e9bfd323 Mon Sep 17 00:00:00 2001 From: Zughy <63455151+Zughy@users.noreply.github.com> Date: Sun, 11 Oct 2020 13:36:13 +0200 Subject: Add missing type check to InvRef:set_lists() (#10476) --- src/script/lua_api/l_inventory.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/script/lua_api/l_inventory.cpp b/src/script/lua_api/l_inventory.cpp index e41b5cb41..434d0a76c 100644 --- a/src/script/lua_api/l_inventory.cpp +++ b/src/script/lua_api/l_inventory.cpp @@ -280,6 +280,7 @@ int InvRef::l_set_lists(lua_State *L) Server *server = getServer(L); lua_pushnil(L); + luaL_checktype(L, 2, LUA_TTABLE); while (lua_next(L, 2)) { const char *listname = lua_tostring(L, -2); read_inventory_list(L, -1, tempInv, listname, server); -- cgit v1.2.3 From 11f3deb9c4512b918de8f5e778bc8b9535bd62c7 Mon Sep 17 00:00:00 2001 From: JosiahWI <41302989+JosiahWI@users.noreply.github.com> Date: Tue, 13 Oct 2020 10:36:01 -0500 Subject: Pass ContentFeatures as reference to read_content_features (#10464) --- src/script/common/c_content.cpp | 5 +---- src/script/common/c_content.h | 3 ++- src/script/lua_api/l_item.cpp | 3 ++- 3 files changed, 5 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/script/common/c_content.cpp b/src/script/common/c_content.cpp index 147f6e3ed..a95cf94a1 100644 --- a/src/script/common/c_content.cpp +++ b/src/script/common/c_content.cpp @@ -491,13 +491,11 @@ TileDef read_tiledef(lua_State *L, int index, u8 drawtype) } /******************************************************************************/ -ContentFeatures read_content_features(lua_State *L, int index) +void read_content_features(lua_State *L, ContentFeatures &f, int index) { if(index < 0) index = lua_gettop(L) + 1 + index; - ContentFeatures f; - /* Cache existence of some callbacks */ lua_getfield(L, index, "on_construct"); if(!lua_isnil(L, -1)) f.has_on_construct = true; @@ -800,7 +798,6 @@ ContentFeatures read_content_features(lua_State *L, int index) getstringfield(L, index, "node_dig_prediction", f.node_dig_prediction); - return f; } void push_content_features(lua_State *L, const ContentFeatures &c) diff --git a/src/script/common/c_content.h b/src/script/common/c_content.h index 8f32e58eb..29d576355 100644 --- a/src/script/common/c_content.h +++ b/src/script/common/c_content.h @@ -67,7 +67,8 @@ struct collisionMoveResult; extern struct EnumString es_TileAnimationType[]; -ContentFeatures read_content_features (lua_State *L, int index); +void read_content_features (lua_State *L, ContentFeatures &f, + int index); void push_content_features (lua_State *L, const ContentFeatures &c); diff --git a/src/script/lua_api/l_item.cpp b/src/script/lua_api/l_item.cpp index 2d1124a4d..9e0da4034 100644 --- a/src/script/lua_api/l_item.cpp +++ b/src/script/lua_api/l_item.cpp @@ -570,7 +570,8 @@ int ModApiItemMod::l_register_item_raw(lua_State *L) // Read the node definition (content features) and register it if (def.type == ITEM_NODE) { - ContentFeatures f = read_content_features(L, table); + ContentFeatures f; + read_content_features(L, f, table); // when a mod reregisters ignore, only texture changes and such should // be done if (f.name == "ignore") -- cgit v1.2.3 From 521a04222a71325ef217d1214febf5591919e169 Mon Sep 17 00:00:00 2001 From: Lars Date: Mon, 12 Oct 2020 19:47:04 -0700 Subject: Avoid drawing invisible blocks on the client. --- src/client/clientmap.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'src') diff --git a/src/client/clientmap.cpp b/src/client/clientmap.cpp index 3124313e7..d372a8e46 100644 --- a/src/client/clientmap.cpp +++ b/src/client/clientmap.cpp @@ -124,12 +124,6 @@ void ClientMap::updateDrawList() v3f camera_position = m_camera_position; v3f camera_direction = m_camera_direction; - f32 camera_fov = m_camera_fov; - - // Use a higher fov to accomodate faster camera movements. - // Blocks are cropped better when they are drawn. - // Or maybe they aren't? Well whatever. - camera_fov *= 1.2; v3s16 cam_pos_nodes = floatToInt(camera_position, BS); v3s16 p_blocks_min; @@ -190,7 +184,7 @@ void ClientMap::updateDrawList() float d = 0.0; if (!isBlockInSight(block->getPos(), camera_position, - camera_direction, camera_fov, range, &d)) + camera_direction, m_camera_fov, range, &d)) continue; -- cgit v1.2.3 From 2341a4aff1242e978d6fad3772d4d4fb015c040d Mon Sep 17 00:00:00 2001 From: Zughy <63455151+Zughy@users.noreply.github.com> Date: Tue, 13 Oct 2020 21:27:52 +0200 Subject: Add ObjectRef:get_children() (#10480) Co-authored-by: Zughy <4279489-marco_a@users.noreply.gitlab.com> --- doc/lua_api.txt | 2 ++ src/script/lua_api/l_object.cpp | 22 ++++++++++++++++++++++ src/script/lua_api/l_object.h | 3 +++ 3 files changed, 27 insertions(+) (limited to 'src') diff --git a/doc/lua_api.txt b/doc/lua_api.txt index c8b294149..1631d564c 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -6206,6 +6206,8 @@ object you are working with still exists. should appear in first person. * `get_attach()`: returns parent, bone, position, rotation, forced_visible, or nil if it isn't attached. +* `get_children()`: returns a list of ObjectRefs that are attached to the + object. * `set_detach()` * `set_bone_position(bone, position, rotation)` * `bone`: string diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index 57ed7e2cd..96c8c687c 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -738,6 +738,27 @@ int ObjectRef::l_get_attach(lua_State *L) return 5; } +// get_children(self) +int ObjectRef::l_get_children(lua_State *L) +{ + GET_ENV_PTR; + + ObjectRef *ref = checkobject(L, 1); + ServerActiveObject *sao = getobject(ref); + if (sao == nullptr) + return 0; + + const std::unordered_set child_ids = sao->getAttachmentChildIds(); + int i = 0; + lua_createtable(L, child_ids.size(), 0); + for (const int id : child_ids) { + ServerActiveObject *child = env->getActiveObject(id); + getScriptApiBase(L)->objectrefGetOrCreate(L, child); + lua_rawseti(L, -2, ++i); + } + return 1; +} + // set_detach(self) int ObjectRef::l_set_detach(lua_State *L) { @@ -2337,6 +2358,7 @@ luaL_Reg ObjectRef::methods[] = { luamethod(ObjectRef, get_bone_position), luamethod(ObjectRef, set_attach), luamethod(ObjectRef, get_attach), + luamethod(ObjectRef, get_children), luamethod(ObjectRef, set_detach), luamethod(ObjectRef, set_properties), luamethod(ObjectRef, get_properties), diff --git a/src/script/lua_api/l_object.h b/src/script/lua_api/l_object.h index ca03dfa2e..097a74cae 100644 --- a/src/script/lua_api/l_object.h +++ b/src/script/lua_api/l_object.h @@ -143,6 +143,9 @@ private: // get_attach(self) static int l_get_attach(lua_State *L); + // get_children(self) + static int l_get_children(lua_State *L); + // set_detach(self) static int l_set_detach(lua_State *L); -- cgit v1.2.3 From 7499ebe46af072e911fa4902faf0a7343559d2c3 Mon Sep 17 00:00:00 2001 From: Zughy <63455151+Zughy@users.noreply.github.com> Date: Tue, 13 Oct 2020 21:28:53 +0200 Subject: Fix float argument check in minetest.set_timeofday() (#10483) Co-authored-by: Zughy <4279489-marco_a@users.noreply.gitlab.com> --- src/script/lua_api/l_env.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/script/lua_api/l_env.cpp b/src/script/lua_api/l_env.cpp index 8d50d664d..021ef2ea7 100644 --- a/src/script/lua_api/l_env.cpp +++ b/src/script/lua_api/l_env.cpp @@ -751,8 +751,9 @@ int ModApiEnvMod::l_set_timeofday(lua_State *L) // Do it float timeofday_f = readParam(L, 1); - sanity_check(timeofday_f >= 0.0 && timeofday_f <= 1.0); - int timeofday_mh = (int)(timeofday_f * 24000.0); + luaL_argcheck(L, timeofday_f >= 0.0f && timeofday_f <= 1.0f, 1, + "value must be between 0 and 1"); + int timeofday_mh = (int)(timeofday_f * 24000.0f); // This should be set directly in the environment but currently // such changes aren't immediately sent to the clients, so call // the server instead. -- cgit v1.2.3 From f43d1cfa81aa496174af6cdfa648dab9dd17288c Mon Sep 17 00:00:00 2001 From: Lars Date: Tue, 13 Oct 2020 12:38:34 -0700 Subject: Rely on max_simultaneous_block_sends_per_client to limit blocks sent to the client. --- src/clientiface.cpp | 18 +----------------- src/clientiface.h | 1 - 2 files changed, 1 insertion(+), 18 deletions(-) (limited to 'src') diff --git a/src/clientiface.cpp b/src/clientiface.cpp index 28a0ee770..a01cba7e0 100644 --- a/src/clientiface.cpp +++ b/src/clientiface.cpp @@ -99,7 +99,6 @@ void RemoteClient::GetNextBlocks ( { // Increment timers m_nothing_to_send_pause_timer -= dtime; - m_nearest_unsent_reset_timer += dtime; if (m_nothing_to_send_pause_timer >= 0) return; @@ -154,14 +153,6 @@ void RemoteClient::GetNextBlocks ( /*infostream<<"m_nearest_unsent_reset_timer=" < 20.0f) { - m_nearest_unsent_reset_timer = 0.0f; - m_nearest_unsent_d = 0; - //infostream<<"Resetting m_nearest_unsent_d for " - // <getPlayerName(peer_id)< d_start + max_d_increment_at_time) - d_max = d_start + max_d_increment_at_time; - // cos(angle between velocity and camera) * |velocity| // Limit to 0.0f in case player moves backwards. f32 dot = rangelim(camera_dir.dotProduct(playerspeed), 0.0f, 300.0f); @@ -238,7 +222,7 @@ void RemoteClient::GetNextBlocks ( const v3s16 cam_pos_nodes = floatToInt(camera_pos, BS); s16 d; - for (d = d_start; d <= d_max; d++) { + for (d = d_start; d <= full_d_max; d++) { /* Get the border/face dot coordinates of a "d-radiused" box diff --git a/src/clientiface.h b/src/clientiface.h index 83fa6fe99..ca2af65fe 100644 --- a/src/clientiface.h +++ b/src/clientiface.h @@ -364,7 +364,6 @@ private: std::set m_blocks_sent; s16 m_nearest_unsent_d = 0; v3s16 m_last_center; - float m_nearest_unsent_reset_timer = 0.0f; const u16 m_max_simul_sends; const float m_min_time_from_building; -- cgit v1.2.3 From ed22260822086f84016aa8384c3174bfc6d1739d Mon Sep 17 00:00:00 2001 From: Lars Date: Mon, 12 Oct 2020 13:29:31 -0700 Subject: Remove all bump mapping and parallax occlusion related code. --- builtin/mainmenu/tab_settings.lua | 30 ++----- builtin/settingtypes.txt | 25 ------ client/shaders/nodes_shader/opengl_fragment.glsl | 99 ----------------------- client/shaders/nodes_shader/opengl_vertex.glsl | 45 +---------- client/shaders/object_shader/opengl_fragment.glsl | 54 ------------- client/shaders/object_shader/opengl_vertex.glsl | 5 -- doc/lua_api.txt | 40 +-------- src/client/game.cpp | 10 +-- src/client/mapblock_mesh.cpp | 41 ++-------- src/client/mapblock_mesh.h | 5 +- src/client/mesh_generator_thread.cpp | 6 +- src/client/mesh_generator_thread.h | 1 - src/client/shader.cpp | 29 ------- src/client/wieldmesh.cpp | 2 +- src/defaultsettings.cpp | 6 -- src/nodedef.cpp | 9 --- src/nodedef.h | 1 - 17 files changed, 24 insertions(+), 384 deletions(-) (limited to 'src') diff --git a/builtin/mainmenu/tab_settings.lua b/builtin/mainmenu/tab_settings.lua index 510346f8d..8a7445394 100644 --- a/builtin/mainmenu/tab_settings.lua +++ b/builtin/mainmenu/tab_settings.lua @@ -187,31 +187,23 @@ local function formspec(tabview, name, tabdata) if shaders_enabled then tab_string = tab_string .. - "checkbox[8.25,0.5;cb_bumpmapping;" .. fgettext("Bump Mapping") .. ";" - .. dump(core.settings:get_bool("enable_bumpmapping")) .. "]" .. - "checkbox[8.25,1;cb_tonemapping;" .. fgettext("Tone Mapping") .. ";" + "checkbox[8.25,0.5;cb_tonemapping;" .. fgettext("Tone Mapping") .. ";" .. dump(core.settings:get_bool("tone_mapping")) .. "]" .. - "checkbox[8.25,1.5;cb_parallax;" .. fgettext("Parallax Occlusion") .. ";" - .. dump(core.settings:get_bool("enable_parallax_occlusion")) .. "]" .. - "checkbox[8.25,2;cb_waving_water;" .. fgettext("Waving Liquids") .. ";" + "checkbox[8.25,1;cb_waving_water;" .. fgettext("Waving Liquids") .. ";" .. dump(core.settings:get_bool("enable_waving_water")) .. "]" .. - "checkbox[8.25,2.5;cb_waving_leaves;" .. fgettext("Waving Leaves") .. ";" + "checkbox[8.25,1.5;cb_waving_leaves;" .. fgettext("Waving Leaves") .. ";" .. dump(core.settings:get_bool("enable_waving_leaves")) .. "]" .. - "checkbox[8.25,3;cb_waving_plants;" .. fgettext("Waving Plants") .. ";" + "checkbox[8.25,2;cb_waving_plants;" .. fgettext("Waving Plants") .. ";" .. dump(core.settings:get_bool("enable_waving_plants")) .. "]" else tab_string = tab_string .. "label[8.38,0.7;" .. core.colorize("#888888", - fgettext("Bump Mapping")) .. "]" .. - "label[8.38,1.2;" .. core.colorize("#888888", fgettext("Tone Mapping")) .. "]" .. - "label[8.38,1.7;" .. core.colorize("#888888", - fgettext("Parallax Occlusion")) .. "]" .. - "label[8.38,2.2;" .. core.colorize("#888888", + "label[8.38,1.2;" .. core.colorize("#888888", fgettext("Waving Liquids")) .. "]" .. - "label[8.38,2.7;" .. core.colorize("#888888", + "label[8.38,1.7;" .. core.colorize("#888888", fgettext("Waving Leaves")) .. "]" .. - "label[8.38,3.2;" .. core.colorize("#888888", + "label[8.38,2.2;" .. core.colorize("#888888", fgettext("Waving Plants")) .. "]" end @@ -263,18 +255,10 @@ local function handle_settings_buttons(this, fields, tabname, tabdata) end return true end - if fields["cb_bumpmapping"] then - core.settings:set("enable_bumpmapping", fields["cb_bumpmapping"]) - return true - end if fields["cb_tonemapping"] then core.settings:set("tone_mapping", fields["cb_tonemapping"]) return true end - if fields["cb_parallax"] then - core.settings:set("enable_parallax_occlusion", fields["cb_parallax"]) - return true - end if fields["cb_waving_water"] then core.settings:set("enable_waving_water", fields["cb_waving_water"]) return true diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index 1c28470d5..27f375693 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -546,31 +546,6 @@ shader_path (Shader path) path # enhanced, highlights and shadows are gradually compressed. tone_mapping (Filmic tone mapping) bool false -[***Bumpmapping] - -# Enables bumpmapping for textures. Normalmaps need to be supplied by the texture pack. -# Requires shaders to be enabled. -enable_bumpmapping (Bumpmapping) bool false - -[***Parallax Occlusion] - -# Enables parallax occlusion mapping. -# Requires shaders to be enabled. -enable_parallax_occlusion (Parallax occlusion) bool false - -# 0 = parallax occlusion with slope information (faster). -# 1 = relief mapping (slower, more accurate). -parallax_occlusion_mode (Parallax occlusion mode) int 1 0 1 - -# Number of parallax occlusion iterations. -parallax_occlusion_iterations (Parallax occlusion iterations) int 4 - -# Overall scale of parallax occlusion effect. -parallax_occlusion_scale (Parallax occlusion scale) float 0.08 - -# Overall bias of parallax occlusion effect, usually scale/2. -parallax_occlusion_bias (Parallax occlusion bias) float 0.04 - [***Waving Nodes] # Set to true to enable waving liquids (like water). diff --git a/client/shaders/nodes_shader/opengl_fragment.glsl b/client/shaders/nodes_shader/opengl_fragment.glsl index 437b325d3..36d47d1f5 100644 --- a/client/shaders/nodes_shader/opengl_fragment.glsl +++ b/client/shaders/nodes_shader/opengl_fragment.glsl @@ -1,6 +1,4 @@ uniform sampler2D baseTexture; -uniform sampler2D normalTexture; -uniform sampler2D textureFlags; uniform vec4 skyBgColor; uniform float fogDistance; @@ -17,17 +15,9 @@ varying vec3 vPosition; // cameraOffset + worldPosition (for large coordinates the limits of float // precision must be considered). varying vec3 worldPosition; -varying float area_enable_parallax; varying vec3 eyeVec; -varying vec3 tsEyeVec; -varying vec3 lightVec; -varying vec3 tsLightVec; -bool normalTexturePresent = false; - -const float e = 2.718281828459; -const float BS = 10.0; const float fogStart = FOG_START; const float fogShadingParameter = 1 / ( 1 - fogStart); @@ -63,87 +53,10 @@ vec4 applyToneMapping(vec4 color) } #endif -void get_texture_flags() -{ - vec4 flags = texture2D(textureFlags, vec2(0.0, 0.0)); - if (flags.r > 0.5) { - normalTexturePresent = true; - } -} - -vec4 get_normal_map(vec2 uv) -{ - vec4 bump = texture2D(normalTexture, uv).rgba; - bump.xyz = normalize(bump.xyz * 2.0 - 1.0); - return bump; -} - -float find_intersection(vec2 dp, vec2 ds) -{ - float depth = 1.0; - float best_depth = 0.0; - float size = 0.0625; - for (int i = 0; i < 15; i++) { - depth -= size; - float h = texture2D(normalTexture, dp + ds * depth).a; - if (depth <= h) { - best_depth = depth; - break; - } - } - depth = best_depth; - for (int i = 0; i < 4; i++) { - size *= 0.5; - float h = texture2D(normalTexture,dp + ds * depth).a; - if (depth <= h) { - best_depth = depth; - depth += size; - } else { - depth -= size; - } - } - return best_depth; -} - void main(void) { vec3 color; - vec4 bump; vec2 uv = gl_TexCoord[0].st; - bool use_normalmap = false; - get_texture_flags(); - -#ifdef ENABLE_PARALLAX_OCCLUSION - vec2 eyeRay = vec2 (tsEyeVec.x, -tsEyeVec.y); - const float scale = PARALLAX_OCCLUSION_SCALE / PARALLAX_OCCLUSION_ITERATIONS; - const float bias = PARALLAX_OCCLUSION_BIAS / PARALLAX_OCCLUSION_ITERATIONS; - -#if PARALLAX_OCCLUSION_MODE == 0 - // Parallax occlusion with slope information - if (normalTexturePresent && area_enable_parallax > 0.0) { - for (int i = 0; i < PARALLAX_OCCLUSION_ITERATIONS; i++) { - vec4 normal = texture2D(normalTexture, uv.xy); - float h = normal.a * scale - bias; - uv += h * normal.z * eyeRay; - } - } -#endif -#if PARALLAX_OCCLUSION_MODE == 1 - // Relief mapping - if (normalTexturePresent && area_enable_parallax > 0.0) { - vec2 ds = eyeRay * PARALLAX_OCCLUSION_SCALE; - float dist = find_intersection(uv, ds); - uv += dist * ds; - } -#endif -#endif - -#if USE_NORMALMAPS == 1 - if (normalTexturePresent) { - bump = get_normal_map(uv); - use_normalmap = true; - } -#endif vec4 base = texture2D(baseTexture, uv).rgba; @@ -155,19 +68,7 @@ void main(void) } #endif -#ifdef ENABLE_BUMPMAPPING - if (use_normalmap) { - vec3 L = normalize(lightVec); - vec3 E = normalize(eyeVec); - float specular = pow(clamp(dot(reflect(L, bump.xyz), E), 0.0, 1.0), 1.0); - float diffuse = dot(-E,bump.xyz); - color = (diffuse + 0.1 * specular) * base.rgb; - } else { - color = base.rgb; - } -#else color = base.rgb; -#endif vec4 col = vec4(color.rgb * gl_Color.rgb, 1.0); diff --git a/client/shaders/nodes_shader/opengl_vertex.glsl b/client/shaders/nodes_shader/opengl_vertex.glsl index 0d8d0a2a5..56bff09a8 100644 --- a/client/shaders/nodes_shader/opengl_vertex.glsl +++ b/client/shaders/nodes_shader/opengl_vertex.glsl @@ -18,10 +18,6 @@ varying vec3 vPosition; varying vec3 worldPosition; varying vec3 eyeVec; -varying vec3 lightVec; -varying vec3 tsEyeVec; -varying vec3 tsLightVec; -varying float area_enable_parallax; // Color of the light emitted by the light sources. const vec3 artificialLight = vec3(1.04, 1.04, 1.04); @@ -86,21 +82,9 @@ float snoise(vec3 p) void main(void) { gl_TexCoord[0] = gl_MultiTexCoord0; - //TODO: make offset depending on view angle and parallax uv displacement - //thats for textures that doesnt align vertically, like dirt with grass - //gl_TexCoord[0].y += 0.008; - - //Allow parallax/relief mapping only for certain kind of nodes - //Variable is also used to control area of the effect -#if (DRAW_TYPE == NDT_NORMAL || DRAW_TYPE == NDT_LIQUID || DRAW_TYPE == NDT_FLOWINGLIQUID) - area_enable_parallax = 1.0; -#else - area_enable_parallax = 0.0; -#endif - -float disp_x; -float disp_z; + float disp_x; + float disp_z; // OpenGL < 4.3 does not support continued preprocessor lines #if (MATERIAL_TYPE == TILE_MATERIAL_WAVING_LEAVES && ENABLE_WAVING_LEAVES) || (MATERIAL_TYPE == TILE_MATERIAL_WAVING_PLANTS && ENABLE_WAVING_PLANTS) vec4 pos2 = mWorld * gl_Vertex; @@ -148,32 +132,7 @@ float disp_z; vPosition = gl_Position.xyz; - // Don't generate heightmaps when too far from the eye - float dist = distance (vec3(0.0, 0.0, 0.0), vPosition); - if (dist > 150.0) { - area_enable_parallax = 0.0; - } - - vec3 sunPosition = vec3 (0.0, eyePosition.y * BS + 900.0, 0.0); - - vec3 normal, tangent, binormal; - normal = normalize(gl_NormalMatrix * gl_Normal); - tangent = normalize(gl_NormalMatrix * gl_MultiTexCoord1.xyz); - binormal = normalize(gl_NormalMatrix * gl_MultiTexCoord2.xyz); - - vec3 v; - - lightVec = sunPosition - worldPosition; - v.x = dot(lightVec, tangent); - v.y = dot(lightVec, binormal); - v.z = dot(lightVec, normal); - tsLightVec = normalize (v); - eyeVec = -(gl_ModelViewMatrix * gl_Vertex).xyz; - v.x = dot(eyeVec, tangent); - v.y = dot(eyeVec, binormal); - v.z = dot(eyeVec, normal); - tsEyeVec = normalize (v); // Calculate color. // Red, green and blue components are pre-multiplied with diff --git a/client/shaders/object_shader/opengl_fragment.glsl b/client/shaders/object_shader/opengl_fragment.glsl index a8a43e1e2..86d5c1c92 100644 --- a/client/shaders/object_shader/opengl_fragment.glsl +++ b/client/shaders/object_shader/opengl_fragment.glsl @@ -1,6 +1,4 @@ uniform sampler2D baseTexture; -uniform sampler2D normalTexture; -uniform sampler2D textureFlags; uniform vec4 emissiveColor; uniform vec4 skyBgColor; @@ -12,14 +10,8 @@ varying vec3 vPosition; varying vec3 worldPosition; varying vec3 eyeVec; -varying vec3 lightVec; varying float vIDiff; -bool normalTexturePresent = false; -bool texTileableHorizontal = false; -bool texTileableVertical = false; -bool texSeamless = false; - const float e = 2.718281828459; const float BS = 10.0; const float fogStart = FOG_START; @@ -57,44 +49,10 @@ vec4 applyToneMapping(vec4 color) } #endif -void get_texture_flags() -{ - vec4 flags = texture2D(textureFlags, vec2(0.0, 0.0)); - if (flags.r > 0.5) { - normalTexturePresent = true; - } - if (flags.g > 0.5) { - texTileableHorizontal = true; - } - if (flags.b > 0.5) { - texTileableVertical = true; - } - if (texTileableHorizontal && texTileableVertical) { - texSeamless = true; - } -} - -vec4 get_normal_map(vec2 uv) -{ - vec4 bump = texture2D(normalTexture, uv).rgba; - bump.xyz = normalize(bump.xyz * 2.0 - 1.0); - return bump; -} - void main(void) { vec3 color; - vec4 bump; vec2 uv = gl_TexCoord[0].st; - bool use_normalmap = false; - get_texture_flags(); - -#if USE_NORMALMAPS == 1 - if (normalTexturePresent) { - bump = get_normal_map(uv); - use_normalmap = true; - } -#endif vec4 base = texture2D(baseTexture, uv).rgba; @@ -106,19 +64,7 @@ void main(void) } #endif -#ifdef ENABLE_BUMPMAPPING - if (use_normalmap) { - vec3 L = normalize(lightVec); - vec3 E = normalize(eyeVec); - float specular = pow(clamp(dot(reflect(L, bump.xyz), E), 0.0, 1.0), 1.0); - float diffuse = dot(-E,bump.xyz); - color = (diffuse + 0.1 * specular) * base.rgb; - } else { - color = base.rgb; - } -#else color = base.rgb; -#endif vec4 col = vec4(color.rgb, base.a); diff --git a/client/shaders/object_shader/opengl_vertex.glsl b/client/shaders/object_shader/opengl_vertex.glsl index 968a07e22..f8c1cd932 100644 --- a/client/shaders/object_shader/opengl_vertex.glsl +++ b/client/shaders/object_shader/opengl_vertex.glsl @@ -9,7 +9,6 @@ varying vec3 vPosition; varying vec3 worldPosition; varying vec3 eyeVec; -varying vec3 lightVec; varying float vIDiff; const float e = 2.718281828459; @@ -33,10 +32,6 @@ void main(void) vPosition = gl_Position.xyz; vNormal = gl_Normal; worldPosition = (mWorld * gl_Vertex).xyz; - - vec3 sunPosition = vec3 (0.0, eyePosition.y * BS + 900.0, 0.0); - - lightVec = sunPosition - worldPosition; eyeVec = -(gl_ModelViewMatrix * gl_Vertex).xyz; #if (MATERIAL_TYPE == TILE_MATERIAL_PLAIN) || (MATERIAL_TYPE == TILE_MATERIAL_PLAIN_ALPHA) diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 1631d564c..d3aaa309c 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -401,35 +401,6 @@ stripping out the file extension: * e.g. `foomod_foothing` -Normalmap Textures ------------------- - -If shaders and bumpmapping or parallax occlusion is enabled, Minetest tries -to load normalmaps. -Those image files have to end with `_normal.png` and start with the same name -as their corresponding texture. -For example a normalmap for `foomod_foothing.png` has to be called -`foomod_foothing_normal.png`. - -The sRGB R, G and B colour values of a normalmap pixel are each directly -mapped from `{0, ..., 255}` to `[-1, 1]` and, taken together, -define the normal vector. -The alpha channel defines the heightmap for parallax occlusion. -To be safe, the alpha values should always be bigger than zero -because the colour values, which define the normal vector, -may be undefined for image formats where colour is discarded in fully -transparent pixels. - -Bumpmapping and parallax occlusion are currently experimental features: - -* Bumpmapping in Minetest happens in an obscure way; there are no light sources - defined in the shaders except the sunlight direction. -* Parallax occlusion with relief-mapping mode does not yet work correctly - together with Minetest's Fastfaces. -* The normalmap files must end with `.png`, so other image files are not - supported. - - Texture modifiers ----------------- @@ -834,7 +805,7 @@ Example (colored grass block): -- Overlay tiles: define them in the same style -- The top and bottom tile does not have overlay overlay_tiles = {"", "", - {name = "default_grass_side.png", tileable_vertical = false}}, + {name = "default_grass_side.png"}}, -- Global color, used in inventory color = "green", -- Palette in the world @@ -1204,7 +1175,7 @@ Look for examples in `games/devtest` or `games/minetest_game`. base cube without affecting them. * The base cube texture tiles are defined as normal, the `plantlike` extension uses the defined special tile, for example: - `special_tiles = {{name = "default_papyrus.png", tileable_vertical = true}},` + `special_tiles = {{name = "default_papyrus.png"}},` `*_optional` drawtypes need less rendering time if deactivated (always client-side). @@ -7043,13 +7014,8 @@ Tile definition * `"image.png"` * `{name="image.png", animation={Tile Animation definition}}` -* `{name="image.png", backface_culling=bool, tileable_vertical=bool, - tileable_horizontal=bool, align_style="node"/"world"/"user", scale=int}` +* `{name="image.png", backface_culling=bool, align_style="node"/"world"/"user", scale=int}` * backface culling enabled by default for most nodes - * tileable flags are info for shaders, how they should treat texture - when displacement mapping is used. - Directions are from the point of view of the tile texture, - not the node it's on. * align style determines whether the texture will be rotated with the node or kept aligned with its surroundings. "user" means that client setting will be used, similar to `glasslike_framed_optional`. diff --git a/src/client/game.cpp b/src/client/game.cpp index 54e0c9f20..309a8e194 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -430,8 +430,6 @@ class GameGlobalShaderConstantSetter : public IShaderConstantSetter CachedPixelShaderSetting m_camera_offset_pixel; CachedPixelShaderSetting m_camera_offset_vertex; CachedPixelShaderSetting m_base_texture; - CachedPixelShaderSetting m_normal_texture; - CachedPixelShaderSetting m_texture_flags; Client *m_client; public: @@ -464,8 +462,6 @@ public: m_camera_offset_pixel("cameraOffset"), m_camera_offset_vertex("cameraOffset"), m_base_texture("baseTexture"), - m_normal_texture("normalTexture"), - m_texture_flags("textureFlags"), m_client(client) { g_settings->registerChangedCallback("enable_fog", settingsCallback, this); @@ -553,12 +549,8 @@ public: m_camera_offset_pixel.set(camera_offset_array, services); m_camera_offset_vertex.set(camera_offset_array, services); - SamplerLayer_t base_tex = 0, - normal_tex = 1, - flags_tex = 2; + SamplerLayer_t base_tex = 0; m_base_texture.set(&base_tex, services); - m_normal_texture.set(&normal_tex, services); - m_texture_flags.set(&flags_tex, services); } }; diff --git a/src/client/mapblock_mesh.cpp b/src/client/mapblock_mesh.cpp index c7790f1e4..6a59fabe3 100644 --- a/src/client/mapblock_mesh.cpp +++ b/src/client/mapblock_mesh.cpp @@ -35,11 +35,9 @@ with this program; if not, write to the Free Software Foundation, Inc., MeshMakeData */ -MeshMakeData::MeshMakeData(Client *client, bool use_shaders, - bool use_tangent_vertices): +MeshMakeData::MeshMakeData(Client *client, bool use_shaders): m_client(client), - m_use_shaders(use_shaders), - m_use_tangent_vertices(use_tangent_vertices) + m_use_shaders(use_shaders) {} void MeshMakeData::fillBlockDataBegin(const v3s16 &blockpos) @@ -1016,7 +1014,6 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset): for (auto &m : m_mesh) m = new scene::SMesh(); m_enable_shaders = data->m_use_shaders; - m_use_tangent_vertices = data->m_use_tangent_vertices; m_enable_vbo = g_settings->getBool("enable_vbo"); if (data->m_client->getMinimap()) { @@ -1170,28 +1167,12 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset): scene::SMesh *mesh = (scene::SMesh *)m_mesh[layer]; - // Create meshbuffer, add to mesh - if (m_use_tangent_vertices) { - scene::SMeshBufferTangents *buf = - new scene::SMeshBufferTangents(); - buf->Material = material; - buf->Vertices.reallocate(p.vertices.size()); - buf->Indices.reallocate(p.indices.size()); - for (const video::S3DVertex &v: p.vertices) - buf->Vertices.push_back(video::S3DVertexTangents(v.Pos, v.Color, v.TCoords)); - for (u16 i: p.indices) - buf->Indices.push_back(i); - buf->recalculateBoundingBox(); - mesh->addMeshBuffer(buf); - buf->drop(); - } else { - scene::SMeshBuffer *buf = new scene::SMeshBuffer(); - buf->Material = material; - buf->append(&p.vertices[0], p.vertices.size(), - &p.indices[0], p.indices.size()); - mesh->addMeshBuffer(buf); - buf->drop(); - } + scene::SMeshBuffer *buf = new scene::SMeshBuffer(); + buf->Material = material; + buf->append(&p.vertices[0], p.vertices.size(), + &p.indices[0], p.indices.size()); + mesh->addMeshBuffer(buf); + buf->drop(); } /* @@ -1201,12 +1182,6 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset): translateMesh(m_mesh[layer], intToFloat(data->m_blockpos * MAP_BLOCKSIZE - camera_offset, BS)); - if (m_use_tangent_vertices) { - scene::IMeshManipulator* meshmanip = - RenderingEngine::get_scene_manager()->getMeshManipulator(); - meshmanip->recalculateTangents(m_mesh[layer], true, false, false); - } - if (m_mesh[layer]) { #if 0 // Usually 1-700 faces and 1-7 materials diff --git a/src/client/mapblock_mesh.h b/src/client/mapblock_mesh.h index f8aed40dc..6a9c00ed5 100644 --- a/src/client/mapblock_mesh.h +++ b/src/client/mapblock_mesh.h @@ -45,10 +45,8 @@ struct MeshMakeData Client *m_client; bool m_use_shaders; - bool m_use_tangent_vertices; - MeshMakeData(Client *client, bool use_shaders, - bool use_tangent_vertices = false); + MeshMakeData(Client *client, bool use_shaders); /* Copy block data manually (to allow optimizations by the caller) @@ -136,7 +134,6 @@ private: IShaderSource *m_shdrsrc; bool m_enable_shaders; - bool m_use_tangent_vertices; bool m_enable_vbo; // Must animate() be called before rendering? diff --git a/src/client/mesh_generator_thread.cpp b/src/client/mesh_generator_thread.cpp index 53b980eeb..c8d1cba26 100644 --- a/src/client/mesh_generator_thread.cpp +++ b/src/client/mesh_generator_thread.cpp @@ -52,9 +52,6 @@ MeshUpdateQueue::MeshUpdateQueue(Client *client): m_client(client) { m_cache_enable_shaders = g_settings->getBool("enable_shaders"); - m_cache_use_tangent_vertices = m_cache_enable_shaders && ( - g_settings->getBool("enable_bumpmapping") || - g_settings->getBool("enable_parallax_occlusion")); m_cache_smooth_lighting = g_settings->getBool("smooth_lighting"); m_meshgen_block_cache_size = g_settings->getS32("meshgen_block_cache_size"); } @@ -207,8 +204,7 @@ CachedMapBlockData* MeshUpdateQueue::getCachedBlock(const v3s16 &p) void MeshUpdateQueue::fillDataFromMapBlockCache(QueuedMeshUpdate *q) { - MeshMakeData *data = new MeshMakeData(m_client, m_cache_enable_shaders, - m_cache_use_tangent_vertices); + MeshMakeData *data = new MeshMakeData(m_client, m_cache_enable_shaders); q->data = data; data->fillBlockDataBegin(q->p); diff --git a/src/client/mesh_generator_thread.h b/src/client/mesh_generator_thread.h index 9a42852a3..f3c5e7da8 100644 --- a/src/client/mesh_generator_thread.h +++ b/src/client/mesh_generator_thread.h @@ -88,7 +88,6 @@ private: // TODO: Add callback to update these when g_settings changes bool m_cache_enable_shaders; - bool m_cache_use_tangent_vertices; bool m_cache_smooth_lighting; int m_meshgen_block_cache_size; diff --git a/src/client/shader.cpp b/src/client/shader.cpp index c5fe5dfe0..e2eeb4ab0 100644 --- a/src/client/shader.cpp +++ b/src/client/shader.cpp @@ -688,35 +688,6 @@ ShaderInfo generate_shader(const std::string &name, u8 material_type, u8 drawtyp shaders_header += itos(drawtype); shaders_header += "\n"; - if (g_settings->getBool("enable_bumpmapping")) - shaders_header += "#define ENABLE_BUMPMAPPING\n"; - - if (g_settings->getBool("enable_parallax_occlusion")){ - int mode = g_settings->getFloat("parallax_occlusion_mode"); - float scale = g_settings->getFloat("parallax_occlusion_scale"); - float bias = g_settings->getFloat("parallax_occlusion_bias"); - int iterations = g_settings->getFloat("parallax_occlusion_iterations"); - shaders_header += "#define ENABLE_PARALLAX_OCCLUSION\n"; - shaders_header += "#define PARALLAX_OCCLUSION_MODE "; - shaders_header += itos(mode); - shaders_header += "\n"; - shaders_header += "#define PARALLAX_OCCLUSION_SCALE "; - shaders_header += ftos(scale); - shaders_header += "\n"; - shaders_header += "#define PARALLAX_OCCLUSION_BIAS "; - shaders_header += ftos(bias); - shaders_header += "\n"; - shaders_header += "#define PARALLAX_OCCLUSION_ITERATIONS "; - shaders_header += itos(iterations); - shaders_header += "\n"; - } - - shaders_header += "#define USE_NORMALMAPS "; - if (g_settings->getBool("enable_bumpmapping") || g_settings->getBool("enable_parallax_occlusion")) - shaders_header += "1\n"; - else - shaders_header += "0\n"; - if (g_settings->getBool("enable_waving_water")){ shaders_header += "#define ENABLE_WAVING_WATER 1\n"; shaders_header += "#define WATER_WAVE_HEIGHT "; diff --git a/src/client/wieldmesh.cpp b/src/client/wieldmesh.cpp index 285cc38e5..ad583210a 100644 --- a/src/client/wieldmesh.cpp +++ b/src/client/wieldmesh.cpp @@ -305,7 +305,7 @@ void WieldMeshSceneNode::setExtruded(const std::string &imagename, scene::SMesh *createSpecialNodeMesh(Client *client, content_t id, std::vector *colors, const ContentFeatures &f) { - MeshMakeData mesh_make_data(client, false, false); + MeshMakeData mesh_make_data(client, false); MeshCollector collector; mesh_make_data.setSmoothLighting(false); MapblockMeshGenerator gen(&mesh_make_data, &collector); diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 8f5ed3e17..6c7d4be97 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -251,12 +251,6 @@ void set_default_settings(Settings *settings) settings->setDefault("bilinear_filter", "false"); settings->setDefault("trilinear_filter", "false"); settings->setDefault("tone_mapping", "false"); - settings->setDefault("enable_bumpmapping", "false"); - settings->setDefault("enable_parallax_occlusion", "false"); - settings->setDefault("parallax_occlusion_mode", "1"); - settings->setDefault("parallax_occlusion_iterations", "4"); - settings->setDefault("parallax_occlusion_scale", "0.08"); - settings->setDefault("parallax_occlusion_bias", "0.04"); settings->setDefault("enable_waving_water", "false"); settings->setDefault("water_wave_height", "1.0"); settings->setDefault("water_wave_length", "20.0"); diff --git a/src/nodedef.cpp b/src/nodedef.cpp index 3a5934cf3..5c2e5cd09 100644 --- a/src/nodedef.cpp +++ b/src/nodedef.cpp @@ -266,9 +266,6 @@ void TextureSettings::readSettings() { connected_glass = g_settings->getBool("connected_glass"); opaque_water = g_settings->getBool("opaque_water"); - bool enable_shaders = g_settings->getBool("enable_shaders"); - bool enable_bumpmapping = g_settings->getBool("enable_bumpmapping"); - bool enable_parallax_occlusion = g_settings->getBool("enable_parallax_occlusion"); bool smooth_lighting = g_settings->getBool("smooth_lighting"); enable_mesh_cache = g_settings->getBool("enable_mesh_cache"); enable_minimap = g_settings->getBool("enable_minimap"); @@ -281,8 +278,6 @@ void TextureSettings::readSettings() if (smooth_lighting) enable_mesh_cache = false; - use_normal_texture = enable_shaders && - (enable_bumpmapping || enable_parallax_occlusion); if (leaves_style_str == "fancy") { leaves_style = LEAVES_FANCY; } else if (leaves_style_str == "simple") { @@ -635,10 +630,6 @@ static void fillTileAttribs(ITextureSource *tsrc, TileLayer *layer, if (!tile.world_aligned) layer->scale = 1; - // Normal texture and shader flags texture - if (tsettings.use_normal_texture) { - layer->normal_texture = tsrc->getNormalTexture(tiledef.name); - } layer->flags_texture = tsrc->getShaderFlagsTexture(layer->normal_texture ? true : false); // Material flags diff --git a/src/nodedef.h b/src/nodedef.h index 71c56bda9..66c21cc07 100644 --- a/src/nodedef.h +++ b/src/nodedef.h @@ -158,7 +158,6 @@ public: int node_texture_size; bool opaque_water; bool connected_glass; - bool use_normal_texture; bool enable_mesh_cache; bool enable_minimap; -- cgit v1.2.3 From 738f62421872c0be5fcd483ad4573e5d879e7418 Mon Sep 17 00:00:00 2001 From: Lars Date: Thu, 15 Oct 2020 00:06:37 -0700 Subject: Periodically release all mesh HW buffers to avoid an Irrlicht bottleneck. --- src/client/game.cpp | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/game.cpp b/src/client/game.cpp index 309a8e194..a7e367ae2 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -909,6 +909,7 @@ private: bool m_does_lost_focus_pause_game = false; + int m_reset_HW_buffer_counter = 0; #ifdef __ANDROID__ bool m_cache_hold_aux1; bool m_android_chat_open; @@ -3686,7 +3687,6 @@ void Game::handleDigging(const PointedThing &pointed, const v3s16 &nodepos, camera->setDigging(0); // Dig animation } - void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime, const CameraOrientation &cam) { @@ -3937,6 +3937,27 @@ void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime, /* End scene */ + if (++m_reset_HW_buffer_counter > 500) { + /* + Periodically remove all mesh HW buffers. + + Work around for a quirk in Irrlicht where a HW buffer is only + released after 20000 iterations (triggered from endScene()). + + Without this, all loaded but unused meshes will retain their HW + buffers for at least 5 minutes, at which point looking up the HW buffers + becomes a bottleneck and the framerate drops (as much as 30%). + + Tests showed that numbers between 50 and 1000 are good, so picked 500. + There are no other public Irrlicht APIs that allow interacting with the + HW buffers without tracking the status of every individual mesh. + + The HW buffers for _visible_ meshes will be reinitialized in the next frame. + */ + infostream << "Game::updateFrame(): Removing all HW buffers." << std::endl; + driver->removeAllHardwareBuffers(); + m_reset_HW_buffer_counter = 0; + } driver->endScene(); stats->drawtime = tt_draw.stop(true); -- cgit v1.2.3 From b826e3973065a0bb81269c8decb5a33073508164 Mon Sep 17 00:00:00 2001 From: Lars Date: Sun, 18 Oct 2020 16:38:51 -0700 Subject: Minor clientmap improvements. - Avoid calculating isBlockInSight for blocks without meshes. - Add metric for how many blocks the client has currently loaded. - Make some variables constant. --- src/client/clientmap.cpp | 36 +++++++++++++++++++----------------- src/mapsector.h | 1 + 2 files changed, 20 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/client/clientmap.cpp b/src/client/clientmap.cpp index d372a8e46..c8561def6 100644 --- a/src/client/clientmap.cpp +++ b/src/client/clientmap.cpp @@ -122,14 +122,17 @@ void ClientMap::updateDrawList() } m_drawlist.clear(); - v3f camera_position = m_camera_position; - v3f camera_direction = m_camera_direction; + const v3f camera_position = m_camera_position; + const v3f camera_direction = m_camera_direction; + const f32 camera_fov = m_camera_fov; v3s16 cam_pos_nodes = floatToInt(camera_position, BS); v3s16 p_blocks_min; v3s16 p_blocks_max; getBlocksInViewRange(cam_pos_nodes, &p_blocks_min, &p_blocks_max); + // Number of blocks currently loaded by the client + u32 blocks_loaded = 0; // Number of blocks with mesh in rendering range u32 blocks_in_range_with_mesh = 0; // Number of blocks occlusion culled @@ -154,6 +157,7 @@ void ClientMap::updateDrawList() MapSector *sector = sector_it.second; v2s16 sp = sector->getPos(); + blocks_loaded += sector->size(); if (!m_control.range_all) { if (sp.X < p_blocks_min.X || sp.X > p_blocks_max.X || sp.Y < p_blocks_min.Z || sp.Y > p_blocks_max.Z) @@ -175,8 +179,12 @@ void ClientMap::updateDrawList() if not seen on display */ - if (block->mesh) + if (block->mesh) { block->mesh->updateCameraOffset(m_camera_offset); + } else { + // Ignore if mesh doesn't exist + continue; + } float range = 100000 * BS; if (!m_control.range_all) @@ -184,14 +192,7 @@ void ClientMap::updateDrawList() float d = 0.0; if (!isBlockInSight(block->getPos(), camera_position, - camera_direction, m_camera_fov, range, &d)) - continue; - - - /* - Ignore if mesh doesn't exist - */ - if (!block->mesh) + camera_direction, camera_fov, range, &d)) continue; blocks_in_range_with_mesh++; @@ -222,6 +223,7 @@ void ClientMap::updateDrawList() g_profiler->avg("MapBlock meshes in range [#]", blocks_in_range_with_mesh); g_profiler->avg("MapBlocks occlusion culled [#]", blocks_occlusion_culled); g_profiler->avg("MapBlocks drawn [#]", m_drawlist.size()); + g_profiler->avg("MapBlocks loaded [#]", blocks_loaded); } struct MeshBufList @@ -287,13 +289,13 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass) /* Get animation parameters */ - float animation_time = m_client->getAnimationTime(); - int crack = m_client->getCrackLevel(); - u32 daynight_ratio = m_client->getEnv().getDayNightRatio(); + const float animation_time = m_client->getAnimationTime(); + const int crack = m_client->getCrackLevel(); + const u32 daynight_ratio = m_client->getEnv().getDayNightRatio(); - v3f camera_position = m_camera_position; - v3f camera_direction = m_camera_direction; - f32 camera_fov = m_camera_fov; + const v3f camera_position = m_camera_position; + const v3f camera_direction = m_camera_direction; + const f32 camera_fov = m_camera_fov; /* Get all blocks and draw all visible ones diff --git a/src/mapsector.h b/src/mapsector.h index dede364f6..ffd4cdd1d 100644 --- a/src/mapsector.h +++ b/src/mapsector.h @@ -62,6 +62,7 @@ public: bool empty() const { return m_blocks.empty(); } + int size() const { return m_blocks.size(); } protected: // The pile of MapBlocks -- cgit v1.2.3 From 660115c1abc76f3d4f6a6597ed0c4737465c6c55 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Mon, 19 Oct 2020 20:38:15 +0200 Subject: Decouple entity minimap markers from nametags replacing with show_on_minimap property (#10443) --- doc/lua_api.txt | 4 ++++ src/client/camera.h | 2 -- src/client/client.cpp | 2 ++ src/client/content_cao.cpp | 27 +++++++++++++++++++++++++++ src/client/content_cao.h | 4 ++++ src/client/minimap.cpp | 35 ++++++++++++++++++++++++++--------- src/client/minimap.h | 11 +++++++++++ src/object_properties.cpp | 8 +++++++- src/object_properties.h | 1 + src/script/common/c_content.cpp | 3 +++ src/server/player_sao.cpp | 1 + 11 files changed, 86 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/doc/lua_api.txt b/doc/lua_api.txt index d3aaa309c..9a46c7b57 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -6880,6 +6880,10 @@ Player properties need to be saved manually. shaded = true, -- Setting this to 'false' disables diffuse lighting of entity + + show_on_minimap = false, + -- Defaults to true for players, false for other entities. + -- If set to true the entity will show as a marker on the minimap. } Entity definition diff --git a/src/client/camera.h b/src/client/camera.h index 3a59637bc..16a1961be 100644 --- a/src/client/camera.h +++ b/src/client/camera.h @@ -169,8 +169,6 @@ public: void removeNametag(Nametag *nametag); - const std::list &getNametags() { return m_nametags; } - void drawNametags(); inline void addArmInertia(f32 player_yaw); diff --git a/src/client/client.cpp b/src/client/client.cpp index 0bd98b256..af69d0ec9 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -326,6 +326,8 @@ Client::~Client() } delete m_minimap; + m_minimap = nullptr; + delete m_media_downloader; } diff --git a/src/client/content_cao.cpp b/src/client/content_cao.cpp index fae06554a..42184b08f 100644 --- a/src/client/content_cao.cpp +++ b/src/client/content_cao.cpp @@ -47,6 +47,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include #include "client/shader.h" +#include "client/minimap.h" class Settings; struct ToolCapabilities; @@ -566,6 +567,9 @@ void GenericCAO::removeFromScene(bool permanent) m_client->getCamera()->removeNametag(m_nametag); m_nametag = nullptr; } + + if (m_marker && m_client->getMinimap()) + m_client->getMinimap()->removeMarker(&m_marker); } void GenericCAO::addToScene(ITextureSource *tsrc) @@ -794,6 +798,7 @@ void GenericCAO::addToScene(ITextureSource *tsrc) node->setParent(m_matrixnode); updateNametag(); + updateMarker(); updateNodePos(); updateAnimation(); updateBonePosition(); @@ -885,6 +890,23 @@ u16 GenericCAO::getLightPosition(v3s16 *pos) return 3; } +void GenericCAO::updateMarker() +{ + if (!m_prop.show_on_minimap) { + if (m_marker) + m_client->getMinimap()->removeMarker(&m_marker); + return; + } + + if (m_marker) + return; + + scene::ISceneNode *node = getSceneNode(); + if (!node) + return; + m_marker = m_client->getMinimap()->addMarker(node); +} + void GenericCAO::updateNametag() { if (m_is_local_player) // No nametag for local player @@ -1576,6 +1598,8 @@ void GenericCAO::processMessage(const std::string &data) u8 cmd = readU8(is); if (cmd == AO_CMD_SET_PROPERTIES) { ObjectProperties newprops; + newprops.show_on_minimap = m_is_player; // default + newprops.deSerialize(is); // Check what exactly changed @@ -1609,6 +1633,8 @@ void GenericCAO::processMessage(const std::string &data) if ((m_is_player && !m_is_local_player) && m_prop.nametag.empty()) m_prop.nametag = m_name; + if (m_is_local_player) + m_prop.show_on_minimap = false; if (expire_visuals) { expireVisuals(); @@ -1621,6 +1647,7 @@ void GenericCAO::processMessage(const std::string &data) updateTextures(m_current_texture_modifier); } updateNametag(); + updateMarker(); } } else if (cmd == AO_CMD_UPDATE_POSITION) { // Not sent by the server if this object is an attachment. diff --git a/src/client/content_cao.h b/src/client/content_cao.h index daf697767..435fc2931 100644 --- a/src/client/content_cao.h +++ b/src/client/content_cao.h @@ -30,6 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc., class Camera; class Client; struct Nametag; +struct MinimapMarker; /* SmoothTranslator @@ -84,6 +85,7 @@ private: scene::IBillboardSceneNode *m_spritenode = nullptr; scene::IDummyTransformationSceneNode *m_matrixnode = nullptr; Nametag *m_nametag = nullptr; + MinimapMarker *m_marker = nullptr; v3f m_position = v3f(0.0f, 10.0f * BS, 0); v3f m_velocity; v3f m_acceleration; @@ -254,6 +256,8 @@ public: void updateNametag(); + void updateMarker(); + void updateNodePos(); void step(float dtime, ClientEnvironment *env); diff --git a/src/client/minimap.cpp b/src/client/minimap.cpp index 6bae408b4..d068ad5f7 100644 --- a/src/client/minimap.cpp +++ b/src/client/minimap.cpp @@ -252,6 +252,10 @@ Minimap::~Minimap() driver->removeTexture(data->minimap_overlay_square); driver->removeTexture(data->object_marker_red); + for (MinimapMarker *m : m_markers) + delete m; + m_markers.clear(); + delete data; delete m_minimap_update_thread; } @@ -678,21 +682,34 @@ void Minimap::drawMinimap(core::rect rect) { } } +MinimapMarker* Minimap::addMarker(scene::ISceneNode *parent_node) +{ + MinimapMarker *m = new MinimapMarker(parent_node); + m_markers.push_back(m); + return m; +} + +void Minimap::removeMarker(MinimapMarker **m) +{ + m_markers.remove(*m); + delete *m; + *m = nullptr; +} + void Minimap::updateActiveMarkers() { video::IImage *minimap_mask = data->minimap_shape_round ? data->minimap_mask_round : data->minimap_mask_square; - const std::list &nametags = client->getCamera()->getNametags(); - m_active_markers.clear(); - - for (Nametag *nametag : nametags) { - v3s16 pos = floatToInt(nametag->parent_node->getAbsolutePosition() + - intToFloat(client->getCamera()->getOffset(), BS), BS); - pos -= data->pos - v3s16(data->mode.map_size / 2, - data->mode.scan_height / 2, - data->mode.map_size / 2); + v3f cam_offset = intToFloat(client->getCamera()->getOffset(), BS); + v3s16 pos_offset = data->pos - v3s16(data->mode.map_size / 2, + data->mode.scan_height / 2, + data->mode.map_size / 2); + + for (MinimapMarker *marker : m_markers) { + v3s16 pos = floatToInt(marker->parent_node->getAbsolutePosition() + + cam_offset, BS) - pos_offset; if (pos.X < 0 || pos.X > data->mode.map_size || pos.Y < 0 || pos.Y > data->mode.scan_height || pos.Z < 0 || pos.Z > data->mode.map_size) { diff --git a/src/client/minimap.h b/src/client/minimap.h index 11374b116..4a2c462f8 100644 --- a/src/client/minimap.h +++ b/src/client/minimap.h @@ -48,6 +48,13 @@ struct MinimapModeDef { u16 scale; }; +struct MinimapMarker { + MinimapMarker(scene::ISceneNode *parent_node): + parent_node(parent_node) + { + } + scene::ISceneNode *parent_node; +}; struct MinimapPixel { //! The topmost node that the minimap displays. MapNode n; @@ -142,6 +149,9 @@ public: scene::SMeshBuffer *getMinimapMeshBuffer(); + MinimapMarker* addMarker(scene::ISceneNode *parent_node); + void removeMarker(MinimapMarker **marker); + void updateActiveMarkers(); void drawMinimap(); void drawMinimap(core::rect rect); @@ -162,5 +172,6 @@ private: u16 m_surface_mode_scan_height; f32 m_angle; std::mutex m_mutex; + std::list m_markers; std::list m_active_markers; }; diff --git a/src/object_properties.cpp b/src/object_properties.cpp index c31c667e7..f31773060 100644 --- a/src/object_properties.cpp +++ b/src/object_properties.cpp @@ -70,6 +70,7 @@ std::string ObjectProperties::dump() os << ", use_texture_alpha=" << use_texture_alpha; os << ", damage_texture_modifier=" << damage_texture_modifier; os << ", shaded=" << shaded; + os << ", show_on_minimap=" << show_on_minimap; return os.str(); } @@ -118,6 +119,7 @@ void ObjectProperties::serialize(std::ostream &os) const writeU8(os, use_texture_alpha); os << serializeString16(damage_texture_modifier); writeU8(os, shaded); + writeU8(os, show_on_minimap); // Add stuff only at the bottom. // Never remove anything, because we don't want new versions of this @@ -174,7 +176,11 @@ void ObjectProperties::deSerialize(std::istream &is) damage_texture_modifier = deSerializeString16(is); u8 tmp = readU8(is); if (is.eof()) - throw SerializationError(""); + return; shaded = tmp; + tmp = readU8(is); + if (is.eof()) + return; + show_on_minimap = tmp; } catch (SerializationError &e) {} } diff --git a/src/object_properties.h b/src/object_properties.h index f010c1daf..adb483527 100644 --- a/src/object_properties.h +++ b/src/object_properties.h @@ -62,6 +62,7 @@ struct ObjectProperties float zoom_fov = 0.0f; bool use_texture_alpha = false; bool shaded = true; + bool show_on_minimap = false; ObjectProperties(); std::string dump(); diff --git a/src/script/common/c_content.cpp b/src/script/common/c_content.cpp index a95cf94a1..e3cb9042e 100644 --- a/src/script/common/c_content.cpp +++ b/src/script/common/c_content.cpp @@ -331,6 +331,7 @@ void read_object_properties(lua_State *L, int index, getfloatfield(L, -1, "zoom_fov", prop->zoom_fov); getboolfield(L, -1, "use_texture_alpha", prop->use_texture_alpha); getboolfield(L, -1, "shaded", prop->shaded); + getboolfield(L, -1, "show_on_minimap", prop->show_on_minimap); getstringfield(L, -1, "damage_texture_modifier", prop->damage_texture_modifier); } @@ -419,6 +420,8 @@ void push_object_properties(lua_State *L, ObjectProperties *prop) lua_setfield(L, -2, "shaded"); lua_pushlstring(L, prop->damage_texture_modifier.c_str(), prop->damage_texture_modifier.size()); lua_setfield(L, -2, "damage_texture_modifier"); + lua_pushboolean(L, prop->show_on_minimap); + lua_setfield(L, -2, "show_on_minimap"); } /******************************************************************************/ diff --git a/src/server/player_sao.cpp b/src/server/player_sao.cpp index 344d18a20..9fb53380c 100644 --- a/src/server/player_sao.cpp +++ b/src/server/player_sao.cpp @@ -55,6 +55,7 @@ PlayerSAO::PlayerSAO(ServerEnvironment *env_, RemotePlayer *player_, session_t p m_prop.backface_culling = false; m_prop.makes_footstep_sound = true; m_prop.stepheight = PLAYER_DEFAULT_STEPHEIGHT * BS; + m_prop.show_on_minimap = true; m_hp = m_prop.hp_max; m_breath = m_prop.breath_max; // Disable zoom in survival mode using a value of 0 -- cgit v1.2.3 From 4f2303849e0f929524695a9e3719ec486b47ddd1 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Mon, 19 Oct 2020 20:38:33 +0200 Subject: Implement unloading of static_save=false objects according to existing docs (#10485) --- src/server/luaentity_sao.h | 1 + src/server/player_sao.h | 1 + src/server/serveractiveobject.h | 9 +++++++++ src/serverenvironment.cpp | 9 ++++++--- 4 files changed, 17 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/server/luaentity_sao.h b/src/server/luaentity_sao.h index 2520c8f5d..e060aa06d 100644 --- a/src/server/luaentity_sao.h +++ b/src/server/luaentity_sao.h @@ -42,6 +42,7 @@ public: void step(float dtime, bool send_recommended); std::string getClientInitializationData(u16 protocol_version); bool isStaticAllowed() const { return m_prop.static_save; } + bool shouldUnload() const { return true; } void getStaticData(std::string *result) const; u16 punch(v3f dir, const ToolCapabilities *toolcap = nullptr, ServerActiveObject *puncher = nullptr, diff --git a/src/server/player_sao.h b/src/server/player_sao.h index 8571bd4f9..3e178d4fc 100644 --- a/src/server/player_sao.h +++ b/src/server/player_sao.h @@ -83,6 +83,7 @@ public: void addedToEnvironment(u32 dtime_s); void removingFromEnvironment(); bool isStaticAllowed() const { return false; } + bool shouldUnload() const { return false; } std::string getClientInitializationData(u16 protocol_version); void getStaticData(std::string *result) const; void step(float dtime, bool send_recommended); diff --git a/src/server/serveractiveobject.h b/src/server/serveractiveobject.h index 927009aef..2764d159e 100644 --- a/src/server/serveractiveobject.h +++ b/src/server/serveractiveobject.h @@ -125,6 +125,7 @@ public: assert(isStaticAllowed()); *result = ""; } + /* Return false in here to never save and instead remove object on unload. getStaticData() will not be called in that case. @@ -132,6 +133,14 @@ public: virtual bool isStaticAllowed() const {return true;} + /* + Return false here to never unload the object. + isStaticAllowed && shouldUnload -> unload when out of active block range + !isStaticAllowed && shouldUnload -> unload when block is unloaded + */ + virtual bool shouldUnload() const + { return true; } + // Returns tool wear virtual u16 punch(v3f dir, const ToolCapabilities *toolcap = nullptr, diff --git a/src/serverenvironment.cpp b/src/serverenvironment.cpp index 6ef56efc8..d044b003d 100644 --- a/src/serverenvironment.cpp +++ b/src/serverenvironment.cpp @@ -1972,8 +1972,8 @@ void ServerEnvironment::deactivateFarObjects(bool _force_delete) // force_delete might be overriden per object bool force_delete = _force_delete; - // Do not deactivate if static data creation not allowed - if (!force_delete && !obj->isStaticAllowed()) + // Do not deactivate if disallowed + if (!force_delete && !obj->shouldUnload()) return false; // removeRemovedObjects() is responsible for these @@ -2002,7 +2002,10 @@ void ServerEnvironment::deactivateFarObjects(bool _force_delete) } // If block is still active, don't remove - if (!force_delete && m_active_blocks.contains(blockpos_o)) + bool still_active = obj->isStaticAllowed() ? + m_active_blocks.contains(blockpos_o) : + getMap().getBlockNoCreateNoEx(blockpos_o) != nullptr; + if (!force_delete && still_active) return false; verbosestream << "ServerEnvironment::deactivateFarObjects(): " -- cgit v1.2.3 From c7aa92aaed27ad8e10af7463b154b5b580c86da5 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Tue, 20 Oct 2020 16:34:14 +0200 Subject: Fix show_on_minimap default value for local player fixes #10526 --- src/client/content_cao.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/client/content_cao.cpp b/src/client/content_cao.cpp index 42184b08f..29a3acf25 100644 --- a/src/client/content_cao.cpp +++ b/src/client/content_cao.cpp @@ -354,6 +354,8 @@ void GenericCAO::initialize(const std::string &data) m_is_local_player = true; m_is_visible = false; player->setCAO(this); + + m_prop.show_on_minimap = false; } } -- cgit v1.2.3 From 5c0a57f6068000b0414cf2a3ef76a8bf4852b379 Mon Sep 17 00:00:00 2001 From: Maksim Date: Wed, 21 Oct 2020 21:42:40 +0200 Subject: Fix Media... 0% on loading screen (#9478) --- src/client/game.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/game.cpp b/src/client/game.cpp index a7e367ae2..0380c1661 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -1641,7 +1641,10 @@ bool Game::getServerContent(bool *aborted) std::stringstream message; std::fixed(message); message.precision(0); - message << gettext("Media...") << " " << (client->mediaReceiveProgress()*100) << "%"; + float receive = client->mediaReceiveProgress() * 100; + message << gettext("Media..."); + if (receive > 0) + message << " " << receive << "%"; message.precision(2); if ((USE_CURL == 0) || -- cgit v1.2.3 From 33b2c5f5b1c565171296f26395d803b08f4575e9 Mon Sep 17 00:00:00 2001 From: Zughy <63455151+Zughy@users.noreply.github.com> Date: Thu, 22 Oct 2020 17:18:01 +0200 Subject: Clean up l_object.cpp (#10512) Co-authored-by: Zughy <4279489-marco_a@users.noreply.gitlab.com> --- doc/lua_api.txt | 48 +- src/script/lua_api/l_object.cpp | 1163 +++++++++++++++++++-------------------- src/script/lua_api/l_object.h | 56 +- 3 files changed, 602 insertions(+), 665 deletions(-) (limited to 'src') diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 9a46c7b57..daf0da3d2 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -6217,18 +6217,18 @@ object you are working with still exists. * `rot` is a vector (radians). X is pitch (elevation), Y is yaw (heading) and Z is roll (bank). * `get_rotation()`: returns the rotation, a vector (radians) -* `set_yaw(radians)`: sets the yaw (heading). +* `set_yaw(yaw)`: sets the yaw in radians (heading). * `get_yaw()`: returns number in radians * `set_texture_mod(mod)` * Set a texture modifier to the base texture, for sprites and meshes. * When calling `set_texture_mod` again, the previous one is discarded. * `mod` the texture modifier. See [Texture modifiers]. * `get_texture_mod()` returns current texture modifier -* `set_sprite(p, num_frames, framelength, select_x_by_camera)` +* `set_sprite(start_frame, num_frames, framelength, select_x_by_camera)` * Specifies and starts a sprite animation * Animations iterate along the frame `y` position. - * `p`: {x=column number, y=row number}, the coordinate of the first frame - default: `{x=0, y=0}` + * `start_frame`: {x=column number, y=row number}, the coordinate of the + first frame, default: `{x=0, y=0}` * `num_frames`: Total frames in the texture, default: `1` * `framelength`: Time per animated frame in seconds, default: `0.2` * `select_x_by_camera`: Only for visual = `sprite`. Changes the frame `x` @@ -6391,8 +6391,8 @@ object you are working with still exists. nodes square) * `selected_mode` is the mode index to be selected after modes have been changed (0 is the first mode). -* `set_sky(parameters)` - * `parameters` is a table with the following optional fields: +* `set_sky(sky_parameters)` + * `sky_parameters` is a table with the following optional fields: * `base_color`: ColorSpec, changes fog in "skybox" and "plain". * `type`: Available types: * `"regular"`: Uses 0 textures, `base_color` ignored @@ -6436,8 +6436,8 @@ object you are working with still exists. * `get_sky()`: returns base_color, type, table of textures, clouds. * `get_sky_color()`: returns a table with the `sky_color` parameters as in `set_sky`. -* `set_sun(parameters)`: - * `parameters` is a table with the following optional fields: +* `set_sun(sun_parameters)`: + * `sun_parameters` is a table with the following optional fields: * `visible`: Boolean for whether the sun is visible. (default: `true`) * `texture`: A regular texture for the sun. Setting to `""` @@ -6451,8 +6451,8 @@ object you are working with still exists. * `scale`: Float controlling the overall size of the sun. (default: `1`) * `get_sun()`: returns a table with the current sun parameters as in `set_sun`. -* `set_moon(parameters)`: - * `parameters` is a table with the following optional fields: +* `set_moon(moon_parameters)`: + * `moon_parameters` is a table with the following optional fields: * `visible`: Boolean for whether the moon is visible. (default: `true`) * `texture`: A regular texture for the moon. Setting to `""` @@ -6462,8 +6462,8 @@ object you are working with still exists. * `scale`: Float controlling the overall size of the moon (default: `1`) * `get_moon()`: returns a table with the current moon parameters as in `set_moon`. -* `set_stars(parameters)`: - * `parameters` is a table with the following optional fields: +* `set_stars(star_parameters)`: + * `star_parameters` is a table with the following optional fields: * `visible`: Boolean for whether the stars are visible. (default: `true`) * `count`: Integer number to set the number of stars in @@ -6475,8 +6475,8 @@ object you are working with still exists. * `scale`: Float controlling the overall size of the stars (default: `1`) * `get_stars()`: returns a table with the current stars parameters as in `set_stars`. -* `set_clouds(parameters)`: set cloud parameters - * `parameters` is a table with the following optional fields: +* `set_clouds(cloud_parameters)`: set cloud parameters + * `cloud_parameters` is a table with the following optional fields: * `density`: from `0` (no clouds) to `1` (full clouds) (default `0.4`) * `color`: basic cloud color with alpha channel, ColorSpec (default `#fff0f0e5`). @@ -6494,21 +6494,17 @@ object you are working with still exists. amount. * `nil`: Disables override, defaulting to sunlight based on day-night cycle * `get_day_night_ratio()`: returns the ratio or nil if it isn't overridden -* `set_local_animation(stand/idle, walk, dig, walk+dig, frame_speed=frame_speed)`: - set animation for player model in third person view - - set_local_animation({x=0, y=79}, -- stand/idle animation key frames - {x=168, y=187}, -- walk animation key frames - {x=189, y=198}, -- dig animation key frames - {x=200, y=219}, -- walk+dig animation key frames - frame_speed=30) -- animation frame speed -* `get_local_animation()`: returns stand, walk, dig, dig+walk tables and +* `set_local_animation(idle, walk, dig, walk_while_dig, frame_speed)`: + set animation for player model in third person view. + * Every animation equals to a `{x=starting frame, y=ending frame}` table. + * `frame_speed` sets the animations frame speed. Default is 30. +* `get_local_animation()`: returns idle, walk, dig, walk_while_dig tables and `frame_speed`. -* `set_eye_offset({x=0,y=0,z=0},{x=0,y=0,z=0})`: defines offset value for - camera per player. +* `set_eye_offset(firstperson, thirdperson)`: defines offset vectors for camera + per player. * in first person view * in third person view (max. values `{x=-10/10,y=-10,15,z=-5/5}`) -* `get_eye_offset()`: returns `offset_first` and `offset_third` +* `get_eye_offset()`: returns first and third person offsets. * `send_mapblock(blockpos)`: * Sends a server-side loaded mapblock to the player. * Returns `false` if failed. diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index 96c8c687c..c3f0ec8e0 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -44,43 +44,44 @@ ObjectRef* ObjectRef::checkobject(lua_State *L, int narg) { luaL_checktype(L, narg, LUA_TUSERDATA); void *ud = luaL_checkudata(L, narg, className); - if (!ud) luaL_typerror(L, narg, className); + if (ud == nullptr) + luaL_typerror(L, narg, className); return *(ObjectRef**)ud; // unbox pointer } ServerActiveObject* ObjectRef::getobject(ObjectRef *ref) { - ServerActiveObject *co = ref->m_object; - if (co && co->isGone()) - return NULL; - return co; + ServerActiveObject *sao = ref->m_object; + if (sao && sao->isGone()) + return nullptr; + return sao; } LuaEntitySAO* ObjectRef::getluaobject(ObjectRef *ref) { - ServerActiveObject *obj = getobject(ref); - if (obj == NULL) - return NULL; - if (obj->getType() != ACTIVEOBJECT_TYPE_LUAENTITY) - return NULL; - return (LuaEntitySAO*)obj; + ServerActiveObject *sao = getobject(ref); + if (sao == nullptr) + return nullptr; + if (sao->getType() != ACTIVEOBJECT_TYPE_LUAENTITY) + return nullptr; + return (LuaEntitySAO*)sao; } PlayerSAO* ObjectRef::getplayersao(ObjectRef *ref) { - ServerActiveObject *obj = getobject(ref); - if (obj == NULL) - return NULL; - if (obj->getType() != ACTIVEOBJECT_TYPE_PLAYER) - return NULL; - return (PlayerSAO*)obj; + ServerActiveObject *sao = getobject(ref); + if (sao == nullptr) + return nullptr; + if (sao->getType() != ACTIVEOBJECT_TYPE_PLAYER) + return nullptr; + return (PlayerSAO*)sao; } RemotePlayer *ObjectRef::getplayer(ObjectRef *ref) { PlayerSAO *playersao = getplayersao(ref); - if (playersao == NULL) - return NULL; + if (playersao == nullptr) + return nullptr; return playersao->getPlayer(); } @@ -88,9 +89,8 @@ RemotePlayer *ObjectRef::getplayer(ObjectRef *ref) // garbage collector int ObjectRef::gc_object(lua_State *L) { - ObjectRef *o = *(ObjectRef **)(lua_touserdata(L, 1)); - //infostream<<"ObjectRef::gc_object: o="<getType() == ACTIVEOBJECT_TYPE_PLAYER) + if (sao->getType() == ACTIVEOBJECT_TYPE_PLAYER) return 0; - co->clearChildAttachments(); - co->clearParentAttachment(); + sao->clearChildAttachments(); + sao->clearParentAttachment(); - verbosestream << "ObjectRef::l_remove(): id=" << co->getId() << std::endl; - co->m_pending_removal = true; + verbosestream << "ObjectRef::l_remove(): id=" << sao->getId() << std::endl; + sao->m_pending_removal = true; return 0; } // get_pos(self) -// returns: {x=num, y=num, z=num} int ObjectRef::l_get_pos(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); - ServerActiveObject *co = getobject(ref); - if (co == NULL) return 0; - push_v3f(L, co->getBasePosition() / BS); + ServerActiveObject *sao = getobject(ref); + if (sao == nullptr) + return 0; + + push_v3f(L, sao->getBasePosition() / BS); return 1; } @@ -131,28 +132,29 @@ int ObjectRef::l_set_pos(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); - ServerActiveObject *co = getobject(ref); - if (co == NULL) return 0; - // pos + ServerActiveObject *sao = getobject(ref); + if (sao == nullptr) + return 0; + v3f pos = checkFloatPos(L, 2); - // Do it - co->setPos(pos); + + sao->setPos(pos); return 0; } -// move_to(self, pos, continuous=false) +// move_to(self, pos, continuous) int ObjectRef::l_move_to(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); - ServerActiveObject *co = getobject(ref); - if (co == NULL) return 0; - // pos + ServerActiveObject *sao = getobject(ref); + if (sao == nullptr) + return 0; + v3f pos = checkFloatPos(L, 2); - // continuous bool continuous = readParam(L, 3); - // Do it - co->moveTo(pos, continuous); + + sao->moveTo(pos, continuous); return 0; } @@ -162,32 +164,28 @@ int ObjectRef::l_punch(lua_State *L) NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); ObjectRef *puncher_ref = checkobject(L, 2); - ServerActiveObject *co = getobject(ref); + ServerActiveObject *sao = getobject(ref); ServerActiveObject *puncher = getobject(puncher_ref); - if (!co || !puncher) + if (sao == nullptr || puncher == nullptr) return 0; - v3f dir; - if (lua_type(L, 5) != LUA_TTABLE) - dir = co->getBasePosition() - puncher->getBasePosition(); - else - dir = read_v3f(L, 5); - float time_from_last_punch = 1000000; - if (lua_isnumber(L, 3)) - time_from_last_punch = lua_tonumber(L, 3); + + float time_from_last_punch = lua_isnil(L, 3) ? + 1000000.0f : readParam(L,3); ToolCapabilities toolcap = read_tool_capabilities(L, 4); - dir.normalize(); + v3f dir = lua_isnil(L, 5) ? + sao->getBasePosition() - puncher->getBasePosition() : check_v3f(L, 5); - u16 src_original_hp = co->getHP(); + dir.normalize(); + u16 src_original_hp = sao->getHP(); u16 dst_origin_hp = puncher->getHP(); - // Do it - u16 wear = co->punch(dir, &toolcap, puncher, time_from_last_punch); + u16 wear = sao->punch(dir, &toolcap, puncher, time_from_last_punch); lua_pushnumber(L, wear); // If the punched is a player, and its HP changed - if (src_original_hp != co->getHP() && - co->getType() == ACTIVEOBJECT_TYPE_PLAYER) { - getServer(L)->SendPlayerHPOrDie((PlayerSAO *)co, + if (src_original_hp != sao->getHP() && + sao->getType() == ACTIVEOBJECT_TYPE_PLAYER) { + getServer(L)->SendPlayerHPOrDie((PlayerSAO *)sao, PlayerHPChangeReason(PlayerHPChangeReason::PLAYER_PUNCH, puncher)); } @@ -195,45 +193,38 @@ int ObjectRef::l_punch(lua_State *L) if (dst_origin_hp != puncher->getHP() && puncher->getType() == ACTIVEOBJECT_TYPE_PLAYER) { getServer(L)->SendPlayerHPOrDie((PlayerSAO *)puncher, - PlayerHPChangeReason(PlayerHPChangeReason::PLAYER_PUNCH, co)); + PlayerHPChangeReason(PlayerHPChangeReason::PLAYER_PUNCH, sao)); } return 1; } -// right_click(self, clicker); clicker = an another ObjectRef +// right_click(self, clicker) int ObjectRef::l_right_click(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); ObjectRef *ref2 = checkobject(L, 2); - ServerActiveObject *co = getobject(ref); - ServerActiveObject *co2 = getobject(ref2); - if (co == NULL) return 0; - if (co2 == NULL) return 0; - // Do it - co->rightClick(co2); + ServerActiveObject *sao = getobject(ref); + ServerActiveObject *sao2 = getobject(ref2); + if (sao == nullptr || sao2 == nullptr) + return 0; + + sao->rightClick(sao2); return 0; } -// set_hp(self, hp) -// hp = number of hitpoints (2 * number of hearts) -// returns: nil +// set_hp(self, hp, reason) int ObjectRef::l_set_hp(lua_State *L) { NO_MAP_LOCK_REQUIRED; - - // Get Object ObjectRef *ref = checkobject(L, 1); - luaL_checknumber(L, 2); - ServerActiveObject *co = getobject(ref); - if (co == NULL) + ServerActiveObject *sao = getobject(ref); + if (sao == nullptr) return 0; - // Get HP - int hp = lua_tonumber(L, 2); - - // Get Reason + int hp = readParam(L, 2); PlayerHPChangeReason reason(PlayerHPChangeReason::SET_HP); + reason.from_mod = true; if (lua_istable(L, 3)) { lua_pushvalue(L, 3); @@ -248,35 +239,28 @@ int ObjectRef::l_set_hp(lua_State *L) reason.lua_reference = luaL_ref(L, LUA_REGISTRYINDEX); } - // Do it - co->setHP(hp, reason); - if (co->getType() == ACTIVEOBJECT_TYPE_PLAYER) - getServer(L)->SendPlayerHPOrDie((PlayerSAO *)co, reason); - + sao->setHP(hp, reason); + if (sao->getType() == ACTIVEOBJECT_TYPE_PLAYER) + getServer(L)->SendPlayerHPOrDie((PlayerSAO *)sao, reason); if (reason.hasLuaReference()) luaL_unref(L, LUA_REGISTRYINDEX, reason.lua_reference); - - // Return return 0; } // get_hp(self) -// returns: number of hitpoints (2 * number of hearts) -// 0 if not applicable to this type of object int ObjectRef::l_get_hp(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); - ServerActiveObject *co = getobject(ref); - if (co == NULL) { + ServerActiveObject *sao = getobject(ref); + if (sao == nullptr) { // Default hp is 1 lua_pushnumber(L, 1); return 1; } - int hp = co->getHP(); - /*infostream<<"ObjectRef::l_get_hp(): id="<getId() - <<" hp="<getHP(); + lua_pushnumber(L, hp); return 1; } @@ -286,11 +270,12 @@ int ObjectRef::l_get_inventory(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); - ServerActiveObject *co = getobject(ref); - if (co == NULL) return 0; - // Do it - InventoryLocation loc = co->getInventoryLocation(); - if (getServerInventoryMgr(L)->getInventory(loc) != NULL) + ServerActiveObject *sao = getobject(ref); + if (sao == nullptr) + return 0; + + InventoryLocation loc = sao->getInventoryLocation(); + if (getServerInventoryMgr(L)->getInventory(loc) != nullptr) InvRef::create(L, loc); else lua_pushnil(L); // An object may have no inventory (nil) @@ -302,11 +287,11 @@ int ObjectRef::l_get_wield_list(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); - ServerActiveObject *co = getobject(ref); - if (!co) + ServerActiveObject *sao = getobject(ref); + if (sao == nullptr) return 0; - lua_pushstring(L, co->getWieldList().c_str()); + lua_pushstring(L, sao->getWieldList().c_str()); return 1; } @@ -315,11 +300,11 @@ int ObjectRef::l_get_wield_index(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); - ServerActiveObject *co = getobject(ref); - if (!co) + ServerActiveObject *sao = getobject(ref); + if (sao == nullptr) return 0; - lua_pushinteger(L, co->getWieldIndex() + 1); + lua_pushinteger(L, sao->getWieldIndex() + 1); return 1; } @@ -328,31 +313,33 @@ int ObjectRef::l_get_wielded_item(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); - ServerActiveObject *co = getobject(ref); - if (!co) { + ServerActiveObject *sao = getobject(ref); + if (sao == nullptr) { // Empty ItemStack LuaItemStack::create(L, ItemStack()); return 1; } ItemStack selected_item; - co->getWieldedItem(&selected_item, nullptr); + sao->getWieldedItem(&selected_item, nullptr); LuaItemStack::create(L, selected_item); return 1; } -// set_wielded_item(self, itemstack or itemstring or table or nil) +// set_wielded_item(self, item) int ObjectRef::l_set_wielded_item(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); - ServerActiveObject *co = getobject(ref); - if (co == NULL) return 0; - // Do it + ServerActiveObject *sao = getobject(ref); + if (sao == nullptr) + return 0; + ItemStack item = read_item(L, 2, getServer(L)->idef()); - bool success = co->setWieldedItem(item); - if (success && co->getType() == ACTIVEOBJECT_TYPE_PLAYER) { - getServer(L)->SendInventory((PlayerSAO *)co, true); + + bool success = sao->setWieldedItem(item); + if (success && sao->getType() == ACTIVEOBJECT_TYPE_PLAYER) { + getServer(L)->SendInventory((PlayerSAO *)sao, true); } lua_pushboolean(L, success); return 1; @@ -363,12 +350,14 @@ int ObjectRef::l_set_armor_groups(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); - ServerActiveObject *co = getobject(ref); - if (co == NULL) return 0; - // Do it + ServerActiveObject *sao = getobject(ref); + if (sao == nullptr) + return 0; + ItemGroupList groups; + read_groups(L, 2, groups); - co->setArmorGroups(groups); + sao->setArmorGroups(groups); return 0; } @@ -377,77 +366,11 @@ int ObjectRef::l_get_armor_groups(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); - ServerActiveObject *co = getobject(ref); - if (co == NULL) + ServerActiveObject *sao = getobject(ref); + if (sao == nullptr) return 0; - // Do it - push_groups(L, co->getArmorGroups()); - return 1; -} -// set_physics_override(self, physics_override_speed, physics_override_jump, -// physics_override_gravity, sneak, sneak_glitch, new_move) -int ObjectRef::l_set_physics_override(lua_State *L) -{ - NO_MAP_LOCK_REQUIRED; - ObjectRef *ref = checkobject(L, 1); - PlayerSAO *co = (PlayerSAO *) getobject(ref); - if (co == NULL) return 0; - // Do it - if (lua_istable(L, 2)) { - co->m_physics_override_speed = getfloatfield_default( - L, 2, "speed", co->m_physics_override_speed); - co->m_physics_override_jump = getfloatfield_default( - L, 2, "jump", co->m_physics_override_jump); - co->m_physics_override_gravity = getfloatfield_default( - L, 2, "gravity", co->m_physics_override_gravity); - co->m_physics_override_sneak = getboolfield_default( - L, 2, "sneak", co->m_physics_override_sneak); - co->m_physics_override_sneak_glitch = getboolfield_default( - L, 2, "sneak_glitch", co->m_physics_override_sneak_glitch); - co->m_physics_override_new_move = getboolfield_default( - L, 2, "new_move", co->m_physics_override_new_move); - co->m_physics_override_sent = false; - } else { - // old, non-table format - if (!lua_isnil(L, 2)) { - co->m_physics_override_speed = lua_tonumber(L, 2); - co->m_physics_override_sent = false; - } - if (!lua_isnil(L, 3)) { - co->m_physics_override_jump = lua_tonumber(L, 3); - co->m_physics_override_sent = false; - } - if (!lua_isnil(L, 4)) { - co->m_physics_override_gravity = lua_tonumber(L, 4); - co->m_physics_override_sent = false; - } - } - return 0; -} - -// get_physics_override(self) -int ObjectRef::l_get_physics_override(lua_State *L) -{ - NO_MAP_LOCK_REQUIRED; - ObjectRef *ref = checkobject(L, 1); - PlayerSAO *co = (PlayerSAO *)getobject(ref); - if (co == NULL) - return 0; - // Do it - lua_newtable(L); - lua_pushnumber(L, co->m_physics_override_speed); - lua_setfield(L, -2, "speed"); - lua_pushnumber(L, co->m_physics_override_jump); - lua_setfield(L, -2, "jump"); - lua_pushnumber(L, co->m_physics_override_gravity); - lua_setfield(L, -2, "gravity"); - lua_pushboolean(L, co->m_physics_override_sneak); - lua_setfield(L, -2, "sneak"); - lua_pushboolean(L, co->m_physics_override_sneak_glitch); - lua_setfield(L, -2, "sneak_glitch"); - lua_pushboolean(L, co->m_physics_override_new_move); - lua_setfield(L, -2, "new_move"); + push_groups(L, sao->getArmorGroups()); return 1; } @@ -456,9 +379,10 @@ int ObjectRef::l_set_animation(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); - ServerActiveObject *co = getobject(ref); - if (co == NULL) return 0; - // Do it + ServerActiveObject *sao = getobject(ref); + if (sao == nullptr) + return 0; + v2f frames = v2f(1, 1); if (!lua_isnil(L, 2)) frames = readParam(L, 2); @@ -471,7 +395,8 @@ int ObjectRef::l_set_animation(lua_State *L) bool frame_loop = true; if (lua_isboolean(L, 5)) frame_loop = readParam(L, 5); - co->setAnimation(frames, frame_speed, frame_blend, frame_loop); + + sao->setAnimation(frames, frame_speed, frame_blend, frame_loop); return 0; } @@ -480,16 +405,16 @@ int ObjectRef::l_get_animation(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); - ServerActiveObject *co = getobject(ref); - if (co == NULL) + ServerActiveObject *sao = getobject(ref); + if (sao == nullptr) return 0; - // Do it + v2f frames = v2f(1,1); float frame_speed = 15; float frame_blend = 0; bool frame_loop = true; - co->getAnimation(&frames, &frame_speed, &frame_blend, &frame_loop); + sao->getAnimation(&frames, &frame_speed, &frame_blend, &frame_loop); push_v2f(L, frames); lua_pushnumber(L, frame_speed); lua_pushnumber(L, frame_blend); @@ -497,23 +422,21 @@ int ObjectRef::l_get_animation(lua_State *L) return 4; } -// set_local_animation(self, {stand/idle}, {walk}, {dig}, {walk+dig}, frame_speed) +// set_local_animation(self, idle, walk, dig, walk_while_dig, frame_speed) int ObjectRef::l_set_local_animation(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); RemotePlayer *player = getplayer(ref); - if (player == NULL) + if (player == nullptr) return 0; - // Do it + v2s32 frames[4]; for (int i=0;i<4;i++) { if (!lua_isnil(L, 2+1)) frames[i] = read_v2s32(L, 2+i); } - float frame_speed = 30; - if (!lua_isnil(L, 6)) - frame_speed = lua_tonumber(L, 6); + float frame_speed = lua_isnil(L, 6) ? 30 : readParam(L, 6); getServer(L)->setLocalPlayerAnimations(player, frames, frame_speed); lua_pushboolean(L, true); @@ -526,7 +449,7 @@ int ObjectRef::l_get_local_animation(lua_State *L) NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); RemotePlayer *player = getplayer(ref); - if (player == NULL) + if (player == nullptr) return 0; v2s32 frames[4]; @@ -541,27 +464,22 @@ int ObjectRef::l_get_local_animation(lua_State *L) return 5; } -// set_eye_offset(self, v3f first pv, v3f third pv) +// set_eye_offset(self, firstperson, thirdperson) int ObjectRef::l_set_eye_offset(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); RemotePlayer *player = getplayer(ref); - if (player == NULL) + if (player == nullptr) return 0; - // Do it - v3f offset_first = v3f(0, 0, 0); - v3f offset_third = v3f(0, 0, 0); - if (!lua_isnil(L, 2)) - offset_first = read_v3f(L, 2); - if (!lua_isnil(L, 3)) - offset_third = read_v3f(L, 3); + v3f offset_first = read_v3f(L, 2); + v3f offset_third = read_v3f(L, 3); // Prevent abuse of offset values (keep player always visible) offset_third.X = rangelim(offset_third.X,-10,10); offset_third.Z = rangelim(offset_third.Z,-5,5); - /* TODO: if possible: improve the camera colision detetion to allow Y <= -1.5) */ + /* TODO: if possible: improve the camera collision detection to allow Y <= -1.5) */ offset_third.Y = rangelim(offset_third.Y,-10,15); //1.5*BS getServer(L)->setPlayerEyeOffset(player, offset_first, offset_third); @@ -575,9 +493,9 @@ int ObjectRef::l_get_eye_offset(lua_State *L) NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); RemotePlayer *player = getplayer(ref); - if (player == NULL) + if (player == nullptr) return 0; - // Do it + push_v3f(L, player->eye_offset_first); push_v3f(L, player->eye_offset_third); return 2; @@ -588,14 +506,14 @@ int ObjectRef::l_send_mapblock(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); - RemotePlayer *player = getplayer(ref); - if (!player) + if (player == nullptr) return 0; - v3s16 p = read_v3s16(L, 2); + + v3s16 pos = read_v3s16(L, 2); session_t peer_id = player->getPeerId(); - bool r = getServer(L)->SendBlock(peer_id, p); + bool r = getServer(L)->SendBlock(peer_id, pos); lua_pushboolean(L, r); return 1; @@ -606,14 +524,13 @@ int ObjectRef::l_set_animation_frame_speed(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); - ServerActiveObject *co = getobject(ref); - if (co == NULL) + ServerActiveObject *sao = getobject(ref); + if (sao == nullptr) return 0; - // Do it if (!lua_isnil(L, 2)) { - float frame_speed = lua_tonumber(L, 2); - co->setAnimationSpeed(frame_speed); + float frame_speed = readParam(L, 2); + sao->setAnimationSpeed(frame_speed); lua_pushboolean(L, true); } else { lua_pushboolean(L, false); @@ -621,24 +538,20 @@ int ObjectRef::l_set_animation_frame_speed(lua_State *L) return 1; } -// set_bone_position(self, std::string bone, v3f position, v3f rotation) +// set_bone_position(self, bone, position, rotation) int ObjectRef::l_set_bone_position(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); - ServerActiveObject *co = getobject(ref); - if (co == NULL) return 0; - // Do it - std::string bone; - if (!lua_isnil(L, 2)) - bone = readParam(L, 2); - v3f position = v3f(0, 0, 0); - if (!lua_isnil(L, 3)) - position = check_v3f(L, 3); - v3f rotation = v3f(0, 0, 0); - if (!lua_isnil(L, 4)) - rotation = check_v3f(L, 4); - co->setBonePosition(bone, position, rotation); + ServerActiveObject *sao = getobject(ref); + if (sao == nullptr) + return 0; + + std::string bone = readParam(L, 2); + v3f position = check_v3f(L, 3); + v3f rotation = check_v3f(L, 4); + + sao->setBonePosition(bone, position, rotation); return 0; } @@ -647,17 +560,15 @@ int ObjectRef::l_get_bone_position(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); - ServerActiveObject *co = getobject(ref); - if (co == NULL) + ServerActiveObject *sao = getobject(ref); + if (sao == nullptr) return 0; - // Do it - std::string bone; - if (!lua_isnil(L, 2)) - bone = readParam(L, 2); + + std::string bone = readParam(L, 2); v3f position = v3f(0, 0, 0); v3f rotation = v3f(0, 0, 0); - co->getBonePosition(bone, &position, &rotation); + sao->getBonePosition(bone, &position, &rotation); push_v3f(L, position); push_v3f(L, rotation); @@ -668,44 +579,34 @@ int ObjectRef::l_get_bone_position(lua_State *L) int ObjectRef::l_set_attach(lua_State *L) { GET_ENV_PTR; - ObjectRef *ref = checkobject(L, 1); ObjectRef *parent_ref = checkobject(L, 2); - ServerActiveObject *co = getobject(ref); + ServerActiveObject *sao = getobject(ref); ServerActiveObject *parent = getobject(parent_ref); - if (co == NULL) + if (sao == nullptr || parent == nullptr) return 0; - - if (parent == NULL) - return 0; - - if (co == parent) + if (sao == parent) throw LuaError("ObjectRef::set_attach: attaching object to itself is not allowed."); - // Do it int parent_id = 0; std::string bone; v3f position = v3f(0, 0, 0); v3f rotation = v3f(0, 0, 0); bool force_visible; - co->getAttachment(&parent_id, &bone, &position, &rotation, &force_visible); + + sao->getAttachment(&parent_id, &bone, &position, &rotation, &force_visible); if (parent_id) { ServerActiveObject *old_parent = env->getActiveObject(parent_id); - old_parent->removeAttachmentChild(co->getId()); + old_parent->removeAttachmentChild(sao->getId()); } - bone = ""; - if (!lua_isnil(L, 3)) - bone = readParam(L, 3); - position = v3f(0, 0, 0); - if (!lua_isnil(L, 4)) - position = read_v3f(L, 4); - rotation = v3f(0, 0, 0); - if (!lua_isnil(L, 5)) - rotation = read_v3f(L, 5); + bone = readParam(L, 3, ""); + position = read_v3f(L, 4); + rotation = read_v3f(L, 5); force_visible = readParam(L, 6, false); - co->setAttachment(parent->getId(), bone, position, rotation, force_visible); - parent->addAttachmentChild(co->getId()); + + sao->setAttachment(parent->getId(), bone, position, rotation, force_visible); + parent->addAttachmentChild(sao->getId()); return 0; } @@ -713,23 +614,22 @@ int ObjectRef::l_set_attach(lua_State *L) int ObjectRef::l_get_attach(lua_State *L) { GET_ENV_PTR; - ObjectRef *ref = checkobject(L, 1); - ServerActiveObject *co = getobject(ref); - if (co == NULL) + ServerActiveObject *sao = getobject(ref); + if (sao == nullptr) return 0; - // Do it int parent_id = 0; std::string bone; v3f position = v3f(0, 0, 0); v3f rotation = v3f(0, 0, 0); bool force_visible; - co->getAttachment(&parent_id, &bone, &position, &rotation, &force_visible); - if (!parent_id) + + sao->getAttachment(&parent_id, &bone, &position, &rotation, &force_visible); + if (parent_id == 0) return 0; - ServerActiveObject *parent = env->getActiveObject(parent_id); + ServerActiveObject *parent = env->getActiveObject(parent_id); getScriptApiBase(L)->objectrefGetOrCreate(L, parent); lua_pushlstring(L, bone.c_str(), bone.size()); push_v3f(L, position); @@ -742,7 +642,6 @@ int ObjectRef::l_get_attach(lua_State *L) int ObjectRef::l_get_children(lua_State *L) { GET_ENV_PTR; - ObjectRef *ref = checkobject(L, 1); ServerActiveObject *sao = getobject(ref); if (sao == nullptr) @@ -750,6 +649,7 @@ int ObjectRef::l_get_children(lua_State *L) const std::unordered_set child_ids = sao->getAttachmentChildIds(); int i = 0; + lua_createtable(L, child_ids.size(), 0); for (const int id : child_ids) { ServerActiveObject *child = env->getActiveObject(id); @@ -763,13 +663,12 @@ int ObjectRef::l_get_children(lua_State *L) int ObjectRef::l_set_detach(lua_State *L) { GET_ENV_PTR; - ObjectRef *ref = checkobject(L, 1); - ServerActiveObject *co = getobject(ref); - if (co == NULL) + ServerActiveObject *sao = getobject(ref); + if (sao == nullptr) return 0; - co->clearParentAttachment(); + sao->clearParentAttachment(); return 0; } @@ -778,16 +677,16 @@ int ObjectRef::l_set_properties(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); - ServerActiveObject *co = getobject(ref); - if (!co) + ServerActiveObject *sao = getobject(ref); + if (sao == nullptr) return 0; - ObjectProperties *prop = co->accessObjectProperties(); - if (!prop) + ObjectProperties *prop = sao->accessObjectProperties(); + if (prop == nullptr) return 0; - read_object_properties(L, 2, co, prop, getServer(L)->idef()); - co->notifyObjectPropertiesModified(); + read_object_properties(L, 2, sao, prop, getServer(L)->idef()); + sao->notifyObjectPropertiesModified(); return 0; } @@ -796,12 +695,14 @@ int ObjectRef::l_get_properties(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); - ServerActiveObject *co = getobject(ref); - if (co == NULL) + ServerActiveObject *sao = getobject(ref); + if (sao == nullptr) return 0; - ObjectProperties *prop = co->accessObjectProperties(); - if (!prop) + + ObjectProperties *prop = sao->accessObjectProperties(); + if (prop == nullptr) return 0; + push_object_properties(L, prop); return 1; } @@ -812,7 +713,7 @@ int ObjectRef::l_is_player(lua_State *L) NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); RemotePlayer *player = getplayer(ref); - lua_pushboolean(L, (player != NULL)); + lua_pushboolean(L, (player != nullptr)); return 1; } @@ -821,12 +722,12 @@ int ObjectRef::l_set_nametag_attributes(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); - ServerActiveObject *co = getobject(ref); - - if (co == NULL) + ServerActiveObject *sao = getobject(ref); + if (sao == nullptr) return 0; - ObjectProperties *prop = co->accessObjectProperties(); - if (!prop) + + ObjectProperties *prop = sao->accessObjectProperties(); + if (prop == nullptr) return 0; lua_getfield(L, 2, "color"); @@ -840,7 +741,7 @@ int ObjectRef::l_set_nametag_attributes(lua_State *L) std::string nametag = getstringfield_default(L, 2, "text", ""); prop->nametag = nametag; - co->notifyObjectPropertiesModified(); + sao->notifyObjectPropertiesModified(); lua_pushboolean(L, true); return 1; } @@ -850,11 +751,11 @@ int ObjectRef::l_get_nametag_attributes(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); - ServerActiveObject *co = getobject(ref); - - if (co == NULL) + ServerActiveObject *sao = getobject(ref); + if (sao == nullptr) return 0; - ObjectProperties *prop = co->accessObjectProperties(); + + ObjectProperties *prop = sao->accessObjectProperties(); if (!prop) return 0; @@ -870,37 +771,39 @@ int ObjectRef::l_get_nametag_attributes(lua_State *L) /* LuaEntitySAO-only */ -// set_velocity(self, {x=num, y=num, z=num}) +// set_velocity(self, velocity) int ObjectRef::l_set_velocity(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); - LuaEntitySAO *co = getluaobject(ref); - if (co == NULL) return 0; - v3f pos = checkFloatPos(L, 2); - // Do it - co->setVelocity(pos); + LuaEntitySAO *sao = getluaobject(ref); + if (sao == nullptr) + return 0; + + v3f vel = checkFloatPos(L, 2); + + sao->setVelocity(vel); return 0; } -// add_velocity(self, {x=num, y=num, z=num}) +// add_velocity(self, velocity) int ObjectRef::l_add_velocity(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); - v3f vel = checkFloatPos(L, 2); - - ServerActiveObject *obj = getobject(ref); - if (obj == nullptr) + ServerActiveObject *sao = getobject(ref); + if (sao == nullptr) return 0; - if (obj->getType() == ACTIVEOBJECT_TYPE_LUAENTITY) { - LuaEntitySAO *co = dynamic_cast(obj); - co->addVelocity(vel); - } else if (obj->getType() == ACTIVEOBJECT_TYPE_PLAYER) { - PlayerSAO *player = dynamic_cast(obj); - player->setMaxSpeedOverride(vel); - getServer(L)->SendPlayerSpeed(player->getPeerID(), vel); + v3f vel = checkFloatPos(L, 2); + + if (sao->getType() == ACTIVEOBJECT_TYPE_LUAENTITY) { + LuaEntitySAO *entitysao = dynamic_cast(sao); + entitysao->addVelocity(vel); + } else if (sao->getType() == ACTIVEOBJECT_TYPE_PLAYER) { + PlayerSAO *playersao = dynamic_cast(sao); + playersao->setMaxSpeedOverride(vel); + getServer(L)->SendPlayerSpeed(playersao->getPeerID(), vel); } return 0; @@ -911,18 +814,17 @@ int ObjectRef::l_get_velocity(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); - - ServerActiveObject *obj = getobject(ref); - if (obj == nullptr) + ServerActiveObject *sao = getobject(ref); + if (sao == nullptr) return 0; - if (obj->getType() == ACTIVEOBJECT_TYPE_LUAENTITY) { - LuaEntitySAO *co = dynamic_cast(obj); - v3f v = co->getVelocity(); - pushFloatPos(L, v); + if (sao->getType() == ACTIVEOBJECT_TYPE_LUAENTITY) { + LuaEntitySAO *entitysao = dynamic_cast(sao); + v3f vel = entitysao->getVelocity(); + pushFloatPos(L, vel); return 1; - } else if (obj->getType() == ACTIVEOBJECT_TYPE_PLAYER) { - RemotePlayer *player = dynamic_cast(obj)->getPlayer(); + } else if (sao->getType() == ACTIVEOBJECT_TYPE_PLAYER) { + RemotePlayer *player = dynamic_cast(sao)->getPlayer(); push_v3f(L, player->getSpeed() / BS); return 1; } @@ -931,17 +833,18 @@ int ObjectRef::l_get_velocity(lua_State *L) return 1; } -// set_acceleration(self, {x=num, y=num, z=num}) +// set_acceleration(self, acceleration) int ObjectRef::l_set_acceleration(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); - LuaEntitySAO *co = getluaobject(ref); - if (co == NULL) return 0; - // pos - v3f pos = checkFloatPos(L, 2); - // Do it - co->setAcceleration(pos); + LuaEntitySAO *entitysao = getluaobject(ref); + if (entitysao == nullptr) + return 0; + + v3f acceleration = checkFloatPos(L, 2); + + entitysao->setAcceleration(acceleration); return 0; } @@ -950,59 +853,61 @@ int ObjectRef::l_get_acceleration(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); - LuaEntitySAO *co = getluaobject(ref); - if (co == NULL) return 0; - // Do it - v3f v = co->getAcceleration(); - pushFloatPos(L, v); + LuaEntitySAO *entitysao = getluaobject(ref); + if (entitysao == nullptr) + return 0; + + v3f acceleration = entitysao->getAcceleration(); + pushFloatPos(L, acceleration); return 1; } -// set_rotation(self, {x=num, y=num, z=num}) -// Each 'num' is in radians +// set_rotation(self, rotation) int ObjectRef::l_set_rotation(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); - LuaEntitySAO *co = getluaobject(ref); - if (!co) + LuaEntitySAO *entitysao = getluaobject(ref); + if (entitysao == nullptr) return 0; v3f rotation = check_v3f(L, 2) * core::RADTODEG; - co->setRotation(rotation); + + entitysao->setRotation(rotation); return 0; } // get_rotation(self) -// returns: {x=num, y=num, z=num} -// Each 'num' is in radians int ObjectRef::l_get_rotation(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); - LuaEntitySAO *co = getluaobject(ref); - if (!co) + LuaEntitySAO *entitysao = getluaobject(ref); + if (entitysao == nullptr) return 0; + v3f rotation = entitysao->getRotation() * core::DEGTORAD; + lua_newtable(L); - v3f rotation = co->getRotation() * core::DEGTORAD; push_v3f(L, rotation); return 1; } -// set_yaw(self, radians) +// set_yaw(self, yaw) int ObjectRef::l_set_yaw(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); - LuaEntitySAO *co = getluaobject(ref); + LuaEntitySAO *entitysao = getluaobject(ref); + if (entitysao == nullptr) + return 0; - if (co == NULL) return 0; if (isNaN(L, 2)) throw LuaError("ObjectRef::set_yaw: NaN value is not allowed."); float yaw = readParam(L, 2) * core::RADTODEG; - co->setRotation(v3f(0, yaw, 0)); + + entitysao->setRotation(v3f(0, yaw, 0)); return 0; } @@ -1011,11 +916,12 @@ int ObjectRef::l_get_yaw(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); - LuaEntitySAO *co = getluaobject(ref); - if (!co) + LuaEntitySAO *entitysao = getluaobject(ref); + if (entitysao == nullptr) return 0; - float yaw = co->getRotation().Y * core::DEGTORAD; + float yaw = entitysao->getRotation().Y * core::DEGTORAD; + lua_pushnumber(L, yaw); return 1; } @@ -1025,11 +931,13 @@ int ObjectRef::l_set_texture_mod(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); - LuaEntitySAO *co = getluaobject(ref); - if (co == NULL) return 0; - // Do it - std::string mod = luaL_checkstring(L, 2); - co->setTextureMod(mod); + LuaEntitySAO *entitysao = getluaobject(ref); + if (entitysao == nullptr) + return 0; + + std::string mod = readParam(L, 2); + + entitysao->setTextureMod(mod); return 0; } @@ -1038,36 +946,31 @@ int ObjectRef::l_get_texture_mod(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); - LuaEntitySAO *co = getluaobject(ref); - if (co == NULL) return 0; - // Do it - std::string mod = co->getTextureMod(); + LuaEntitySAO *entitysao = getluaobject(ref); + if (entitysao == nullptr) + return 0; + + std::string mod = entitysao->getTextureMod(); + lua_pushstring(L, mod.c_str()); return 1; } -// set_sprite(self, p={x=0,y=0}, num_frames=1, framelength=0.2, -// select_horiz_by_yawpitch=false) +// set_sprite(self, start_frame, num_frames, framelength, select_x_by_camera) int ObjectRef::l_set_sprite(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); - LuaEntitySAO *co = getluaobject(ref); - if (co == NULL) return 0; - // Do it - v2s16 p(0,0); - if (!lua_isnil(L, 2)) - p = readParam(L, 2); - int num_frames = 1; - if (!lua_isnil(L, 3)) - num_frames = lua_tonumber(L, 3); - float framelength = 0.2; - if (!lua_isnil(L, 4)) - framelength = lua_tonumber(L, 4); - bool select_horiz_by_yawpitch = false; - if (!lua_isnil(L, 5)) - select_horiz_by_yawpitch = readParam(L, 5); - co->setSprite(p, num_frames, framelength, select_horiz_by_yawpitch); + LuaEntitySAO *entitysao = getluaobject(ref); + if (entitysao == nullptr) + return 0; + + v2s16 start_frame = lua_isnil(L, 2) ? v2s16(0,0) : readParam(L, 2); + int num_frames = lua_isnil(L, 3) ? 1 : luaL_checkint(L, 3); + float framelength = lua_isnil(L, 4) ? 0.2 : lua_tonumber(L, 4); + bool select_x_by_camera = readParam(L, 5, false); + + entitysao->setSprite(start_frame, num_frames, framelength, select_x_by_camera); return 0; } @@ -1077,11 +980,13 @@ int ObjectRef::l_get_entity_name(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); - LuaEntitySAO *co = getluaobject(ref); + LuaEntitySAO *entitysao = getluaobject(ref); log_deprecated(L,"Deprecated call to \"get_entity_name"); - if (co == NULL) return 0; - // Do it - std::string name = co->getName(); + if (entitysao == nullptr) + return 0; + + std::string name = entitysao->getName(); + lua_pushstring(L, name.c_str()); return 1; } @@ -1091,39 +996,27 @@ int ObjectRef::l_get_luaentity(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); - LuaEntitySAO *co = getluaobject(ref); - if (co == NULL) return 0; - // Do it - luaentity_get(L, co->getId()); + LuaEntitySAO *entitysao = getluaobject(ref); + if (entitysao == nullptr) + return 0; + + luaentity_get(L, entitysao->getId()); return 1; } /* Player-only */ -// is_player_connected(self) -int ObjectRef::l_is_player_connected(lua_State *L) -{ - NO_MAP_LOCK_REQUIRED; - // This method was once added for a bugfix, but never documented - log_deprecated(L, "is_player_connected is undocumented and " - "will be removed in a future release"); - ObjectRef *ref = checkobject(L, 1); - RemotePlayer *player = getplayer(ref); - lua_pushboolean(L, (player != NULL && player->getPeerId() != PEER_ID_INEXISTENT)); - return 1; -} - // get_player_name(self) int ObjectRef::l_get_player_name(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); RemotePlayer *player = getplayer(ref); - if (player == NULL) { + if (player == nullptr) { lua_pushlstring(L, "", 0); return 1; } - // Do it + lua_pushstring(L, player->getName()); return 1; } @@ -1133,13 +1026,15 @@ int ObjectRef::l_get_look_dir(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); - PlayerSAO* co = getplayersao(ref); - if (co == NULL) return 0; - // Do it - float pitch = co->getRadLookPitchDep(); - float yaw = co->getRadYawDep(); + PlayerSAO* playersao = getplayersao(ref); + if (playersao == nullptr) + return 0; + + float pitch = playersao->getRadLookPitchDep(); + float yaw = playersao->getRadYawDep(); v3f v(std::cos(pitch) * std::cos(yaw), std::sin(pitch), std::cos(pitch) * std::sin(yaw)); + push_v3f(L, v); return 1; } @@ -1154,10 +1049,11 @@ int ObjectRef::l_get_look_pitch(lua_State *L) "Deprecated call to get_look_pitch, use get_look_vertical instead"); ObjectRef *ref = checkobject(L, 1); - PlayerSAO* co = getplayersao(ref); - if (co == NULL) return 0; - // Do it - lua_pushnumber(L, co->getRadLookPitchDep()); + PlayerSAO* playersao = getplayersao(ref); + if (playersao == nullptr) + return 0; + + lua_pushnumber(L, playersao->getRadLookPitchDep()); return 1; } @@ -1171,34 +1067,37 @@ int ObjectRef::l_get_look_yaw(lua_State *L) "Deprecated call to get_look_yaw, use get_look_horizontal instead"); ObjectRef *ref = checkobject(L, 1); - PlayerSAO* co = getplayersao(ref); - if (co == NULL) return 0; - // Do it - lua_pushnumber(L, co->getRadYawDep()); + PlayerSAO* playersao = getplayersao(ref); + if (playersao == nullptr) + return 0; + + lua_pushnumber(L, playersao->getRadYawDep()); return 1; } -// get_look_pitch2(self) +// get_look_vertical(self) int ObjectRef::l_get_look_vertical(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); - PlayerSAO* co = getplayersao(ref); - if (co == NULL) return 0; - // Do it - lua_pushnumber(L, co->getRadLookPitch()); + PlayerSAO* playersao = getplayersao(ref); + if (playersao == nullptr) + return 0; + + lua_pushnumber(L, playersao->getRadLookPitch()); return 1; } -// get_look_yaw2(self) +// get_look_horizontal(self) int ObjectRef::l_get_look_horizontal(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); - PlayerSAO* co = getplayersao(ref); - if (co == NULL) return 0; - // Do it - lua_pushnumber(L, co->getRadRotation().Y); + PlayerSAO* playersao = getplayersao(ref); + if (playersao == nullptr) + return 0; + + lua_pushnumber(L, playersao->getRadRotation().Y); return 1; } @@ -1207,11 +1106,13 @@ int ObjectRef::l_set_look_vertical(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); - PlayerSAO* co = getplayersao(ref); - if (co == NULL) return 0; + PlayerSAO* playersao = getplayersao(ref); + if (playersao == nullptr) + return 0; + float pitch = readParam(L, 2) * core::RADTODEG; - // Do it - co->setLookPitchAndSend(pitch); + + playersao->setLookPitchAndSend(pitch); return 1; } @@ -1220,11 +1121,13 @@ int ObjectRef::l_set_look_horizontal(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); - PlayerSAO* co = getplayersao(ref); - if (co == NULL) return 0; + PlayerSAO* playersao = getplayersao(ref); + if (playersao == nullptr) + return 0; + float yaw = readParam(L, 2) * core::RADTODEG; - // Do it - co->setPlayerYawAndSend(yaw); + + playersao->setPlayerYawAndSend(yaw); return 1; } @@ -1238,11 +1141,13 @@ int ObjectRef::l_set_look_pitch(lua_State *L) "Deprecated call to set_look_pitch, use set_look_vertical instead."); ObjectRef *ref = checkobject(L, 1); - PlayerSAO* co = getplayersao(ref); - if (co == NULL) return 0; + PlayerSAO* playersao = getplayersao(ref); + if (playersao == nullptr) + return 0; + float pitch = readParam(L, 2) * core::RADTODEG; - // Do it - co->setLookPitchAndSend(pitch); + + playersao->setLookPitchAndSend(pitch); return 1; } @@ -1256,30 +1161,32 @@ int ObjectRef::l_set_look_yaw(lua_State *L) "Deprecated call to set_look_yaw, use set_look_horizontal instead."); ObjectRef *ref = checkobject(L, 1); - PlayerSAO* co = getplayersao(ref); - if (co == NULL) return 0; + PlayerSAO* playersao = getplayersao(ref); + if (playersao == nullptr) + return 0; + float yaw = readParam(L, 2) * core::RADTODEG; - // Do it - co->setPlayerYawAndSend(yaw); + + playersao->setPlayerYawAndSend(yaw); return 1; } -// set_fov(self, degrees[, is_multiplier, transition_time]) +// set_fov(self, degrees, is_multiplier, transition_time) int ObjectRef::l_set_fov(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); RemotePlayer *player = getplayer(ref); - if (!player) + if (player == nullptr) return 0; - player->setFov({ - static_cast(luaL_checknumber(L, 2)), - readParam(L, 3, false), - lua_isnumber(L, 4) ? static_cast(luaL_checknumber(L, 4)) : 0.0f - }); - getServer(L)->SendPlayerFov(player->getPeerId()); + float degrees = static_cast(luaL_checknumber(L, 2)); + bool is_multiplier = readParam(L, 3, false); + float transition_time = lua_isnumber(L, 4) ? + static_cast(luaL_checknumber(L, 4)) : 0.0f; + player->setFov({degrees, is_multiplier, transition_time}); + getServer(L)->SendPlayerFov(player->getPeerId()); return 0; } @@ -1289,14 +1196,14 @@ int ObjectRef::l_get_fov(lua_State *L) NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); RemotePlayer *player = getplayer(ref); - if (!player) + if (player == nullptr) return 0; PlayerFovSpec fov_spec = player->getFov(); + lua_pushnumber(L, fov_spec.fov); lua_pushboolean(L, fov_spec.is_multiplier); lua_pushnumber(L, fov_spec.transition_time); - return 3; } @@ -1305,11 +1212,13 @@ int ObjectRef::l_set_breath(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); - PlayerSAO* co = getplayersao(ref); - if (co == NULL) return 0; + PlayerSAO* playersao = getplayersao(ref); + if (playersao == nullptr) + return 0; + u16 breath = luaL_checknumber(L, 2); - co->setBreath(breath); + playersao->setBreath(breath); return 0; } @@ -1318,11 +1227,13 @@ int ObjectRef::l_get_breath(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); - PlayerSAO* co = getplayersao(ref); - if (co == NULL) return 0; - // Do it - u16 breath = co->getBreath(); - lua_pushinteger (L, breath); + PlayerSAO* playersao = getplayersao(ref); + if (playersao == nullptr) + return 0; + + u16 breath = playersao->getBreath(); + + lua_pushinteger(L, breath); return 1; } @@ -1333,16 +1244,16 @@ int ObjectRef::l_set_attribute(lua_State *L) "Deprecated call to set_attribute, use MetaDataRef methods instead."); ObjectRef *ref = checkobject(L, 1); - PlayerSAO* co = getplayersao(ref); - if (co == NULL) + PlayerSAO* playersao = getplayersao(ref); + if (playersao == nullptr) return 0; std::string attr = luaL_checkstring(L, 2); if (lua_isnil(L, 3)) { - co->getMeta().removeString(attr); + playersao->getMeta().removeString(attr); } else { std::string value = luaL_checkstring(L, 3); - co->getMeta().setString(attr, value); + playersao->getMeta().setString(attr, value); } return 1; } @@ -1354,14 +1265,14 @@ int ObjectRef::l_get_attribute(lua_State *L) "Deprecated call to get_attribute, use MetaDataRef methods instead."); ObjectRef *ref = checkobject(L, 1); - PlayerSAO* co = getplayersao(ref); - if (co == NULL) + PlayerSAO* playersao = getplayersao(ref); + if (playersao == nullptr) return 0; std::string attr = luaL_checkstring(L, 2); std::string value; - if (co->getMeta().getStringToRef(attr, value)) { + if (playersao->getMeta().getStringToRef(attr, value)) { lua_pushstring(L, value.c_str()); return 1; } @@ -1374,11 +1285,11 @@ int ObjectRef::l_get_attribute(lua_State *L) int ObjectRef::l_get_meta(lua_State *L) { ObjectRef *ref = checkobject(L, 1); - PlayerSAO *co = getplayersao(ref); - if (co == NULL) + PlayerSAO *playersao = getplayersao(ref); + if (playersao == nullptr) return 0; - PlayerMetaRef::create(L, &co->getMeta()); + PlayerMetaRef::create(L, &playersao->getMeta()); return 1; } @@ -1389,7 +1300,9 @@ int ObjectRef::l_set_inventory_formspec(lua_State *L) NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); RemotePlayer *player = getplayer(ref); - if (player == NULL) return 0; + if (player == nullptr) + return 0; + std::string formspec = luaL_checkstring(L, 2); player->inventory_formspec = formspec; @@ -1404,9 +1317,11 @@ int ObjectRef::l_get_inventory_formspec(lua_State *L) NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); RemotePlayer *player = getplayer(ref); - if (player == NULL) return 0; + if (player == nullptr) + return 0; std::string formspec = player->inventory_formspec; + lua_pushlstring(L, formspec.c_str(), formspec.size()); return 1; } @@ -1417,7 +1332,7 @@ int ObjectRef::l_set_formspec_prepend(lua_State *L) NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); RemotePlayer *player = getplayer(ref); - if (player == NULL) + if (player == nullptr) return 0; std::string formspec = luaL_checkstring(L, 2); @@ -1428,16 +1343,17 @@ int ObjectRef::l_set_formspec_prepend(lua_State *L) return 1; } -// get_formspec_prepend(self) -> formspec +// get_formspec_prepend(self) int ObjectRef::l_get_formspec_prepend(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); RemotePlayer *player = getplayer(ref); - if (player == NULL) + if (player == nullptr) return 0; std::string formspec = player->formspec_prepend; + lua_pushlstring(L, formspec.c_str(), formspec.size()); return 1; } @@ -1448,7 +1364,7 @@ int ObjectRef::l_get_player_control(lua_State *L) NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); RemotePlayer *player = getplayer(ref); - if (player == NULL) { + if (player == nullptr) { lua_pushlstring(L, "", 0); return 1; } @@ -1489,22 +1405,73 @@ int ObjectRef::l_get_player_control_bits(lua_State *L) NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); RemotePlayer *player = getplayer(ref); - if (player == NULL) { + if (player == nullptr) { lua_pushlstring(L, "", 0); return 1; } - // Do it + lua_pushnumber(L, player->keyPressed); return 1; } -// hud_add(self, form) +// set_physics_override(self, override_table) +int ObjectRef::l_set_physics_override(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + PlayerSAO *playersao = (PlayerSAO *) getobject(ref); + if (playersao == nullptr) + return 0; + + luaL_checktype(L, 2, LUA_TTABLE); + playersao->m_physics_override_speed = getfloatfield_default( + L, 2, "speed", playersao->m_physics_override_speed); + playersao->m_physics_override_jump = getfloatfield_default( + L, 2, "jump", playersao->m_physics_override_jump); + playersao->m_physics_override_gravity = getfloatfield_default( + L, 2, "gravity", playersao->m_physics_override_gravity); + playersao->m_physics_override_sneak = getboolfield_default( + L, 2, "sneak", playersao->m_physics_override_sneak); + playersao->m_physics_override_sneak_glitch = getboolfield_default( + L, 2, "sneak_glitch", playersao->m_physics_override_sneak_glitch); + playersao->m_physics_override_new_move = getboolfield_default( + L, 2, "new_move", playersao->m_physics_override_new_move); + playersao->m_physics_override_sent = false; + return 0; +} + +// get_physics_override(self) +int ObjectRef::l_get_physics_override(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + PlayerSAO *playersao = (PlayerSAO *)getobject(ref); + if (playersao == nullptr) + return 0; + + lua_newtable(L); + lua_pushnumber(L, playersao->m_physics_override_speed); + lua_setfield(L, -2, "speed"); + lua_pushnumber(L, playersao->m_physics_override_jump); + lua_setfield(L, -2, "jump"); + lua_pushnumber(L, playersao->m_physics_override_gravity); + lua_setfield(L, -2, "gravity"); + lua_pushboolean(L, playersao->m_physics_override_sneak); + lua_setfield(L, -2, "sneak"); + lua_pushboolean(L, playersao->m_physics_override_sneak_glitch); + lua_setfield(L, -2, "sneak_glitch"); + lua_pushboolean(L, playersao->m_physics_override_new_move); + lua_setfield(L, -2, "new_move"); + return 1; +} + +// hud_add(self, hud) int ObjectRef::l_hud_add(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); RemotePlayer *player = getplayer(ref); - if (player == NULL) + if (player == nullptr) return 0; HudElement *elem = new HudElement; @@ -1526,12 +1493,10 @@ int ObjectRef::l_hud_remove(lua_State *L) NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); RemotePlayer *player = getplayer(ref); - if (player == NULL) + if (player == nullptr) return 0; - u32 id = -1; - if (!lua_isnil(L, 2)) - id = lua_tonumber(L, 2); + u32 id = luaL_checkint(L, 2); if (!getServer(L)->hudRemove(player, id)) return 0; @@ -1546,17 +1511,17 @@ int ObjectRef::l_hud_change(lua_State *L) NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); RemotePlayer *player = getplayer(ref); - if (player == NULL) + if (player == nullptr) return 0; - u32 id = lua_isnumber(L, 2) ? lua_tonumber(L, 2) : -1; + u32 id = luaL_checkint(L, 2); - HudElement *e = player->getHud(id); - if (!e) + HudElement *elem = player->getHud(id); + if (elem == nullptr) return 0; - void *value = NULL; - HudElementStat stat = read_hud_change(L, e, &value); + void *value = nullptr; + HudElementStat stat = read_hud_change(L, elem, &value); getServer(L)->hudChange(player, id, stat, value); @@ -1570,15 +1535,16 @@ int ObjectRef::l_hud_get(lua_State *L) NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); RemotePlayer *player = getplayer(ref); - if (player == NULL) + if (player == nullptr) return 0; - u32 id = lua_tonumber(L, -1); + u32 id = luaL_checkint(L, 2); - HudElement *e = player->getHud(id); - if (!e) + HudElement *elem = player->getHud(id); + if (elem == nullptr) return 0; - push_hud_element(L, e); + + push_hud_element(L, elem); return 1; } @@ -1588,7 +1554,7 @@ int ObjectRef::l_hud_set_flags(lua_State *L) NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); RemotePlayer *player = getplayer(ref); - if (player == NULL) + if (player == nullptr) return 0; u32 flags = 0; @@ -1609,12 +1575,13 @@ int ObjectRef::l_hud_set_flags(lua_State *L) return 1; } +// hud_get_flags(self) int ObjectRef::l_hud_get_flags(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); RemotePlayer *player = getplayer(ref); - if (player == NULL) + if (player == nullptr) return 0; lua_newtable(L); @@ -1632,7 +1599,6 @@ int ObjectRef::l_hud_get_flags(lua_State *L) lua_setfield(L, -2, "minimap"); lua_pushboolean(L, player->hud_flags & HUD_FLAG_MINIMAP_RADAR_VISIBLE); lua_setfield(L, -2, "minimap_radar"); - return 1; } @@ -1642,10 +1608,10 @@ int ObjectRef::l_hud_set_hotbar_itemcount(lua_State *L) NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); RemotePlayer *player = getplayer(ref); - if (player == NULL) + if (player == nullptr) return 0; - s32 hotbar_itemcount = lua_tonumber(L, 2); + s32 hotbar_itemcount = luaL_checkint(L, 2); if (!getServer(L)->hudSetHotbarItemcount(player, hotbar_itemcount)) return 0; @@ -1660,7 +1626,7 @@ int ObjectRef::l_hud_get_hotbar_itemcount(lua_State *L) NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); RemotePlayer *player = getplayer(ref); - if (player == NULL) + if (player == nullptr) return 0; lua_pushnumber(L, player->getHotbarItemcount()); @@ -1673,7 +1639,7 @@ int ObjectRef::l_hud_set_hotbar_image(lua_State *L) NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); RemotePlayer *player = getplayer(ref); - if (player == NULL) + if (player == nullptr) return 0; std::string name = readParam(L, 2); @@ -1688,10 +1654,11 @@ int ObjectRef::l_hud_get_hotbar_image(lua_State *L) NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); RemotePlayer *player = getplayer(ref); - if (player == NULL) + if (player == nullptr) return 0; const std::string &name = player->getHotbarImage(); + lua_pushlstring(L, name.c_str(), name.size()); return 1; } @@ -1702,7 +1669,7 @@ int ObjectRef::l_hud_set_hotbar_selected_image(lua_State *L) NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); RemotePlayer *player = getplayer(ref); - if (player == NULL) + if (player == nullptr) return 0; std::string name = readParam(L, 2); @@ -1717,44 +1684,45 @@ int ObjectRef::l_hud_get_hotbar_selected_image(lua_State *L) NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); RemotePlayer *player = getplayer(ref); - if (player == NULL) + if (player == nullptr) return 0; const std::string &name = player->getHotbarSelectedImage(); + lua_pushlstring(L, name.c_str(), name.size()); return 1; } -// set_sky(self, {base_color=, type=, textures=, clouds=, sky_colors={}}) +// set_sky(self, sky_parameters) int ObjectRef::l_set_sky(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); RemotePlayer *player = getplayer(ref); - if (!player) + if (player == nullptr) return 0; + SkyboxParams sky_params = player->getSkyParams(); bool is_colorspec = is_color_table(L, 2); - SkyboxParams skybox_params = player->getSkyParams(); if (lua_istable(L, 2) && !is_colorspec) { lua_getfield(L, 2, "base_color"); if (!lua_isnil(L, -1)) - read_color(L, -1, &skybox_params.bgcolor); + read_color(L, -1, &sky_params.bgcolor); lua_pop(L, 1); lua_getfield(L, 2, "type"); if (!lua_isnil(L, -1)) - skybox_params.type = luaL_checkstring(L, -1); + sky_params.type = luaL_checkstring(L, -1); lua_pop(L, 1); lua_getfield(L, 2, "textures"); - skybox_params.textures.clear(); - if (lua_istable(L, -1) && skybox_params.type == "skybox") { + sky_params.textures.clear(); + if (lua_istable(L, -1) && sky_params.type == "skybox") { lua_pushnil(L); while (lua_next(L, -2) != 0) { // Key is at index -2 and value at index -1 - skybox_params.textures.emplace_back(readParam(L, -1)); + sky_params.textures.emplace_back(readParam(L, -1)); // Removes the value, but keeps the key for iteration lua_pop(L, 1); } @@ -1767,56 +1735,56 @@ int ObjectRef::l_set_sky(lua_State *L) using "regular" or "plain" skybox modes as textures aren't needed. */ - if (skybox_params.textures.size() != 6 && skybox_params.textures.size() > 0) + if (sky_params.textures.size() != 6 && sky_params.textures.size() > 0) throw LuaError("Skybox expects 6 textures!"); - skybox_params.clouds = getboolfield_default(L, 2, - "clouds", skybox_params.clouds); + sky_params.clouds = getboolfield_default(L, 2, + "clouds", sky_params.clouds); lua_getfield(L, 2, "sky_color"); if (lua_istable(L, -1)) { lua_getfield(L, -1, "day_sky"); - read_color(L, -1, &skybox_params.sky_color.day_sky); + read_color(L, -1, &sky_params.sky_color.day_sky); lua_pop(L, 1); lua_getfield(L, -1, "day_horizon"); - read_color(L, -1, &skybox_params.sky_color.day_horizon); + read_color(L, -1, &sky_params.sky_color.day_horizon); lua_pop(L, 1); lua_getfield(L, -1, "dawn_sky"); - read_color(L, -1, &skybox_params.sky_color.dawn_sky); + read_color(L, -1, &sky_params.sky_color.dawn_sky); lua_pop(L, 1); lua_getfield(L, -1, "dawn_horizon"); - read_color(L, -1, &skybox_params.sky_color.dawn_horizon); + read_color(L, -1, &sky_params.sky_color.dawn_horizon); lua_pop(L, 1); lua_getfield(L, -1, "night_sky"); - read_color(L, -1, &skybox_params.sky_color.night_sky); + read_color(L, -1, &sky_params.sky_color.night_sky); lua_pop(L, 1); lua_getfield(L, -1, "night_horizon"); - read_color(L, -1, &skybox_params.sky_color.night_horizon); + read_color(L, -1, &sky_params.sky_color.night_horizon); lua_pop(L, 1); lua_getfield(L, -1, "indoors"); - read_color(L, -1, &skybox_params.sky_color.indoors); + read_color(L, -1, &sky_params.sky_color.indoors); lua_pop(L, 1); // Prevent flickering clouds at dawn/dusk: - skybox_params.fog_sun_tint = video::SColor(255, 255, 255, 255); + sky_params.fog_sun_tint = video::SColor(255, 255, 255, 255); lua_getfield(L, -1, "fog_sun_tint"); - read_color(L, -1, &skybox_params.fog_sun_tint); + read_color(L, -1, &sky_params.fog_sun_tint); lua_pop(L, 1); - skybox_params.fog_moon_tint = video::SColor(255, 255, 255, 255); + sky_params.fog_moon_tint = video::SColor(255, 255, 255, 255); lua_getfield(L, -1, "fog_moon_tint"); - read_color(L, -1, &skybox_params.fog_moon_tint); + read_color(L, -1, &sky_params.fog_moon_tint); lua_pop(L, 1); lua_getfield(L, -1, "fog_tint_type"); if (!lua_isnil(L, -1)) - skybox_params.fog_tint_type = luaL_checkstring(L, -1); + sky_params.fog_tint_type = luaL_checkstring(L, -1); lua_pop(L, 1); // Because we need to leave the "sky_color" table. @@ -1832,14 +1800,14 @@ int ObjectRef::l_set_sky(lua_State *L) StarParams star_params = player->getStarParams(); // Prevent erroneous background colors - skybox_params.bgcolor = video::SColor(255, 255, 255, 255); - read_color(L, 2, &skybox_params.bgcolor); + sky_params.bgcolor = video::SColor(255, 255, 255, 255); + read_color(L, 2, &sky_params.bgcolor); - skybox_params.type = luaL_checkstring(L, 3); + sky_params.type = luaL_checkstring(L, 3); // Preserve old behaviour of the sun, moon and stars // when using the old set_sky call. - if (skybox_params.type == "regular") { + if (sky_params.type == "regular") { sun_params.visible = true; sun_params.sunrise_visible = true; moon_params.visible = true; @@ -1851,31 +1819,31 @@ int ObjectRef::l_set_sky(lua_State *L) star_params.visible = false; } - skybox_params.textures.clear(); + sky_params.textures.clear(); if (lua_istable(L, 4)) { lua_pushnil(L); while (lua_next(L, 4) != 0) { // Key at index -2, and value at index -1 if (lua_isstring(L, -1)) - skybox_params.textures.emplace_back(readParam(L, -1)); + sky_params.textures.emplace_back(readParam(L, -1)); else - skybox_params.textures.emplace_back(""); + sky_params.textures.emplace_back(""); // Remove the value, keep the key for the next iteration lua_pop(L, 1); } } - if (skybox_params.type == "skybox" && skybox_params.textures.size() != 6) + if (sky_params.type == "skybox" && sky_params.textures.size() != 6) throw LuaError("Skybox expects 6 textures."); - skybox_params.clouds = true; + sky_params.clouds = true; if (lua_isboolean(L, 5)) - skybox_params.clouds = readParam(L, 5); + sky_params.clouds = readParam(L, 5); getServer(L)->setSun(player, sun_params); getServer(L)->setMoon(player, moon_params); getServer(L)->setStars(player, star_params); } - getServer(L)->setSky(player, skybox_params); + getServer(L)->setSky(player, sky_params); lua_pushboolean(L, true); return 1; } @@ -1886,18 +1854,17 @@ int ObjectRef::l_get_sky(lua_State *L) NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); RemotePlayer *player = getplayer(ref); - - if (!player) + if (player == nullptr) return 0; - SkyboxParams skybox_params; - skybox_params = player->getSkyParams(); + + SkyboxParams skybox_params = player->getSkyParams(); push_ARGB8(L, skybox_params.bgcolor); lua_pushlstring(L, skybox_params.type.c_str(), skybox_params.type.size()); lua_newtable(L); s16 i = 1; - for (const std::string& texture : skybox_params.textures) { + for (const std::string &texture : skybox_params.textures) { lua_pushlstring(L, texture.c_str(), texture.size()); lua_rawseti(L, -2, i++); } @@ -1911,11 +1878,10 @@ int ObjectRef::l_get_sky_color(lua_State *L) NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); RemotePlayer *player = getplayer(ref); - - if (!player) + if (player == nullptr) return 0; - const SkyboxParams& skybox_params = player->getSkyParams(); + const SkyboxParams &skybox_params = player->getSkyParams(); lua_newtable(L); if (skybox_params.type == "regular") { @@ -1943,18 +1909,16 @@ int ObjectRef::l_get_sky_color(lua_State *L) return 1; } -// set_sun(self, {visible, texture=, tonemap=, sunrise=, rotation=, scale=}) +// set_sun(self, sun_parameters) int ObjectRef::l_set_sun(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); RemotePlayer *player = getplayer(ref); - if (!player) - return 0; - - if (!lua_istable(L, 2)) + if (player == nullptr) return 0; + luaL_checktype(L, 2, LUA_TTABLE); SunParams sun_params = player->getSunParams(); sun_params.visible = getboolfield_default(L, 2, @@ -1981,8 +1945,9 @@ int ObjectRef::l_get_sun(lua_State *L) NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); RemotePlayer *player = getplayer(ref); - if (!player) + if (player == nullptr) return 0; + const SunParams &sun_params = player->getSunParams(); lua_newtable(L); @@ -1998,21 +1963,19 @@ int ObjectRef::l_get_sun(lua_State *L) lua_setfield(L, -2, "sunrise_visible"); lua_pushnumber(L, sun_params.scale); lua_setfield(L, -2, "scale"); - return 1; } -// set_moon(self, {visible, texture=, tonemap=, sunrise=, rotation=, scale=}) +// set_moon(self, moon_parameters) int ObjectRef::l_set_moon(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); RemotePlayer *player = getplayer(ref); - if (!player) - return 0; - if (!lua_istable(L, 2)) + if (player == nullptr) return 0; + luaL_checktype(L, 2, LUA_TTABLE); MoonParams moon_params = player->getMoonParams(); moon_params.visible = getboolfield_default(L, 2, @@ -2035,8 +1998,9 @@ int ObjectRef::l_get_moon(lua_State *L) NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); RemotePlayer *player = getplayer(ref); - if (!player) + if (player == nullptr) return 0; + const MoonParams &moon_params = player->getMoonParams(); lua_newtable(L); @@ -2048,21 +2012,19 @@ int ObjectRef::l_get_moon(lua_State *L) lua_setfield(L, -2, "tonemap"); lua_pushnumber(L, moon_params.scale); lua_setfield(L, -2, "scale"); - return 1; } -// set_stars(self, {visible, count=, starcolor=, rotation=, scale=}) +// set_stars(self, star_parameters) int ObjectRef::l_set_stars(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); RemotePlayer *player = getplayer(ref); - if (!player) - return 0; - if (!lua_istable(L, 2)) + if (player == nullptr) return 0; + luaL_checktype(L, 2, LUA_TTABLE); StarParams star_params = player->getStarParams(); star_params.visible = getboolfield_default(L, 2, @@ -2089,8 +2051,9 @@ int ObjectRef::l_get_stars(lua_State *L) NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); RemotePlayer *player = getplayer(ref); - if (!player) + if (player == nullptr) return 0; + const StarParams &star_params = player->getStarParams(); lua_newtable(L); @@ -2102,21 +2065,19 @@ int ObjectRef::l_get_stars(lua_State *L) lua_setfield(L, -2, "star_color"); lua_pushnumber(L, star_params.scale); lua_setfield(L, -2, "scale"); - return 1; } -// set_clouds(self, {density=, color=, ambient=, height=, thickness=, speed=}) +// set_clouds(self, cloud_parameters) int ObjectRef::l_set_clouds(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); RemotePlayer *player = getplayer(ref); - if (!player) - return 0; - if (!lua_istable(L, 2)) + if (player == nullptr) return 0; + luaL_checktype(L, 2, LUA_TTABLE); CloudParams cloud_params = player->getCloudParams(); cloud_params.density = getfloatfield_default(L, 2, "density", cloud_params.density); @@ -2152,8 +2113,9 @@ int ObjectRef::l_get_clouds(lua_State *L) NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); RemotePlayer *player = getplayer(ref); - if (!player) + if (player == nullptr) return 0; + const CloudParams &cloud_params = player->getCloudParams(); lua_newtable(L); @@ -2173,25 +2135,27 @@ int ObjectRef::l_get_clouds(lua_State *L) lua_pushnumber(L, cloud_params.speed.Y); lua_setfield(L, -2, "y"); lua_setfield(L, -2, "speed"); - return 1; } -// override_day_night_ratio(self, brightness=0...1) +// override_day_night_ratio(self, ratio) int ObjectRef::l_override_day_night_ratio(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); RemotePlayer *player = getplayer(ref); - if (player == NULL) + if (player == nullptr) return 0; bool do_override = false; float ratio = 0.0f; + if (!lua_isnil(L, 2)) { do_override = true; ratio = readParam(L, 2); + luaL_argcheck(L, ratio >= 0.0f && ratio <= 1.0f, 1, + "value must be between 0 and 1"); } getServer(L)->overrideDayNightRatio(player, do_override, ratio); @@ -2205,7 +2169,7 @@ int ObjectRef::l_get_day_night_ratio(lua_State *L) NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); RemotePlayer *player = getplayer(ref); - if (player == NULL) + if (player == nullptr) return 0; bool do_override; @@ -2220,26 +2184,18 @@ int ObjectRef::l_get_day_night_ratio(lua_State *L) return 1; } -// set_minimap_modes(self, modes, modeindex) +// set_minimap_modes(self, modes, selected_mode) int ObjectRef::l_set_minimap_modes(lua_State *L) { NO_MAP_LOCK_REQUIRED; - - // Arg 1 should be a player ObjectRef *ref = checkobject(L, 1); RemotePlayer *player = getplayer(ref); - if (player == NULL) + if (player == nullptr) return 0; - // Arg 2 should be a table (of tables) - if (!lua_istable(L, 2)) { - return 0; - } - - // Arg 3 should be a number - s16 wantedmode = lua_tonumber(L, 3); - + luaL_checktype(L, 2, LUA_TTABLE); std::vector modes; + s16 selected_mode = luaL_checkint(L, 3); lua_pushnil(L); while (lua_next(L, 2) != 0) { @@ -2277,31 +2233,28 @@ int ObjectRef::l_set_minimap_modes(lua_State *L) } lua_pop(L, 1); // Remove key - getServer(L)->SendMinimapModes(player->getPeerId(), modes, wantedmode); + getServer(L)->SendMinimapModes(player->getPeerId(), modes, selected_mode); return 0; } ObjectRef::ObjectRef(ServerActiveObject *object): m_object(object) -{ - //infostream<<"ObjectRef created for id="<getId()< formspec + // get_inventory_formspec(self) static int l_get_inventory_formspec(lua_State *L); // set_formspec_prepend(self, formspec) static int l_set_formspec_prepend(lua_State *L); - // get_formspec_prepend(self) -> formspec + // get_formspec_prepend(self) static int l_get_formspec_prepend(lua_State *L); // get_player_control(self) @@ -321,7 +313,7 @@ private: // hud_get_hotbar_selected_image(self) static int l_hud_get_hotbar_selected_image(lua_State *L); - // set_sky({base_color=, type=, textures=, clouds=, sky_colors={}}) + // set_sky(self, sky_parameters) static int l_set_sky(lua_State *L); // get_sky(self) @@ -330,25 +322,25 @@ private: // get_sky_color(self) static int l_get_sky_color(lua_State* L); - // set_sun(self, {visible, texture=, tonemap=, sunrise=, rotation=, scale=}) + // set_sun(self, sun_parameters) static int l_set_sun(lua_State *L); // get_sun(self) static int l_get_sun(lua_State *L); - // set_moon(self, {visible, texture=, tonemap=, rotation, scale=}) + // set_moon(self, moon_parameters) static int l_set_moon(lua_State *L); // get_moon(self) static int l_get_moon(lua_State *L); - // set_stars(self, {visible, count=, starcolor=, rotation, scale=}) + // set_stars(self, star_parameters) static int l_set_stars(lua_State *L); // get_stars(self) static int l_get_stars(lua_State *L); - // set_clouds(self, {density=, color=, ambient=, height=, thickness=, speed=}) + // set_clouds(self, cloud_parameters) static int l_set_clouds(lua_State *L); // get_clouds(self) @@ -360,13 +352,13 @@ private: // get_day_night_ratio(self) static int l_get_day_night_ratio(lua_State *L); - // set_local_animation(self, {stand/idle}, {walk}, {dig}, {walk+dig}, frame_speed) + // set_local_animation(self, idle, walk, dig, walk_while_dig, frame_speed) static int l_set_local_animation(lua_State *L); // get_local_animation(self) static int l_get_local_animation(lua_State *L); - // set_eye_offset(self, v3f first pv, v3f third pv) + // set_eye_offset(self, firstperson, thirdperson) static int l_set_eye_offset(lua_State *L); // get_eye_offset(self) -- cgit v1.2.3 From 707c8c1e95d8db2d84909e7957b4dc9138e05599 Mon Sep 17 00:00:00 2001 From: Vitaliy Date: Sun, 25 Oct 2020 20:01:03 +0300 Subject: Shaders for Android (GLES 2) (#10506) Shader support for OpenGL ES 2 devices (Android) Co-authored-by: sfan5 --- build/android/app/build.gradle | 5 +- builtin/mainmenu/tab_settings.lua | 11 +- builtin/settingtypes.txt | 4 +- .../3d_interlaced_merge/opengl_fragment.glsl | 4 +- .../shaders/3d_interlaced_merge/opengl_vertex.glsl | 7 +- client/shaders/default_shader/opengl_fragment.glsl | 4 +- client/shaders/default_shader/opengl_vertex.glsl | 8 +- client/shaders/minimap_shader/opengl_fragment.glsl | 7 +- client/shaders/minimap_shader/opengl_vertex.glsl | 10 +- client/shaders/nodes_shader/opengl_fragment.glsl | 13 +- client/shaders/nodes_shader/opengl_vertex.glsl | 42 ++--- client/shaders/object_shader/opengl_fragment.glsl | 11 +- client/shaders/object_shader/opengl_vertex.glsl | 25 +-- .../shaders/selection_shader/opengl_fragment.glsl | 7 +- client/shaders/selection_shader/opengl_vertex.glsl | 9 +- games/devtest/mods/basenodes/init.lua | 4 + src/client/shader.cpp | 182 +++++++++++++++------ 17 files changed, 233 insertions(+), 120 deletions(-) (limited to 'src') diff --git a/build/android/app/build.gradle b/build/android/app/build.gradle index 812726030..fccb7b3b4 100644 --- a/build/android/app/build.gradle +++ b/build/android/app/build.gradle @@ -64,10 +64,9 @@ task prepareAssets() { copy { from "${projRoot}/builtin" into "${assetsFolder}/builtin" } - /*copy { - // ToDo: fix Minetest shaders that currently don't work with OpenGL ES + copy { from "${projRoot}/client/shaders" into "${assetsFolder}/client/shaders" - }*/ + } copy { from "../native/deps/Android/Irrlicht/shaders" into "${assetsFolder}/client/shaders/Irrlicht" } diff --git a/builtin/mainmenu/tab_settings.lua b/builtin/mainmenu/tab_settings.lua index 8a7445394..29744048a 100644 --- a/builtin/mainmenu/tab_settings.lua +++ b/builtin/mainmenu/tab_settings.lua @@ -154,15 +154,18 @@ local function formspec(tabview, name, tabdata) "box[8,0;3.75,4.5;#999999]" local video_driver = core.settings:get("video_driver") - local shaders_supported = video_driver == "opengl" - local shaders_enabled = false - if shaders_supported then - shaders_enabled = core.settings:get_bool("enable_shaders") + local shaders_enabled = core.settings:get_bool("enable_shaders") + if video_driver == "opengl" then tab_string = tab_string .. "checkbox[8.25,0;cb_shaders;" .. fgettext("Shaders") .. ";" .. tostring(shaders_enabled) .. "]" + elseif video_driver == "ogles2" then + tab_string = tab_string .. + "checkbox[8.25,0;cb_shaders;" .. fgettext("Shaders (experimental)") .. ";" + .. tostring(shaders_enabled) .. "]" else core.settings:set_bool("enable_shaders", false) + shaders_enabled = false tab_string = tab_string .. "label[8.38,0.2;" .. core.colorize("#888888", fgettext("Shaders (unavailable)")) .. "]" diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index 27f375693..36446f808 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -658,8 +658,8 @@ texture_path (Texture path) path # The rendering back-end for Irrlicht. # A restart is required after changing this. # Note: On Android, stick with OGLES1 if unsure! App may fail to start otherwise. -# On other platforms, OpenGL is recommended, and it’s the only driver with -# shader support currently. +# On other platforms, OpenGL is recommended. +# Shaders are supported by OpenGL (desktop only) and OGLES2 (experimental) video_driver (Video driver) enum opengl null,software,burningsvideo,direct3d8,direct3d9,opengl,ogles1,ogles2 # Radius of cloud area stated in number of 64 node cloud squares. diff --git a/client/shaders/3d_interlaced_merge/opengl_fragment.glsl b/client/shaders/3d_interlaced_merge/opengl_fragment.glsl index 25945ad7f..7cba61b39 100644 --- a/client/shaders/3d_interlaced_merge/opengl_fragment.glsl +++ b/client/shaders/3d_interlaced_merge/opengl_fragment.glsl @@ -6,9 +6,11 @@ uniform sampler2D textureFlags; #define rightImage normalTexture #define maskImage textureFlags +varying mediump vec2 varTexCoord; + void main(void) { - vec2 uv = gl_TexCoord[0].st; + vec2 uv = varTexCoord.st; vec4 left = texture2D(leftImage, uv).rgba; vec4 right = texture2D(rightImage, uv).rgba; vec4 mask = texture2D(maskImage, uv).rgba; diff --git a/client/shaders/3d_interlaced_merge/opengl_vertex.glsl b/client/shaders/3d_interlaced_merge/opengl_vertex.glsl index 4e0b2b125..860049481 100644 --- a/client/shaders/3d_interlaced_merge/opengl_vertex.glsl +++ b/client/shaders/3d_interlaced_merge/opengl_vertex.glsl @@ -1,6 +1,7 @@ +varying mediump vec2 varTexCoord; + void main(void) { - gl_TexCoord[0] = gl_MultiTexCoord0; - gl_Position = gl_Vertex; - gl_FrontColor = gl_BackColor = gl_Color; + varTexCoord = inTexCoord0; + gl_Position = inVertexPosition; } diff --git a/client/shaders/default_shader/opengl_fragment.glsl b/client/shaders/default_shader/opengl_fragment.glsl index 925ab6e1d..5018ac6ea 100644 --- a/client/shaders/default_shader/opengl_fragment.glsl +++ b/client/shaders/default_shader/opengl_fragment.glsl @@ -1,4 +1,6 @@ +varying lowp vec4 varColor; + void main(void) { - gl_FragColor = gl_Color; + gl_FragColor = varColor; } diff --git a/client/shaders/default_shader/opengl_vertex.glsl b/client/shaders/default_shader/opengl_vertex.glsl index d0b16c8b0..d95a3c2d3 100644 --- a/client/shaders/default_shader/opengl_vertex.glsl +++ b/client/shaders/default_shader/opengl_vertex.glsl @@ -1,9 +1,7 @@ -uniform mat4 mWorldViewProj; +varying lowp vec4 varColor; void main(void) { - gl_TexCoord[0] = gl_MultiTexCoord0; - gl_Position = mWorldViewProj * gl_Vertex; - - gl_FrontColor = gl_BackColor = gl_Color; + gl_Position = mWorldViewProj * inVertexPosition; + varColor = inVertexColor; } diff --git a/client/shaders/minimap_shader/opengl_fragment.glsl b/client/shaders/minimap_shader/opengl_fragment.glsl index fa4f9cb1a..cef359e8a 100644 --- a/client/shaders/minimap_shader/opengl_fragment.glsl +++ b/client/shaders/minimap_shader/opengl_fragment.glsl @@ -2,9 +2,12 @@ uniform sampler2D baseTexture; uniform sampler2D normalTexture; uniform vec3 yawVec; +varying lowp vec4 varColor; +varying mediump vec2 varTexCoord; + void main (void) { - vec2 uv = gl_TexCoord[0].st; + vec2 uv = varTexCoord.st; //texture sampling rate const float step = 1.0 / 256.0; @@ -27,6 +30,6 @@ void main (void) vec3 color = (1.1 * diffuse + 0.05 * height + 0.5 * specular) * base.rgb; vec4 col = vec4(color.rgb, base.a); - col *= gl_Color; + col *= varColor; gl_FragColor = vec4(col.rgb, base.a); } diff --git a/client/shaders/minimap_shader/opengl_vertex.glsl b/client/shaders/minimap_shader/opengl_vertex.glsl index 88f9356d5..1a9491805 100644 --- a/client/shaders/minimap_shader/opengl_vertex.glsl +++ b/client/shaders/minimap_shader/opengl_vertex.glsl @@ -1,9 +1,11 @@ -uniform mat4 mWorldViewProj; uniform mat4 mWorld; +varying lowp vec4 varColor; +varying mediump vec2 varTexCoord; + void main(void) { - gl_TexCoord[0] = gl_MultiTexCoord0; - gl_Position = mWorldViewProj * gl_Vertex; - gl_FrontColor = gl_BackColor = gl_Color; + varTexCoord = inTexCoord0.st; + gl_Position = mWorldViewProj * inVertexPosition; + varColor = inVertexColor; } diff --git a/client/shaders/nodes_shader/opengl_fragment.glsl b/client/shaders/nodes_shader/opengl_fragment.glsl index 36d47d1f5..82c87073a 100644 --- a/client/shaders/nodes_shader/opengl_fragment.glsl +++ b/client/shaders/nodes_shader/opengl_fragment.glsl @@ -15,11 +15,12 @@ varying vec3 vPosition; // cameraOffset + worldPosition (for large coordinates the limits of float // precision must be considered). varying vec3 worldPosition; - +varying lowp vec4 varColor; +varying mediump vec2 varTexCoord; varying vec3 eyeVec; const float fogStart = FOG_START; -const float fogShadingParameter = 1 / ( 1 - fogStart); +const float fogShadingParameter = 1.0 / ( 1.0 - fogStart); #ifdef ENABLE_TONE_MAPPING @@ -56,13 +57,13 @@ vec4 applyToneMapping(vec4 color) void main(void) { vec3 color; - vec2 uv = gl_TexCoord[0].st; + vec2 uv = varTexCoord.st; vec4 base = texture2D(baseTexture, uv).rgba; - #ifdef USE_DISCARD // If alpha is zero, we can just discard the pixel. This fixes transparency - // on GPUs like GC7000L, where GL_ALPHA_TEST is not implemented in mesa. + // on GPUs like GC7000L, where GL_ALPHA_TEST is not implemented in mesa, + // and also on GLES 2, where GL_ALPHA_TEST is missing entirely. if (base.a == 0.0) { discard; } @@ -70,7 +71,7 @@ void main(void) color = base.rgb; - vec4 col = vec4(color.rgb * gl_Color.rgb, 1.0); + vec4 col = vec4(color.rgb * varColor.rgb, 1.0); #ifdef ENABLE_TONE_MAPPING col = applyToneMapping(col); diff --git a/client/shaders/nodes_shader/opengl_vertex.glsl b/client/shaders/nodes_shader/opengl_vertex.glsl index 56bff09a8..cb344f6e6 100644 --- a/client/shaders/nodes_shader/opengl_vertex.glsl +++ b/client/shaders/nodes_shader/opengl_vertex.glsl @@ -1,4 +1,3 @@ -uniform mat4 mWorldViewProj; uniform mat4 mWorld; // Color of the light emitted by the sun. @@ -16,7 +15,8 @@ varying vec3 vPosition; // cameraOffset + worldPosition (for large coordinates the limits of float // precision must be considered). varying vec3 worldPosition; - +varying lowp vec4 varColor; +varying mediump vec2 varTexCoord; varying vec3 eyeVec; // Color of the light emitted by the light sources. @@ -81,13 +81,13 @@ float snoise(vec3 p) void main(void) { - gl_TexCoord[0] = gl_MultiTexCoord0; + varTexCoord = inTexCoord0.st; float disp_x; float disp_z; // OpenGL < 4.3 does not support continued preprocessor lines #if (MATERIAL_TYPE == TILE_MATERIAL_WAVING_LEAVES && ENABLE_WAVING_LEAVES) || (MATERIAL_TYPE == TILE_MATERIAL_WAVING_PLANTS && ENABLE_WAVING_PLANTS) - vec4 pos2 = mWorld * gl_Vertex; + vec4 pos2 = mWorld * inVertexPosition; float tOffset = (pos2.x + pos2.y) * 0.001 + pos2.z * 0.002; disp_x = (smoothTriangleWave(animationTimer * 23.0 + tOffset) + smoothTriangleWave(animationTimer * 11.0 + tOffset)) * 0.4; @@ -96,43 +96,43 @@ void main(void) smoothTriangleWave(animationTimer * 13.0 + tOffset)) * 0.5; #endif - worldPosition = (mWorld * gl_Vertex).xyz; + worldPosition = (mWorld * inVertexPosition).xyz; // OpenGL < 4.3 does not support continued preprocessor lines #if (MATERIAL_TYPE == TILE_MATERIAL_WAVING_LIQUID_TRANSPARENT || MATERIAL_TYPE == TILE_MATERIAL_WAVING_LIQUID_OPAQUE || MATERIAL_TYPE == TILE_MATERIAL_WAVING_LIQUID_BASIC) && ENABLE_WAVING_WATER // Generate waves with Perlin-type noise. // The constants are calibrated such that they roughly // correspond to the old sine waves. - vec4 pos = gl_Vertex; + vec4 pos = inVertexPosition; vec3 wavePos = worldPosition + cameraOffset; // The waves are slightly compressed along the z-axis to get // wave-fronts along the x-axis. - wavePos.x /= WATER_WAVE_LENGTH * 3; - wavePos.z /= WATER_WAVE_LENGTH * 2; - wavePos.z += animationTimer * WATER_WAVE_SPEED * 10; - pos.y += (snoise(wavePos) - 1) * WATER_WAVE_HEIGHT * 5; + wavePos.x /= WATER_WAVE_LENGTH * 3.0; + wavePos.z /= WATER_WAVE_LENGTH * 2.0; + wavePos.z += animationTimer * WATER_WAVE_SPEED * 10.0; + pos.y += (snoise(wavePos) - 1.0) * WATER_WAVE_HEIGHT * 5.0; gl_Position = mWorldViewProj * pos; #elif MATERIAL_TYPE == TILE_MATERIAL_WAVING_LEAVES && ENABLE_WAVING_LEAVES - vec4 pos = gl_Vertex; + vec4 pos = inVertexPosition; pos.x += disp_x; pos.y += disp_z * 0.1; pos.z += disp_z; gl_Position = mWorldViewProj * pos; #elif MATERIAL_TYPE == TILE_MATERIAL_WAVING_PLANTS && ENABLE_WAVING_PLANTS - vec4 pos = gl_Vertex; - if (gl_TexCoord[0].y < 0.05) { + vec4 pos = inVertexPosition; + if (varTexCoord.y < 0.05) { pos.x += disp_x; pos.z += disp_z; } gl_Position = mWorldViewProj * pos; #else - gl_Position = mWorldViewProj * gl_Vertex; + gl_Position = mWorldViewProj * inVertexPosition; #endif vPosition = gl_Position.xyz; - eyeVec = -(gl_ModelViewMatrix * gl_Vertex).xyz; + eyeVec = -(mWorldView * inVertexPosition).xyz; // Calculate color. // Red, green and blue components are pre-multiplied with @@ -141,16 +141,16 @@ void main(void) // The pre-baked colors are halved to prevent overflow. vec4 color; // The alpha gives the ratio of sunlight in the incoming light. - float nightRatio = 1 - gl_Color.a; - color.rgb = gl_Color.rgb * (gl_Color.a * dayLight.rgb + - nightRatio * artificialLight.rgb) * 2; - color.a = 1; + float nightRatio = 1.0 - inVertexColor.a; + color.rgb = inVertexColor.rgb * (inVertexColor.a * dayLight.rgb + + nightRatio * artificialLight.rgb) * 2.0; + color.a = 1.0; // Emphase blue a bit in darker places // See C++ implementation in mapblock_mesh.cpp final_color_blend() - float brightness = (color.r + color.g + color.b) / 3; + float brightness = (color.r + color.g + color.b) / 3.0; color.b += max(0.0, 0.021 - abs(0.2 * brightness - 0.021) + 0.07 * brightness); - gl_FrontColor = gl_BackColor = clamp(color, 0.0, 1.0); + varColor = clamp(color, 0.0, 1.0); } diff --git a/client/shaders/object_shader/opengl_fragment.glsl b/client/shaders/object_shader/opengl_fragment.glsl index 86d5c1c92..7ac182a63 100644 --- a/client/shaders/object_shader/opengl_fragment.glsl +++ b/client/shaders/object_shader/opengl_fragment.glsl @@ -8,6 +8,8 @@ uniform vec3 eyePosition; varying vec3 vNormal; varying vec3 vPosition; varying vec3 worldPosition; +varying lowp vec4 varColor; +varying mediump vec2 varTexCoord; varying vec3 eyeVec; varying float vIDiff; @@ -15,7 +17,7 @@ varying float vIDiff; const float e = 2.718281828459; const float BS = 10.0; const float fogStart = FOG_START; -const float fogShadingParameter = 1 / ( 1 - fogStart); +const float fogShadingParameter = 1.0 / (1.0 - fogStart); #ifdef ENABLE_TONE_MAPPING @@ -52,13 +54,14 @@ vec4 applyToneMapping(vec4 color) void main(void) { vec3 color; - vec2 uv = gl_TexCoord[0].st; + vec2 uv = varTexCoord.st; vec4 base = texture2D(baseTexture, uv).rgba; #ifdef USE_DISCARD // If alpha is zero, we can just discard the pixel. This fixes transparency - // on GPUs like GC7000L, where GL_ALPHA_TEST is not implemented in mesa. + // on GPUs like GC7000L, where GL_ALPHA_TEST is not implemented in mesa, + // and also on GLES 2, where GL_ALPHA_TEST is missing entirely. if (base.a == 0.0) { discard; } @@ -68,7 +71,7 @@ void main(void) vec4 col = vec4(color.rgb, base.a); - col.rgb *= gl_Color.rgb; + col.rgb *= varColor.rgb; col.rgb *= emissiveColor.rgb * vIDiff; diff --git a/client/shaders/object_shader/opengl_vertex.glsl b/client/shaders/object_shader/opengl_vertex.glsl index f8c1cd932..e44984dc8 100644 --- a/client/shaders/object_shader/opengl_vertex.glsl +++ b/client/shaders/object_shader/opengl_vertex.glsl @@ -1,4 +1,3 @@ -uniform mat4 mWorldViewProj; uniform mat4 mWorld; uniform vec3 eyePosition; @@ -7,6 +6,8 @@ uniform float animationTimer; varying vec3 vNormal; varying vec3 vPosition; varying vec3 worldPosition; +varying lowp vec4 varColor; +varying mediump vec2 varTexCoord; varying vec3 eyeVec; varying float vIDiff; @@ -18,31 +19,31 @@ float directional_ambient(vec3 normal) { vec3 v = normal * normal; - if (normal.y < 0) - return dot(v, vec3(0.670820f, 0.447213f, 0.836660f)); + if (normal.y < 0.0) + return dot(v, vec3(0.670820, 0.447213, 0.836660)); - return dot(v, vec3(0.670820f, 1.000000f, 0.836660f)); + return dot(v, vec3(0.670820, 1.000000, 0.836660)); } void main(void) { - gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; - gl_Position = mWorldViewProj * gl_Vertex; + varTexCoord = (mTexture * inTexCoord0).st; + gl_Position = mWorldViewProj * inVertexPosition; vPosition = gl_Position.xyz; - vNormal = gl_Normal; - worldPosition = (mWorld * gl_Vertex).xyz; - eyeVec = -(gl_ModelViewMatrix * gl_Vertex).xyz; + vNormal = inVertexNormal; + worldPosition = (mWorld * inVertexPosition).xyz; + eyeVec = -(mWorldView * inVertexPosition).xyz; #if (MATERIAL_TYPE == TILE_MATERIAL_PLAIN) || (MATERIAL_TYPE == TILE_MATERIAL_PLAIN_ALPHA) vIDiff = 1.0; #else // This is intentional comparison with zero without any margin. // If normal is not equal to zero exactly, then we assume it's a valid, just not normalized vector - vIDiff = length(gl_Normal) == 0.0 + vIDiff = length(inVertexNormal) == 0.0 ? 1.0 - : directional_ambient(normalize(gl_Normal)); + : directional_ambient(normalize(inVertexNormal)); #endif - gl_FrontColor = gl_BackColor = gl_Color; + varColor = inVertexColor; } diff --git a/client/shaders/selection_shader/opengl_fragment.glsl b/client/shaders/selection_shader/opengl_fragment.glsl index c679d0e12..35b1f8902 100644 --- a/client/shaders/selection_shader/opengl_fragment.glsl +++ b/client/shaders/selection_shader/opengl_fragment.glsl @@ -1,9 +1,12 @@ uniform sampler2D baseTexture; +varying lowp vec4 varColor; +varying mediump vec2 varTexCoord; + void main(void) { - vec2 uv = gl_TexCoord[0].st; + vec2 uv = varTexCoord.st; vec4 color = texture2D(baseTexture, uv); - color.rgb *= gl_Color.rgb; + color.rgb *= varColor.rgb; gl_FragColor = color; } diff --git a/client/shaders/selection_shader/opengl_vertex.glsl b/client/shaders/selection_shader/opengl_vertex.glsl index d0b16c8b0..9ca87a9cf 100644 --- a/client/shaders/selection_shader/opengl_vertex.glsl +++ b/client/shaders/selection_shader/opengl_vertex.glsl @@ -1,9 +1,10 @@ -uniform mat4 mWorldViewProj; +varying lowp vec4 varColor; +varying mediump vec2 varTexCoord; void main(void) { - gl_TexCoord[0] = gl_MultiTexCoord0; - gl_Position = mWorldViewProj * gl_Vertex; + varTexCoord = inTexCoord0.st; + gl_Position = mWorldViewProj * inVertexPosition; - gl_FrontColor = gl_BackColor = gl_Color; + varColor = inVertexColor; } diff --git a/games/devtest/mods/basenodes/init.lua b/games/devtest/mods/basenodes/init.lua index 7ffbadbea..0cb85d808 100644 --- a/games/devtest/mods/basenodes/init.lua +++ b/games/devtest/mods/basenodes/init.lua @@ -127,6 +127,7 @@ minetest.register_node("basenodes:water_source", { description = "Water Source".."\n".. "Drowning damage: 1", drawtype = "liquid", + waving = 3, tiles = {"default_water.png"}, special_tiles = { {name = "default_water.png", backface_culling = false}, @@ -152,6 +153,7 @@ minetest.register_node("basenodes:water_flowing", { description = "Flowing Water".."\n".. "Drowning damage: 1", drawtype = "flowingliquid", + waving = 3, tiles = {"default_water_flowing.png"}, special_tiles = { {name = "default_water_flowing.png", backface_culling = false}, @@ -178,6 +180,7 @@ minetest.register_node("basenodes:river_water_source", { description = "River Water Source".."\n".. "Drowning damage: 1", drawtype = "liquid", + waving = 3, tiles = { "default_river_water.png" }, special_tiles = { {name = "default_river_water.png", backface_culling = false}, @@ -205,6 +208,7 @@ minetest.register_node("basenodes:river_water_flowing", { description = "Flowing River Water".."\n".. "Drowning damage: 1", drawtype = "flowingliquid", + waving = 3, tiles = {"default_river_water_flowing.png"}, special_tiles = { {name = "default_river_water_flowing.png", backface_culling = false}, diff --git a/src/client/shader.cpp b/src/client/shader.cpp index e2eeb4ab0..f2aa00246 100644 --- a/src/client/shader.cpp +++ b/src/client/shader.cpp @@ -37,6 +37,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "log.h" #include "gamedef.h" #include "client/tile.h" +#include "config.h" #if ENABLE_GLES #ifdef _IRR_COMPILE_WITH_OGLES1_ @@ -230,11 +231,24 @@ class MainShaderConstantSetter : public IShaderConstantSetter { CachedVertexShaderSetting m_world_view_proj; CachedVertexShaderSetting m_world; +#if ENABLE_GLES + // Modelview matrix + CachedVertexShaderSetting m_world_view; + // Texture matrix + CachedVertexShaderSetting m_texture; + // Normal matrix + CachedVertexShaderSetting m_normal; +#endif public: MainShaderConstantSetter() : - m_world_view_proj("mWorldViewProj"), - m_world("mWorld") + m_world_view_proj("mWorldViewProj") + , m_world("mWorld") +#if ENABLE_GLES + , m_world_view("mWorldView") + , m_texture("mTexture") + , m_normal("mNormal") +#endif {} ~MainShaderConstantSetter() = default; @@ -244,23 +258,42 @@ public: 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); + // Set clip matrix + core::matrix4 worldView; + worldView = driver->getTransform(video::ETS_VIEW); + worldView *= world; core::matrix4 worldViewProj; worldViewProj = driver->getTransform(video::ETS_PROJECTION); - worldViewProj *= driver->getTransform(video::ETS_VIEW); - worldViewProj *= driver->getTransform(video::ETS_WORLD); + worldViewProj *= worldView; if (is_highlevel) m_world_view_proj.set(*reinterpret_cast(worldViewProj.pointer()), services); else services->setVertexShaderConstant(worldViewProj.pointer(), 0, 4); - // 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); - +#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 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 } }; @@ -620,15 +653,62 @@ ShaderInfo generate_shader(const std::string &name, u8 material_type, u8 drawtyp return shaderinfo; // Create shaders header - std::string shaders_header = "#version 120\n"; - + bool use_gles = false; +#if ENABLE_GLES + use_gles = driver->getDriverType() == video::EDT_OGLES2; +#endif + std::string shaders_header, vertex_header, pixel_header; // geometry shaders aren’t supported in GLES<3 + if (use_gles) { + shaders_header = + "#version 100\n" + ; + vertex_header = R"( + uniform highp mat4 mWorldView; + uniform highp mat4 mWorldViewProj; + uniform mediump mat4 mTexture; + uniform mediump mat3 mNormal; + + attribute highp vec4 inVertexPosition; + attribute lowp vec4 inVertexColor; + attribute mediump vec4 inTexCoord0; + attribute mediump vec3 inVertexNormal; + attribute mediump vec4 inVertexTangent; + attribute mediump vec4 inVertexBinormal; + )"; + pixel_header = R"( + precision mediump float; + )"; + } else { + shaders_header = R"( + #version 120 + #define lowp + #define mediump + #define highp + )"; + vertex_header = R"( + #define mWorldView gl_ModelViewMatrix + #define mWorldViewProj gl_ModelViewProjectionMatrix + #define mTexture (gl_TextureMatrix[0]) + #define mNormal gl_NormalMatrix + + #define inVertexPosition gl_Vertex + #define inVertexColor gl_Color + #define inTexCoord0 gl_MultiTexCoord0 + #define inVertexNormal gl_Normal + #define inVertexTangent gl_MultiTexCoord1 + #define inVertexBinormal gl_MultiTexCoord2 + )"; + } + + bool use_discard = use_gles; #ifdef __unix__ // For renderers that should use discard instead of GL_ALPHA_TEST const char* gl_renderer = (const char*)glGetString(GL_RENDERER); - if (strstr(gl_renderer, "GC7000")) { - shaders_header += "#define USE_DISCARD\n"; - } + if (strstr(gl_renderer, "GC7000")) + use_discard = true; #endif + if (use_discard && shaderinfo.base_material != video::EMT_SOLID) + shaders_header += "#define USE_DISCARD\n"; static const char* drawTypes[] = { "NDT_NORMAL", @@ -654,7 +734,7 @@ ShaderInfo generate_shader(const std::string &name, u8 material_type, u8 drawtyp shaders_header += "#define "; shaders_header += drawTypes[i]; shaders_header += " "; - shaders_header += itos(i); + shaders_header += std::to_string(i); shaders_header += "\n"; } @@ -677,27 +757,27 @@ ShaderInfo generate_shader(const std::string &name, u8 material_type, u8 drawtyp shaders_header += "#define "; shaders_header += materialTypes[i]; shaders_header += " "; - shaders_header += itos(i); + shaders_header += std::to_string(i); shaders_header += "\n"; } shaders_header += "#define MATERIAL_TYPE "; - shaders_header += itos(material_type); + shaders_header += std::to_string(material_type); shaders_header += "\n"; shaders_header += "#define DRAW_TYPE "; - shaders_header += itos(drawtype); + shaders_header += std::to_string(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 += ftos(g_settings->getFloat("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 += ftos(g_settings->getFloat("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 += ftos(g_settings->getFloat("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"; @@ -719,7 +799,7 @@ ShaderInfo generate_shader(const std::string &name, u8 material_type, u8 drawtyp shaders_header += "#define ENABLE_TONE_MAPPING\n"; shaders_header += "#define FOG_START "; - shaders_header += ftos(rangelim(g_settings->getFloat("fog_start"), 0.0f, 0.99f)); + shaders_header += std::to_string(rangelim(g_settings->getFloat("fog_start"), 0.0f, 0.99f)); shaders_header += "\n"; // Call addHighLevelShaderMaterial() or addShaderMaterial() @@ -727,11 +807,11 @@ ShaderInfo generate_shader(const std::string &name, u8 material_type, u8 drawtyp const c8* pixel_program_ptr = 0; const c8* geometry_program_ptr = 0; if (!vertex_program.empty()) { - vertex_program = shaders_header + vertex_program; + vertex_program = shaders_header + vertex_header + vertex_program; vertex_program_ptr = vertex_program.c_str(); } if (!pixel_program.empty()) { - pixel_program = shaders_header + pixel_program; + pixel_program = shaders_header + pixel_header + pixel_program; pixel_program_ptr = pixel_program.c_str(); } if (!geometry_program.empty()) { @@ -813,27 +893,37 @@ void load_shaders(const std::string &name, SourceShaderCache *sourcecache, geometry_program = ""; is_highlevel = false; - if(enable_shaders){ - // Look for high level shaders - if(drivertype == 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; - } - else if(drivertype == video::EDT_OPENGL){ - // 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"); - } - if (!vertex_program.empty() || !pixel_program.empty() || !geometry_program.empty()){ - is_highlevel = true; - return; - } - } + 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, -- cgit v1.2.3 From 61a196378ff91411af3245504c5861da026b3b25 Mon Sep 17 00:00:00 2001 From: luk3yx Date: Mon, 26 Oct 2020 06:01:39 +1300 Subject: Fix CSMs on arm64 (#10553) --- src/script/cpp_api/s_security.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/script/cpp_api/s_security.cpp b/src/script/cpp_api/s_security.cpp index 2afa3a191..01333b941 100644 --- a/src/script/cpp_api/s_security.cpp +++ b/src/script/cpp_api/s_security.cpp @@ -629,7 +629,11 @@ int ScriptApiSecurity::sl_g_loadfile(lua_State *L) { #ifndef SERVER lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_SCRIPTAPI); +#if INDIRECT_SCRIPTAPI_RIDX + ScriptApiBase *script = (ScriptApiBase *) *(void**)(lua_touserdata(L, -1)); +#else ScriptApiBase *script = (ScriptApiBase *) lua_touserdata(L, -1); +#endif lua_pop(L, 1); // Client implementation -- cgit v1.2.3 From 68cd93b8657c0c8cad0196e79fb63e3275322e38 Mon Sep 17 00:00:00 2001 From: Lars Date: Wed, 21 Oct 2020 14:46:04 -0700 Subject: Avoid resending near blocks unnecessarily. --- src/clientiface.cpp | 79 +++++++++++++++++++++++++---------------------------- src/clientiface.h | 9 +++--- 2 files changed, 42 insertions(+), 46 deletions(-) (limited to 'src') diff --git a/src/clientiface.cpp b/src/clientiface.cpp index a01cba7e0..f5e32469b 100644 --- a/src/clientiface.cpp +++ b/src/clientiface.cpp @@ -138,26 +138,6 @@ void RemoteClient::GetNextBlocks ( camera_dir.rotateYZBy(sao->getLookPitch()); camera_dir.rotateXZBy(sao->getRotation().Y); - /*infostream<<"camera_dir=("<range_all ? "All" : itos(draw_control->wanted_range)) - << std::setprecision(3) - << " | RTT: " << client->getRTT() << "s"; + << std::setprecision(2) + << " | RTT: " << (client->getRTT() * 1000.0f) << "ms"; setStaticText(m_guitext, utf8_to_wide(os.str()).c_str()); m_guitext->setRelativePosition(core::rect(5, 5, screensize.X, -- cgit v1.2.3 From 2dff3dd03f7ba25f3fab7c360759ddbf93615668 Mon Sep 17 00:00:00 2001 From: Lars Müller <34514239+appgurueu@users.noreply.github.com> Date: Thu, 29 Oct 2020 20:15:46 +0100 Subject: Player physics: Ensure larger dtime simulation steps (#10563) --- src/client/clientenvironment.cpp | 113 ++++++++++++++++----------------------- 1 file changed, 45 insertions(+), 68 deletions(-) (limited to 'src') diff --git a/src/client/clientenvironment.cpp b/src/client/clientenvironment.cpp index f831978a8..ea7be4200 100644 --- a/src/client/clientenvironment.cpp +++ b/src/client/clientenvironment.cpp @@ -183,84 +183,61 @@ void ClientEnvironment::step(float dtime) if(dtime > 0.5) dtime = 0.5; - f32 dtime_downcount = dtime; - /* Stuff that has a maximum time increment */ - u32 loopcount = 0; - do - { - loopcount++; - - f32 dtime_part; - if(dtime_downcount > dtime_max_increment) - { - dtime_part = dtime_max_increment; - dtime_downcount -= dtime_part; - } - else - { - dtime_part = dtime_downcount; - /* - Setting this to 0 (no -=dtime_part) disables an infinite loop - when dtime_part is so small that dtime_downcount -= dtime_part - does nothing - */ - dtime_downcount = 0; - } - + u32 steps = ceil(dtime / dtime_max_increment); + f32 dtime_part = dtime / steps; + for (; steps > 0; --steps) { /* - Handle local player + Local player handling */ - { - // Control local player - lplayer->applyControl(dtime_part, this); - - // Apply physics - if (!free_move && !is_climbing) { - // Gravity - v3f speed = lplayer->getSpeed(); - if (!lplayer->in_liquid) - speed.Y -= lplayer->movement_gravity * - lplayer->physics_override_gravity * dtime_part * 2.0f; - - // Liquid floating / sinking - if (lplayer->in_liquid && !lplayer->swimming_vertical && - !lplayer->swimming_pitch) - speed.Y -= lplayer->movement_liquid_sink * dtime_part * 2.0f; - - // Liquid resistance - if (lplayer->in_liquid_stable || lplayer->in_liquid) { - // How much the node's viscosity blocks movement, ranges - // between 0 and 1. Should match the scale at which viscosity - // increase affects other liquid attributes. - static const f32 viscosity_factor = 0.3f; - - v3f d_wanted = -speed / lplayer->movement_liquid_fluidity; - f32 dl = d_wanted.getLength(); - if (dl > lplayer->movement_liquid_fluidity_smooth) - dl = lplayer->movement_liquid_fluidity_smooth; - - dl *= (lplayer->liquid_viscosity * viscosity_factor) + - (1 - viscosity_factor); - v3f d = d_wanted.normalize() * (dl * dtime_part * 100.0f); - speed += d; - } - - lplayer->setSpeed(speed); + // Control local player + lplayer->applyControl(dtime_part, this); + + // Apply physics + if (!free_move && !is_climbing) { + // Gravity + v3f speed = lplayer->getSpeed(); + if (!lplayer->in_liquid) + speed.Y -= lplayer->movement_gravity * + lplayer->physics_override_gravity * dtime_part * 2.0f; + + // Liquid floating / sinking + if (lplayer->in_liquid && !lplayer->swimming_vertical && + !lplayer->swimming_pitch) + speed.Y -= lplayer->movement_liquid_sink * dtime_part * 2.0f; + + // Liquid resistance + if (lplayer->in_liquid_stable || lplayer->in_liquid) { + // How much the node's viscosity blocks movement, ranges + // between 0 and 1. Should match the scale at which viscosity + // increase affects other liquid attributes. + static const f32 viscosity_factor = 0.3f; + + v3f d_wanted = -speed / lplayer->movement_liquid_fluidity; + f32 dl = d_wanted.getLength(); + if (dl > lplayer->movement_liquid_fluidity_smooth) + dl = lplayer->movement_liquid_fluidity_smooth; + + dl *= (lplayer->liquid_viscosity * viscosity_factor) + + (1 - viscosity_factor); + v3f d = d_wanted.normalize() * (dl * dtime_part * 100.0f); + speed += d; } - /* - Move the lplayer. - This also does collision detection. - */ - lplayer->move(dtime_part, this, position_max_increment, - &player_collisions); + lplayer->setSpeed(speed); } - } while (dtime_downcount > 0.001); + + /* + Move the lplayer. + This also does collision detection. + */ + lplayer->move(dtime_part, this, position_max_increment, + &player_collisions); + } bool player_immortal = lplayer->getCAO() && lplayer->getCAO()->isImmortal(); -- cgit v1.2.3 From 89dd05fdf35ce465fcc2b3588337f79f818a78aa Mon Sep 17 00:00:00 2001 From: rubenwardy Date: Sat, 31 Oct 2020 18:19:23 +0000 Subject: Fix segfault in deprecation logging due to tail call, log by default (#10174) --- builtin/settingtypes.txt | 6 ++-- src/defaultsettings.cpp | 4 --- src/script/common/c_internal.cpp | 20 +++++++------ src/script/common/c_internal.h | 20 +++++++++++++ src/script/lua_api/l_base.cpp | 61 +++++++--------------------------------- src/script/lua_api/l_base.h | 21 +++++++++----- src/script/lua_api/l_internal.h | 11 +++++++- src/script/lua_api/l_noise.cpp | 2 -- src/script/lua_api/l_object.cpp | 6 ++-- 9 files changed, 71 insertions(+), 80 deletions(-) (limited to 'src') diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index 36446f808..0b650c722 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -1220,10 +1220,10 @@ movement_gravity (Gravity) float 9.81 [**Advanced] # Handling for deprecated Lua API calls: -# - legacy: (try to) mimic old behaviour (default for release). -# - log: mimic and log backtrace of deprecated call (default for debug). +# - none: Do not log deprecated calls +# - log: mimic and log backtrace of deprecated call (default). # - error: abort on usage of deprecated call (suggested for mod developers). -deprecated_lua_api_handling (Deprecated Lua API handling) enum legacy legacy,log,error +deprecated_lua_api_handling (Deprecated Lua API handling) enum log none,log,error # Number of extra blocks that can be loaded by /clearobjects at once. # This is a trade-off between sqlite transaction overhead and diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 6c7d4be97..fcdf6b536 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -358,11 +358,7 @@ void set_default_settings(Settings *settings) settings->setDefault("disallow_empty_password", "false"); settings->setDefault("disable_anticheat", "false"); settings->setDefault("enable_rollback_recording", "false"); -#ifdef NDEBUG - settings->setDefault("deprecated_lua_api_handling", "legacy"); -#else settings->setDefault("deprecated_lua_api_handling", "log"); -#endif settings->setDefault("kick_msg_shutdown", "Server shutting down."); settings->setDefault("kick_msg_crash", "This server has experienced an internal error. You will now be disconnected."); diff --git a/src/script/common/c_internal.cpp b/src/script/common/c_internal.cpp index 6df1f8b7b..ad5f836c5 100644 --- a/src/script/common/c_internal.cpp +++ b/src/script/common/c_internal.cpp @@ -155,24 +155,28 @@ static void script_log(lua_State *L, const std::string &message, infostream << script_get_backtrace(L) << std::endl; } -void log_deprecated(lua_State *L, const std::string &message, int stack_depth) +DeprecatedHandlingMode get_deprecated_handling_mode() { static thread_local bool configured = false; - static thread_local bool do_log = false; - static thread_local bool do_error = false; + static thread_local DeprecatedHandlingMode ret = DeprecatedHandlingMode::Ignore; // Only read settings on first call if (!configured) { std::string value = g_settings->get("deprecated_lua_api_handling"); if (value == "log") { - do_log = true; + ret = DeprecatedHandlingMode::Log; } else if (value == "error") { - do_log = true; - do_error = true; + ret = DeprecatedHandlingMode::Error; } configured = true; } - if (do_log) - script_log(L, message, warningstream, do_error, stack_depth); + return ret; +} + +void log_deprecated(lua_State *L, const std::string &message, int stack_depth) +{ + DeprecatedHandlingMode mode = get_deprecated_handling_mode(); + if (mode != DeprecatedHandlingMode::Ignore) + script_log(L, message, warningstream, mode == DeprecatedHandlingMode::Error, stack_depth); } diff --git a/src/script/common/c_internal.h b/src/script/common/c_internal.h index 442546332..452c2dd5e 100644 --- a/src/script/common/c_internal.h +++ b/src/script/common/c_internal.h @@ -114,5 +114,25 @@ void script_error(lua_State *L, int pcall_result, const char *mod, const char *f void script_run_callbacks_f(lua_State *L, int nargs, RunCallbacksMode mode, const char *fxn); +enum class DeprecatedHandlingMode { + Ignore, + Log, + Error +}; + +/** + * Reads `deprecated_lua_api_handling` in settings, returns cached value. + * + * @return DeprecatedHandlingMode + */ +DeprecatedHandlingMode get_deprecated_handling_mode(); + +/** + * Handles a deprecation warning based on user settings + * + * @param L Lua State + * @param message The deprecation method + * @param stack_depth How far on the stack to the first user function (ie: not builtin or core) + */ void log_deprecated(lua_State *L, const std::string &message, int stack_depth=1); diff --git a/src/script/lua_api/l_base.cpp b/src/script/lua_api/l_base.cpp index 03ef5447a..f842671b8 100644 --- a/src/script/lua_api/l_base.cpp +++ b/src/script/lua_api/l_base.cpp @@ -100,32 +100,21 @@ bool ModApiBase::registerFunction(lua_State *L, const char *name, return true; } -std::unordered_map ModApiBase::m_deprecated_wrappers; -bool ModApiBase::m_error_deprecated_calls = false; - -int ModApiBase::l_deprecated_function(lua_State *L) +int ModApiBase::l_deprecated_function(lua_State *L, const char *good, const char *bad, lua_CFunction func) { thread_local std::vector deprecated_logged; + DeprecatedHandlingMode dep_mode = get_deprecated_handling_mode(); + if (dep_mode == DeprecatedHandlingMode::Ignore) + return func(L); + u64 start_time = porting::getTimeUs(); lua_Debug ar; - // Get function name for lookup - FATAL_ERROR_IF(!lua_getstack(L, 0, &ar), "lua_getstack() failed"); - FATAL_ERROR_IF(!lua_getinfo(L, "n", &ar), "lua_getinfo() failed"); - - // Combine name with line and script backtrace + // Get caller name with line and script backtrace FATAL_ERROR_IF(!lua_getstack(L, 1, &ar), "lua_getstack() failed"); FATAL_ERROR_IF(!lua_getinfo(L, "Sl", &ar), "lua_getinfo() failed"); - // Get parent class to get the wrappers map - luaL_checktype(L, 1, LUA_TUSERDATA); - void *ud = lua_touserdata(L, 1); - ModApiBase *o = *(ModApiBase**)ud; - - // New function and new function name - auto it = o->m_deprecated_wrappers.find(ar.name); - // Get backtrace and hash it to reduce the warning flood std::string backtrace = ar.short_src; backtrace.append(":").append(std::to_string(ar.currentline)); @@ -135,46 +124,16 @@ int ModApiBase::l_deprecated_function(lua_State *L) == deprecated_logged.end()) { deprecated_logged.emplace_back(hash); - warningstream << "Call to deprecated function '" << ar.name << "', please use '" - << it->second.name << "' at " << backtrace << std::endl; + warningstream << "Call to deprecated function '" << bad << "', please use '" + << good << "' at " << backtrace << std::endl; - if (m_error_deprecated_calls) + if (dep_mode == DeprecatedHandlingMode::Error) script_error(L, LUA_ERRRUN, NULL, NULL); } u64 end_time = porting::getTimeUs(); g_profiler->avg("l_deprecated_function", end_time - start_time); - return it->second.func(L); + return func(L); } -void ModApiBase::markAliasDeprecated(luaL_Reg *reg) -{ - std::string value = g_settings->get("deprecated_lua_api_handling"); - m_error_deprecated_calls = value == "error"; - - if (!m_error_deprecated_calls && value != "log") - return; - - const char *last_name = nullptr; - lua_CFunction last_func = nullptr; - - // ! Null termination ! - while (reg->func) { - if (last_func == reg->func) { - // Duplicate found - luaL_Reg original_reg; - // Do not inline struct. Breaks MSVC or is error-prone - original_reg.name = last_name; - original_reg.func = reg->func; - m_deprecated_wrappers.emplace( - std::pair(reg->name, original_reg)); - reg->func = l_deprecated_function; - } else { - last_func = reg->func; - last_name = reg->name; - } - - ++reg; - } -} diff --git a/src/script/lua_api/l_base.h b/src/script/lua_api/l_base.h index 65fce8481..aa5905d26 100644 --- a/src/script/lua_api/l_base.h +++ b/src/script/lua_api/l_base.h @@ -41,7 +41,6 @@ class Environment; class ServerInventoryManager; class ModApiBase : protected LuaHelper { - public: static ScriptApiBase* getScriptApiBase(lua_State *L); static Server* getServer(lua_State *L); @@ -75,10 +74,18 @@ public: lua_CFunction func, int top); - static int l_deprecated_function(lua_State *L); - static void markAliasDeprecated(luaL_Reg *reg); -private: - // = { , } - static std::unordered_map m_deprecated_wrappers; - static bool m_error_deprecated_calls; + /** + * A wrapper for deprecated functions. + * + * When called, handles the deprecation according to user settings and then calls `func`. + * + * @throws Lua Error if required by the user settings. + * + * @param L Lua state + * @param good Name of good function/method + * @param bad Name of deprecated function/method + * @param func Actual implementation of function + * @return value from `func` + */ + static int l_deprecated_function(lua_State *L, const char *good, const char *bad, lua_CFunction func); }; diff --git a/src/script/lua_api/l_internal.h b/src/script/lua_api/l_internal.h index a86eeaf79..a10c259ba 100644 --- a/src/script/lua_api/l_internal.h +++ b/src/script/lua_api/l_internal.h @@ -29,7 +29,16 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "common/c_internal.h" #define luamethod(class, name) {#name, class::l_##name} -#define luamethod_aliased(class, name, alias) {#name, class::l_##name}, {#alias, class::l_##name} + +#define luamethod_dep(class, good, bad) \ + {#bad, [](lua_State *L) -> int { \ + return l_deprecated_function(L, #bad, #good, &class::l_##good); \ + }} + +#define luamethod_aliased(class, name, alias) \ + luamethod(class, name), \ + luamethod_dep(class, name, alias) + #define API_FCT(name) registerFunction(L, #name, l_##name, top) // For future use diff --git a/src/script/lua_api/l_noise.cpp b/src/script/lua_api/l_noise.cpp index 9aeb15709..e0861126a 100644 --- a/src/script/lua_api/l_noise.cpp +++ b/src/script/lua_api/l_noise.cpp @@ -122,7 +122,6 @@ void LuaPerlinNoise::Register(lua_State *L) lua_pop(L, 1); - markAliasDeprecated(methods); luaL_openlib(L, 0, methods, 0); lua_pop(L, 1); @@ -381,7 +380,6 @@ void LuaPerlinNoiseMap::Register(lua_State *L) lua_pop(L, 1); - markAliasDeprecated(methods); luaL_openlib(L, 0, methods, 0); lua_pop(L, 1); diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index c3f0ec8e0..beb8dd339 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -2278,7 +2278,6 @@ void ObjectRef::Register(lua_State *L) lua_pop(L, 1); // drop metatable - markAliasDeprecated(methods); luaL_openlib(L, 0, methods, 0); // fill methodtable lua_pop(L, 1); // drop methodtable } @@ -2316,10 +2315,9 @@ luaL_Reg ObjectRef::methods[] = { luamethod(ObjectRef, get_nametag_attributes), luamethod_aliased(ObjectRef, set_velocity, setvelocity), - luamethod(ObjectRef, add_velocity), - {"add_player_velocity", ObjectRef::l_add_velocity}, + luamethod_aliased(ObjectRef, add_velocity, add_player_velocity), luamethod_aliased(ObjectRef, get_velocity, getvelocity), - {"get_player_velocity", ObjectRef::l_get_velocity}, + luamethod_dep(ObjectRef, get_velocity, get_player_velocity), // LuaEntitySAO-only luamethod_aliased(ObjectRef, set_acceleration, setacceleration), -- cgit v1.2.3 From 9c9344ceb31892a8563994190f1ec31cb872f12c Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Sun, 1 Nov 2020 12:52:09 +0100 Subject: Fix incorrect deprecation hints "good" and "bad" were swapped in the process, resulting in wrong deprecation messages --- src/script/lua_api/l_internal.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/script/lua_api/l_internal.h b/src/script/lua_api/l_internal.h index a10c259ba..672e535ca 100644 --- a/src/script/lua_api/l_internal.h +++ b/src/script/lua_api/l_internal.h @@ -32,12 +32,12 @@ with this program; if not, write to the Free Software Foundation, Inc., #define luamethod_dep(class, good, bad) \ {#bad, [](lua_State *L) -> int { \ - return l_deprecated_function(L, #bad, #good, &class::l_##good); \ + return l_deprecated_function(L, #good, #bad, &class::l_##good); \ }} -#define luamethod_aliased(class, name, alias) \ - luamethod(class, name), \ - luamethod_dep(class, name, alias) +#define luamethod_aliased(class, good, bad) \ + luamethod(class, good), \ + luamethod_dep(class, good, bad) #define API_FCT(name) registerFunction(L, #name, l_##name, top) -- cgit v1.2.3 From 0abb3e89fa6298041faa7e46d437e5a81f71cdd3 Mon Sep 17 00:00:00 2001 From: red-001 Date: Mon, 2 Nov 2020 21:21:03 +0000 Subject: Block attempts to connect to the client (#10589) A Minetest peer initiates a connection by sending a packet with an invalid peer_id, for whatever reason the code for doing this ran on both the client and the server meaning you could connect to a client if you knew what the address:port tuple it was listening on. --- src/network/connection.cpp | 2 +- src/network/connection.h | 5 +++++ src/network/connectionthreads.cpp | 5 ++++- 3 files changed, 10 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/network/connection.cpp b/src/network/connection.cpp index 1875d1461..0ba8c36b2 100644 --- a/src/network/connection.cpp +++ b/src/network/connection.cpp @@ -1566,7 +1566,7 @@ void Connection::sendAck(session_t peer_id, u8 channelnum, u16 seqnum) UDPPeer* Connection::createServerPeer(Address& address) { - if (getPeerNoEx(PEER_ID_SERVER) != 0) + if (ConnectedToServer()) { throw ConnectionException("Already connected to a server"); } diff --git a/src/network/connection.h b/src/network/connection.h index 2dc6d4397..24cd4fe4a 100644 --- a/src/network/connection.h +++ b/src/network/connection.h @@ -809,6 +809,11 @@ protected: void putEvent(ConnectionEvent &e); void TriggerSend(); + + bool ConnectedToServer() + { + return getPeerNoEx(PEER_ID_SERVER) != nullptr; + } private: MutexedQueue m_event_queue; diff --git a/src/network/connectionthreads.cpp b/src/network/connectionthreads.cpp index 28ed798d9..7b62bc792 100644 --- a/src/network/connectionthreads.cpp +++ b/src/network/connectionthreads.cpp @@ -956,8 +956,11 @@ void ConnectionReceiveThread::receive(SharedBuffer &packetdata, // command was sent reliably. } - /* The peer was not found in our lists. Add it. */ if (peer_id == PEER_ID_INEXISTENT) { + /* Ignore it if we are a client */ + if (m_connection->ConnectedToServer()) + return; + /* The peer was not found in our lists. Add it. */ peer_id = m_connection->createPeer(sender, MTP_MINETEST_RELIABLE_UDP, 0); } -- cgit v1.2.3 From aa4d3cb14837409b3cb5e17060776c6f5269d0be Mon Sep 17 00:00:00 2001 From: Lars Date: Tue, 3 Nov 2020 15:39:03 -0800 Subject: Increase defaults for viewing_range, active_object_range and related settings #10597 --- builtin/settingtypes.txt | 12 ++++++------ src/defaultsettings.cpp | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index 0b650c722..8eb667bdd 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -594,7 +594,7 @@ fps_max_unfocused (FPS when unfocused or paused) int 20 1 pause_on_lost_focus (Pause on lost window focus) bool false # View distance in nodes. -viewing_range (Viewing range) int 100 20 4000 +viewing_range (Viewing range) int 190 20 4000 # Camera 'near clipping plane' distance in nodes, between 0 and 0.25 # Only works on GLES platforms. Most users will not need to change this. @@ -978,7 +978,7 @@ client_unload_unused_data_timeout (Mapblock unload timeout) int 600 # Maximum number of mapblocks for client to be kept in memory. # Set to -1 for unlimited amount. -client_mapblock_limit (Mapblock limit) int 5000 +client_mapblock_limit (Mapblock limit) int 7500 # Whether to show the client debug info (has the same effect as hitting F5). show_debug (Show debug info) bool false @@ -1137,17 +1137,17 @@ ask_reconnect_on_crash (Ask to reconnect after crash) bool false # Setting this larger than active_block_range will also cause the server # to maintain active objects up to this distance in the direction the # player is looking. (This can avoid mobs suddenly disappearing from view) -active_object_send_range_blocks (Active object send range) int 4 +active_object_send_range_blocks (Active object send range) int 8 # The radius of the volume of blocks around every player that is subject to the # active block stuff, stated in mapblocks (16 nodes). # In active blocks objects are loaded and ABMs run. # This is also the minimum range in which active objects (mobs) are maintained. # This should be configured together with active_object_send_range_blocks. -active_block_range (Active block range) int 3 +active_block_range (Active block range) int 4 # From how far blocks are sent to clients, stated in mapblocks (16 nodes). -max_block_send_distance (Max block send distance) int 10 +max_block_send_distance (Max block send distance) int 12 # Maximum number of forceloaded mapblocks. max_forceloaded_blocks (Maximum forceloaded blocks) int 16 @@ -1433,7 +1433,7 @@ mg_name (Mapgen name) enum v7 v7,valleys,carpathian,v5,flat,fractal,singlenode,v water_level (Water level) int 1 # From how far blocks are generated for clients, stated in mapblocks (16 nodes). -max_block_generate_distance (Max block generate distance) int 8 +max_block_generate_distance (Max block generate distance) int 10 # Limit of map generation, in nodes, in all 6 directions from (0, 0, 0). # Only mapchunks completely within the mapgen limit are generated. diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index fcdf6b536..dc0276733 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -52,7 +52,7 @@ void set_default_settings(Settings *settings) settings->setDefault("screenshot_format", "png"); settings->setDefault("screenshot_quality", "0"); settings->setDefault("client_unload_unused_data_timeout", "600"); - settings->setDefault("client_mapblock_limit", "5000"); + settings->setDefault("client_mapblock_limit", "7500"); settings->setDefault("enable_build_where_you_stand", "false"); settings->setDefault("curl_timeout", "5000"); settings->setDefault("curl_parallel_limit", "8"); @@ -166,7 +166,7 @@ void set_default_settings(Settings *settings) settings->setDefault("tooltip_append_itemname", "false"); settings->setDefault("fps_max", "60"); settings->setDefault("fps_max_unfocused", "20"); - settings->setDefault("viewing_range", "100"); + settings->setDefault("viewing_range", "190"); #if ENABLE_GLES settings->setDefault("near_plane", "0.1"); #endif @@ -366,11 +366,11 @@ void set_default_settings(Settings *settings) settings->setDefault("chat_message_format", "<@name> @message"); settings->setDefault("profiler_print_interval", "0"); - settings->setDefault("active_object_send_range_blocks", "4"); - settings->setDefault("active_block_range", "3"); + settings->setDefault("active_object_send_range_blocks", "8"); + settings->setDefault("active_block_range", "4"); //settings->setDefault("max_simultaneous_block_sends_per_client", "1"); // This causes frametime jitter on client side, or does it? - settings->setDefault("max_block_send_distance", "10"); + settings->setDefault("max_block_send_distance", "12"); settings->setDefault("block_send_optimize_distance", "4"); settings->setDefault("server_side_occlusion_culling", "true"); settings->setDefault("csm_restriction_flags", "62"); @@ -429,7 +429,7 @@ void set_default_settings(Settings *settings) settings->setDefault("mapgen_limit", "31000"); settings->setDefault("chunksize", "5"); settings->setDefault("fixed_map_seed", ""); - settings->setDefault("max_block_generate_distance", "8"); + settings->setDefault("max_block_generate_distance", "10"); settings->setDefault("enable_mapgen_debug_info", "false"); Mapgen::setDefaultSettings(settings); -- cgit v1.2.3 From 39213bd00a8d00861616d94a29823cb2214f742e Mon Sep 17 00:00:00 2001 From: Lars Date: Mon, 2 Nov 2020 09:27:15 -0800 Subject: Slight simplification and optimization of RemoteClient. --- src/clientiface.cpp | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/clientiface.cpp b/src/clientiface.cpp index f5e32469b..08d5d3be7 100644 --- a/src/clientiface.cpp +++ b/src/clientiface.cpp @@ -298,20 +298,14 @@ void RemoteClient::GetNextBlocks ( */ MapBlock *block = env->getMap().getBlockNoCreateNoEx(p); - bool surely_not_found_on_disk = false; - bool block_is_invalid = false; + bool block_not_found = false; if (block) { // Reset usage timer, this block will be of use in the future. block->resetUsageTimer(); - // Block is dummy if data doesn't exist. - // It means it has been not found from disk and not generated - if (block->isDummy()) { - surely_not_found_on_disk = true; - } - - if (!block->isGenerated()) - block_is_invalid = true; + // Check whether the block exists (with data) + if (block->isDummy() || !block->isGenerated()) + block_not_found = true; /* If block is not close, don't send it unless it is near @@ -325,7 +319,7 @@ void RemoteClient::GetNextBlocks ( continue; } - if (m_occ_cull && !block_is_invalid && + if (m_occ_cull && !block_not_found && env->getMap().isBlockOccluded(block, cam_pos_nodes)) { continue; } @@ -335,7 +329,7 @@ void RemoteClient::GetNextBlocks ( If block has been marked to not exist on disk (dummy) or is not generated and generating new ones is not wanted, skip block. */ - if (!generate && (surely_not_found_on_disk || block_is_invalid)) { + if (!generate && block_not_found) { // get next one. continue; } @@ -343,7 +337,7 @@ void RemoteClient::GetNextBlocks ( /* Add inexistent block to emerge queue. */ - if (block == NULL || surely_not_found_on_disk || block_is_invalid) { + if (block == NULL || block_not_found) { if (emerge->enqueueBlockEmerge(peer_id, p, generate)) { if (nearest_emerged_d == -1) nearest_emerged_d = d; -- cgit v1.2.3 From 72b93ec0d75e97ec343e5b936b858d686580677d Mon Sep 17 00:00:00 2001 From: Zughy <63455151+Zughy@users.noreply.github.com> Date: Wed, 4 Nov 2020 21:43:18 +0100 Subject: Fix ObjectRef errors due to lua_isnil() (#10564) Treat 'none' values as 'nil' --- src/script/common/helper.cpp | 44 ++++++++++++++++++++++------------------- src/script/common/helper.h | 5 ++++- src/script/lua_api/l_object.cpp | 32 +++++++++++------------------- 3 files changed, 39 insertions(+), 42 deletions(-) (limited to 'src') diff --git a/src/script/common/helper.cpp b/src/script/common/helper.cpp index f53a2b7e8..488144790 100644 --- a/src/script/common/helper.cpp +++ b/src/script/common/helper.cpp @@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include #include +#include #include "c_types.h" #include "c_internal.h" @@ -54,17 +55,14 @@ template <> bool LuaHelper::readParam(lua_State *L, int index) return lua_toboolean(L, index) != 0; } -template <> bool LuaHelper::readParam(lua_State *L, int index, const bool &default_value) +template <> s16 LuaHelper::readParam(lua_State *L, int index) { - if (lua_isnil(L, index)) - return default_value; - - return lua_toboolean(L, index) != 0; + return lua_tonumber(L, index); } -template <> s16 LuaHelper::readParam(lua_State *L, int index) +template <> int LuaHelper::readParam(lua_State *L, int index) { - return lua_tonumber(L, index); + return luaL_checkint(L, index); } template <> float LuaHelper::readParam(lua_State *L, int index) @@ -105,6 +103,25 @@ template <> v2f LuaHelper::readParam(lua_State *L, int index) return p; } +template <> v3f LuaHelper::readParam(lua_State *L, int index) +{ + v3f p; + CHECK_POS_TAB(index); + lua_getfield(L, index, "x"); + CHECK_POS_COORD("x"); + p.X = readParam(L, -1); + lua_pop(L, 1); + lua_getfield(L, index, "y"); + CHECK_POS_COORD("y"); + p.Y = readParam(L, -1); + lua_pop(L, 1); + lua_getfield(L, index, "z"); + CHECK_POS_COORD("z"); + p.Z = readParam(L, -1); + lua_pop(L, 1); + return p; +} + template <> std::string LuaHelper::readParam(lua_State *L, int index) { size_t length; @@ -113,16 +130,3 @@ template <> std::string LuaHelper::readParam(lua_State *L, int index) result.assign(str, length); return result; } - -template <> -std::string LuaHelper::readParam( - lua_State *L, int index, const std::string &default_value) -{ - std::string result; - const char *str = lua_tostring(L, index); - if (str) - result.append(str); - else - result = default_value; - return result; -} diff --git a/src/script/common/helper.h b/src/script/common/helper.h index d639d6e16..7a794dc9b 100644 --- a/src/script/common/helper.h +++ b/src/script/common/helper.h @@ -50,5 +50,8 @@ protected: * @return read value from Lua or default value if nil */ template - static T readParam(lua_State *L, int index, const T &default_value); + static inline T readParam(lua_State *L, int index, const T &default_value) + { + return lua_isnoneornil(L, index) ? default_value : readParam(L, index); + } }; diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index beb8dd339..a6a7c05f9 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -169,11 +169,9 @@ int ObjectRef::l_punch(lua_State *L) if (sao == nullptr || puncher == nullptr) return 0; - float time_from_last_punch = lua_isnil(L, 3) ? - 1000000.0f : readParam(L,3); + float time_from_last_punch = readParam(L, 3, 1000000.0f); ToolCapabilities toolcap = read_tool_capabilities(L, 4); - v3f dir = lua_isnil(L, 5) ? - sao->getBasePosition() - puncher->getBasePosition() : check_v3f(L, 5); + v3f dir = readParam(L, 5, sao->getBasePosition() - puncher->getBasePosition()); dir.normalize(); u16 src_original_hp = sao->getHP(); @@ -383,20 +381,12 @@ int ObjectRef::l_set_animation(lua_State *L) if (sao == nullptr) return 0; - v2f frames = v2f(1, 1); - if (!lua_isnil(L, 2)) - frames = readParam(L, 2); - float frame_speed = 15; - if (!lua_isnil(L, 3)) - frame_speed = lua_tonumber(L, 3); - float frame_blend = 0; - if (!lua_isnil(L, 4)) - frame_blend = lua_tonumber(L, 4); - bool frame_loop = true; - if (lua_isboolean(L, 5)) - frame_loop = readParam(L, 5); + v2f frame_range = readParam(L, 2, v2f(1, 1)); + float frame_speed = readParam(L, 3, 15.0f); + float frame_blend = readParam(L, 4, 0.0f); + bool frame_loop = readParam(L, 5, true); - sao->setAnimation(frames, frame_speed, frame_blend, frame_loop); + sao->setAnimation(frame_range, frame_speed, frame_blend, frame_loop); return 0; } @@ -436,7 +426,7 @@ int ObjectRef::l_set_local_animation(lua_State *L) if (!lua_isnil(L, 2+1)) frames[i] = read_v2s32(L, 2+i); } - float frame_speed = lua_isnil(L, 6) ? 30 : readParam(L, 6); + float frame_speed = readParam(L, 6, 30.0f); getServer(L)->setLocalPlayerAnimations(player, frames, frame_speed); lua_pushboolean(L, true); @@ -965,9 +955,9 @@ int ObjectRef::l_set_sprite(lua_State *L) if (entitysao == nullptr) return 0; - v2s16 start_frame = lua_isnil(L, 2) ? v2s16(0,0) : readParam(L, 2); - int num_frames = lua_isnil(L, 3) ? 1 : luaL_checkint(L, 3); - float framelength = lua_isnil(L, 4) ? 0.2 : lua_tonumber(L, 4); + v2s16 start_frame = readParam(L, 2, v2s16(0,0)); + int num_frames = readParam(L, 3, 1); + float framelength = readParam(L, 4, 0.2f); bool select_x_by_camera = readParam(L, 5, false); entitysao->setSprite(start_frame, num_frames, framelength, select_x_by_camera); -- cgit v1.2.3 From e3bd6704a0eb65e9490347680441c7a08df36f7a Mon Sep 17 00:00:00 2001 From: Lars Müller <34514239+appgurueu@users.noreply.github.com> Date: Wed, 4 Nov 2020 21:43:32 +0100 Subject: Revert "Fix short 180 degree rotation when using set_bone_position (#10405)" (#10534) This reverts commit 0f98b54aa4b2361575002d92b29fe222703ba557. --- src/client/content_cao.cpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/client/content_cao.cpp b/src/client/content_cao.cpp index 29a3acf25..e7f9db845 100644 --- a/src/client/content_cao.cpp +++ b/src/client/content_cao.cpp @@ -1487,17 +1487,24 @@ void GenericCAO::updateBonePosition() if (!bone) continue; + //If bone is manually positioned there is no need to perform the bug check + bool skip = false; + for (auto &it : m_bone_position) { + if (it.first == bone->getName()) { + skip = true; + break; + } + } + if (skip) + continue; + // Workaround for Irrlicht bug // We check each bone to see if it has been rotated ~180deg from its expected position due to a bug in Irricht // when using EJUOR_CONTROL joint control. If the bug is detected we update the bone to the proper position // and update the bones transformation. v3f bone_rot = bone->getRelativeTransformation().getRotationDegrees(); - float offset_X = fabsf(bone_rot.X - bone->getRotation().X); - float offset_Y = fabsf(bone_rot.Y - bone->getRotation().Y); - float offset_Z = fabsf(bone_rot.Z - bone->getRotation().Z); - if ((offset_X > 179.9f && offset_X < 180.1f) - || (offset_Y > 179.9f && offset_Y < 180.1f) - || (offset_Z > 179.9f && offset_Z < 180.1f)) { + float offset = fabsf(bone_rot.X - bone->getRotation().X); + if (offset > 179.9f && offset < 180.1f) { bone->setRotation(bone_rot); bone->updateAbsolutePosition(); } -- cgit v1.2.3 From 3356da01513860d899cde503408436f7e1918f63 Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Wed, 4 Nov 2020 21:46:18 +0100 Subject: Add model[] formspec element (#10320) Formspec element to display models, written by @kilbith, rebased and tweaked. Co-authored-by: Jean-Patrick Guerrero Co-authored-by: sfan5 --- doc/lua_api.txt | 16 ++ games/devtest/mods/testformspec/LICENSE.txt | 14 ++ games/devtest/mods/testformspec/formspec.lua | 4 + .../testformspec/models/testformspec_character.b3d | Bin 0 -> 73433 bytes .../testformspec/models/testformspec_chest.obj | 79 +++++++ .../testformspec/textures/default_chest_front.png | Bin 0 -> 423 bytes .../testformspec/textures/default_chest_inside.png | Bin 0 -> 102 bytes .../testformspec/textures/default_chest_side.png | Bin 0 -> 375 bytes .../testformspec/textures/default_chest_top.png | Bin 0 -> 423 bytes .../textures/testformspec_character.png | Bin 0 -> 2754 bytes src/gui/CMakeLists.txt | 1 + src/gui/guiFormSpecMenu.cpp | 86 +++++++ src/gui/guiFormSpecMenu.h | 2 +- src/gui/guiScene.cpp | 257 +++++++++++++++++++++ src/gui/guiScene.h | 85 +++++++ util/ci/clang-format-whitelist.txt | 2 + 16 files changed, 545 insertions(+), 1 deletion(-) create mode 100644 games/devtest/mods/testformspec/LICENSE.txt create mode 100644 games/devtest/mods/testformspec/models/testformspec_character.b3d create mode 100644 games/devtest/mods/testformspec/models/testformspec_chest.obj create mode 100644 games/devtest/mods/testformspec/textures/default_chest_front.png create mode 100644 games/devtest/mods/testformspec/textures/default_chest_inside.png create mode 100644 games/devtest/mods/testformspec/textures/default_chest_side.png create mode 100644 games/devtest/mods/testformspec/textures/default_chest_top.png create mode 100644 games/devtest/mods/testformspec/textures/testformspec_character.png create mode 100644 src/gui/guiScene.cpp create mode 100644 src/gui/guiScene.h (limited to 'src') diff --git a/doc/lua_api.txt b/doc/lua_api.txt index daf0da3d2..38fc3066a 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -2272,6 +2272,18 @@ 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[,;,;;;;;;]` + +* Show a mesh model. +* `name`: Element name that can be used for styling +* `mesh`: The mesh model to use. +* `textures`: The mesh textures to use according to the mesh materials. + Texture names must be separated by commas. +* `rotation {X,Y}` (Optional): Initial rotation of the camera. + 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`. + ### `item_image[,;,;]` * Show an inventory image of registered item/node @@ -2842,6 +2854,10 @@ Some types may inherit styles from parent types. * font_size - Sets font size. See button `font_size` property for more information. * noclip - boolean, set to true to allow the element to exceed formspec bounds. * textcolor - color. Default white. +* model + * bgcolor - color, sets background color. + * noclip - boolean, set to true to allow the element to exceed formspec bounds. + * Default to false in formspec_version version 3 or higher * image * noclip - boolean, set to true to allow the element to exceed formspec bounds. * Default to false in formspec_version version 3 or higher diff --git a/games/devtest/mods/testformspec/LICENSE.txt b/games/devtest/mods/testformspec/LICENSE.txt new file mode 100644 index 000000000..07696cc30 --- /dev/null +++ b/games/devtest/mods/testformspec/LICENSE.txt @@ -0,0 +1,14 @@ +License of media files +---------------------- +Content imported from minetest_game. + + +BlockMen (CC BY-SA 3.0) + default_chest_front.png + default_chest_lock.png + default_chest_side.png + default_chest_top.png + +stujones11 (CC BY-SA 3.0) +An0n3m0us (CC BY-SA 3.0) + testformspec_character.b3d diff --git a/games/devtest/mods/testformspec/formspec.lua b/games/devtest/mods/testformspec/formspec.lua index 87a05fc96..5495896ce 100644 --- a/games/devtest/mods/testformspec/formspec.lua +++ b/games/devtest/mods/testformspec/formspec.lua @@ -327,6 +327,10 @@ Number] animated_image[3,4.25;1,1;;testformspec_animation.png;4;0;3] animated_image[5.5,0.5;5,2;;testformspec_animation.png;4;100] animated_image[5.5,2.75;5,2;;testformspec_animation.jpg;4;100] + + style[m1;bgcolor=black] + model[0.5,6;4,4;m1;testformspec_character.b3d;testformspec_character.png] + model[5,6;4,4;m2;testformspec_chest.obj;default_chest_top.png,default_chest_top.png,default_chest_side.png,default_chest_side.png,default_chest_front.png,default_chest_inside.png;30,1;true;true] ]], -- Scroll containers diff --git a/games/devtest/mods/testformspec/models/testformspec_character.b3d b/games/devtest/mods/testformspec/models/testformspec_character.b3d new file mode 100644 index 000000000..8edbaf637 Binary files /dev/null and b/games/devtest/mods/testformspec/models/testformspec_character.b3d differ diff --git a/games/devtest/mods/testformspec/models/testformspec_chest.obj b/games/devtest/mods/testformspec/models/testformspec_chest.obj new file mode 100644 index 000000000..72ba175a0 --- /dev/null +++ b/games/devtest/mods/testformspec/models/testformspec_chest.obj @@ -0,0 +1,79 @@ +# Blender v2.78 (sub 0) OBJ File: 'chest-open.blend' +# www.blender.org +o Top_Cube.002_None_Top_Cube.002_None_bottom +v -0.500000 0.408471 0.720970 +v -0.500000 1.115578 0.013863 +v -0.500000 0.894607 -0.207108 +v -0.500000 0.187501 0.499999 +v 0.500000 1.115578 0.013863 +v 0.500000 0.408471 0.720970 +v 0.500000 0.187501 0.499999 +v 0.500000 0.894607 -0.207108 +v -0.500000 0.187500 -0.500000 +v -0.500000 -0.500000 -0.500000 +v -0.500000 -0.500000 0.500000 +v 0.500000 0.187500 -0.500000 +v 0.500000 -0.500000 0.500000 +v 0.500000 -0.500000 -0.500000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 0.0000 1.0000 +vt 1.0000 1.0000 +vt 1.0000 0.6875 +vt 0.0000 0.6875 +vt 1.0000 1.0000 +vt 0.0000 0.6875 +vt 1.0000 0.6875 +vt 1.0000 0.6875 +vt 1.0000 0.0000 +vt 0.0000 0.0000 +vt 1.0000 0.6875 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 1.0000 0.6875 +vt 1.0000 0.0000 +vt 0.0000 1.0000 +vt 0.0000 0.6875 +vt 0.0000 0.6875 +vt 0.0000 0.0000 +vt 1.0000 0.5000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.5000 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vn 0.0000 0.7071 0.7071 +vn -0.0000 -1.0000 -0.0000 +vn -1.0000 0.0000 0.0000 +vn 1.0000 0.0000 -0.0000 +vn 0.0000 -0.7071 0.7071 +vn 0.0000 0.0000 1.0000 +vn -0.0000 0.7071 -0.7071 +vn -0.0000 0.0000 -1.0000 +vn -0.0000 -0.7071 -0.7071 +vn -0.0000 1.0000 -0.0000 +g Top_Cube.002_None_Top_Cube.002_None_bottom_Top_Cube.002_None_Top_Cube.002_None_bottom_Top +s off +f 6/1/1 5/2/1 2/3/1 1/4/1 +g Top_Cube.002_None_Top_Cube.002_None_bottom_Top_Cube.002_None_Top_Cube.002_None_bottom_Bottom +f 11/5/2 10/6/2 14/7/2 13/8/2 +g Top_Cube.002_None_Top_Cube.002_None_bottom_Top_Cube.002_None_Top_Cube.002_None_bottom_Right-Left +f 1/9/3 2/10/3 3/11/3 4/12/3 +f 5/13/4 6/1/4 7/14/4 8/15/4 +f 4/12/3 9/16/3 10/17/3 11/18/3 +f 12/19/4 7/14/4 13/8/4 14/20/4 +g Top_Cube.002_None_Top_Cube.002_None_bottom_Top_Cube.002_None_Top_Cube.002_None_bottom_Back +f 6/21/5 1/9/5 4/12/5 7/22/5 +f 7/22/6 4/12/6 11/18/6 13/23/6 +g Top_Cube.002_None_Top_Cube.002_None_bottom_Top_Cube.002_None_Top_Cube.002_None_bottom_Front +f 2/10/7 5/24/7 8/25/7 3/11/7 +f 9/16/8 12/26/8 14/27/8 10/17/8 +g Top_Cube.002_None_Top_Cube.002_None_bottom_Top_Cube.002_None_Top_Cube.002_None_bottom_Inside +f 4/28/9 3/29/9 8/30/9 7/31/9 +f 7/31/10 12/32/10 9/33/10 4/28/10 diff --git a/games/devtest/mods/testformspec/textures/default_chest_front.png b/games/devtest/mods/testformspec/textures/default_chest_front.png new file mode 100644 index 000000000..85227d8fd Binary files /dev/null and b/games/devtest/mods/testformspec/textures/default_chest_front.png differ diff --git a/games/devtest/mods/testformspec/textures/default_chest_inside.png b/games/devtest/mods/testformspec/textures/default_chest_inside.png new file mode 100644 index 000000000..5f7b6b132 Binary files /dev/null and b/games/devtest/mods/testformspec/textures/default_chest_inside.png differ diff --git a/games/devtest/mods/testformspec/textures/default_chest_side.png b/games/devtest/mods/testformspec/textures/default_chest_side.png new file mode 100644 index 000000000..44a65a43d Binary files /dev/null and b/games/devtest/mods/testformspec/textures/default_chest_side.png differ diff --git a/games/devtest/mods/testformspec/textures/default_chest_top.png b/games/devtest/mods/testformspec/textures/default_chest_top.png new file mode 100644 index 000000000..f4a92ee07 Binary files /dev/null and b/games/devtest/mods/testformspec/textures/default_chest_top.png differ diff --git a/games/devtest/mods/testformspec/textures/testformspec_character.png b/games/devtest/mods/testformspec/textures/testformspec_character.png new file mode 100644 index 000000000..05021781e Binary files /dev/null and b/games/devtest/mods/testformspec/textures/testformspec_character.png differ diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 147f445f4..5305e7ad3 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -15,6 +15,7 @@ set(gui_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/guiKeyChangeMenu.cpp ${CMAKE_CURRENT_SOURCE_DIR}/guiPasswordChange.cpp ${CMAKE_CURRENT_SOURCE_DIR}/guiPathSelectMenu.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/guiScene.cpp ${CMAKE_CURRENT_SOURCE_DIR}/guiScrollBar.cpp ${CMAKE_CURRENT_SOURCE_DIR}/guiScrollContainer.cpp ${CMAKE_CURRENT_SOURCE_DIR}/guiSkin.cpp diff --git a/src/gui/guiFormSpecMenu.cpp b/src/gui/guiFormSpecMenu.cpp index 7e3ad3b15..039b28e79 100644 --- a/src/gui/guiFormSpecMenu.cpp +++ b/src/gui/guiFormSpecMenu.cpp @@ -65,6 +65,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "guiScrollContainer.h" #include "intlGUIEditBox.h" #include "guiHyperText.h" +#include "guiScene.h" #define MY_CHECKPOS(a,b) \ if (v_pos.size() != 2) { \ @@ -2695,6 +2696,86 @@ void GUIFormSpecMenu::parseSetFocus(const std::string &element) << "'" << std::endl; } +void GUIFormSpecMenu::parseModel(parserData *data, const std::string &element) +{ + std::vector parts = split(element, ';'); + + if (parts.size() < 5 || (parts.size() > 8 && + m_formspec_version <= FORMSPEC_API_VERSION)) { + errorstream << "Invalid model element (" << parts.size() << "): '" << element + << "'" << std::endl; + return; + } + + // Avoid length checks by resizing + if (parts.size() < 8) + parts.resize(8); + + std::vector v_pos = split(parts[0], ','); + std::vector v_geom = split(parts[1], ','); + std::string name = unescape_string(parts[2]); + std::string meshstr = unescape_string(parts[3]); + std::vector textures = split(parts[4], ','); + 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 + + MY_CHECKPOS("model", 0); + MY_CHECKGEOM("model", 1); + + v2s32 pos; + v2s32 geom; + + if (data->real_coordinates) { + pos = getRealCoordinateBasePos(v_pos); + geom = getRealCoordinateGeometry(v_geom); + } else { + pos = getElementBasePos(&v_pos); + geom.X = stof(v_geom[0]) * (float)imgsize.X; + geom.Y = stof(v_geom[1]) * (float)imgsize.Y; + } + + if (!data->explicit_size) + warningstream << "invalid use of model without a size[] element" << std::endl; + + scene::IAnimatedMesh *mesh = m_client->getMesh(meshstr); + + if (!mesh) { + errorstream << "Invalid model element: Unable to load mesh:" + << std::endl << "\t" << meshstr << std::endl; + return; + } + + FieldSpec spec( + name, + L"", + L"", + 258 + m_fields.size() + ); + + core::rect rect(pos, pos + geom); + + GUIScene *e = new GUIScene(Environment, RenderingEngine::get_scene_manager(), + data->current_parent, rect, spec.fid); + + auto meshnode = e->setMesh(mesh); + + for (u32 i = 0; i < textures.size() && i < meshnode->getMaterialCount(); ++i) + e->setTexture(i, m_tsrc->getTexture(textures[i])); + + if (vec_rot.size() >= 2) + e->setRotation(v2f(stof(vec_rot[0]), stof(vec_rot[1]))); + + e->enableContinuousRotation(inf_rotation); + e->enableMouseControl(mousectrl); + + auto style = getStyleForElement("model", spec.fname); + e->setStyles(style); + e->drop(); + + m_fields.push_back(spec); +} + void GUIFormSpecMenu::parseElement(parserData* data, const std::string &element) { //some prechecks @@ -2891,6 +2972,11 @@ void GUIFormSpecMenu::parseElement(parserData* data, const std::string &element) return; } + if (type == "model") { + parseModel(data, description); + return; + } + // Ignore others infostream << "Unknown DrawSpec: type=" << type << ", data=\"" << description << "\"" << std::endl; diff --git a/src/gui/guiFormSpecMenu.h b/src/gui/guiFormSpecMenu.h index 613acaa04..c5d662a69 100644 --- a/src/gui/guiFormSpecMenu.h +++ b/src/gui/guiFormSpecMenu.h @@ -38,7 +38,6 @@ with this program; if not, write to the Free Software Foundation, Inc., class InventoryManager; class ISimpleTextureSource; class Client; -class TexturePool; class GUIScrollContainer; typedef enum { @@ -444,6 +443,7 @@ private: void parseAnchor(parserData *data, const std::string &element); bool parseStyle(parserData *data, const std::string &element, bool style_type); void parseSetFocus(const std::string &element); + void parseModel(parserData *data, const std::string &element); void tryClose(); diff --git a/src/gui/guiScene.cpp b/src/gui/guiScene.cpp new file mode 100644 index 000000000..08f119e07 --- /dev/null +++ b/src/gui/guiScene.cpp @@ -0,0 +1,257 @@ +/* +Minetest +Copyright (C) 2020 Jean-Patrick Guerrero + +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 "guiScene.h" + +#include +#include +#include +#include "porting.h" + +GUIScene::GUIScene(gui::IGUIEnvironment *env, scene::ISceneManager *smgr, + gui::IGUIElement *parent, core::recti rect, s32 id) + : IGUIElement(gui::EGUIET_ELEMENT, env, parent, id, rect) +{ + m_driver = env->getVideoDriver(); + m_smgr = smgr->createNewSceneManager(false); + + m_cam = m_smgr->addCameraSceneNode(0, v3f(0.f, 0.f, -100.f), v3f(0.f)); + m_cam->setFOV(30.f * core::DEGTORAD); + + scene::ILightSceneNode *light = m_smgr->addLightSceneNode(m_cam); + light->setRadius(1000.f); + + m_smgr->getParameters()->setAttribute(scene::ALLOW_ZWRITE_ON_TRANSPARENT, true); +} + +GUIScene::~GUIScene() +{ + setMesh(nullptr); + + m_smgr->drop(); +} + +scene::IAnimatedMeshSceneNode *GUIScene::setMesh(scene::IAnimatedMesh *mesh) +{ + if (m_mesh) { + m_mesh->remove(); + m_mesh = nullptr; + } + + if (!mesh) + return nullptr; + + m_mesh = m_smgr->addAnimatedMeshSceneNode(mesh); + m_mesh->setPosition(-m_mesh->getBoundingBox().getCenter()); + m_mesh->animateJoints(); + return m_mesh; +} + +void GUIScene::setTexture(u32 idx, video::ITexture *texture) +{ + video::SMaterial &material = m_mesh->getMaterial(idx); + material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; + material.MaterialTypeParam = 0.5f; + material.TextureLayer[0].Texture = texture; + material.setFlag(video::EMF_LIGHTING, false); + material.setFlag(video::EMF_FOG_ENABLE, true); + material.setFlag(video::EMF_BILINEAR_FILTER, false); + material.setFlag(video::EMF_BACK_FACE_CULLING, false); +} + +void GUIScene::draw() +{ + // Control rotation speed based on time + u64 new_time = porting::getTimeMs(); + u64 dtime_ms = 0; + if (m_last_time != 0) + dtime_ms = porting::getDeltaMs(m_last_time, new_time); + m_last_time = new_time; + + core::rect oldViewPort = m_driver->getViewPort(); + m_driver->setViewPort(getAbsoluteClippingRect()); + core::recti borderRect = Environment->getRootGUIElement()->getAbsoluteClippingRect(); + + if (m_bgcolor != 0) { + Environment->getSkin()->draw3DSunkenPane( + this, m_bgcolor, false, true, borderRect, 0); + } + + core::dimension2d size = getAbsoluteClippingRect().getSize(); + m_smgr->getActiveCamera()->setAspectRatio((f32)size.Width / (f32)size.Height); + + if (!m_target) { + updateCamera(m_smgr->addEmptySceneNode()); + rotateCamera(v3f(0.f)); + m_cam->bindTargetAndRotation(true); + } + + cameraLoop(); + + // Continuous rotation + if (m_inf_rot) + rotateCamera(v3f(0.f, -0.03f * (float)dtime_ms, 0.f)); + + m_smgr->drawAll(); + + if (m_initial_rotation && m_mesh) { + rotateCamera(v3f(m_custom_rot.X, m_custom_rot.Y, 0.f)); + calcOptimalDistance(); + + m_initial_rotation = false; + } + + m_driver->setViewPort(oldViewPort); +} + +bool GUIScene::OnEvent(const SEvent &event) +{ + if (m_mouse_ctrl && event.EventType == EET_MOUSE_INPUT_EVENT) { + if (event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN) { + m_last_pos = v2f((f32)event.MouseInput.X, (f32)event.MouseInput.Y); + return true; + } else if (event.MouseInput.Event == EMIE_MOUSE_MOVED) { + if (event.MouseInput.isLeftPressed()) { + m_curr_pos = v2f((f32)event.MouseInput.X, (f32)event.MouseInput.Y); + + rotateCamera(v3f( + m_last_pos.Y - m_curr_pos.Y, + m_curr_pos.X - m_last_pos.X, 0.f)); + + m_last_pos = m_curr_pos; + return true; + } + } + } + + return gui::IGUIElement::OnEvent(event); +} + +void GUIScene::setStyles(const std::array &styles) +{ + StyleSpec::State state = StyleSpec::STATE_DEFAULT; + StyleSpec style = StyleSpec::getStyleFromStatePropagation(styles, state); + + setNotClipped(style.getBool(StyleSpec::NOCLIP, false)); + setBackgroundColor(style.getColor(StyleSpec::BGCOLOR, m_bgcolor)); +} + +/* Camera control functions */ + +inline void GUIScene::calcOptimalDistance() +{ + core::aabbox3df box = m_mesh->getBoundingBox(); + f32 width = box.MaxEdge.X - box.MinEdge.X; + f32 height = box.MaxEdge.Y - box.MinEdge.Y; + f32 depth = box.MaxEdge.Z - box.MinEdge.Z; + f32 max_width = width > depth ? width : depth; + + const scene::SViewFrustum *f = m_cam->getViewFrustum(); + f32 cam_far = m_cam->getFarValue(); + f32 far_width = core::line3df(f->getFarLeftUp(), f->getFarRightUp()).getLength(); + f32 far_height = core::line3df(f->getFarLeftUp(), f->getFarLeftDown()).getLength(); + + core::recti rect = getAbsolutePosition(); + f32 zoomX = rect.getWidth() / max_width; + f32 zoomY = rect.getHeight() / height; + f32 dist; + + if (zoomX < zoomY) + dist = (max_width / (far_width / cam_far)) + (0.5f * max_width); + else + dist = (height / (far_height / cam_far)) + (0.5f * max_width); + + m_cam_distance = dist; + m_update_cam = true; +} + +void GUIScene::updateCamera(scene::ISceneNode *target) +{ + m_target = target; + updateTargetPos(); + + m_last_target_pos = m_target_pos; + updateCameraPos(); + + m_update_cam = true; +} + +void GUIScene::updateTargetPos() +{ + m_last_target_pos = m_target_pos; + m_target->updateAbsolutePosition(); + m_target_pos = m_target->getAbsolutePosition(); +} + +void GUIScene::setCameraRotation(v3f rot) +{ + correctBounds(rot); + + core::matrix4 mat; + mat.setRotationDegrees(rot); + + m_cam_pos = v3f(0.f, 0.f, m_cam_distance); + mat.rotateVect(m_cam_pos); + + m_cam_pos += m_target_pos; + m_cam->setPosition(m_cam_pos); + m_update_cam = false; +} + +bool GUIScene::correctBounds(v3f &rot) +{ + const float ROTATION_MAX_1 = 60.0f; + const float ROTATION_MAX_2 = 300.0f; + + // Limit and correct the rotation when needed + if (rot.X < 90.f) { + if (rot.X > ROTATION_MAX_1) { + rot.X = ROTATION_MAX_1; + return true; + } + } else if (rot.X < ROTATION_MAX_2) { + rot.X = ROTATION_MAX_2; + return true; + } + + // Not modified + return false; +} + +void GUIScene::cameraLoop() +{ + updateCameraPos(); + updateTargetPos(); + + if (m_target_pos != m_last_target_pos) + m_update_cam = true; + + if (m_update_cam) { + m_cam_pos = m_target_pos + (m_cam_pos - m_target_pos).normalize() * m_cam_distance; + + v3f rot = getCameraRotation(); + if (correctBounds(rot)) + setCameraRotation(rot); + + m_cam->setPosition(m_cam_pos); + m_cam->setTarget(m_target_pos); + + m_update_cam = false; + } +} diff --git a/src/gui/guiScene.h b/src/gui/guiScene.h new file mode 100644 index 000000000..707e6f66a --- /dev/null +++ b/src/gui/guiScene.h @@ -0,0 +1,85 @@ +/* +Minetest +Copyright (C) 2020 Jean-Patrick Guerrero + +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 "irrlichttypes_extrabloated.h" +#include "ICameraSceneNode.h" +#include "StyleSpec.h" + +using namespace irr; + +class GUIScene : public gui::IGUIElement +{ +public: + GUIScene(gui::IGUIEnvironment *env, scene::ISceneManager *smgr, + gui::IGUIElement *parent, core::recti rect, s32 id = -1); + + ~GUIScene(); + + 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 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; }; + void setStyles(const std::array &styles); + + virtual void draw(); + virtual bool OnEvent(const SEvent &event); + +private: + void calcOptimalDistance(); + void updateTargetPos(); + void updateCamera(scene::ISceneNode *target); + void setCameraRotation(v3f rot); + /// @return true indicates that the rotation was corrected + bool correctBounds(v3f &rot); + void cameraLoop(); + + void updateCameraPos() { m_cam_pos = m_cam->getPosition(); }; + v3f getCameraRotation() const { return (m_cam_pos - m_target_pos).getHorizontalAngle(); }; + void rotateCamera(const v3f &delta) { setCameraRotation(getCameraRotation() + delta); }; + + scene::ISceneManager *m_smgr; + video::IVideoDriver *m_driver; + scene::ICameraSceneNode *m_cam; + scene::ISceneNode *m_target = nullptr; + scene::IAnimatedMeshSceneNode *m_mesh = nullptr; + + f32 m_cam_distance = 50.f; + + u64 m_last_time = 0; + + v3f m_cam_pos; + v3f m_target_pos; + v3f m_last_target_pos; + // Cursor positions + v2f m_curr_pos; + v2f m_last_pos; + // Initial rotation + v2f m_custom_rot; + + bool m_mouse_ctrl = true; + bool m_update_cam = false; + bool m_inf_rot = false; + bool m_initial_rotation = true; + + video::SColor m_bgcolor = 0; +}; diff --git a/util/ci/clang-format-whitelist.txt b/util/ci/clang-format-whitelist.txt index 3334257ae..75d99f4cd 100644 --- a/util/ci/clang-format-whitelist.txt +++ b/util/ci/clang-format-whitelist.txt @@ -183,6 +183,8 @@ src/gui/guiMainMenu.h src/gui/guiPasswordChange.cpp src/gui/guiPathSelectMenu.cpp src/gui/guiPathSelectMenu.h +src/gui/guiScene.cpp +src/gui/guiScene.h src/gui/guiScrollBar.cpp src/gui/guiSkin.cpp src/gui/guiSkin.h -- cgit v1.2.3 From 627c22c36e32185d48d2faf8197e22cbaa4c50b2 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Thu, 5 Nov 2020 19:34:40 +0100 Subject: Fix integer-string conversion for shaders closes #10605 --- src/client/shader.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/client/shader.cpp b/src/client/shader.cpp index f2aa00246..4f6430579 100644 --- a/src/client/shader.cpp +++ b/src/client/shader.cpp @@ -734,7 +734,7 @@ ShaderInfo generate_shader(const std::string &name, u8 material_type, u8 drawtyp shaders_header += "#define "; shaders_header += drawTypes[i]; shaders_header += " "; - shaders_header += std::to_string(i); + shaders_header += itos(i); shaders_header += "\n"; } @@ -757,15 +757,15 @@ ShaderInfo generate_shader(const std::string &name, u8 material_type, u8 drawtyp shaders_header += "#define "; shaders_header += materialTypes[i]; shaders_header += " "; - shaders_header += std::to_string(i); + shaders_header += itos(i); shaders_header += "\n"; } shaders_header += "#define MATERIAL_TYPE "; - shaders_header += std::to_string(material_type); + shaders_header += itos(material_type); shaders_header += "\n"; shaders_header += "#define DRAW_TYPE "; - shaders_header += std::to_string(drawtype); + shaders_header += itos(drawtype); shaders_header += "\n"; if (g_settings->getBool("enable_waving_water")){ -- cgit v1.2.3 From 8c1871fa2c066a2086988684256da97bd0f4ab6f Mon Sep 17 00:00:00 2001 From: Lars Date: Fri, 6 Nov 2020 10:54:04 -0800 Subject: Revert #10495 and simplify. --- src/clientiface.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/clientiface.cpp b/src/clientiface.cpp index 08d5d3be7..01852c5d1 100644 --- a/src/clientiface.cpp +++ b/src/clientiface.cpp @@ -209,6 +209,13 @@ void RemoteClient::GetNextBlocks ( s16 d_max_gen = std::min(adjustDist(m_max_gen_distance, prop_zoom_fov), wanted_range); + s16 d_max = full_d_max; + + // Don't loop very much at a time + s16 max_d_increment_at_time = 2; + if (d_max > d_start + max_d_increment_at_time) + d_max = d_start + max_d_increment_at_time; + // cos(angle between velocity and camera) * |velocity| // Limit to 0.0f in case player moves backwards. f32 dot = rangelim(camera_dir.dotProduct(playerspeed), 0.0f, 300.0f); @@ -225,7 +232,7 @@ void RemoteClient::GetNextBlocks ( const v3s16 cam_pos_nodes = floatToInt(camera_pos, BS); s16 d; - for (d = d_start; d <= full_d_max; d++) { + for (d = d_start; d <= d_max; d++) { /* Get the border/face dot coordinates of a "d-radiused" box -- cgit v1.2.3 From c940a57a384b1a75730776906451078d25c5aa52 Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Sun, 8 Nov 2020 11:30:16 +0100 Subject: ContentCAO: Fix segfault when minimap is disabled --- src/client/content_cao.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/client/content_cao.cpp b/src/client/content_cao.cpp index e7f9db845..7c349244f 100644 --- a/src/client/content_cao.cpp +++ b/src/client/content_cao.cpp @@ -894,6 +894,9 @@ u16 GenericCAO::getLightPosition(v3s16 *pos) void GenericCAO::updateMarker() { + if (!m_client->getMinimap()) + return; + if (!m_prop.show_on_minimap) { if (m_marker) m_client->getMinimap()->removeMarker(&m_marker); -- cgit v1.2.3 From 7589cbe086a5558eea018e1e3d25e388b26d51e8 Mon Sep 17 00:00:00 2001 From: rubenwardy Date: Mon, 9 Nov 2020 10:55:15 +0000 Subject: Fix object interaction distance not being checked (#10547) --- doc/lua_api.txt | 4 ++-- src/network/serverpackethandler.cpp | 13 +++++++------ 2 files changed, 9 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 38fc3066a..985af2f6e 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -6189,9 +6189,9 @@ object you are working with still exists. * `bone`: string * `position`: `{x=num, y=num, z=num}` (relative) * `rotation`: `{x=num, y=num, z=num}` = Rotation on each axis, in degrees - * `forced_visible`: Boolean to control whether the attached entity + * `forced_visible`: Boolean to control whether the attached entity should appear in first person. -* `get_attach()`: returns parent, bone, position, rotation, forced_visible, +* `get_attach()`: returns parent, bone, position, rotation, forced_visible, or nil if it isn't attached. * `get_children()`: returns a list of ObjectRefs that are attached to the object. diff --git a/src/network/serverpackethandler.cpp b/src/network/serverpackethandler.cpp index 0bd09e637..95e7c548e 100644 --- a/src/network/serverpackethandler.cpp +++ b/src/network/serverpackethandler.cpp @@ -1050,12 +1050,13 @@ void Server::handleCommand_Interact(NetworkPacket *pkt) } float d = playersao->getEyePosition().getDistanceFrom(target_pos); - if (!checkInteractDistance(player, d, pointed.dump()) - && pointed.type == POINTEDTHING_NODE) { - // Re-send block to revert change on client-side - RemoteClient *client = getClient(peer_id); - v3s16 blockpos = getNodeBlockPos(pointed.node_undersurface); - client->SetBlockNotSent(blockpos); + if (!checkInteractDistance(player, d, pointed.dump())) { + if (pointed.type == POINTEDTHING_NODE) { + // Re-send block to revert change on client-side + RemoteClient *client = getClient(peer_id); + v3s16 blockpos = getNodeBlockPos(pointed.node_undersurface); + client->SetBlockNotSent(blockpos); + } return; } } -- cgit v1.2.3 From e1142ee57f2d7b59a86f6d0d72ae043844bc3121 Mon Sep 17 00:00:00 2001 From: Markus Koch Date: Sat, 7 Nov 2020 17:45:32 +0100 Subject: Joystick: Remap joystick-specific KeyTypes to generic ones According to the following table: * MOUSE_L -> DIG * MOUSE_R -> PLACE * SCROLL_UP -> HOTBAR_NEXT * SCROLL_DOWN -> HOTBAR_PREV This commit entirely removes the special KeyTypes used for joysticks. Support for the MOUSE KeyTypes had already been removed in the main game code without adapting the joystick code, breaking joystick input. This commit restores joystick functionality. --- src/client/game.cpp | 16 ++++++---------- src/client/joystick_controller.cpp | 22 +++++++++++----------- src/client/keys.h | 6 ------ 3 files changed, 17 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/client/game.cpp b/src/client/game.cpp index 0380c1661..5c38e027d 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -2014,15 +2014,11 @@ void Game::processItemSelection(u16 *new_playeritem) s32 dir = wheel; - if (input->joystick.wasKeyDown(KeyType::SCROLL_DOWN) || - wasKeyDown(KeyType::HOTBAR_NEXT)) { + if (wasKeyDown(KeyType::HOTBAR_NEXT)) dir = -1; - } - if (input->joystick.wasKeyDown(KeyType::SCROLL_UP) || - wasKeyDown(KeyType::HOTBAR_PREV)) { + if (wasKeyDown(KeyType::HOTBAR_PREV)) dir = 1; - } if (dir < 0) *new_playeritem = *new_playeritem < max_item ? *new_playeritem + 1 : 0; @@ -3138,11 +3134,11 @@ void Game::processPlayerInteraction(f32 dtime, bool show_hud, bool show_debug) input->clearWasKeyPressed(); input->clearWasKeyReleased(); - input->joystick.clearWasKeyDown(KeyType::MOUSE_L); - input->joystick.clearWasKeyDown(KeyType::MOUSE_R); + input->joystick.clearWasKeyDown(KeyType::DIG); + input->joystick.clearWasKeyDown(KeyType::PLACE); - input->joystick.clearWasKeyReleased(KeyType::MOUSE_L); - input->joystick.clearWasKeyReleased(KeyType::MOUSE_R); + input->joystick.clearWasKeyReleased(KeyType::DIG); + input->joystick.clearWasKeyReleased(KeyType::PLACE); } diff --git a/src/client/joystick_controller.cpp b/src/client/joystick_controller.cpp index c29e8b639..742115046 100644 --- a/src/client/joystick_controller.cpp +++ b/src/client/joystick_controller.cpp @@ -74,8 +74,8 @@ JoystickLayout create_default_layout() // Accessible without four modifier button pressed // regardless whether start is pressed or not - JLO_B_PB(KeyType::MOUSE_L, fb | 1 << 4, 1 << 4); - JLO_B_PB(KeyType::MOUSE_R, fb | 1 << 5, 1 << 5); + JLO_B_PB(KeyType::DIG, fb | 1 << 4, 1 << 4); + JLO_B_PB(KeyType::PLACE, fb | 1 << 5, 1 << 5); // Accessible without any modifier pressed JLO_B_PB(KeyType::JUMP, bm | 1 << 0, 1 << 0); @@ -83,9 +83,9 @@ JoystickLayout create_default_layout() // Accessible with start button not pressed, but four pressed // TODO find usage for button 0 - JLO_B_PB(KeyType::DROP, bm | 1 << 1, fb | 1 << 1); - JLO_B_PB(KeyType::SCROLL_UP, bm | 1 << 4, fb | 1 << 4); - JLO_B_PB(KeyType::SCROLL_DOWN,bm | 1 << 5, fb | 1 << 5); + JLO_B_PB(KeyType::DROP, bm | 1 << 1, fb | 1 << 1); + JLO_B_PB(KeyType::HOTBAR_PREV, bm | 1 << 4, fb | 1 << 4); + JLO_B_PB(KeyType::HOTBAR_NEXT, bm | 1 << 5, fb | 1 << 5); // Accessible with start button and four pressed // TODO find usage for buttons 0, 1 and 4, 5 @@ -99,8 +99,8 @@ JoystickLayout create_default_layout() JLO_A_PB(KeyType::RIGHT, 0, -1, 1024); // Scroll buttons - JLO_A_PB(KeyType::SCROLL_UP, 2, -1, 1024); - JLO_A_PB(KeyType::SCROLL_DOWN, 5, -1, 1024); + JLO_A_PB(KeyType::HOTBAR_PREV, 2, -1, 1024); + JLO_A_PB(KeyType::HOTBAR_NEXT, 5, -1, 1024); return jlo; } @@ -134,10 +134,10 @@ JoystickLayout create_xbox_layout() JLO_B_PB(KeyType::SNEAK, 1 << 12, 1 << 12); // right // Triggers - JLO_B_PB(KeyType::MOUSE_L, 1 << 6, 1 << 6); // lt - JLO_B_PB(KeyType::MOUSE_R, 1 << 7, 1 << 7); // rt - JLO_B_PB(KeyType::SCROLL_UP, 1 << 4, 1 << 4); // lb - JLO_B_PB(KeyType::SCROLL_DOWN, 1 << 5, 1 << 5); // rb + JLO_B_PB(KeyType::DIG, 1 << 6, 1 << 6); // lt + JLO_B_PB(KeyType::PLACE, 1 << 7, 1 << 7); // rt + JLO_B_PB(KeyType::HOTBAR_PREV, 1 << 4, 1 << 4); // lb + JLO_B_PB(KeyType::HOTBAR_NEXT, 1 << 5, 1 << 5); // rb // D-PAD JLO_B_PB(KeyType::ZOOM, 1 << 15, 1 << 15); // up diff --git a/src/client/keys.h b/src/client/keys.h index b6ce59b4a..60a7a3c45 100644 --- a/src/client/keys.h +++ b/src/client/keys.h @@ -110,12 +110,6 @@ public: SLOT_31, SLOT_32, - // joystick specific keys - MOUSE_L, - MOUSE_R, - SCROLL_UP, - SCROLL_DOWN, - // Fake keycode for array size and internal checks INTERNAL_ENUM_COUNT -- cgit v1.2.3 From b6e47a30bb05a6424fd6d5f2f0151afba4c5d825 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Mon, 9 Nov 2020 15:12:25 +0100 Subject: Update fallback font to newer version --- fonts/DroidSansFallbackFull-LICENSE.txt | 2 +- fonts/DroidSansFallbackFull.ttf | Bin 4529044 -> 5398328 bytes src/CMakeLists.txt | 2 -- 3 files changed, 1 insertion(+), 3 deletions(-) (limited to 'src') diff --git a/fonts/DroidSansFallbackFull-LICENSE.txt b/fonts/DroidSansFallbackFull-LICENSE.txt index d3a2eaa8c..a7bf409b7 100644 --- a/fonts/DroidSansFallbackFull-LICENSE.txt +++ b/fonts/DroidSansFallbackFull-LICENSE.txt @@ -1,4 +1,4 @@ -Copyright (C) 2008 The Android Open Source Project +Copyright (C) 2012 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/fonts/DroidSansFallbackFull.ttf b/fonts/DroidSansFallbackFull.ttf index a9df00585..0cacabedc 100644 Binary files a/fonts/DroidSansFallbackFull.ttf and b/fonts/DroidSansFallbackFull.ttf differ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b5d4fae0e..4724bf431 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -677,9 +677,7 @@ endif(BUILD_SERVER) # Blacklisted locales that don't work. # see issue #4638 set(GETTEXT_BLACKLISTED_LOCALES - be he - ko ky ) -- cgit v1.2.3 From 97aefe9b81414fa560d1ff37a3060266ac9735a9 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Mon, 9 Nov 2020 15:22:06 +0100 Subject: Mark additional locales as broken --- src/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4724bf431..b8ce69f1d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -677,8 +677,11 @@ endif(BUILD_SERVER) # Blacklisted locales that don't work. # see issue #4638 set(GETTEXT_BLACKLISTED_LOCALES + ar he ky + ms_Arab + th ) option(APPLY_LOCALE_BLACKLIST "Use a blacklist to avoid broken locales" TRUE) -- cgit v1.2.3 From fca4db4184ac054c53446c0960ec578ebc6b5857 Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Tue, 10 Nov 2020 21:02:53 +0100 Subject: ObjectRef: Re-add legacy code for set_physics_override (#10585) These arguments are used at least by MTG beds and homedecor_common. A deprecation warning is shown to safely remove it in a future release. --- src/script/lua_api/l_object.cpp | 42 +++++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index a6a7c05f9..bc59bd55c 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -1413,20 +1413,34 @@ int ObjectRef::l_set_physics_override(lua_State *L) if (playersao == nullptr) return 0; - luaL_checktype(L, 2, LUA_TTABLE); - playersao->m_physics_override_speed = getfloatfield_default( - L, 2, "speed", playersao->m_physics_override_speed); - playersao->m_physics_override_jump = getfloatfield_default( - L, 2, "jump", playersao->m_physics_override_jump); - playersao->m_physics_override_gravity = getfloatfield_default( - L, 2, "gravity", playersao->m_physics_override_gravity); - playersao->m_physics_override_sneak = getboolfield_default( - L, 2, "sneak", playersao->m_physics_override_sneak); - playersao->m_physics_override_sneak_glitch = getboolfield_default( - L, 2, "sneak_glitch", playersao->m_physics_override_sneak_glitch); - playersao->m_physics_override_new_move = getboolfield_default( - L, 2, "new_move", playersao->m_physics_override_new_move); - playersao->m_physics_override_sent = false; + if (lua_istable(L, 2)) { + bool modified = false; + modified |= getfloatfield(L, 2, "speed", playersao->m_physics_override_speed); + modified |= getfloatfield(L, 2, "jump", playersao->m_physics_override_jump); + modified |= getfloatfield(L, 2, "gravity", playersao->m_physics_override_gravity); + modified |= getboolfield(L, 2, "sneak", playersao->m_physics_override_sneak); + modified |= getboolfield(L, 2, "sneak_glitch", playersao->m_physics_override_sneak_glitch); + modified |= getboolfield(L, 2, "new_move", playersao->m_physics_override_new_move); + if (modified) + playersao->m_physics_override_sent = false; + } else { + // old, non-table format + // TODO: Remove this code after version 5.4.0 + log_deprecated(L, "Deprecated use of set_physics_override(num, num, num)"); + + if (!lua_isnil(L, 2)) { + playersao->m_physics_override_speed = lua_tonumber(L, 2); + playersao->m_physics_override_sent = false; + } + if (!lua_isnil(L, 3)) { + playersao->m_physics_override_jump = lua_tonumber(L, 3); + playersao->m_physics_override_sent = false; + } + if (!lua_isnil(L, 4)) { + playersao->m_physics_override_gravity = lua_tonumber(L, 4); + playersao->m_physics_override_sent = false; + } + } return 0; } -- cgit v1.2.3 From be8d1d2d99ad835b5de7277b7b518c334113e795 Mon Sep 17 00:00:00 2001 From: Lars Date: Sun, 8 Nov 2020 12:30:38 -0800 Subject: Increase default emerge queue limits and limit enqueue requests for active blocks. --- builtin/settingtypes.txt | 6 +++--- src/defaultsettings.cpp | 6 +++--- src/emerge.cpp | 4 ++++ 3 files changed, 10 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index 8eb667bdd..c4dc82dfe 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -2152,15 +2152,15 @@ chunksize (Chunk size) int 5 enable_mapgen_debug_info (Mapgen debug) bool false # Maximum number of blocks that can be queued for loading. -emergequeue_limit_total (Absolute limit of queued blocks to emerge) int 512 +emergequeue_limit_total (Absolute limit of queued blocks to emerge) int 1024 # Maximum number of blocks to be queued that are to be loaded from file. # This limit is enforced per player. -emergequeue_limit_diskonly (Per-player limit of queued blocks load from disk) int 64 +emergequeue_limit_diskonly (Per-player limit of queued blocks load from disk) int 128 # Maximum number of blocks to be queued that are to be generated. # This limit is enforced per player. -emergequeue_limit_generate (Per-player limit of queued blocks to generate) int 64 +emergequeue_limit_generate (Per-player limit of queued blocks to generate) int 128 # Number of emerge threads to use. # Value 0: diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index dc0276733..177955589 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -396,9 +396,9 @@ void set_default_settings(Settings *settings) settings->setDefault("debug_log_level", "action"); settings->setDefault("debug_log_size_max", "50"); settings->setDefault("chat_log_level", "error"); - settings->setDefault("emergequeue_limit_total", "512"); - settings->setDefault("emergequeue_limit_diskonly", "64"); - settings->setDefault("emergequeue_limit_generate", "64"); + settings->setDefault("emergequeue_limit_total", "1024"); + settings->setDefault("emergequeue_limit_diskonly", "128"); + settings->setDefault("emergequeue_limit_generate", "128"); settings->setDefault("num_emerge_threads", "1"); settings->setDefault("secure.enable_security", "true"); settings->setDefault("secure.trusted_mods", ""); diff --git a/src/emerge.cpp b/src/emerge.cpp index 0ac26a682..12e407797 100644 --- a/src/emerge.cpp +++ b/src/emerge.cpp @@ -426,6 +426,10 @@ bool EmergeManager::pushBlockEmergeData( m_qlimit_generate : m_qlimit_diskonly; if (count_peer >= qlimit_peer) return false; + } else { + // limit block enqueue requests for active blocks to 1/2 of total + if (count_peer * 2 >= m_qlimit_total) + return false; } } -- cgit v1.2.3 From adffef2b94f2d9cb3104cbc75e315cda3c0728aa Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Thu, 12 Nov 2020 19:15:41 +0100 Subject: PlayerSAO: Run on_player_hpchange raw change values (#10478) The callback is only run when a change in HP is to be expected. Following cases will not trigger the callback: * Dead player damaged further * Healing full-health player * Change of 0 HP --- src/server/player_sao.cpp | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/server/player_sao.cpp b/src/server/player_sao.cpp index 9fb53380c..62515d1c9 100644 --- a/src/server/player_sao.cpp +++ b/src/server/player_sao.cpp @@ -458,20 +458,25 @@ u16 PlayerSAO::punch(v3f dir, void PlayerSAO::setHP(s32 hp, const PlayerHPChangeReason &reason) { - s32 oldhp = m_hp; + if (hp == (s32)m_hp) + return; // Nothing to do - hp = rangelim(hp, 0, m_prop.hp_max); + if (m_hp <= 0 && hp < (s32)m_hp) + return; // Cannot take more damage - if (oldhp != hp) { - s32 hp_change = m_env->getScriptIface()->on_player_hpchange(this, hp - oldhp, reason); + { + s32 hp_change = m_env->getScriptIface()->on_player_hpchange(this, hp - m_hp, reason); if (hp_change == 0) return; - hp = rangelim(oldhp + hp_change, 0, m_prop.hp_max); + hp = m_hp + hp_change; } + s32 oldhp = m_hp; + hp = rangelim(hp, 0, m_prop.hp_max); + if (hp < oldhp && isImmortal()) - return; + return; // Do not allow immortal players to be damaged m_hp = hp; -- cgit v1.2.3 From 68139a28eb8b43b3685b81c77258912ffc5e0b8f Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Thu, 12 Nov 2020 19:16:02 +0100 Subject: Revert "Replace MyEventReceiver KeyList with std::unordered_set" (#10622) This reverts commit 787561b29afdbc78769f68c2f5c4f2cff1b32340. --- src/client/inputhandler.cpp | 48 +++++++++----------- src/client/inputhandler.h | 108 ++++++++++++++++++++++++++++++++++++-------- src/client/keycode.h | 19 -------- 3 files changed, 111 insertions(+), 64 deletions(-) (limited to 'src') diff --git a/src/client/inputhandler.cpp b/src/client/inputhandler.cpp index ee3e37ae9..608a405a8 100644 --- a/src/client/inputhandler.cpp +++ b/src/client/inputhandler.cpp @@ -112,7 +112,7 @@ bool MyEventReceiver::OnEvent(const SEvent &event) // Remember whether each key is down or up if (event.EventType == irr::EET_KEY_INPUT_EVENT) { const KeyPress &keyCode = event.KeyInput; - if (keysListenedFor.count(keyCode)) { + if (keysListenedFor[keyCode]) { // If the key is being held down then the OS may // send a continuous stream of keydown events. // In this case, we don't want to let this @@ -120,15 +120,15 @@ bool MyEventReceiver::OnEvent(const SEvent &event) // certain actions to repeat constantly. if (event.KeyInput.PressedDown) { if (!IsKeyDown(keyCode)) { - keyWasDown.insert(keyCode); - keyWasPressed.insert(keyCode); + keyWasDown.set(keyCode); + keyWasPressed.set(keyCode); } - keyIsDown.insert(keyCode); + keyIsDown.set(keyCode); } else { if (IsKeyDown(keyCode)) - keyWasReleased.insert(keyCode); + keyWasReleased.set(keyCode); - keyIsDown.erase(keyCode); + keyIsDown.unset(keyCode); } return true; @@ -153,36 +153,36 @@ bool MyEventReceiver::OnEvent(const SEvent &event) switch (event.MouseInput.Event) { case EMIE_LMOUSE_PRESSED_DOWN: key = "KEY_LBUTTON"; - keyIsDown.insert(key); - keyWasDown.insert(key); - keyWasPressed.insert(key); + keyIsDown.set(key); + keyWasDown.set(key); + keyWasPressed.set(key); break; case EMIE_MMOUSE_PRESSED_DOWN: key = "KEY_MBUTTON"; - keyIsDown.insert(key); - keyWasDown.insert(key); - keyWasPressed.insert(key); + keyIsDown.set(key); + keyWasDown.set(key); + keyWasPressed.set(key); break; case EMIE_RMOUSE_PRESSED_DOWN: key = "KEY_RBUTTON"; - keyIsDown.insert(key); - keyWasDown.insert(key); - keyWasPressed.insert(key); + keyIsDown.set(key); + keyWasDown.set(key); + keyWasPressed.set(key); break; case EMIE_LMOUSE_LEFT_UP: key = "KEY_LBUTTON"; - keyIsDown.erase(key); - keyWasReleased.insert(key); + keyIsDown.unset(key); + keyWasReleased.set(key); break; case EMIE_MMOUSE_LEFT_UP: key = "KEY_MBUTTON"; - keyIsDown.erase(key); - keyWasReleased.insert(key); + keyIsDown.unset(key); + keyWasReleased.set(key); break; case EMIE_RMOUSE_LEFT_UP: key = "KEY_RBUTTON"; - keyIsDown.erase(key); - keyWasReleased.insert(key); + keyIsDown.unset(key); + keyWasReleased.set(key); break; case EMIE_MOUSE_WHEEL: mouse_wheel += event.MouseInput.Wheel; @@ -235,11 +235,7 @@ void RandomInputHandler::step(float dtime) i.counter -= dtime; if (i.counter < 0.0) { i.counter = 0.1 * Rand(1, i.time_max); - KeyPress k = getKeySetting(i.key.c_str()); - if (keydown.count(k)) - keydown.erase(k); - else - keydown.insert(k); + keydown.toggle(getKeySetting(i.key.c_str())); } } { diff --git a/src/client/inputhandler.h b/src/client/inputhandler.h index 885f34e05..def147a82 100644 --- a/src/client/inputhandler.h +++ b/src/client/inputhandler.h @@ -21,9 +21,9 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "irrlichttypes_extrabloated.h" #include "joystick_controller.h" +#include #include "keycode.h" #include "renderingengine.h" -#include #ifdef HAVE_TOUCHSCREENGUI #include "gui/touchscreengui.h" @@ -61,32 +61,98 @@ struct KeyCache InputHandler *handler; }; +class KeyList : private std::list +{ + typedef std::list super; + typedef super::iterator iterator; + typedef super::const_iterator const_iterator; + + virtual const_iterator find(const KeyPress &key) const + { + const_iterator f(begin()); + const_iterator e(end()); + + while (f != e) { + if (*f == key) + return f; + + ++f; + } + + return e; + } + + virtual iterator find(const KeyPress &key) + { + iterator f(begin()); + iterator e(end()); + + while (f != e) { + if (*f == key) + return f; + + ++f; + } + + return e; + } + +public: + void clear() { super::clear(); } + + void set(const KeyPress &key) + { + if (find(key) == end()) + push_back(key); + } + + void unset(const KeyPress &key) + { + iterator p(find(key)); + + if (p != end()) + erase(p); + } + + void toggle(const KeyPress &key) + { + iterator p(this->find(key)); + + if (p != end()) + erase(p); + else + push_back(key); + } + + bool operator[](const KeyPress &key) const { return find(key) != end(); } +}; + class MyEventReceiver : public IEventReceiver { public: // This is the one method that we have to implement virtual bool OnEvent(const SEvent &event); - bool IsKeyDown(const KeyPress &keyCode) const { return keyIsDown.count(keyCode); } + bool IsKeyDown(const KeyPress &keyCode) const { return keyIsDown[keyCode]; } // Checks whether a key was down and resets the state bool WasKeyDown(const KeyPress &keyCode) { - bool b = keyWasDown.count(keyCode); + bool b = keyWasDown[keyCode]; if (b) - keyWasDown.erase(keyCode); + keyWasDown.unset(keyCode); return b; } // Checks whether a key was just pressed. State will be cleared // in the subsequent iteration of Game::processPlayerInteraction - bool WasKeyPressed(const KeyPress &keycode) const { return keyWasPressed.count(keycode); } + bool WasKeyPressed(const KeyPress &keycode) const { return keyWasPressed[keycode]; } // Checks whether a key was just released. State will be cleared // in the subsequent iteration of Game::processPlayerInteraction - bool WasKeyReleased(const KeyPress &keycode) const { return keyWasReleased.count(keycode); } + bool WasKeyReleased(const KeyPress &keycode) const { return keyWasReleased[keycode]; } - void listenForKey(const KeyPress &keyCode) { keysListenedFor.insert(keyCode); } + void listenForKey(const KeyPress &keyCode) { keysListenedFor.set(keyCode); } void dontListenForKeys() { keysListenedFor.clear(); } s32 getMouseWheel() @@ -132,20 +198,24 @@ public: #endif private: - //! The current state of keys - std::unordered_set keyIsDown; + // The current state of keys + KeyList keyIsDown; - //! Whether a key was down - std::unordered_set keyWasDown; + // Whether a key was down + KeyList keyWasDown; - //! Whether a key has just been pressed - std::unordered_set keyWasPressed; + // Whether a key has just been pressed + KeyList keyWasPressed; - //! Whether a key has just been released - std::unordered_set keyWasReleased; + // Whether a key has just been released + KeyList keyWasReleased; - //! List of keys we listen for - std::unordered_set keysListenedFor; + // List of keys we listen for + // TODO perhaps the type of this is not really + // performant as KeyList is designed for few but + // often changing keys, and keysListenedFor is expected + // to change seldomly but contain lots of keys. + KeyList keysListenedFor; }; class InputHandler @@ -277,7 +347,7 @@ public: return true; } - virtual bool isKeyDown(GameKeyType k) { return keydown.count(keycache.key[k]); } + virtual bool isKeyDown(GameKeyType k) { return keydown[keycache.key[k]]; } virtual bool wasKeyDown(GameKeyType k) { return false; } virtual bool wasKeyPressed(GameKeyType k) { return false; } virtual bool wasKeyReleased(GameKeyType k) { return false; } @@ -292,7 +362,7 @@ public: s32 Rand(s32 min, s32 max); private: - std::unordered_set keydown; + KeyList keydown; v2s32 mousepos; v2s32 mousespeed; }; diff --git a/src/client/keycode.h b/src/client/keycode.h index 263b722c7..7036705d1 100644 --- a/src/client/keycode.h +++ b/src/client/keycode.h @@ -24,20 +24,12 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include -class KeyPress; -namespace std -{ - template <> struct hash; -} - /* A key press, consisting of either an Irrlicht keycode or an actual char */ class KeyPress { public: - friend struct std::hash; - KeyPress() = default; KeyPress(const char *name); @@ -63,17 +55,6 @@ protected: std::string m_name = ""; }; -namespace std -{ - template <> struct hash - { - size_t operator()(const KeyPress &key) const - { - return key.Key; - } - }; -} - extern const KeyPress EscapeKey; extern const KeyPress CancelKey; -- cgit v1.2.3 From 8eb2cbac613c92c1a7656ecb542e63fed9023061 Mon Sep 17 00:00:00 2001 From: red-001 Date: Thu, 12 Nov 2020 20:05:47 +0000 Subject: Fix warnings about an unused variables and implicit conversion (#10586) --- src/gui/guiScrollBar.cpp | 2 +- src/gui/guiScrollBar.h | 1 - src/mapgen/mg_ore.cpp | 6 +++++- 3 files changed, 6 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/gui/guiScrollBar.cpp b/src/gui/guiScrollBar.cpp index b04ccb9d5..c6a03f3e4 100644 --- a/src/gui/guiScrollBar.cpp +++ b/src/gui/guiScrollBar.cpp @@ -21,7 +21,7 @@ GUIScrollBar::GUIScrollBar(IGUIEnvironment *environment, IGUIElement *parent, s3 is_horizontal(horizontal), is_auto_scaling(auto_scale), dragged_by_slider(false), tray_clicked(false), scroll_pos(0), draw_center(0), thumb_size(0), min_pos(0), max_pos(100), small_step(10), - large_step(50), last_change(0), drag_offset(0), page_size(100), border_size(0) + large_step(50), drag_offset(0), page_size(100), border_size(0) { refreshControls(); setNotClipped(false); diff --git a/src/gui/guiScrollBar.h b/src/gui/guiScrollBar.h index 29493bb99..d18f8e875 100644 --- a/src/gui/guiScrollBar.h +++ b/src/gui/guiScrollBar.h @@ -68,7 +68,6 @@ private: s32 max_pos; s32 small_step; s32 large_step; - u32 last_change; s32 drag_offset; s32 page_size; s32 border_size; diff --git a/src/mapgen/mg_ore.cpp b/src/mapgen/mg_ore.cpp index b50ed6a32..5814f433a 100644 --- a/src/mapgen/mg_ore.cpp +++ b/src/mapgen/mg_ore.cpp @@ -498,7 +498,11 @@ void OreVein::generate(MMVManip *vm, int mapseed, u32 blockseed, } // randval ranges from -1..1 - float randval = (float)pr.next() / (pr.RANDOM_RANGE / 2) - 1.f; + /* + Note: can generate values slightly larger than 1 + but this can't be changed as mapgen must be deterministic accross versions. + */ + float randval = (float)pr.next() / float(pr.RANDOM_RANGE / 2) - 1.f; float noiseval = contour(noise->result[index]); float noiseval2 = contour(noise2->result[index]); if (noiseval * noiseval2 + randval * random_factor < nthresh) -- cgit v1.2.3 From c441baa91b71c48a369178df287eeb91e15ea7d1 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Tue, 10 Nov 2020 21:22:02 +0100 Subject: Fix overloaded virtual warnings with get/setAttachment() --- src/client/content_cao.cpp | 49 +++++++++++++++++++++++----------------------- src/client/content_cao.h | 12 ++++-------- 2 files changed, 29 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/client/content_cao.cpp b/src/client/content_cao.cpp index 7c349244f..c52bc62c5 100644 --- a/src/client/content_cao.cpp +++ b/src/client/content_cao.cpp @@ -460,18 +460,20 @@ void GenericCAO::setChildrenVisible(bool toset) GenericCAO *obj = m_env->getGenericCAO(cao_id); if (obj) { // Check if the entity is forced to appear in first person. - obj->setVisible(obj->isForcedVisible() ? true : toset); + obj->setVisible(obj->m_force_visible ? true : toset); } } } -void GenericCAO::setAttachment(int parent_id, const std::string &bone, v3f position, v3f rotation) +void GenericCAO::setAttachment(int parent_id, const std::string &bone, + v3f position, v3f rotation, bool force_visible) { int old_parent = m_attachment_parent_id; m_attachment_parent_id = parent_id; m_attachment_bone = bone; m_attachment_position = position; m_attachment_rotation = rotation; + m_force_visible = force_visible; ClientActiveObject *parent = m_env->getActiveObject(parent_id); @@ -482,15 +484,30 @@ void GenericCAO::setAttachment(int parent_id, const std::string &bone, v3f posit parent->addAttachmentChild(m_id); } updateAttachments(); + + // Forcibly show attachments if required by set_attach + if (m_force_visible) { + m_is_visible = true; + } else if (!m_is_local_player) { + // Objects attached to the local player should be hidden in first person + m_is_visible = !m_attached_to_local || + m_client->getCamera()->getCameraMode() != CAMERA_MODE_FIRST; + m_force_visible = false; + } else { + // Local players need to have this set, + // otherwise first person attachments fail. + m_is_visible = true; + } } void GenericCAO::getAttachment(int *parent_id, std::string *bone, v3f *position, - v3f *rotation) const + v3f *rotation, bool *force_visible) const { *parent_id = m_attachment_parent_id; *bone = m_attachment_bone; *position = m_attachment_position; *rotation = m_attachment_rotation; + *force_visible = m_force_visible; } void GenericCAO::clearChildAttachments() @@ -509,9 +526,9 @@ void GenericCAO::clearChildAttachments() void GenericCAO::clearParentAttachment() { if (m_attachment_parent_id) - setAttachment(0, "", m_attachment_position, m_attachment_rotation); + setAttachment(0, "", m_attachment_position, m_attachment_rotation, false); else - setAttachment(0, "", v3f(), v3f()); + setAttachment(0, "", v3f(), v3f(), false); } void GenericCAO::addAttachmentChild(int child_id) @@ -1781,25 +1798,9 @@ void GenericCAO::processMessage(const std::string &data) std::string bone = deSerializeString16(is); v3f position = readV3F32(is); v3f rotation = readV3F32(is); - m_force_visible = readU8(is); // Returns false for EOF - - setAttachment(parent_id, bone, position, rotation); - - // Forcibly show attachments if required by set_attach - if (m_force_visible) - m_is_visible = true; - // localplayer itself can't be attached to localplayer - else if (!m_is_local_player) { - // Objects attached to the local player should be hidden in first - // person provided the forced boolean isn't set. - m_is_visible = !m_attached_to_local || - m_client->getCamera()->getCameraMode() != CAMERA_MODE_FIRST; - m_force_visible = false; - } else { - // Local players need to have this set, - // otherwise first person attachments fail. - m_is_visible = true; - } + bool force_visible = readU8(is); // Returns false for EOF + + setAttachment(parent_id, bone, position, rotation, force_visible); } else if (cmd == AO_CMD_PUNCHED) { u16 result_hp = readU16(is); diff --git a/src/client/content_cao.h b/src/client/content_cao.h index 435fc2931..7c134fb48 100644 --- a/src/client/content_cao.h +++ b/src/client/content_cao.h @@ -111,6 +111,7 @@ private: v3f m_attachment_position; v3f m_attachment_rotation; bool m_attached_to_local = false; + bool m_force_visible = false; int m_anim_frame = 0; int m_anim_num_frames = 1; @@ -126,7 +127,6 @@ private: float m_step_distance_counter = 0.0f; u8 m_last_light = 255; bool m_is_visible = false; - bool m_force_visible = false; s8 m_glow = 0; // Material video::E_MATERIAL_TYPE m_material_type; @@ -218,15 +218,11 @@ public: m_is_visible = toset; } - inline bool isForcedVisible() const - { - return m_force_visible; - } - void setChildrenVisible(bool toset); - void setAttachment(int parent_id, const std::string &bone, v3f position, v3f rotation); + void setAttachment(int parent_id, const std::string &bone, v3f position, + v3f rotation, bool force_visible); void getAttachment(int *parent_id, std::string *bone, v3f *position, - v3f *rotation) const; + v3f *rotation, bool *force_visible) const; void clearChildAttachments(); void clearParentAttachment(); void addAttachmentChild(int child_id); -- cgit v1.2.3 From b504a1aa4bdc56676b4b1c398ebfe98d336f8f6e Mon Sep 17 00:00:00 2001 From: sfan5 Date: Tue, 10 Nov 2020 21:36:58 +0100 Subject: Fix player sprite visibility in first person closes #10525 --- src/client/content_cao.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/client/content_cao.cpp b/src/client/content_cao.cpp index c52bc62c5..c645900aa 100644 --- a/src/client/content_cao.cpp +++ b/src/client/content_cao.cpp @@ -1919,13 +1919,23 @@ void GenericCAO::updateMeshCulling() if (!m_is_local_player) return; - // Grab the active player scene node so we know there's - // at least a mesh to occlude from the camera. + const bool hidden = m_client->getCamera()->getCameraMode() == CAMERA_MODE_FIRST; + + if (m_meshnode && m_prop.visual == "upright_sprite") { + u32 buffers = m_meshnode->getMesh()->getMeshBufferCount(); + for (u32 i = 0; i < buffers; i++) { + video::SMaterial &mat = m_meshnode->getMesh()->getMeshBuffer(i)->getMaterial(); + // upright sprite has no backface culling + mat.setFlag(video::EMF_FRONT_FACE_CULLING, hidden); + } + return; + } + irr::scene::ISceneNode *node = getSceneNode(); if (!node) return; - if (m_client->getCamera()->getCameraMode() == CAMERA_MODE_FIRST) { + if (hidden) { // Hide the mesh by culling both front and // back faces. Serious hackyness but it works for our // purposes. This also preserves the skeletal armature. -- cgit v1.2.3 From ad58ece18062d4c545432b45d71ce6dbe841746b Mon Sep 17 00:00:00 2001 From: sfan5 Date: Tue, 10 Nov 2020 21:46:30 +0100 Subject: serverpackethandler: Minor log message fixes closes #10434 --- src/network/serverpackethandler.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/network/serverpackethandler.cpp b/src/network/serverpackethandler.cpp index 95e7c548e..3db4eb286 100644 --- a/src/network/serverpackethandler.cpp +++ b/src/network/serverpackethandler.cpp @@ -1657,19 +1657,18 @@ void Server::handleCommand_SrpBytesM(NetworkPacket* pkt) bool wantSudo = (cstate == CS_Active); - verbosestream << "Server: Received TOCLIENT_SRP_BYTES_M." << std::endl; + verbosestream << "Server: Received TOSERVER_SRP_BYTES_M." << std::endl; if (!((cstate == CS_HelloSent) || (cstate == CS_Active))) { - actionstream << "Server: got SRP _M packet in wrong state " - << cstate << " from " << addr_s - << ". Ignoring." << std::endl; + warningstream << "Server: got SRP_M packet in wrong state " + << cstate << " from " << addr_s << ". Ignoring." << std::endl; return; } if (client->chosen_mech != AUTH_MECHANISM_SRP && client->chosen_mech != AUTH_MECHANISM_LEGACY_PASSWORD) { - actionstream << "Server: got SRP _M packet, while auth" - << "is going on with mech " << client->chosen_mech << " from " + warningstream << "Server: got SRP_M packet, while auth " + "is going on with mech " << client->chosen_mech << " from " << addr_s << " (wantSudo=" << wantSudo << "). Denying." << std::endl; if (wantSudo) { DenySudoAccess(peer_id); @@ -1717,7 +1716,7 @@ void Server::handleCommand_SrpBytesM(NetworkPacket* pkt) std::string checkpwd; // not used, but needed for passing something if (!m_script->getAuth(playername, &checkpwd, NULL)) { - actionstream << "Server: " << playername << + errorstream << "Server: " << playername << " cannot be authenticated (auth handler does not work?)" << std::endl; DenyAccess(peer_id, SERVER_ACCESSDENIED_SERVER_FAIL); -- cgit v1.2.3 From 2f6393f49d5ebf21abfaa7bff876b8c0cf4ca191 Mon Sep 17 00:00:00 2001 From: Lars Date: Thu, 12 Nov 2020 10:37:34 -0800 Subject: Increase limit for simultaneous blocks sent per client and the meshgen cache. --- builtin/settingtypes.txt | 4 ++-- src/defaultsettings.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index c4dc82dfe..dd4914201 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -747,7 +747,7 @@ mesh_generation_interval (Mapblock mesh generation delay) int 0 0 50 # Size of the MapBlock cache of the mesh generator. Increasing this will # increase the cache hit %, reducing the data being copied from the main # thread, thus reducing jitter. -meshgen_block_cache_size (Mapblock mesh generator's MapBlock cache size in MB) int 20 0 1000 +meshgen_block_cache_size (Mapblock mesh generator's MapBlock cache size in MB) int 40 0 1000 # Enables minimap. enable_minimap (Minimap) bool true @@ -1037,7 +1037,7 @@ ipv6_server (IPv6 server) bool false # Maximum number of blocks that are simultaneously sent per client. # The maximum total count is calculated dynamically: # max_total = ceil((#clients + max_users) * per_client / 4) -max_simultaneous_block_sends_per_client (Maximum simultaneous block sends per client) int 40 +max_simultaneous_block_sends_per_client (Maximum simultaneous block sends per client) int 128 # To reduce lag, block transfers are slowed down when a player is building something. # This determines how long they are slowed down after placing or removing a node. diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 177955589..42e7fc16b 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -42,7 +42,7 @@ void set_default_settings(Settings *settings) settings->setDefault("mute_sound", "false"); settings->setDefault("enable_mesh_cache", "false"); settings->setDefault("mesh_generation_interval", "0"); - settings->setDefault("meshgen_block_cache_size", "20"); + settings->setDefault("meshgen_block_cache_size", "40"); settings->setDefault("enable_vbo", "true"); settings->setDefault("free_move", "false"); settings->setDefault("pitch_move", "false"); @@ -343,7 +343,7 @@ void set_default_settings(Settings *settings) settings->setDefault("port", "30000"); settings->setDefault("strict_protocol_version_checking", "false"); settings->setDefault("player_transfer_distance", "0"); - settings->setDefault("max_simultaneous_block_sends_per_client", "40"); + settings->setDefault("max_simultaneous_block_sends_per_client", "128"); settings->setDefault("time_send_interval", "5"); settings->setDefault("default_game", "minetest"); -- cgit v1.2.3 From 872dce5020c5d05597a251c5ce63ebde256f2b64 Mon Sep 17 00:00:00 2001 From: Paramat Date: Fri, 20 Nov 2020 16:11:19 +0000 Subject: Move Mapgen V7 river generation into the main generation loop (#10639) All terrain generation now occurs in one loop, instead of rivers being carved afterwards in a separate loop. Fixes the removal of nodes added by mods in 'register on generated'. Avoids other problems and reduces the chance of future bugs. Mapchunk generation time is reduced. Also fixes a code mistake which resulted in river channel generation being disabled at floatland altitudes even when floatlands were disabled. --- src/mapgen/mapgen_v7.cpp | 79 +++++++++++++++++++----------------------------- src/mapgen/mapgen_v7.h | 2 +- 2 files changed, 32 insertions(+), 49 deletions(-) (limited to 'src') diff --git a/src/mapgen/mapgen_v7.cpp b/src/mapgen/mapgen_v7.cpp index a1fe25ab6..6b0779e9f 100644 --- a/src/mapgen/mapgen_v7.cpp +++ b/src/mapgen/mapgen_v7.cpp @@ -342,10 +342,6 @@ void MapgenV7::makeChunk(BlockMakeData *data) // Generate base and mountain terrain s16 stone_surface_max_y = generateTerrain(); - // Generate rivers - if (spflags & MGV7_RIDGES) - generateRidgeTerrain(); - // Create heightmap updateHeightmap(node_min, node_max); @@ -467,6 +463,23 @@ bool MapgenV7::getMountainTerrainFromMap(int idx_xyz, int idx_xz, s16 y) } +bool MapgenV7::getRiverChannelFromMap(int idx_xyz, int idx_xz, s16 y) +{ + // Maximum width of river channel. Creates the vertical canyon walls + float width = 0.2f; + float absuwatern = std::fabs(noise_ridge_uwater->result[idx_xz]) * 2.0f; + if (absuwatern > width) + return false; + + float altitude = y - water_level; + float height_mod = (altitude + 17.0f) / 2.5f; + float width_mod = width - absuwatern; + float nridge = noise_ridge->result[idx_xyz] * std::fmax(altitude, 0.0f) / 7.0f; + + return nridge + width_mod * height_mod >= 0.6f; +} + + bool MapgenV7::getFloatlandTerrainFromMap(int idx_xyz, float float_offset) { return noise_floatland->result[idx_xyz] + floatland_density - float_offset >= 0.0f; @@ -521,6 +534,15 @@ int MapgenV7::generateTerrain() } } + // 'Generate rivers in this mapchunk' bool for + // simplification of condition checks in y-loop. + bool gen_rivers = (spflags & MGV7_RIDGES) && node_max.Y >= water_level - 16 && + !gen_floatlands; + if (gen_rivers) { + noise_ridge->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z); + noise_ridge_uwater->perlinMap2D(node_min.X, node_min.Z); + } + //// Place nodes const v3s16 &em = vm->m_area.getExtent(); s16 stone_surface_max_y = -MAX_MAP_GENERATION_LIMIT; @@ -544,10 +566,13 @@ int MapgenV7::generateTerrain() if (vm->m_data[vi].getContent() != CONTENT_IGNORE) continue; - if (y <= surface_y) { + bool is_river_channel = gen_rivers && + getRiverChannelFromMap(index3d, index2d, y); + if (y <= surface_y && !is_river_channel) { vm->m_data[vi] = n_stone; // Base terrain } else if ((spflags & MGV7_MOUNTAINS) && - getMountainTerrainFromMap(index3d, index2d, y)) { + getMountainTerrainFromMap(index3d, index2d, y) && + !is_river_channel) { vm->m_data[vi] = n_stone; // Mountain terrain if (y > stone_surface_max_y) stone_surface_max_y = y; @@ -569,45 +594,3 @@ int MapgenV7::generateTerrain() return stone_surface_max_y; } - - -void MapgenV7::generateRidgeTerrain() -{ - if (node_max.Y < water_level - 16 || - (node_max.Y >= floatland_ymin && node_min.Y <= floatland_ymax)) - return; - - noise_ridge->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z); - noise_ridge_uwater->perlinMap2D(node_min.X, node_min.Z); - - MapNode n_water(c_water_source); - MapNode n_air(CONTENT_AIR); - u32 index3d = 0; - float width = 0.2f; - - for (s16 z = node_min.Z; z <= node_max.Z; z++) - for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; y++) { - u32 vi = vm->m_area.index(node_min.X, y, z); - for (s16 x = node_min.X; x <= node_max.X; x++, index3d++, vi++) { - u32 index2d = (z - node_min.Z) * csize.X + (x - node_min.X); - float uwatern = noise_ridge_uwater->result[index2d] * 2.0f; - if (std::fabs(uwatern) > width) - continue; - // Optimises, but also avoids removing nodes placed by mods in - // 'on-generated', when generating outside mapchunk. - content_t c = vm->m_data[vi].getContent(); - if (c != c_stone) - continue; - - float altitude = y - water_level; - float height_mod = (altitude + 17.0f) / 2.5f; - float width_mod = width - std::fabs(uwatern); - float nridge = noise_ridge->result[index3d] * - std::fmax(altitude, 0.0f) / 7.0f; - if (nridge + width_mod * height_mod < 0.6f) - continue; - - vm->m_data[vi] = (y > water_level) ? n_air : n_water; - } - } -} diff --git a/src/mapgen/mapgen_v7.h b/src/mapgen/mapgen_v7.h index 4020cd935..5db10a304 100644 --- a/src/mapgen/mapgen_v7.h +++ b/src/mapgen/mapgen_v7.h @@ -94,10 +94,10 @@ public: float baseTerrainLevelFromMap(int index); bool getMountainTerrainAtPoint(s16 x, s16 y, s16 z); bool getMountainTerrainFromMap(int idx_xyz, int idx_xz, s16 y); + bool getRiverChannelFromMap(int idx_xyz, int idx_xz, s16 y); bool getFloatlandTerrainFromMap(int idx_xyz, float float_offset); int generateTerrain(); - void generateRidgeTerrain(); private: s16 mount_zero_level; -- cgit v1.2.3 From 78273027bf4bbee7488c76c6d65f85381ec7c0ba Mon Sep 17 00:00:00 2001 From: Pierre-Yves Rollo Date: Wed, 16 Sep 2020 17:10:17 +0200 Subject: Add sound to press event of some formspecs elements (#10402) --- doc/lua_api.txt | 5 +++++ src/client/game.cpp | 12 ++++++------ src/gui/StyleSpec.h | 3 +++ src/gui/guiEngine.cpp | 1 + src/gui/guiFormSpecMenu.cpp | 40 +++++++++++++++++++++++++++++++++++++--- src/gui/guiFormSpecMenu.h | 6 +++++- 6 files changed, 57 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/doc/lua_api.txt b/doc/lua_api.txt index ef283f0c1..27f871618 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -2843,11 +2843,14 @@ Some types may inherit styles from parent types. * noclip - boolean, set to true to allow the element to exceed formspec bounds. * padding - rect, adds space between the edges of the button and the content. This value is relative to bgimg_middle. + * sound - a sound to be played when clicked. * textcolor - color, default white. * checkbox * noclip - boolean, set to true to allow the element to exceed formspec bounds. + * sound - a sound to be played when clicked. * dropdown * noclip - boolean, set to true to allow the element to exceed formspec bounds. + * sound - a sound to be played when clicked. * field, pwdfield, textarea * border - set to false to hide the textbox background and border. Default true. * font - Sets font type. See button `font` property for more information. @@ -2874,10 +2877,12 @@ Some types may inherit styles from parent types. * fgimg_pressed - image when pressed. Defaults to fgimg when not provided. * This is deprecated, use states instead. * NOTE: The parameters of any given image_button will take precedence over fgimg/fgimg_pressed + * sound - a sound to be played when clicked. * scrollbar * noclip - boolean, set to true to allow the element to exceed formspec bounds. * tabheader * noclip - boolean, set to true to allow the element to exceed formspec bounds. + * sound - a sound to be played when clicked. * textcolor - color. Default white. * table, textlist * font - Sets font type. See button `font` property for more information. diff --git a/src/client/game.cpp b/src/client/game.cpp index 5c38e027d..b7bb0a330 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -2071,7 +2071,7 @@ void Game::openInventory() TextDest *txt_dst = new TextDestPlayerInventory(client); auto *&formspec = m_game_ui->updateFormspec(""); GUIFormSpecMenu::create(formspec, client, &input->joystick, fs_src, - txt_dst, client->getFormspecPrepend()); + txt_dst, client->getFormspecPrepend(), sound); formspec->setFormSpec(fs_src->getForm(), inventoryloc); } @@ -2603,7 +2603,7 @@ void Game::handleClientEvent_ShowFormSpec(ClientEvent *event, CameraOrientation auto *&formspec = m_game_ui->updateFormspec(*(event->show_formspec.formname)); GUIFormSpecMenu::create(formspec, client, &input->joystick, - fs_src, txt_dst, client->getFormspecPrepend()); + fs_src, txt_dst, client->getFormspecPrepend(), sound); } delete event->show_formspec.formspec; @@ -2616,7 +2616,7 @@ void Game::handleClientEvent_ShowLocalFormSpec(ClientEvent *event, CameraOrienta LocalFormspecHandler *txt_dst = new LocalFormspecHandler(*event->show_formspec.formname, client); GUIFormSpecMenu::create(m_game_ui->getFormspecGUI(), client, &input->joystick, - fs_src, txt_dst, client->getFormspecPrepend()); + fs_src, txt_dst, client->getFormspecPrepend(), sound); delete event->show_formspec.formspec; delete event->show_formspec.formname; @@ -3336,7 +3336,7 @@ bool Game::nodePlacement(const ItemDefinition &selected_def, auto *&formspec = m_game_ui->updateFormspec(""); GUIFormSpecMenu::create(formspec, client, &input->joystick, fs_src, - txt_dst, client->getFormspecPrepend()); + txt_dst, client->getFormspecPrepend(), sound); formspec->setFormSpec(meta->getString("formspec"), inventoryloc); return false; @@ -4108,7 +4108,7 @@ void Game::showDeathFormspec() auto *&formspec = m_game_ui->getFormspecGUI(); GUIFormSpecMenu::create(formspec, client, &input->joystick, - fs_src, txt_dst, client->getFormspecPrepend()); + fs_src, txt_dst, client->getFormspecPrepend(), sound); formspec->setFocus("btn_respawn"); } @@ -4242,7 +4242,7 @@ void Game::showPauseMenu() auto *&formspec = m_game_ui->getFormspecGUI(); GUIFormSpecMenu::create(formspec, client, &input->joystick, - fs_src, txt_dst, client->getFormspecPrepend()); + fs_src, txt_dst, client->getFormspecPrepend(), sound); formspec->setFocus("btn_continue"); formspec->doPause = true; } diff --git a/src/gui/StyleSpec.h b/src/gui/StyleSpec.h index 36ad51a89..f2844ce28 100644 --- a/src/gui/StyleSpec.h +++ b/src/gui/StyleSpec.h @@ -54,6 +54,7 @@ public: COLORS, BORDERCOLORS, BORDERWIDTHS, + SOUND, NUM_PROPERTIES, NONE }; @@ -116,6 +117,8 @@ public: return BORDERCOLORS; } else if (name == "borderwidths") { return BORDERWIDTHS; + } else if (name == "sound") { + return SOUND; } else { return NONE; } diff --git a/src/gui/guiEngine.cpp b/src/gui/guiEngine.cpp index 4a13f0b11..c5ad5c323 100644 --- a/src/gui/guiEngine.cpp +++ b/src/gui/guiEngine.cpp @@ -170,6 +170,7 @@ GUIEngine::GUIEngine(JoystickController *joystick, m_menumanager, NULL /* &client */, m_texture_source, + m_sound_manager, m_formspecgui, m_buttonhandler, "", diff --git a/src/gui/guiFormSpecMenu.cpp b/src/gui/guiFormSpecMenu.cpp index 039b28e79..632b15992 100644 --- a/src/gui/guiFormSpecMenu.cpp +++ b/src/gui/guiFormSpecMenu.cpp @@ -48,6 +48,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "settings.h" #include "client/client.h" #include "client/fontengine.h" +#include "client/sound.h" #include "util/hex.h" #include "util/numeric.h" #include "util/string.h" // for parseColorString() @@ -95,11 +96,13 @@ inline u32 clamp_u8(s32 value) GUIFormSpecMenu::GUIFormSpecMenu(JoystickController *joystick, gui::IGUIElement *parent, s32 id, IMenuManager *menumgr, - Client *client, ISimpleTextureSource *tsrc, IFormSource *fsrc, TextDest *tdst, + Client *client, ISimpleTextureSource *tsrc, ISoundManager *sound_manager, + IFormSource *fsrc, TextDest *tdst, const std::string &formspecPrepend, bool remap_dbl_click): GUIModalMenu(RenderingEngine::get_gui_env(), parent, id, menumgr, remap_dbl_click), m_invmgr(client), m_tsrc(tsrc), + m_sound_manager(sound_manager), m_client(client), m_formspec_prepend(formspecPrepend), m_form_src(fsrc), @@ -143,11 +146,12 @@ GUIFormSpecMenu::~GUIFormSpecMenu() void GUIFormSpecMenu::create(GUIFormSpecMenu *&cur_formspec, Client *client, JoystickController *joystick, IFormSource *fs_src, TextDest *txt_dest, - const std::string &formspecPrepend) + const std::string &formspecPrepend, ISoundManager *sound_manager) { if (cur_formspec == nullptr) { cur_formspec = new GUIFormSpecMenu(joystick, guiroot, -1, &g_menumgr, - client, client->getTextureSource(), fs_src, txt_dest, formspecPrepend); + client, client->getTextureSource(), sound_manager, fs_src, + txt_dest, formspecPrepend); cur_formspec->doPause = false; /* @@ -614,6 +618,9 @@ void GUIFormSpecMenu::parseCheckbox(parserData* data, const std::string &element data->current_parent, spec.fid, spec.flabel.c_str()); auto style = getDefaultStyleForElement("checkbox", name); + + spec.sound = style.get(StyleSpec::Property::SOUND, ""); + e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false)); if (spec.fname == m_focused_element) { @@ -1020,6 +1027,9 @@ void GUIFormSpecMenu::parseButton(parserData* data, const std::string &element, data->current_parent, spec.fid, spec.flabel.c_str()); auto style = getStyleForElement(type, name, (type != "button") ? "button" : ""); + + spec.sound = style[StyleSpec::STATE_DEFAULT].get(StyleSpec::Property::SOUND, ""); + e->setStyles(style); if (spec.fname == m_focused_element) { @@ -1381,6 +1391,9 @@ void GUIFormSpecMenu::parseDropDown(parserData* data, const std::string &element e->setSelected(stoi(str_initial_selection)-1); auto style = getDefaultStyleForElement("dropdown", name); + + spec.sound = style.get(StyleSpec::Property::SOUND, ""); + e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false)); m_fields.push_back(spec); @@ -1747,6 +1760,10 @@ void GUIFormSpecMenu::parseHyperText(parserData *data, const std::string &elemen ); spec.ftype = f_HyperText; + + auto style = getDefaultStyleForElement("hypertext", spec.fname); + spec.sound = style.get(StyleSpec::Property::SOUND, ""); + GUIHyperText *e = new GUIHyperText(spec.flabel.c_str(), Environment, data->current_parent, spec.fid, rect, m_client, m_tsrc); e->drop(); @@ -1999,6 +2016,8 @@ void GUIFormSpecMenu::parseImageButton(parserData* data, const std::string &elem auto style = getStyleForElement("image_button", spec.fname); + spec.sound = style[StyleSpec::STATE_DEFAULT].get(StyleSpec::Property::SOUND, ""); + // Override style properties with values specified directly in the element if (!image_name.empty()) style[StyleSpec::STATE_DEFAULT].set(StyleSpec::FGIMG, image_name); @@ -2107,6 +2126,9 @@ void GUIFormSpecMenu::parseTabHeader(parserData* data, const std::string &elemen e->setTabHeight(geom.Y); auto style = getDefaultStyleForElement("tabheader", name); + + spec.sound = style.get(StyleSpec::Property::SOUND, ""); + e->setNotClipped(style.getBool(StyleSpec::NOCLIP, true)); for (const std::string &button : buttons) { @@ -2195,6 +2217,9 @@ void GUIFormSpecMenu::parseItemImageButton(parserData* data, const std::string & item_name, m_client); auto style = getStyleForElement("item_image_button", spec_btn.fname, "image_button"); + + spec_btn.sound = style[StyleSpec::STATE_DEFAULT].get(StyleSpec::Property::SOUND, ""); + e_btn->setStyles(style); if (spec_btn.fname == m_focused_element) { @@ -4486,6 +4511,8 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) for (GUIFormSpecMenu::FieldSpec &s : m_fields) { if ((s.ftype == f_TabHeader) && (s.fid == event.GUIEvent.Caller->getID())) { + if (!s.sound.empty() && m_sound_manager) + m_sound_manager->playSound(s.sound, false, 1.0f); s.send = true; acceptInput(); s.send = false; @@ -4529,6 +4556,9 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) continue; if (s.ftype == f_Button || s.ftype == f_CheckBox) { + if (!s.sound.empty() && m_sound_manager) + m_sound_manager->playSound(s.sound, false, 1.0f); + s.send = true; if (s.is_exit) { if (m_allowclose) { @@ -4551,6 +4581,8 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) s2.send = false; } } + if (!s.sound.empty() && m_sound_manager) + m_sound_manager->playSound(s.sound, false, 1.0f); s.send = true; acceptInput(quit_mode_no); @@ -4567,6 +4599,8 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) acceptInput(quit_mode_no); s.fdefault = L""; } else if (s.ftype == f_Unknown || s.ftype == f_HyperText) { + if (!s.sound.empty() && m_sound_manager) + m_sound_manager->playSound(s.sound, false, 1.0f); s.send = true; acceptInput(); s.send = false; diff --git a/src/gui/guiFormSpecMenu.h b/src/gui/guiFormSpecMenu.h index c5d662a69..53076e3bd 100644 --- a/src/gui/guiFormSpecMenu.h +++ b/src/gui/guiFormSpecMenu.h @@ -39,6 +39,7 @@ class InventoryManager; class ISimpleTextureSource; class Client; class GUIScrollContainer; +class ISoundManager; typedef enum { f_Button, @@ -127,6 +128,7 @@ class GUIFormSpecMenu : public GUIModalMenu int priority; core::rect rect; gui::ECURSOR_ICON fcursor_icon; + std::string sound; }; struct TooltipSpec @@ -151,6 +153,7 @@ public: IMenuManager *menumgr, Client *client, ISimpleTextureSource *tsrc, + ISoundManager *sound_manager, IFormSource* fs_src, TextDest* txt_dst, const std::string &formspecPrepend, @@ -160,7 +163,7 @@ public: static void create(GUIFormSpecMenu *&cur_formspec, Client *client, JoystickController *joystick, IFormSource *fs_src, TextDest *txt_dest, - const std::string &formspecPrepend); + const std::string &formspecPrepend, ISoundManager *sound_manager); void setFormSpec(const std::string &formspec_string, const InventoryLocation ¤t_inventory_location) @@ -293,6 +296,7 @@ protected: InventoryManager *m_invmgr; ISimpleTextureSource *m_tsrc; + ISoundManager *m_sound_manager; Client *m_client; std::string m_formspec_string; -- cgit v1.2.3 From 8dc70ebb936277f740dffe9a11b5ee0fecc9de8e Mon Sep 17 00:00:00 2001 From: Lars Date: Tue, 24 Nov 2020 09:23:18 -0800 Subject: Fix camera panning glitches (partially revert 10489.) --- src/client/clientmap.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/clientmap.cpp b/src/client/clientmap.cpp index c8561def6..09072858a 100644 --- a/src/client/clientmap.cpp +++ b/src/client/clientmap.cpp @@ -124,7 +124,10 @@ void ClientMap::updateDrawList() const v3f camera_position = m_camera_position; const v3f camera_direction = m_camera_direction; - const f32 camera_fov = m_camera_fov; + + // Use a higher fov to accomodate faster camera movements. + // Blocks are cropped better when they are drawn. + const f32 camera_fov = m_camera_fov * 1.1f; v3s16 cam_pos_nodes = floatToInt(camera_position, BS); v3s16 p_blocks_min; -- cgit v1.2.3 From f1349be5422ab11b488309bee89fdcf868e860bb Mon Sep 17 00:00:00 2001 From: Lars Date: Wed, 25 Nov 2020 17:16:41 -0800 Subject: Avoid marking map blocks dirty upon deserialization. --- src/mapblock.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/mapblock.cpp b/src/mapblock.cpp index 5fb6b221b..8bfecd755 100644 --- a/src/mapblock.cpp +++ b/src/mapblock.cpp @@ -533,7 +533,7 @@ void MapBlock::deSerialize(std::istream &is, u8 version, bool disk) // Timestamp TRACESTREAM(<<"MapBlock::deSerialize "<= 17) { - setTimestamp(readU32(is)); + setTimestampNoChangedFlag(readU32(is)); m_disk_timestamp = m_timestamp; } else { - setTimestamp(BLOCK_TIMESTAMP_UNDEFINED); + setTimestampNoChangedFlag(BLOCK_TIMESTAMP_UNDEFINED); } // Dynamically re-set ids based on node names -- cgit v1.2.3 From 095f82692d3d1b8b190178d640f0a166d1851f60 Mon Sep 17 00:00:00 2001 From: numzero Date: Sun, 22 Nov 2020 09:13:16 +0300 Subject: Batch cloud drawing --- src/client/clouds.cpp | 47 +++++++++++++++++++++++------------------------ 1 file changed, 23 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/client/clouds.cpp b/src/client/clouds.cpp index 887a62f25..ccc94cc88 100644 --- a/src/client/clouds.cpp +++ b/src/client/clouds.cpp @@ -170,8 +170,9 @@ void Clouds::render() // Read noise - bool *grid = new bool[m_cloud_radius_i * 2 * m_cloud_radius_i * 2]; - + std::vector grid(m_cloud_radius_i * 2 * m_cloud_radius_i * 2); // vector is broken + std::vector vertices; + vertices.reserve(16 * m_cloud_radius_i * m_cloud_radius_i); for(s16 zi = -m_cloud_radius_i; zi < m_cloud_radius_i; zi++) { u32 si = (zi + m_cloud_radius_i) * m_cloud_radius_i * 2 + m_cloud_radius_i; @@ -195,12 +196,7 @@ void Clouds::render() { s16 zi = zi0; s16 xi = xi0; - // Draw from front to back (needed for transparency) - /*if(zi <= 0) - zi = -m_cloud_radius_i - zi; - if(xi <= 0) - xi = -m_cloud_radius_i - xi;*/ - // Draw from back to front + // Draw from back to front for proper transparency if(zi >= 0) zi = m_cloud_radius_i - zi - 1; if(xi >= 0) @@ -220,17 +216,10 @@ void Clouds::render() video::S3DVertex(0,0,0, 0,0,0, c_top, 0, 0) }; - /*if(zi <= 0 && xi <= 0){ - v[0].Color.setBlue(255); - v[1].Color.setBlue(255); - v[2].Color.setBlue(255); - v[3].Color.setBlue(255); - }*/ - - f32 rx = cloud_size / 2.0f; + const f32 rx = cloud_size / 2.0f; // if clouds are flat, the top layer should be at the given height - f32 ry = m_enable_3d ? m_params.thickness * BS : 0.0f; - f32 rz = cloud_size / 2; + const f32 ry = m_enable_3d ? m_params.thickness * BS : 0.0f; + const f32 rz = cloud_size / 2; for(int i=0; idrawVertexPrimitiveList(v, 4, indices, 2, - video::EVT_STANDARD, scene::EPT_TRIANGLES, video::EIT_16BIT); + vertices.push_back(vertex); + } } } - - delete[] grid; + int quad_count = vertices.size() / 4; + std::vector indices; + indices.reserve(quad_count * 6); + for (int k = 0; k < quad_count; k++) { + indices.push_back(4 * k + 0); + indices.push_back(4 * k + 1); + indices.push_back(4 * k + 2); + indices.push_back(4 * k + 2); + indices.push_back(4 * k + 3); + indices.push_back(4 * k + 0); + } + driver->drawVertexPrimitiveList(vertices.data(), vertices.size(), indices.data(), 2 * quad_count, + video::EVT_STANDARD, scene::EPT_TRIANGLES, video::EIT_16BIT); // Restore fog settings driver->setFog(fog_color, fog_type, fog_start, fog_end, fog_density, -- cgit v1.2.3 From 89cc5bf53730d72744d45f92fc11dc9ab6c232c9 Mon Sep 17 00:00:00 2001 From: numzero Date: Sun, 22 Nov 2020 16:43:38 +0300 Subject: Don't evaluate things many times --- src/client/clouds.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/client/clouds.cpp b/src/client/clouds.cpp index ccc94cc88..253dee8b9 100644 --- a/src/client/clouds.cpp +++ b/src/client/clouds.cpp @@ -341,14 +341,13 @@ void Clouds::step(float dtime) void Clouds::update(const v3f &camera_p, const video::SColorf &color_diffuse) { + video::SColorf ambient(m_params.color_ambient); + video::SColorf bright(m_params.color_bright); m_camera_pos = camera_p; - m_color.r = MYMIN(MYMAX(color_diffuse.r * m_params.color_bright.getRed(), - m_params.color_ambient.getRed()), 255) / 255.0f; - m_color.g = MYMIN(MYMAX(color_diffuse.g * m_params.color_bright.getGreen(), - m_params.color_ambient.getGreen()), 255) / 255.0f; - m_color.b = MYMIN(MYMAX(color_diffuse.b * m_params.color_bright.getBlue(), - m_params.color_ambient.getBlue()), 255) / 255.0f; - m_color.a = m_params.color_bright.getAlpha() / 255.0f; + m_color.r = core::clamp(color_diffuse.r * bright.r, ambient.r, 1.0f); + m_color.g = core::clamp(color_diffuse.g * bright.g, ambient.g, 1.0f); + m_color.b = core::clamp(color_diffuse.b * bright.b, ambient.b, 1.0f); + m_color.a = bright.a; // is the camera inside the cloud mesh? m_camera_inside_cloud = false; // default -- cgit v1.2.3 From 3077afc0a2039cd4c8d64d9df62ed9b2ba6463dc Mon Sep 17 00:00:00 2001 From: numzero Date: Sun, 22 Nov 2020 16:29:31 +0300 Subject: Store stars in a single static mesh buffer --- src/client/sky.cpp | 199 +++++++++++++++++++++++------------------------------ src/client/sky.h | 8 ++- 2 files changed, 92 insertions(+), 115 deletions(-) (limited to 'src') diff --git a/src/client/sky.cpp b/src/client/sky.cpp index 2e0cbca86..29a0545ab 100644 --- a/src/client/sky.cpp +++ b/src/client/sky.cpp @@ -1,6 +1,7 @@ /* Minetest Copyright (C) 2010-2013 celeron55, Perttu Ahola +Copyright (C) 2020 numzero, Lobachevskiy Vitaliy 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 @@ -34,16 +35,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "config.h" using namespace irr::core; -Sky::Sky(s32 id, ITextureSource *tsrc) : - scene::ISceneNode(RenderingEngine::get_scene_manager()->getRootSceneNode(), - RenderingEngine::get_scene_manager(), id) -{ - setAutomaticCulling(scene::EAC_OFF); - m_box.MaxEdge.set(0, 0, 0); - m_box.MinEdge.set(0, 0, 0); - - // Create material - +static video::SMaterial baseMaterial() { video::SMaterial mat; mat.Lighting = false; #if ENABLE_GLES @@ -56,14 +48,29 @@ Sky::Sky(s32 id, ITextureSource *tsrc) : mat.TextureLayer[0].TextureWrapU = video::ETC_CLAMP_TO_EDGE; mat.TextureLayer[0].TextureWrapV = video::ETC_CLAMP_TO_EDGE; mat.BackfaceCulling = false; + return mat; +}; + +Sky::Sky(s32 id, ITextureSource *tsrc) : + scene::ISceneNode(RenderingEngine::get_scene_manager()->getRootSceneNode(), + RenderingEngine::get_scene_manager(), id) +{ + setAutomaticCulling(scene::EAC_OFF); + m_box.MaxEdge.set(0, 0, 0); + m_box.MinEdge.set(0, 0, 0); + + // Create materials - m_materials[0] = mat; + m_materials[0] = baseMaterial(); + m_materials[0].MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; + m_materials[0].Lighting = true; + m_materials[0].ColorMaterial = video::ECM_NONE; - m_materials[1] = mat; + m_materials[1] = baseMaterial(); //m_materials[1].MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA; m_materials[1].MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; - m_materials[2] = mat; + m_materials[2] = baseMaterial(); m_materials[2].setTexture(0, tsrc->getTextureForMesh("sunrisebg.png")); m_materials[2].MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; //m_materials[2].MaterialType = video::EMT_TRANSPARENT_ADD_COLOR; @@ -80,7 +87,7 @@ Sky::Sky(s32 id, ITextureSource *tsrc) : tsrc->getTexture(m_moon_params.tonemap) : NULL; if (m_sun_texture) { - m_materials[3] = mat; + m_materials[3] = baseMaterial(); m_materials[3].setTexture(0, m_sun_texture); m_materials[3].MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; // Disables texture filtering @@ -92,7 +99,7 @@ Sky::Sky(s32 id, ITextureSource *tsrc) : m_materials[3].Lighting = true; } if (m_moon_texture) { - m_materials[4] = mat; + m_materials[4] = baseMaterial(); m_materials[4].setTexture(0, m_moon_texture); m_materials[4].MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; // Disables texture filtering @@ -105,7 +112,7 @@ Sky::Sky(s32 id, ITextureSource *tsrc) : } for (int i = 5; i < 11; i++) { - m_materials[i] = mat; + m_materials[i] = baseMaterial(); m_materials[i].Lighting = true; m_materials[i].MaterialType = video::EMT_SOLID; } @@ -673,13 +680,12 @@ void Sky::draw_moon(video::IVideoDriver *driver, float moonsize, const video::SC c = video::SColor(255, 255, 255, 255); draw_sky_body(vertices, -d, d, c); place_sky_body(vertices, -90, wicked_time_of_day * 360 - 90); - driver->drawIndexedTriangleFan(&vertices[0], 4, indices, 2); + driver->drawIndexedTriangleList(&vertices[0], 4, indices, 2); } } void Sky::draw_stars(video::IVideoDriver * driver, float wicked_time_of_day) { - driver->setMaterial(m_materials[1]); // Tune values so that stars first appear just after the sun // disappears over the horizon, and disappear just before the sun // appears over the horizon. @@ -687,87 +693,19 @@ void Sky::draw_stars(video::IVideoDriver * driver, float wicked_time_of_day) // to time 4000. float tod = wicked_time_of_day < 0.5f ? wicked_time_of_day : (1.0f - wicked_time_of_day); - float starbrightness = clamp((0.25f - fabsf(tod)) * 20.0f, 0.0f, 1.0f); - - float f = starbrightness; - float d = (0.006 / 2) * m_star_params.scale; - - video::SColor starcolor = m_star_params.starcolor; - starcolor.setAlpha(f * m_star_params.starcolor.getAlpha()); - - // Stars are only drawn when not fully transparent - if (m_star_params.starcolor.getAlpha() < 1) + float starbrightness = (0.25f - fabsf(tod)) * 20.0f; + int alpha = clamp(starbrightness * m_star_params.starcolor.getAlpha(), 0, 255); + if (!alpha) // Stars are only drawn when not fully transparent return; -#if ENABLE_GLES - u16 *indices = new u16[m_star_params.count * 3]; - video::S3DVertex *vertices = - new video::S3DVertex[m_star_params.count * 3]; - for (u32 i = 0; i < m_star_params.count; i++) { - indices[i * 3 + 0] = i * 3 + 0; - indices[i * 3 + 1] = i * 3 + 1; - indices[i * 3 + 2] = i * 3 + 2; - v3f r = m_stars[i]; - core::CMatrix4 a; - a.buildRotateFromTo(v3f(0, 1, 0), r); - v3f p = v3f(-d, 1, -d); - v3f p1 = v3f(d, 1, 0); - v3f p2 = v3f(-d, 1, d); - a.rotateVect(p); - a.rotateVect(p1); - a.rotateVect(p2); - p.rotateXYBy(wicked_time_of_day * 360 - 90); - p1.rotateXYBy(wicked_time_of_day * 360 - 90); - p2.rotateXYBy(wicked_time_of_day * 360 - 90); - vertices[i * 3 + 0].Pos = p; - vertices[i * 3 + 0].Color = starcolor; - vertices[i * 3 + 1].Pos = p1; - vertices[i * 3 + 1].Color = starcolor; - vertices[i * 3 + 2].Pos = p2; - vertices[i * 3 + 2].Color = starcolor; - } - driver->drawIndexedTriangleList(vertices, m_star_params.count * 3, - indices, m_star_params.count); - delete[] indices; - delete[] vertices; -#else - u16 *indices = new u16[m_star_params.count * 4]; - video::S3DVertex *vertices = - new video::S3DVertex[m_star_params.count * 4]; - for (u32 i = 0; i < m_star_params.count; i++) { - indices[i * 4 + 0] = i * 4 + 0; - indices[i * 4 + 1] = i * 4 + 1; - indices[i * 4 + 2] = i * 4 + 2; - indices[i * 4 + 3] = i * 4 + 3; - v3f r = m_stars[i]; - core::CMatrix4 a; - a.buildRotateFromTo(v3f(0, 1, 0), r); - v3f p = v3f(-d, 1, -d); - v3f p1 = v3f(d, 1, -d); - v3f p2 = v3f(d, 1, d); - v3f p3 = v3f(-d, 1, d); - a.rotateVect(p); - a.rotateVect(p1); - a.rotateVect(p2); - a.rotateVect(p3); - p.rotateXYBy(wicked_time_of_day * 360 - 90); - p1.rotateXYBy(wicked_time_of_day * 360 - 90); - p2.rotateXYBy(wicked_time_of_day * 360 - 90); - p3.rotateXYBy(wicked_time_of_day * 360 - 90); - vertices[i * 4 + 0].Pos = p; - vertices[i * 4 + 0].Color = starcolor; - vertices[i * 4 + 1].Pos = p1; - vertices[i * 4 + 1].Color = starcolor; - vertices[i * 4 + 2].Pos = p2; - vertices[i * 4 + 2].Color = starcolor; - vertices[i * 4 + 3].Pos = p3; - vertices[i * 4 + 3].Color = starcolor; - } - driver->drawVertexPrimitiveList(vertices, m_star_params.count * 4, - indices, m_star_params.count, video::EVT_STANDARD, - scene::EPT_QUADS, video::EIT_16BIT); - delete[] indices; - delete[] vertices; -#endif + + m_materials[0].DiffuseColor = video::SColor(alpha, 0, 0, 0); + m_materials[0].EmissiveColor = m_star_params.starcolor; + auto sky_rotation = core::matrix4().setRotationAxisRadians(2.0f * M_PI * (wicked_time_of_day - 0.25f), v3f(0.0f, 0.0f, 1.0f)); + auto world_matrix = driver->getTransform(video::ETS_WORLD); + driver->setTransform(video::ETS_WORLD, world_matrix * sky_rotation); + driver->setMaterial(m_materials[0]); + driver->drawMeshBuffer(m_stars.get()); + driver->setTransform(video::ETS_WORLD, world_matrix); } void Sky::draw_sky_body(std::array &vertices, float pos_1, float pos_2, const video::SColor &c) @@ -822,7 +760,7 @@ void Sky::setSunTexture(std::string sun_texture, m_sun_texture = tsrc->getTextureForMesh(m_sun_params.texture); if (m_sun_texture) { - m_materials[3] = m_materials[0]; + m_materials[3] = baseMaterial(); m_materials[3].setTexture(0, m_sun_texture); m_materials[3].MaterialType = video:: EMT_TRANSPARENT_ALPHA_CHANNEL; @@ -870,7 +808,7 @@ void Sky::setMoonTexture(std::string moon_texture, m_moon_texture = tsrc->getTextureForMesh(m_moon_params.texture); if (m_moon_texture) { - m_materials[4] = m_materials[0]; + m_materials[4] = baseMaterial(); m_materials[4].setTexture(0, m_moon_texture); m_materials[4].MaterialType = video:: EMT_TRANSPARENT_ALPHA_CHANNEL; @@ -892,19 +830,54 @@ void Sky::setStarCount(u16 star_count, bool force_update) // Allow force updating star count at game init. if (m_star_params.count != star_count || force_update) { m_star_params.count = star_count; - m_stars.clear(); - // Rebuild the stars surrounding the camera - for (u16 i = 0; i < star_count; i++) { - v3f star = v3f( - myrand_range(-10000, 10000), - myrand_range(-10000, 10000), - myrand_range(-10000, 10000) - ); - - star.normalize(); - m_stars.emplace_back(star); - } + updateStars(); + } +} + +void Sky::updateStars() { + m_stars.reset(new scene::SMeshBuffer()); + // Stupid IrrLicht doesn’t allow non-indexed rendering, and indexed quad + // rendering is slow due to lack of hardware support. So as indices are + // 16-bit and there are 4 vertices per star... the limit is 2^16/4 = 0x4000. + // That should be well enough actually. + if (m_star_params.count > 0x4000) { + warningstream << "Requested " << m_star_params.count << " stars but " << 0x4000 << " is the max\n"; + m_star_params.count = 0x4000; + } + m_stars->Vertices.reallocate(4 * m_star_params.count); + m_stars->Indices.reallocate(6 * m_star_params.count); + + float d = (0.006 / 2) * m_star_params.scale; + for (u16 i = 0; i < m_star_params.count; i++) { + v3f r = v3f( + myrand_range(-10000, 10000), + myrand_range(-10000, 10000), + myrand_range(-10000, 10000) + ); + core::CMatrix4 a; + a.buildRotateFromTo(v3f(0, 1, 0), r); + v3f p = v3f(-d, 1, -d); + v3f p1 = v3f(d, 1, -d); + v3f p2 = v3f(d, 1, d); + v3f p3 = v3f(-d, 1, d); + a.rotateVect(p); + a.rotateVect(p1); + a.rotateVect(p2); + a.rotateVect(p3); + m_stars->Vertices.push_back(video::S3DVertex(p, {}, {}, {})); + m_stars->Vertices.push_back(video::S3DVertex(p1, {}, {}, {})); + m_stars->Vertices.push_back(video::S3DVertex(p2, {}, {}, {})); + m_stars->Vertices.push_back(video::S3DVertex(p3, {}, {}, {})); + } + for (u16 i = 0; i < m_star_params.count; i++) { + m_stars->Indices.push_back(i * 4 + 0); + m_stars->Indices.push_back(i * 4 + 1); + m_stars->Indices.push_back(i * 4 + 2); + m_stars->Indices.push_back(i * 4 + 2); + m_stars->Indices.push_back(i * 4 + 3); + m_stars->Indices.push_back(i * 4 + 0); } + m_stars->setHardwareMappingHint(scene::EHM_STATIC); } void Sky::setSkyColors(const SkyColor &sky_color) @@ -936,7 +909,7 @@ void Sky::addTextureToSkybox(std::string texture, int material_id, // Keep a list of texture names handy. m_sky_params.textures.emplace_back(texture); video::ITexture *result = tsrc->getTextureForMesh(texture); - m_materials[material_id+5] = m_materials[0]; + m_materials[material_id+5] = baseMaterial(); m_materials[material_id+5].setTexture(0, result); m_materials[material_id+5].MaterialType = video::EMT_SOLID; } diff --git a/src/client/sky.h b/src/client/sky.h index 3227e8f59..176545015 100644 --- a/src/client/sky.h +++ b/src/client/sky.h @@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include "camera.h" #include "irrlichttypes_extrabloated.h" +#include "irr_ptr.h" #include "skyparams.h" #pragma once @@ -77,7 +78,7 @@ public: void setStarsVisible(bool stars_visible) { m_star_params.visible = stars_visible; } void setStarCount(u16 star_count, bool force_update); void setStarColor(video::SColor star_color) { m_star_params.starcolor = star_color; } - void setStarScale(f32 star_scale) { m_star_params.scale = star_scale; } + void setStarScale(f32 star_scale) { m_star_params.scale = star_scale; updateStars(); } bool getCloudsVisible() const { return m_clouds_visible && m_clouds_enabled; } const video::SColorf &getCloudColor() const { return m_cloudcolor_f; } @@ -178,13 +179,16 @@ private: bool m_default_tint = true; - std::vector m_stars; + irr_ptr m_stars; video::ITexture *m_sun_texture; video::ITexture *m_moon_texture; video::ITexture *m_sun_tonemap; video::ITexture *m_moon_tonemap; + void updateStars(); + void updateStarsColor(video::SColor color); + void draw_sun(video::IVideoDriver *driver, float sunsize, const video::SColor &suncolor, const video::SColor &suncolor2, float wicked_time_of_day); void draw_moon(video::IVideoDriver *driver, float moonsize, const video::SColor &mooncolor, -- cgit v1.2.3 From 560627eef8c02f8201e639c75fcd5301d3a33077 Mon Sep 17 00:00:00 2001 From: numzero Date: Sun, 22 Nov 2020 16:41:36 +0300 Subject: Reuse seed when updating stars The only currently relevant parameter is scale which can now be changed without resetting stars position --- src/client/sky.cpp | 8 +++++--- src/client/sky.h | 1 + 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/client/sky.cpp b/src/client/sky.cpp index 29a0545ab..cc9fb7d36 100644 --- a/src/client/sky.cpp +++ b/src/client/sky.cpp @@ -830,6 +830,7 @@ void Sky::setStarCount(u16 star_count, bool force_update) // Allow force updating star count at game init. if (m_star_params.count != star_count || force_update) { m_star_params.count = star_count; + m_seed = (u64)myrand() << 32 | myrand(); updateStars(); } } @@ -847,12 +848,13 @@ void Sky::updateStars() { m_stars->Vertices.reallocate(4 * m_star_params.count); m_stars->Indices.reallocate(6 * m_star_params.count); + PcgRandom rgen(m_seed); float d = (0.006 / 2) * m_star_params.scale; for (u16 i = 0; i < m_star_params.count; i++) { v3f r = v3f( - myrand_range(-10000, 10000), - myrand_range(-10000, 10000), - myrand_range(-10000, 10000) + rgen.range(-10000, 10000), + rgen.range(-10000, 10000), + rgen.range(-10000, 10000) ); core::CMatrix4 a; a.buildRotateFromTo(v3f(0, 1, 0), r); diff --git a/src/client/sky.h b/src/client/sky.h index 176545015..9f859f961 100644 --- a/src/client/sky.h +++ b/src/client/sky.h @@ -179,6 +179,7 @@ private: bool m_default_tint = true; + u64 m_seed = 0; irr_ptr m_stars; video::ITexture *m_sun_texture; -- cgit v1.2.3 From d7cf40a0ce996985cff20a156c56437f8b64c772 Mon Sep 17 00:00:00 2001 From: numzero Date: Sun, 22 Nov 2020 16:44:00 +0300 Subject: Replace TriangleFan as poorly supported --- src/client/sky.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/client/sky.cpp b/src/client/sky.cpp index cc9fb7d36..dda59dd11 100644 --- a/src/client/sky.cpp +++ b/src/client/sky.cpp @@ -209,7 +209,7 @@ void Sky::render() const f32 t = 1.0f; const f32 o = 0.0f; - static const u16 indices[4] = {0, 1, 2, 3}; + static const u16 indices[6] = {0, 1, 2, 0, 2, 3}; video::S3DVertex vertices[4]; driver->setMaterial(m_materials[1]); @@ -251,7 +251,7 @@ void Sky::render() vertex.Pos.rotateXZBy(180); } } - driver->drawIndexedTriangleFan(&vertices[0], 4, indices, 2); + driver->drawIndexedTriangleList(&vertices[0], 4, indices, 2); } } @@ -277,7 +277,7 @@ void Sky::render() // Switch from -Z (south) to +Z (north) vertex.Pos.rotateXZBy(-180); } - driver->drawIndexedTriangleFan(&vertices[0], 4, indices, 2); + driver->drawIndexedTriangleList(&vertices[0], 4, indices, 2); } } @@ -308,7 +308,7 @@ void Sky::render() // Switch from -Z (south) to -X (west) vertex.Pos.rotateXZBy(-90); } - driver->drawIndexedTriangleFan(&vertices[0], 4, indices, 2); + driver->drawIndexedTriangleList(&vertices[0], 4, indices, 2); } // Draw sun @@ -344,7 +344,7 @@ void Sky::render() // Switch from -Z (south) to +Z (north) vertex.Pos.rotateXZBy(-180); } - driver->drawIndexedTriangleFan(&vertices[0], 4, indices, 2); + driver->drawIndexedTriangleList(&vertices[0], 4, indices, 2); } // Draw bottom far cloudy fog thing in front of sun, moon and stars @@ -353,7 +353,7 @@ void Sky::render() vertices[1] = video::S3DVertex( 1, -1.0, -1, 0, 1, 0, c, o, t); vertices[2] = video::S3DVertex( 1, -1.0, 1, 0, 1, 0, c, o, o); vertices[3] = video::S3DVertex(-1, -1.0, 1, 0, 1, 0, c, t, o); - driver->drawIndexedTriangleFan(&vertices[0], 4, indices, 2); + driver->drawIndexedTriangleList(&vertices[0], 4, indices, 2); } } } @@ -597,7 +597,7 @@ void Sky::draw_sun(video::IVideoDriver *driver, float sunsize, const video::SCol * wicked_time_of_day: current time of day, to know where should be the sun in the sky */ { - static const u16 indices[4] = {0, 1, 2, 3}; + static const u16 indices[] = {0, 1, 2, 0, 2, 3}; std::array vertices; if (!m_sun_texture) { driver->setMaterial(m_materials[1]); @@ -615,7 +615,7 @@ void Sky::draw_sun(video::IVideoDriver *driver, float sunsize, const video::SCol for (int i = 0; i < 4; i++) { draw_sky_body(vertices, -sunsizes[i], sunsizes[i], colors[i]); place_sky_body(vertices, 90, wicked_time_of_day * 360 - 90); - driver->drawIndexedTriangleFan(&vertices[0], 4, indices, 2); + driver->drawIndexedTriangleList(&vertices[0], 4, indices, 2); } } else { driver->setMaterial(m_materials[3]); @@ -627,7 +627,7 @@ void Sky::draw_sun(video::IVideoDriver *driver, float sunsize, const video::SCol c = video::SColor(255, 255, 255, 255); draw_sky_body(vertices, -d, d, c); place_sky_body(vertices, 90, wicked_time_of_day * 360 - 90); - driver->drawIndexedTriangleFan(&vertices[0], 4, indices, 2); + driver->drawIndexedTriangleList(&vertices[0], 4, indices, 2); } } @@ -644,7 +644,7 @@ void Sky::draw_moon(video::IVideoDriver *driver, float moonsize, const video::SC * the sky */ { - static const u16 indices[4] = {0, 1, 2, 3}; + static const u16 indices[] = {0, 1, 2, 0, 2, 3}; std::array vertices; if (!m_moon_texture) { driver->setMaterial(m_materials[1]); @@ -668,7 +668,7 @@ void Sky::draw_moon(video::IVideoDriver *driver, float moonsize, const video::SC for (int i = 0; i < 4; i++) { draw_sky_body(vertices, moonsizes_1[i], moonsizes_2[i], colors[i]); place_sky_body(vertices, -90, wicked_time_of_day * 360 - 90); - driver->drawIndexedTriangleFan(&vertices[0], 4, indices, 2); + driver->drawIndexedTriangleList(&vertices[0], 4, indices, 2); } } else { driver->setMaterial(m_materials[4]); -- cgit v1.2.3 From be59668f4743bb3bf85b37a188ffc1759601c152 Mon Sep 17 00:00:00 2001 From: numzero Date: Sun, 22 Nov 2020 17:36:59 +0300 Subject: Allow missing shaders --- src/client/shader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/shader.cpp b/src/client/shader.cpp index 4f6430579..1cec20d2c 100644 --- a/src/client/shader.cpp +++ b/src/client/shader.cpp @@ -577,7 +577,6 @@ ShaderInfo generate_shader(const std::string &name, u8 material_type, u8 drawtyp shaderinfo.name = name; shaderinfo.material_type = material_type; shaderinfo.drawtype = drawtype; - shaderinfo.material = video::EMT_SOLID; switch (material_type) { case TILE_MATERIAL_OPAQUE: case TILE_MATERIAL_LIQUID_OPAQUE: @@ -598,6 +597,7 @@ ShaderInfo generate_shader(const std::string &name, u8 material_type, u8 drawtyp shaderinfo.base_material = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; break; } + shaderinfo.material = shaderinfo.base_material; bool enable_shaders = g_settings->getBool("enable_shaders"); if (!enable_shaders) -- cgit v1.2.3 From cdcf7dca7c9afb329d49f2016964f77ac379ed67 Mon Sep 17 00:00:00 2001 From: numzero Date: Sun, 22 Nov 2020 18:25:41 +0300 Subject: Sky: support GLES2 IrrLicht built-in shader is broken, have to write my own --- client/shaders/stars_shader/opengl_fragment.glsl | 6 ++++++ client/shaders/stars_shader/opengl_vertex.glsl | 4 ++++ src/client/game.cpp | 8 +++++++- src/client/sky.cpp | 15 ++++++++------- src/client/sky.h | 8 ++++++-- 5 files changed, 31 insertions(+), 10 deletions(-) create mode 100644 client/shaders/stars_shader/opengl_fragment.glsl create mode 100644 client/shaders/stars_shader/opengl_vertex.glsl (limited to 'src') diff --git a/client/shaders/stars_shader/opengl_fragment.glsl b/client/shaders/stars_shader/opengl_fragment.glsl new file mode 100644 index 000000000..a9ed741bf --- /dev/null +++ b/client/shaders/stars_shader/opengl_fragment.glsl @@ -0,0 +1,6 @@ +uniform vec4 starColor; + +void main(void) +{ + gl_FragColor = starColor; +} diff --git a/client/shaders/stars_shader/opengl_vertex.glsl b/client/shaders/stars_shader/opengl_vertex.glsl new file mode 100644 index 000000000..77c401f34 --- /dev/null +++ b/client/shaders/stars_shader/opengl_vertex.glsl @@ -0,0 +1,4 @@ +void main(void) +{ + gl_Position = mWorldViewProj * inVertexPosition; +} diff --git a/src/client/game.cpp b/src/client/game.cpp index b7bb0a330..2001f0487 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -424,6 +424,7 @@ class GameGlobalShaderConstantSetter : public IShaderConstantSetter CachedVertexShaderSetting m_animation_timer_vertex; CachedPixelShaderSetting m_animation_timer_pixel; CachedPixelShaderSetting m_day_light; + CachedPixelShaderSetting m_star_color; CachedPixelShaderSetting m_eye_position_pixel; CachedVertexShaderSetting m_eye_position_vertex; CachedPixelShaderSetting m_minimap_yaw; @@ -456,6 +457,7 @@ public: m_animation_timer_vertex("animationTimer"), m_animation_timer_pixel("animationTimer"), m_day_light("dayLight"), + m_star_color("starColor"), m_eye_position_pixel("eyePosition"), m_eye_position_vertex("eyePosition"), m_minimap_yaw("yawVec"), @@ -507,6 +509,10 @@ public: sunlight.b }; m_day_light.set(dnc, services); + video::SColorf star_color = m_sky->getCurrentStarColor(); + float clr[4] = {star_color.r, star_color.g, star_color.b, star_color.a}; + m_star_color.set(clr, services); + u32 animation_timer = porting::getTimeMs() % 1000000; float animation_timer_f = (float)animation_timer / 100000.f; m_animation_timer_vertex.set(&animation_timer_f, services); @@ -1363,7 +1369,7 @@ bool Game::createClient(const GameStartData &start_data) /* Skybox */ - sky = new Sky(-1, texture_src); + sky = new Sky(-1, texture_src, shader_src); scsf->setSky(sky); skybox = NULL; // This is used/set later on in the main run loop diff --git a/src/client/sky.cpp b/src/client/sky.cpp index dda59dd11..3fc5a95b4 100644 --- a/src/client/sky.cpp +++ b/src/client/sky.cpp @@ -51,7 +51,7 @@ static video::SMaterial baseMaterial() { return mat; }; -Sky::Sky(s32 id, ITextureSource *tsrc) : +Sky::Sky(s32 id, ITextureSource *tsrc, IShaderSource *ssrc) : scene::ISceneNode(RenderingEngine::get_scene_manager()->getRootSceneNode(), RenderingEngine::get_scene_manager(), id) { @@ -59,10 +59,12 @@ Sky::Sky(s32 id, ITextureSource *tsrc) : m_box.MaxEdge.set(0, 0, 0); m_box.MinEdge.set(0, 0, 0); + m_enable_shaders = g_settings->getBool("enable_shaders"); + // Create materials m_materials[0] = baseMaterial(); - m_materials[0].MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; + m_materials[0].MaterialType = ssrc->getShaderInfo(ssrc->getShader("stars_shader", TILE_MATERIAL_ALPHA, 0)).material; m_materials[0].Lighting = true; m_materials[0].ColorMaterial = video::ECM_NONE; @@ -694,12 +696,11 @@ void Sky::draw_stars(video::IVideoDriver * driver, float wicked_time_of_day) float tod = wicked_time_of_day < 0.5f ? wicked_time_of_day : (1.0f - wicked_time_of_day); float starbrightness = (0.25f - fabsf(tod)) * 20.0f; - int alpha = clamp(starbrightness * m_star_params.starcolor.getAlpha(), 0, 255); - if (!alpha) // Stars are only drawn when not fully transparent + m_star_color = m_star_params.starcolor; + m_star_color.a = clamp(starbrightness * m_star_color.a, 0.0f, 1.0f); + if (m_star_color.a <= 0.0f) // Stars are only drawn when not fully transparent return; - - m_materials[0].DiffuseColor = video::SColor(alpha, 0, 0, 0); - m_materials[0].EmissiveColor = m_star_params.starcolor; + m_materials[0].DiffuseColor = m_materials[0].EmissiveColor = m_star_color.toSColor(); auto sky_rotation = core::matrix4().setRotationAxisRadians(2.0f * M_PI * (wicked_time_of_day - 0.25f), v3f(0.0f, 0.0f, 1.0f)); auto world_matrix = driver->getTransform(video::ETS_WORLD); driver->setTransform(video::ETS_WORLD, world_matrix * sky_rotation); diff --git a/src/client/sky.h b/src/client/sky.h index 9f859f961..10e1cd976 100644 --- a/src/client/sky.h +++ b/src/client/sky.h @@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "camera.h" #include "irrlichttypes_extrabloated.h" #include "irr_ptr.h" +#include "shader.h" #include "skyparams.h" #pragma once @@ -35,7 +36,7 @@ class Sky : public scene::ISceneNode { public: //! constructor - Sky(s32 id, ITextureSource *tsrc); + Sky(s32 id, ITextureSource *tsrc, IShaderSource *ssrc); virtual void OnRegisterSceneNode(); @@ -102,6 +103,8 @@ public: void clearSkyboxTextures() { m_sky_params.textures.clear(); } void addTextureToSkybox(std::string texture, int material_id, ITextureSource *tsrc); + const video::SColorf &getCurrentStarColor() const { return m_star_color; } + private: aabb3f m_box; video::SMaterial m_materials[SKY_MATERIAL_COUNT]; @@ -155,6 +158,7 @@ private: bool m_clouds_enabled = true; // Initialised to true, reset only by set_sky API bool m_directional_colored_fog; bool m_in_clouds = true; // Prevent duplicating bools to remember old values + bool m_enable_shaders = false; video::SColorf m_bgcolor_bright_f = video::SColorf(1.0f, 1.0f, 1.0f, 1.0f); video::SColorf m_skycolor_bright_f = video::SColorf(1.0f, 1.0f, 1.0f, 1.0f); @@ -181,6 +185,7 @@ private: u64 m_seed = 0; irr_ptr m_stars; + video::SColorf m_star_color; video::ITexture *m_sun_texture; video::ITexture *m_moon_texture; @@ -188,7 +193,6 @@ private: video::ITexture *m_moon_tonemap; void updateStars(); - void updateStarsColor(video::SColor color); void draw_sun(video::IVideoDriver *driver, float sunsize, const video::SColor &suncolor, const video::SColor &suncolor2, float wicked_time_of_day); -- cgit v1.2.3 From c158e20e5beab1037c905fe96b2a56baccddaec7 Mon Sep 17 00:00:00 2001 From: numzero Date: Sun, 22 Nov 2020 19:49:38 +0300 Subject: Provide fallback star color for GLES 2 with MT shaders disabled --- src/client/sky.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/client/sky.cpp b/src/client/sky.cpp index 3fc5a95b4..0fccf067c 100644 --- a/src/client/sky.cpp +++ b/src/client/sky.cpp @@ -849,6 +849,7 @@ void Sky::updateStars() { m_stars->Vertices.reallocate(4 * m_star_params.count); m_stars->Indices.reallocate(6 * m_star_params.count); + video::SColor fallback_color = m_star_params.starcolor; // used on GLES 2 “without shaders” PcgRandom rgen(m_seed); float d = (0.006 / 2) * m_star_params.scale; for (u16 i = 0; i < m_star_params.count; i++) { @@ -867,10 +868,10 @@ void Sky::updateStars() { a.rotateVect(p1); a.rotateVect(p2); a.rotateVect(p3); - m_stars->Vertices.push_back(video::S3DVertex(p, {}, {}, {})); - m_stars->Vertices.push_back(video::S3DVertex(p1, {}, {}, {})); - m_stars->Vertices.push_back(video::S3DVertex(p2, {}, {}, {})); - m_stars->Vertices.push_back(video::S3DVertex(p3, {}, {}, {})); + m_stars->Vertices.push_back(video::S3DVertex(p, {}, fallback_color, {})); + m_stars->Vertices.push_back(video::S3DVertex(p1, {}, fallback_color, {})); + m_stars->Vertices.push_back(video::S3DVertex(p2, {}, fallback_color, {})); + m_stars->Vertices.push_back(video::S3DVertex(p3, {}, fallback_color, {})); } for (u16 i = 0; i < m_star_params.count; i++) { m_stars->Indices.push_back(i * 4 + 0); -- cgit v1.2.3 From 8689e00fca2cf55594d53f4e112f0d7b6676c8b0 Mon Sep 17 00:00:00 2001 From: numzero Date: Mon, 23 Nov 2020 01:04:31 +0300 Subject: Fix style --- src/client/sky.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/client/sky.cpp b/src/client/sky.cpp index 0fccf067c..180d43066 100644 --- a/src/client/sky.cpp +++ b/src/client/sky.cpp @@ -35,7 +35,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "config.h" using namespace irr::core; -static video::SMaterial baseMaterial() { +static video::SMaterial baseMaterial() +{ video::SMaterial mat; mat.Lighting = false; #if ENABLE_GLES @@ -836,7 +837,8 @@ void Sky::setStarCount(u16 star_count, bool force_update) } } -void Sky::updateStars() { +void Sky::updateStars() +{ m_stars.reset(new scene::SMeshBuffer()); // Stupid IrrLicht doesn’t allow non-indexed rendering, and indexed quad // rendering is slow due to lack of hardware support. So as indices are -- cgit v1.2.3 From 868749b4f8e898be0c01f892ea78d859d054c17e Mon Sep 17 00:00:00 2001 From: sfan5 Date: Thu, 26 Nov 2020 22:17:11 +0100 Subject: Return star color calculation to what it previously was --- src/client/sky.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/sky.cpp b/src/client/sky.cpp index 180d43066..9a2614eda 100644 --- a/src/client/sky.cpp +++ b/src/client/sky.cpp @@ -698,7 +698,7 @@ void Sky::draw_stars(video::IVideoDriver * driver, float wicked_time_of_day) float tod = wicked_time_of_day < 0.5f ? wicked_time_of_day : (1.0f - wicked_time_of_day); float starbrightness = (0.25f - fabsf(tod)) * 20.0f; m_star_color = m_star_params.starcolor; - m_star_color.a = clamp(starbrightness * m_star_color.a, 0.0f, 1.0f); + m_star_color.a *= clamp(starbrightness, 0.0f, 1.0f); if (m_star_color.a <= 0.0f) // Stars are only drawn when not fully transparent return; m_materials[0].DiffuseColor = m_materials[0].EmissiveColor = m_star_color.toSColor(); -- cgit v1.2.3 From 9bb381ebd387cd783da8d582949bf284a29d9b3a Mon Sep 17 00:00:00 2001 From: sfan5 Date: Thu, 26 Nov 2020 22:19:46 +0100 Subject: Change typedef to normal definitions in GUI code --- src/gui/guiEngine.h | 10 +++++----- src/gui/guiFormSpecMenu.h | 18 +++++++++--------- 2 files changed, 14 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/gui/guiEngine.h b/src/gui/guiEngine.h index e5b3edce7..eef1ad8aa 100644 --- a/src/gui/guiEngine.h +++ b/src/gui/guiEngine.h @@ -29,22 +29,22 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "util/enriched_string.h" /******************************************************************************/ -/* Typedefs and macros */ +/* Structs and macros */ /******************************************************************************/ /** texture layer ids */ -typedef enum { +enum texture_layer { TEX_LAYER_BACKGROUND = 0, TEX_LAYER_OVERLAY, TEX_LAYER_HEADER, TEX_LAYER_FOOTER, TEX_LAYER_MAX -} texture_layer; +}; -typedef struct { +struct image_definition { video::ITexture *texture = nullptr; bool tile; unsigned int minsize; -} image_definition; +}; /******************************************************************************/ /* forward declarations */ diff --git a/src/gui/guiFormSpecMenu.h b/src/gui/guiFormSpecMenu.h index 53076e3bd..37106cb65 100644 --- a/src/gui/guiFormSpecMenu.h +++ b/src/gui/guiFormSpecMenu.h @@ -41,7 +41,7 @@ class Client; class GUIScrollContainer; class ISoundManager; -typedef enum { +enum FormspecFieldType { f_Button, f_Table, f_TabHeader, @@ -53,13 +53,13 @@ typedef enum { f_HyperText, f_AnimatedImage, f_Unknown -} FormspecFieldType; +}; -typedef enum { +enum FormspecQuitMode { quit_mode_no, quit_mode_accept, quit_mode_cancel -} FormspecQuitMode; +}; struct TextDest { @@ -356,7 +356,7 @@ private: JoystickController *m_joystick; bool m_show_debug = false; - typedef struct { + struct parserData { bool explicit_size; bool real_coordinates; u8 simple_field_count; @@ -384,16 +384,16 @@ private: // used to restore table selection/scroll/treeview state std::unordered_map table_dyndata; - } parserData; + }; - typedef struct { + struct fs_key_pending { bool key_up; bool key_down; bool key_enter; bool key_escape; - } fs_key_pendig; + }; - fs_key_pendig current_keys_pending; + fs_key_pending current_keys_pending; std::string current_field_enter_pending = ""; std::vector m_hovered_item_tooltips; -- cgit v1.2.3 From f1d72d212a0661588be27003069abf4bd8092e55 Mon Sep 17 00:00:00 2001 From: Lars Date: Sun, 15 Nov 2020 22:58:57 -0800 Subject: Avoid generating the same chunk more than once with multiple emerge threads. --- src/emerge.h | 1 - src/map.cpp | 5 ++++- src/map.h | 1 + src/mapgen/mapgen_carpathian.cpp | 6 ------ src/mapgen/mapgen_flat.cpp | 6 ------ src/mapgen/mapgen_fractal.cpp | 6 ------ src/mapgen/mapgen_singlenode.cpp | 6 ------ src/mapgen/mapgen_v5.cpp | 6 ------ src/mapgen/mapgen_v6.cpp | 6 ------ src/mapgen/mapgen_v7.cpp | 6 ------ src/mapgen/mapgen_valleys.cpp | 6 ------ 11 files changed, 5 insertions(+), 50 deletions(-) (limited to 'src') diff --git a/src/emerge.h b/src/emerge.h index 6f204666d..da845e243 100644 --- a/src/emerge.h +++ b/src/emerge.h @@ -52,7 +52,6 @@ struct BlockMakeData { u64 seed = 0; v3s16 blockpos_min; v3s16 blockpos_max; - v3s16 blockpos_requested; UniqueQueue transforming_liquid; const NodeDefManager *nodedef = nullptr; diff --git a/src/map.cpp b/src/map.cpp index ef7eddb39..37b6e9b6b 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -1345,6 +1345,9 @@ bool ServerMap::initBlockMake(v3s16 blockpos, BlockMakeData *data) v3s16 bpmin = EmergeManager::getContainingChunk(blockpos, csize); v3s16 bpmax = bpmin + v3s16(1, 1, 1) * (csize - 1); + if (!m_chunks_in_progress.insert(bpmin).second) + return false; + bool enable_mapgen_debug_info = m_emerge->enable_mapgen_debug_info; EMERGE_DBG_OUT("initBlockMake(): " PP(bpmin) " - " PP(bpmax)); @@ -1360,7 +1363,6 @@ bool ServerMap::initBlockMake(v3s16 blockpos, BlockMakeData *data) data->seed = getSeed(); data->blockpos_min = bpmin; data->blockpos_max = bpmax; - data->blockpos_requested = blockpos; data->nodedef = m_nodedef; /* @@ -1482,6 +1484,7 @@ void ServerMap::finishBlockMake(BlockMakeData *data, NOTE: Will be saved later. */ //save(MOD_STATE_WRITE_AT_UNLOAD); + m_chunks_in_progress.erase(bpmin); } MapSector *ServerMap::createSector(v2s16 p2d) diff --git a/src/map.h b/src/map.h index b28f34db3..3bc30c482 100644 --- a/src/map.h +++ b/src/map.h @@ -423,6 +423,7 @@ private: // Chunks core::map m_chunks; #endif + std::set m_chunks_in_progress; /* Metadata is re-written on disk only if this is true. diff --git a/src/mapgen/mapgen_carpathian.cpp b/src/mapgen/mapgen_carpathian.cpp index 74ed263ba..b3a0bd270 100644 --- a/src/mapgen/mapgen_carpathian.cpp +++ b/src/mapgen/mapgen_carpathian.cpp @@ -260,12 +260,6 @@ void MapgenCarpathian::makeChunk(BlockMakeData *data) // Pre-conditions assert(data->vmanip); assert(data->nodedef); - assert(data->blockpos_requested.X >= data->blockpos_min.X && - data->blockpos_requested.Y >= data->blockpos_min.Y && - data->blockpos_requested.Z >= data->blockpos_min.Z); - assert(data->blockpos_requested.X <= data->blockpos_max.X && - data->blockpos_requested.Y <= data->blockpos_max.Y && - data->blockpos_requested.Z <= data->blockpos_max.Z); this->generating = true; this->vm = data->vmanip; diff --git a/src/mapgen/mapgen_flat.cpp b/src/mapgen/mapgen_flat.cpp index d62548014..342455029 100644 --- a/src/mapgen/mapgen_flat.cpp +++ b/src/mapgen/mapgen_flat.cpp @@ -209,12 +209,6 @@ void MapgenFlat::makeChunk(BlockMakeData *data) // Pre-conditions assert(data->vmanip); assert(data->nodedef); - assert(data->blockpos_requested.X >= data->blockpos_min.X && - data->blockpos_requested.Y >= data->blockpos_min.Y && - data->blockpos_requested.Z >= data->blockpos_min.Z); - assert(data->blockpos_requested.X <= data->blockpos_max.X && - data->blockpos_requested.Y <= data->blockpos_max.Y && - data->blockpos_requested.Z <= data->blockpos_max.Z); this->generating = true; this->vm = data->vmanip; diff --git a/src/mapgen/mapgen_fractal.cpp b/src/mapgen/mapgen_fractal.cpp index 3b6bbd6c1..fabb1b2b1 100644 --- a/src/mapgen/mapgen_fractal.cpp +++ b/src/mapgen/mapgen_fractal.cpp @@ -209,12 +209,6 @@ void MapgenFractal::makeChunk(BlockMakeData *data) // Pre-conditions assert(data->vmanip); assert(data->nodedef); - assert(data->blockpos_requested.X >= data->blockpos_min.X && - data->blockpos_requested.Y >= data->blockpos_min.Y && - data->blockpos_requested.Z >= data->blockpos_min.Z); - assert(data->blockpos_requested.X <= data->blockpos_max.X && - data->blockpos_requested.Y <= data->blockpos_max.Y && - data->blockpos_requested.Z <= data->blockpos_max.Z); //TimeTaker t("makeChunk"); diff --git a/src/mapgen/mapgen_singlenode.cpp b/src/mapgen/mapgen_singlenode.cpp index cade9e7a8..5382423fa 100644 --- a/src/mapgen/mapgen_singlenode.cpp +++ b/src/mapgen/mapgen_singlenode.cpp @@ -50,12 +50,6 @@ void MapgenSinglenode::makeChunk(BlockMakeData *data) // Pre-conditions assert(data->vmanip); assert(data->nodedef); - assert(data->blockpos_requested.X >= data->blockpos_min.X && - data->blockpos_requested.Y >= data->blockpos_min.Y && - data->blockpos_requested.Z >= data->blockpos_min.Z); - assert(data->blockpos_requested.X <= data->blockpos_max.X && - data->blockpos_requested.Y <= data->blockpos_max.Y && - data->blockpos_requested.Z <= data->blockpos_max.Z); this->generating = true; this->vm = data->vmanip; diff --git a/src/mapgen/mapgen_v5.cpp b/src/mapgen/mapgen_v5.cpp index 0f6a19fa1..87e54755f 100644 --- a/src/mapgen/mapgen_v5.cpp +++ b/src/mapgen/mapgen_v5.cpp @@ -201,12 +201,6 @@ void MapgenV5::makeChunk(BlockMakeData *data) // Pre-conditions assert(data->vmanip); assert(data->nodedef); - assert(data->blockpos_requested.X >= data->blockpos_min.X && - data->blockpos_requested.Y >= data->blockpos_min.Y && - data->blockpos_requested.Z >= data->blockpos_min.Z); - assert(data->blockpos_requested.X <= data->blockpos_max.X && - data->blockpos_requested.Y <= data->blockpos_max.Y && - data->blockpos_requested.Z <= data->blockpos_max.Z); this->generating = true; this->vm = data->vmanip; diff --git a/src/mapgen/mapgen_v6.cpp b/src/mapgen/mapgen_v6.cpp index 90a52e031..e04180f96 100644 --- a/src/mapgen/mapgen_v6.cpp +++ b/src/mapgen/mapgen_v6.cpp @@ -512,12 +512,6 @@ void MapgenV6::makeChunk(BlockMakeData *data) // Pre-conditions assert(data->vmanip); assert(data->nodedef); - assert(data->blockpos_requested.X >= data->blockpos_min.X && - data->blockpos_requested.Y >= data->blockpos_min.Y && - data->blockpos_requested.Z >= data->blockpos_min.Z); - assert(data->blockpos_requested.X <= data->blockpos_max.X && - data->blockpos_requested.Y <= data->blockpos_max.Y && - data->blockpos_requested.Z <= data->blockpos_max.Z); this->generating = true; this->vm = data->vmanip; diff --git a/src/mapgen/mapgen_v7.cpp b/src/mapgen/mapgen_v7.cpp index 6b0779e9f..cc5f5726d 100644 --- a/src/mapgen/mapgen_v7.cpp +++ b/src/mapgen/mapgen_v7.cpp @@ -317,12 +317,6 @@ void MapgenV7::makeChunk(BlockMakeData *data) // Pre-conditions assert(data->vmanip); assert(data->nodedef); - assert(data->blockpos_requested.X >= data->blockpos_min.X && - data->blockpos_requested.Y >= data->blockpos_min.Y && - data->blockpos_requested.Z >= data->blockpos_min.Z); - assert(data->blockpos_requested.X <= data->blockpos_max.X && - data->blockpos_requested.Y <= data->blockpos_max.Y && - data->blockpos_requested.Z <= data->blockpos_max.Z); //TimeTaker t("makeChunk"); diff --git a/src/mapgen/mapgen_valleys.cpp b/src/mapgen/mapgen_valleys.cpp index d7b6f738f..c4234857e 100644 --- a/src/mapgen/mapgen_valleys.cpp +++ b/src/mapgen/mapgen_valleys.cpp @@ -210,12 +210,6 @@ void MapgenValleys::makeChunk(BlockMakeData *data) // Pre-conditions assert(data->vmanip); assert(data->nodedef); - assert(data->blockpos_requested.X >= data->blockpos_min.X && - data->blockpos_requested.Y >= data->blockpos_min.Y && - data->blockpos_requested.Z >= data->blockpos_min.Z); - assert(data->blockpos_requested.X <= data->blockpos_max.X && - data->blockpos_requested.Y <= data->blockpos_max.Y && - data->blockpos_requested.Z <= data->blockpos_max.Z); //TimeTaker t("makeChunk"); -- cgit v1.2.3