// Luanti // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (C) 2013, 2017 celeron55, Perttu Ahola #pragma once #include #include #include #include #include "mapblock_mesh.h" #include "threading/mutex_auto_lock.h" #include "util/thread.h" #include #include #include struct QueuedMeshUpdate { v3s16 p = v3s16(-1337, -1337, -1337); std::vector ack_list; int crack_level = -1; v3s16 crack_pos; MeshMakeData *data = nullptr; // This is generated in MeshUpdateQueue::pop() std::vector map_blocks; bool urgent = false; QueuedMeshUpdate() = default; ~QueuedMeshUpdate(); }; /* A thread-safe queue of mesh update tasks and a cache of MapBlock data */ class MeshUpdateQueue { enum UpdateMode { FORCE_UPDATE, SKIP_UPDATE_IF_ALREADY_CACHED, }; public: MeshUpdateQueue(Client *client); ~MeshUpdateQueue(); // Caches the block at p and its neighbors (if needed) and queues a mesh // update for the block at p bool addBlock(Map *map, v3s16 p, bool ack_block_to_server, bool urgent); // Returned pointer must be deleted // Returns NULL if queue is empty QueuedMeshUpdate *pop(); // Marks a position as finished, unblocking the next update void done(v3s16 pos); u32 size() { MutexAutoLock lock(m_mutex); return m_queue.size(); } private: Client *m_client; std::vector m_queue; std::unordered_set m_urgents; std::unordered_set m_inflight_blocks; std::mutex m_mutex; // TODO: Add callback to update these when g_settings changes bool m_cache_enable_shaders; bool m_cache_smooth_lighting; void fillDataFromMapBlocks(QueuedMeshUpdate *q); void cleanupCache(); }; struct MeshUpdateResult { v3s16 p = v3s16(-1338, -1338, -1338); MapBlockMesh *mesh = nullptr; u8 solid_sides; std::vector ack_list; bool urgent = false; std::vector map_blocks; MeshUpdateResult() = default; }; class MeshUpdateManager; class MeshUpdateWorkerThread : public UpdateThread { public: MeshUpdateWorkerThread(Client *client, MeshUpdateQueue *queue_in, MeshUpdateManager *manager, v3s16 *camera_offset); protected: virtual void doUpdate(); private: Client *m_client; MeshUpdateQueue *m_queue_in; MeshUpdateManager *m_manager; v3s16 *m_camera_offset; // TODO: Add callback to update these when g_settings changes int m_generation_interval; }; class MeshUpdateManager { public: MeshUpdateManager(Client *client); // Caches the block at p and its neighbors (if needed) and queues a mesh // update for the block at p void updateBlock(Map *map, v3s16 p, bool ack_block_to_server, bool urgent, bool update_neighbors = false); void putResult(const MeshUpdateResult &r); bool getNextResult(MeshUpdateResult &r); v3s16 m_camera_offset; void start(); void stop(); void wait(); bool isRunning(); private: void deferUpdate(); MeshUpdateQueue m_queue_in; MutexedQueue m_queue_out; MutexedQueue m_queue_out_urgent; std::vector> m_workers; };