]> git.lizzy.rs Git - minetest.git/blobdiff - src/client/client.cpp
Dual wielding
[minetest.git] / src / client / client.cpp
index b7d1cbfe03d63ccb9c7549ca9a07a9341d832bbf..8760b416da43c922ecbdd6f9d170db6813ebba9b 100644 (file)
@@ -41,6 +41,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "filesys.h"
 #include "mapblock_mesh.h"
 #include "mapblock.h"
+#include "mapsector.h"
 #include "minimap.h"
 #include "modchannels.h"
 #include "content/mods.h"
@@ -111,7 +112,7 @@ Client::Client(
        m_sound(sound),
        m_event(event),
        m_rendering_engine(rendering_engine),
-       m_mesh_update_thread(this),
+       m_mesh_update_manager(this),
        m_env(
                new ClientMap(this, rendering_engine, control, 666),
                tsrc, this
@@ -134,7 +135,7 @@ Client::Client(
 
        // Make the mod storage database and begin the save for later
        m_mod_storage_database =
-               new ModMetadataDatabaseSQLite3(porting::path_user + DIR_DELIM + "client");
+                       new ModStorageDatabaseSQLite3(porting::path_user + DIR_DELIM + "client");
        m_mod_storage_database->beginSave();
 
        if (g_settings->getBool("enable_minimap")) {
@@ -142,6 +143,7 @@ Client::Client(
        }
 
        m_cache_save_interval = g_settings->getU16("server_map_save_interval");
+       m_mesh_grid = { g_settings->getU16("client_mesh_chunk") };
 }
 
 void Client::migrateModStorage()
@@ -151,7 +153,7 @@ void Client::migrateModStorage()
        if (fs::IsDir(old_mod_storage)) {
                infostream << "Migrating client mod storage to SQLite3 database" << std::endl;
                {
-                       ModMetadataDatabaseFiles files_db(mod_storage_dir);
+                       ModStorageDatabaseFiles files_db(mod_storage_dir);
                        std::vector<std::string> mod_list;
                        files_db.listMods(&mod_list);
                        for (const std::string &modname : mod_list) {
@@ -196,6 +198,7 @@ void Client::loadMods()
        // Load builtin
        scanModIntoMemory(BUILTIN_MOD_NAME, getBuiltinLuaPath());
        m_script->loadModFromMemory(BUILTIN_MOD_NAME);
+       m_script->checkSetByBuiltin();
 
        ModConfiguration modconf;
        {
@@ -213,9 +216,10 @@ void Client::loadMods()
        }
 
        m_mods = modconf.getMods();
+
        // complain about mods with unsatisfied dependencies
        if (!modconf.isConsistent()) {
-               modconf.printUnsatisfiedModsError();
+               errorstream << modconf.getUnsatisfiedModsError() << std::endl;
                return;
        }
 
@@ -310,7 +314,7 @@ void Client::Stop()
        if (m_mods_loaded)
                m_script->on_shutdown();
        //request all client managed threads to stop
-       m_mesh_update_thread.stop();
+       m_mesh_update_manager.stop();
        // Save local server map
        if (m_localdb) {
                infostream << "Local map saving ended." << std::endl;
@@ -323,7 +327,7 @@ void Client::Stop()
 
 bool Client::isShutdown()
 {
-       return m_shutdown || !m_mesh_update_thread.isRunning();
+       return m_shutdown || !m_mesh_update_manager.isRunning();
 }
 
 Client::~Client()
@@ -333,14 +337,17 @@ Client::~Client()
 
        deleteAuthData();
 
-       m_mesh_update_thread.stop();
-       m_mesh_update_thread.wait();
-       while (!m_mesh_update_thread.m_queue_out.empty()) {
-               MeshUpdateResult r = m_mesh_update_thread.m_queue_out.pop_frontNoEx();
+       m_mesh_update_manager.stop();
+       m_mesh_update_manager.wait();
+       
+       MeshUpdateResult r;
+       while (m_mesh_update_manager.getNextResult(r)) {
+               for (auto block : r.map_blocks)
+                       if (block)
+                               block->refDrop();
                delete r.mesh;
        }
 
-
        delete m_inventory_from_server;
 
        // Delete detached inventories
@@ -545,23 +552,32 @@ void Client::step(float dtime)
                int num_processed_meshes = 0;
                std::vector<v3s16> blocks_to_ack;
                bool force_update_shadows = false;
-               while (!m_mesh_update_thread.m_queue_out.empty())
+               MeshUpdateResult r;
+               while (m_mesh_update_manager.getNextResult(r))
                {
                        num_processed_meshes++;
 
-                       MinimapMapblock *minimap_mapblock = NULL;
+                       std::vector<MinimapMapblock*> minimap_mapblocks;
                        bool do_mapper_update = true;
 
-                       MeshUpdateResult r = m_mesh_update_thread.m_queue_out.pop_frontNoEx();
-                       MapBlock *block = m_env.getMap().getBlockNoCreateNoEx(r.p);
+                       MapSector *sector = m_env.getMap().emergeSector(v2s16(r.p.X, r.p.Z));
+
+                       MapBlock *block = sector->getBlockNoCreateNoEx(r.p.Y);
+
+                       // The block in question is not visible (perhaps it is culled at the server),
+                       // create a blank block just to hold the chunk's mesh.
+                       // If the block becomes visible later it will replace the blank block.
+                       if (!block && r.mesh)
+                               block = sector->createBlankBlock(r.p.Y);
+
                        if (block) {
                                // Delete the old mesh
                                delete block->mesh;
                                block->mesh = nullptr;
 
                                if (r.mesh) {
-                                       minimap_mapblock = r.mesh->moveMinimapMapblock();
-                                       if (minimap_mapblock == NULL)
+                                       minimap_mapblocks = r.mesh->moveMinimapMapblocks();
+                                       if (minimap_mapblocks.empty())
                                                do_mapper_update = false;
 
                                        bool is_empty = true;
@@ -582,17 +598,37 @@ void Client::step(float dtime)
                                delete r.mesh;
                        }
 
-                       if (m_minimap && do_mapper_update)
-                               m_minimap->addBlock(r.p, minimap_mapblock);
+                       for (auto p : r.solid_sides) {
+                               auto block = m_env.getMap().getBlockNoCreateNoEx(p.first);
+                               if (block)
+                                       block->solid_sides = p.second;
+                       }
+
+                       if (m_minimap && do_mapper_update) {
+                               v3s16 ofs;
 
-                       if (r.ack_block_to_server) {
+                               // See also mapblock_mesh.cpp for the code that creates the array of minimap blocks.
+                               for (ofs.Z = 0; ofs.Z < m_mesh_grid.cell_size; ofs.Z++)
+                               for (ofs.Y = 0; ofs.Y < m_mesh_grid.cell_size; ofs.Y++)
+                               for (ofs.X = 0; ofs.X < m_mesh_grid.cell_size; ofs.X++) {
+                                       size_t i = m_mesh_grid.getOffsetIndex(ofs);
+                                       if (i < minimap_mapblocks.size() && minimap_mapblocks[i])
+                                               m_minimap->addBlock(r.p + ofs, minimap_mapblocks[i]);
+                               }
+                       }
+
+                       for (auto p : r.ack_list) {
                                if (blocks_to_ack.size() == 255) {
                                        sendGotBlocks(blocks_to_ack);
                                        blocks_to_ack.clear();
                                }
 
-                               blocks_to_ack.emplace_back(r.p);
+                               blocks_to_ack.emplace_back(p);
                        }
+
+                       for (auto block : r.map_blocks)
+                               if (block)
+                                       block->refDrop();
                }
                if (blocks_to_ack.size() > 0) {
                                // Acknowledge block(s)
@@ -887,7 +923,7 @@ void Client::ReceiveAll()
 {
        NetworkPacket pkt;
        u64 start_ms = porting::getTimeMs();
-       const u64 budget = 100;
+       const u64 budget = 10;
        for(;;) {
                // Limit time even if there would be huge amounts of data to
                // process
@@ -1379,6 +1415,17 @@ void Client::sendHaveMedia(const std::vector<u32> &tokens)
        Send(&pkt);
 }
 
+void Client::sendUpdateClientInfo(const ClientDynamicInfo& info)
+{
+       NetworkPacket pkt(TOSERVER_UPDATE_CLIENT_INFO, 4*2 + 4 + 4 + 4*2);
+       pkt << (u32)info.render_target_size.X << (u32)info.render_target_size.Y;
+       pkt << info.real_gui_scaling;
+       pkt << info.real_hud_scaling;
+       pkt << (f32)info.max_fs_size.X << (f32)info.max_fs_size.Y;
+
+       Send(&pkt);
+}
+
 void Client::removeNode(v3s16 p)
 {
        std::map<v3s16, MapBlock*> modified_blocks;
@@ -1488,6 +1535,8 @@ bool Client::updateWieldedItem()
                list->setModified(false);
        if (auto *list = player->inventory.getList("hand"))
                list->setModified(false);
+       if (auto *list = player->inventory.getList("offhand"))
+               list->setModified(false);
 
        return true;
 }
@@ -1653,12 +1702,12 @@ void Client::addUpdateMeshTask(v3s16 p, bool ack_to_server, bool urgent)
        if (b == NULL)
                return;
 
-       m_mesh_update_thread.updateBlock(&m_env.getMap(), p, ack_to_server, urgent);
+       m_mesh_update_manager.updateBlock(&m_env.getMap(), p, ack_to_server, urgent);
 }
 
 void Client::addUpdateMeshTaskWithEdge(v3s16 blockpos, bool ack_to_server, bool urgent)
 {
-       m_mesh_update_thread.updateBlock(&m_env.getMap(), blockpos, ack_to_server, urgent, true);
+       m_mesh_update_manager.updateBlock(&m_env.getMap(), blockpos, ack_to_server, urgent, true);
 }
 
 void Client::addUpdateMeshTaskForNode(v3s16 nodepos, bool ack_to_server, bool urgent)
@@ -1672,7 +1721,7 @@ void Client::addUpdateMeshTaskForNode(v3s16 nodepos, bool ack_to_server, bool ur
 
        v3s16 blockpos = getNodeBlockPos(nodepos);
        v3s16 blockpos_relative = blockpos * MAP_BLOCKSIZE;
-       m_mesh_update_thread.updateBlock(&m_env.getMap(), blockpos, ack_to_server, urgent, false);
+       m_mesh_update_manager.updateBlock(&m_env.getMap(), blockpos, ack_to_server, urgent, false);
        // Leading edge
        if (nodepos.X == blockpos_relative.X)
                addUpdateMeshTask(blockpos + v3s16(-1, 0, 0), false, urgent);
@@ -1718,7 +1767,7 @@ void Client::showUpdateProgressTexture(void *args, u32 progress, u32 max_progres
                TextureUpdateArgs* targs = (TextureUpdateArgs*) args;
                u16 cur_percent = ceil(progress / (double) max_progress * 100.);
 
-               // update the loading menu -- if neccessary
+               // update the loading menu -- if necessary
                bool do_draw = false;
                u64 time_ms = targs->last_time_ms;
                if (cur_percent != targs->last_percent) {
@@ -1791,7 +1840,7 @@ void Client::afterContentReceived()
 
        // Start mesh update thread after setting up content definitions
        infostream<<"- Starting mesh update thread"<<std::endl;
-       m_mesh_update_thread.start();
+       m_mesh_update_manager.start();
 
        m_state = LC_Ready;
        sendReady();
@@ -1990,26 +2039,6 @@ const std::string* Client::getModFile(std::string filename)
        return &it->second;
 }
 
-bool Client::registerModStorage(ModMetadata *storage)
-{
-       if (m_mod_storages.find(storage->getModName()) != m_mod_storages.end()) {
-               errorstream << "Unable to register same mod storage twice. Storage name: "
-                               << storage->getModName() << std::endl;
-               return false;
-       }
-
-       m_mod_storages[storage->getModName()] = storage;
-       return true;
-}
-
-void Client::unregisterModStorage(const std::string &name)
-{
-       std::unordered_map<std::string, ModMetadata *>::const_iterator it =
-               m_mod_storages.find(name);
-       if (it != m_mod_storages.end())
-               m_mod_storages.erase(name);
-}
-
 /*
  * Mod channels
  */