diff --git a/.gitignore b/.gitignore index a74eeba06..647b2ed00 100644 --- a/.gitignore +++ b/.gitignore @@ -30,6 +30,8 @@ gtags.files build/.cmake/ # Gradle .gradle +# Clang +.cache ## Files related to Minetest development cycle /*.patch diff --git a/src/client/clientmap.cpp b/src/client/clientmap.cpp index 3b6a319f3..83f9beb89 100644 --- a/src/client/clientmap.cpp +++ b/src/client/clientmap.cpp @@ -146,12 +146,8 @@ void ClientMap::OnRegisterSceneNode() } ISceneNode::OnRegisterSceneNode(); - - if (!m_added_to_shadow_renderer) { - m_added_to_shadow_renderer = true; - if (auto shadows = m_rendering_engine->get_shadow_renderer()) - shadows->addNodeToShadowList(this); - } + // It's not needed to register this node to the shadow renderer + // we have other way to find it } void ClientMap::getBlocksInViewRange(v3s16 cam_pos_nodes, @@ -721,7 +717,7 @@ void ClientMap::renderMapShadows(video::IVideoDriver *driver, return; } - for (auto &i : m_drawlist_shadow) { + for (const auto &i : m_drawlist_shadow) { // only process specific part of the list & break early ++count; if (count <= low_bound) diff --git a/src/client/clientmap.h b/src/client/clientmap.h index 8c45b5382..f5e02d6d0 100644 --- a/src/client/clientmap.h +++ b/src/client/clientmap.h @@ -204,6 +204,5 @@ private: bool m_cache_trilinear_filter; bool m_cache_bilinear_filter; bool m_cache_anistropic_filter; - bool m_added_to_shadow_renderer{false}; u16 m_cache_transparency_sorting_distance; }; diff --git a/src/client/content_cao.cpp b/src/client/content_cao.cpp index a03154340..993fa6e59 100644 --- a/src/client/content_cao.cpp +++ b/src/client/content_cao.cpp @@ -568,7 +568,8 @@ void GenericCAO::removeFromScene(bool permanent) } if (auto shadow = RenderingEngine::get_shadow_renderer()) - shadow->removeNodeFromShadowList(getSceneNode()); + if (auto node = getSceneNode()) + shadow->removeNodeFromShadowList(node); if (m_meshnode) { m_meshnode->remove(); diff --git a/src/client/shadows/dynamicshadowsrender.cpp b/src/client/shadows/dynamicshadowsrender.cpp index e9b2053e3..ebdd1d2af 100644 --- a/src/client/shadows/dynamicshadowsrender.cpp +++ b/src/client/shadows/dynamicshadowsrender.cpp @@ -132,7 +132,7 @@ void ShadowRenderer::initialize() m_texture_format_color = m_shadow_map_texture_32bit ? video::ECOLOR_FORMAT::ECF_G32R32F : video::ECOLOR_FORMAT::ECF_G16R16F; - + m_shadows_enabled &= m_shadows_supported; } @@ -176,16 +176,15 @@ void ShadowRenderer::setShadowIntensity(float shadow_intensity) void ShadowRenderer::addNodeToShadowList( scene::ISceneNode *node, E_SHADOW_MODE shadowMode) { - if (!node) - return; m_shadow_node_array.emplace_back(node, shadowMode); + // node should never be ClientMap + assert(strcmp(node->getName(), "ClientMap") != 0); + node->setMaterialTexture(TEXTURE_LAYER_SHADOW, shadowMapTextureFinal); } void ShadowRenderer::removeNodeFromShadowList(scene::ISceneNode *node) { - if (!node) - return; node->setMaterialTexture(TEXTURE_LAYER_SHADOW, nullptr); for (auto it = m_shadow_node_array.begin(); it != m_shadow_node_array.end();) { if (it->node == node) { @@ -286,7 +285,7 @@ void ShadowRenderer::updateSMTextures() cb->PerspectiveBiasZ = getPerspectiveBiasZ(); cb->CameraPos = light.getFuturePlayerPos(); } - + // set the Render Target // right now we can only render in usual RTT, not // Depth texture is available in irrlicth maybe we @@ -349,7 +348,7 @@ void ShadowRenderer::update(video::ITexture *outputTarget) for (DirectionalLight &light : m_light_list) { // Static shader values for entities are set in updateSMTextures - // SM texture for entities is not updated incrementally and + // SM texture for entities is not updated incrementally and // must by updated using current player position. m_shadow_depth_entity_cb->CameraPos = light.getPlayerPos(); @@ -392,7 +391,7 @@ void ShadowRenderer::drawDebug() m_driver->draw2DImage(shadowMapClientMap, core::rect(0, 50 + 128, 128, 128 + 50 + 128), core::rect({0, 0}, shadowMapTextureFinal->getSize())); - + if (shadowMapTextureDynamicObjects) m_driver->draw2DImage(shadowMapTextureDynamicObjects, core::rect(0, 128 + 50 + 128, 128, @@ -429,39 +428,32 @@ void ShadowRenderer::renderShadowMap(video::ITexture *target, m_driver->setTransform(video::ETS_VIEW, light.getFutureViewMatrix()); m_driver->setTransform(video::ETS_PROJECTION, light.getFutureProjectionMatrix()); - // Operate on the client map - for (const auto &shadow_node : m_shadow_node_array) { - if (strcmp(shadow_node.node->getName(), "ClientMap") != 0) - continue; + ClientMap &map_node = static_cast(m_client->getEnv().getMap()); - ClientMap *map_node = static_cast(shadow_node.node); - - video::SMaterial material; - if (map_node->getMaterialCount() > 0) { - // we only want the first material, which is the one with the albedo info - material = map_node->getMaterial(0); - } - - material.BackfaceCulling = false; - material.FrontfaceCulling = true; - - if (m_shadow_map_colored && pass != scene::ESNRP_SOLID) { - material.MaterialType = (video::E_MATERIAL_TYPE) depth_shader_trans; - } - else { - material.MaterialType = (video::E_MATERIAL_TYPE) depth_shader; - material.BlendOperation = video::EBO_MIN; - } - - m_driver->setTransform(video::ETS_WORLD, - map_node->getAbsoluteTransformation()); - - int frame = m_force_update_shadow_map ? 0 : m_current_frame; - int total_frames = m_force_update_shadow_map ? 1 : m_map_shadow_update_frames; - - map_node->renderMapShadows(m_driver, material, pass, frame, total_frames); - break; + video::SMaterial material; + if (map_node.getMaterialCount() > 0) { + // we only want the first material, which is the one with the albedo info + material = map_node.getMaterial(0); } + + material.BackfaceCulling = false; + material.FrontfaceCulling = true; + + if (m_shadow_map_colored && pass != scene::ESNRP_SOLID) { + material.MaterialType = (video::E_MATERIAL_TYPE) depth_shader_trans; + } + else { + material.MaterialType = (video::E_MATERIAL_TYPE) depth_shader; + material.BlendOperation = video::EBO_MIN; + } + + m_driver->setTransform(video::ETS_WORLD, + map_node.getAbsoluteTransformation()); + + int frame = m_force_update_shadow_map ? 0 : m_current_frame; + int total_frames = m_force_update_shadow_map ? 1 : m_map_shadow_update_frames; + + map_node.renderMapShadows(m_driver, material, pass, frame, total_frames); } void ShadowRenderer::renderShadowObjects( @@ -472,8 +464,7 @@ void ShadowRenderer::renderShadowObjects( for (const auto &shadow_node : m_shadow_node_array) { // we only take care of the shadow casters - if (shadow_node.shadowMode == ESM_RECEIVE || - strcmp(shadow_node.node->getName(), "ClientMap") == 0) + if (shadow_node.shadowMode == ESM_RECEIVE) continue; // render other objects diff --git a/src/client/shadows/dynamicshadowsrender.h b/src/client/shadows/dynamicshadowsrender.h index 79dd25c44..7fe3461bc 100644 --- a/src/client/shadows/dynamicshadowsrender.h +++ b/src/client/shadows/dynamicshadowsrender.h @@ -163,7 +163,7 @@ private: /** * @brief Create a shadow renderer if settings allow this. - * + * * @param device Device to be used to render shadows. * @param client Reference to the client context. * @return A new ShadowRenderer instance or nullptr if shadows are disabled or not supported. diff --git a/src/environment.cpp b/src/environment.cpp index 39b40ee0f..0f74ae6bb 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -44,7 +44,7 @@ Environment::Environment(IGameDef *gamedef): u32 Environment::getDayNightRatio() { - MutexAutoLock lock(this->m_time_lock); + MutexAutoLock lock(m_time_lock); if (m_enable_day_night_ratio_override) return m_day_night_ratio_override; return time_to_daynight_ratio(m_time_of_day_f * 24000, m_cache_enable_shaders); @@ -57,14 +57,14 @@ void Environment::setTimeOfDaySpeed(float speed) void Environment::setDayNightRatioOverride(bool enable, u32 value) { - MutexAutoLock lock(this->m_time_lock); + MutexAutoLock lock(m_time_lock); m_enable_day_night_ratio_override = enable; m_day_night_ratio_override = value; } void Environment::setTimeOfDay(u32 time) { - MutexAutoLock lock(this->m_time_lock); + MutexAutoLock lock(m_time_lock); if (m_time_of_day > time) ++m_day_count; m_time_of_day = time; @@ -73,13 +73,13 @@ void Environment::setTimeOfDay(u32 time) u32 Environment::getTimeOfDay() { - MutexAutoLock lock(this->m_time_lock); + MutexAutoLock lock(m_time_lock); return m_time_of_day; } float Environment::getTimeOfDayF() { - MutexAutoLock lock(this->m_time_lock); + MutexAutoLock lock(m_time_lock); return m_time_of_day_f; } diff --git a/src/gui/guiFormSpecMenu.cpp b/src/gui/guiFormSpecMenu.cpp index 18bcef292..68222b319 100644 --- a/src/gui/guiFormSpecMenu.cpp +++ b/src/gui/guiFormSpecMenu.cpp @@ -127,23 +127,7 @@ GUIFormSpecMenu::GUIFormSpecMenu(JoystickController *joystick, GUIFormSpecMenu::~GUIFormSpecMenu() { - removeAllChildren(); - removeTooltip(); - - for (auto &table_it : m_tables) - table_it.second->drop(); - for (auto &inventorylist_it : m_inventorylists) - inventorylist_it->drop(); - for (auto &checkbox_it : m_checkboxes) - checkbox_it.second->drop(); - for (auto &scrollbar_it : m_scrollbars) - scrollbar_it.second->drop(); - for (auto &tooltip_rect_it : m_tooltip_rects) - tooltip_rect_it.first->drop(); - for (auto &clickthrough_it : m_clickthrough_elements) - clickthrough_it->drop(); - for (auto &scroll_container_it : m_scroll_containers) - scroll_container_it.second->drop(); + removeAll(); delete m_selected_item; delete m_form_src; @@ -2807,6 +2791,28 @@ void GUIFormSpecMenu::parseModel(parserData *data, const std::string &element) m_fields.push_back(spec); } +void GUIFormSpecMenu::removeAll() +{ + // Remove children + removeAllChildren(); + removeTooltip(); + + for (auto &table_it : m_tables) + table_it.second->drop(); + for (auto &inventorylist_it : m_inventorylists) + inventorylist_it->drop(); + for (auto &checkbox_it : m_checkboxes) + checkbox_it.second->drop(); + for (auto &scrollbar_it : m_scrollbars) + scrollbar_it.second->drop(); + for (auto &tooltip_rect_it : m_tooltip_rects) + tooltip_rect_it.first->drop(); + for (auto &clickthrough_it : m_clickthrough_elements) + clickthrough_it->drop(); + for (auto &scroll_container_it : m_scroll_containers) + scroll_container_it.second->drop(); +} + void GUIFormSpecMenu::parseElement(parserData* data, const std::string &element) { //some prechecks @@ -3049,24 +3055,7 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize) m_focused_element = nullopt; } - // Remove children - removeAllChildren(); - removeTooltip(); - - for (auto &table_it : m_tables) - table_it.second->drop(); - for (auto &inventorylist_it : m_inventorylists) - inventorylist_it->drop(); - for (auto &checkbox_it : m_checkboxes) - checkbox_it.second->drop(); - for (auto &scrollbar_it : m_scrollbars) - scrollbar_it.second->drop(); - for (auto &tooltip_rect_it : m_tooltip_rects) - tooltip_rect_it.first->drop(); - for (auto &clickthrough_it : m_clickthrough_elements) - clickthrough_it->drop(); - for (auto &scroll_container_it : m_scroll_containers) - scroll_container_it.second->drop(); + removeAll(); mydata.size = v2s32(100, 100); mydata.screensize = screensize; diff --git a/src/gui/guiFormSpecMenu.h b/src/gui/guiFormSpecMenu.h index d745eab80..36a84c13c 100644 --- a/src/gui/guiFormSpecMenu.h +++ b/src/gui/guiFormSpecMenu.h @@ -404,6 +404,8 @@ private: std::string current_field_enter_pending = ""; std::vector m_hovered_item_tooltips; + void removeAll(); + void parseElement(parserData* data, const std::string &element); void parseSize(parserData* data, const std::string &element); diff --git a/src/map.cpp b/src/map.cpp index 10a0c3543..3a0117769 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -1010,7 +1010,7 @@ NodeTimer Map::getNodeTimer(v3s16 p) <m_node_timers.get(p_rel); + NodeTimer t = block->getNodeTimer(p_rel); NodeTimer nt(t.timeout, t.elapsed, p); return nt; } @@ -1032,7 +1032,7 @@ void Map::setNodeTimer(const NodeTimer &t) return; } NodeTimer nt(t.timeout, t.elapsed, p_rel); - block->m_node_timers.set(nt); + block->setNodeTimer(nt); } void Map::removeNodeTimer(v3s16 p) @@ -1046,7 +1046,7 @@ void Map::removeNodeTimer(v3s16 p) <m_node_timers.remove(p_rel); + block->removeNodeTimer(p_rel); } bool Map::determineAdditionalOcclusionCheck(const v3s16 &pos_camera, diff --git a/src/mapblock.cpp b/src/mapblock.cpp index ca2145cef..b85183a40 100644 --- a/src/mapblock.cpp +++ b/src/mapblock.cpp @@ -27,7 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "gamedef.h" #include "log.h" #include "nameidmapping.h" -#include "content_mapnode.h" // For legacy name-id mapping +#include "content_mapnode.h" // For legacy name-id mapping #include "content_nodemeta.h" // For legacy deserialization #include "serialization.h" #ifndef SERVER @@ -61,7 +61,6 @@ static const char *modified_reason_strings[] = { "unknown", }; - /* MapBlock */ @@ -85,6 +84,63 @@ MapBlock::~MapBlock() #endif } +bool MapBlock::onObjectsActivation() +{ + // Ignore if no stored objects (to not set changed flag) + if (m_static_objects.getAllStored().empty()) + return false; + + verbosestream << "MapBlock::onObjectsActivation(): " + << "activating objects of block " << PP(getPos()) << " (" + << m_static_objects.getStoredSize() << " objects)" << std::endl; + + if (m_static_objects.getStoredSize() > g_settings->getU16("max_objects_per_block")) { + errorstream << "suspiciously large amount of objects detected: " + << m_static_objects.getStoredSize() << " in " + << PP(getPos()) << "; removing all of them." << std::endl; + // Clear stored list + m_static_objects.clearStored(); + raiseModified(MOD_STATE_WRITE_NEEDED, MOD_REASON_TOO_MANY_OBJECTS); + return false; + } + + return true; +} + +bool MapBlock::saveStaticObject(u16 id, const StaticObject &obj, u32 reason) +{ + if (m_static_objects.getStoredSize() >= g_settings->getU16("max_objects_per_block")) { + warningstream << "MapBlock::saveStaticObject(): Trying to store id = " << id + << " statically but block " << PP(getPos()) << " already contains " + << m_static_objects.getStoredSize() << " objects." + << std::endl; + return false; + } + + m_static_objects.insert(id, obj); + if (reason != MOD_REASON_UNKNOWN) // Do not mark as modified if requested + raiseModified(MOD_STATE_WRITE_NEEDED, reason); + + return true; +} + +// This method is only for Server, don't call it on client +void MapBlock::step(float dtime, const std::function &on_timer_cb) +{ + // Run script callbacks for elapsed node_timers + std::vector elapsed_timers = m_node_timers.step(dtime); + if (!elapsed_timers.empty()) { + MapNode n; + v3s16 p; + for (const NodeTimer &elapsed_timer : elapsed_timers) { + n = getNodeNoEx(elapsed_timer.position); + p = elapsed_timer.position + getPosRelative(); + if (on_timer_cb(p, n, elapsed_timer.elapsed)) + setNodeTimer(NodeTimer(elapsed_timer.timeout, 0, elapsed_timer.position)); + } + } +} + bool MapBlock::isValidPositionParent(v3s16 p) { if (isValidPosition(p)) { @@ -392,9 +448,8 @@ void MapBlock::serialize(std::ostream &os_compressed, u8 version, bool disk, int /* Data that goes to disk, but not the network */ - if(disk) - { - if(version <= 24){ + if (disk) { + if (version <= 24) { // Node timers m_node_timers.serialize(os, version); } @@ -402,7 +457,7 @@ void MapBlock::serialize(std::ostream &os_compressed, u8 version, bool disk, int // Static objects m_static_objects.serialize(os); - if(version < 29){ + if (version < 29) { // Timestamp writeU32(os, getTimestamp()); @@ -410,7 +465,7 @@ void MapBlock::serialize(std::ostream &os_compressed, u8 version, bool disk, int nimap.serialize(os); } - if(version >= 25){ + if (version >= 25) { // Node timers m_node_timers.serialize(os, version); } @@ -522,16 +577,15 @@ void MapBlock::deSerialize(std::istream &in_compressed, u8 version, bool disk) /* Data that is only on disk */ - if(disk) - { + if (disk) { // Node timers - if(version == 23){ + if (version == 23) { // Read unused zero readU8(is); } - if(version == 24){ - TRACESTREAM(<<"MapBlock::deSerialize "< 0) { + m_static_objects.clear(); + raiseModified(MOD_STATE_WRITE_NEEDED, MOD_REASON_CLEAR_ALL_OBJECTS); + } + return size; +} /* Legacy serialization */ @@ -656,7 +730,7 @@ void MapBlock::deSerialize_pre22(std::istream &is, u8 version, bool disk) is.read((char*)&flags, 1); is_underground = (flags & 0x01) != 0; m_day_night_differs = (flags & 0x02) != 0; - if(version >= 18) + if (version >= 18) m_generated = (flags & 0x08) == 0; // Uncompress data @@ -747,12 +821,10 @@ void MapBlock::deSerialize_pre22(std::istream &is, u8 version, bool disk) correctBlockNodeIds(&nimap, data, m_gamedef); } - // Legacy data changes // This code has to convert from pre-22 to post-22 format. const NodeDefManager *nodedef = m_gamedef->ndef(); - for(u32 i=0; iget(data[i].getContent()); // Mineral if(nodedef->getId("default:stone") == data[i].getContent() @@ -768,21 +840,17 @@ void MapBlock::deSerialize_pre22(std::istream &is, u8 version, bool disk) data[i].setParam1(0); } // facedir_simple - if(f.legacy_facedir_simple) - { + if (f.legacy_facedir_simple) { data[i].setParam2(data[i].getParam1()); data[i].setParam1(0); } // wall_mounted - if(f.legacy_wallmounted) - { + if (f.legacy_wallmounted) { u8 wallmounted_new_to_old[8] = {0x04, 0x08, 0x01, 0x02, 0x10, 0x20, 0, 0}; u8 dir_old_format = data[i].getParam2(); u8 dir_new_format = 0; - for(u8 j=0; j<8; j++) - { - if((dir_old_format & wallmounted_new_to_old[j]) != 0) - { + for (u8 j = 0; j < 8; j++) { + if ((dir_old_format & wallmounted_new_to_old[j]) != 0) { dir_new_format = j; break; } @@ -790,7 +858,6 @@ void MapBlock::deSerialize_pre22(std::istream &is, u8 version, bool disk) data[i].setParam2(dir_new_format); } } - } /* @@ -798,7 +865,7 @@ void MapBlock::deSerialize_pre22(std::istream &is, u8 version, bool disk) */ std::string analyze_block(MapBlock *block) { - if(block == NULL) + if (block == NULL) return "NULL"; std::ostringstream desc; diff --git a/src/mapblock.h b/src/mapblock.h index 1ab0ce80c..7df4fcaa7 100644 --- a/src/mapblock.h +++ b/src/mapblock.h @@ -325,6 +325,11 @@ public: return m_day_night_differs; } + bool onObjectsActivation(); + bool saveStaticObject(u16 id, const StaticObject &obj, u32 reason); + + void step(float dtime, const std::function &on_timer_cb); + //// //// Timestamp (see m_timestamp) //// @@ -428,6 +433,11 @@ public: void serializeNetworkSpecific(std::ostream &os); void deSerializeNetworkSpecific(std::istream &is); + + bool storeActiveObject(u16 id); + // clearObject and return removed objects count + u32 clearObjects(); + private: /* Private methods @@ -445,7 +455,6 @@ public: #endif NodeMetadataList m_node_metadata; - NodeTimerList m_node_timers; StaticObjectList m_static_objects; static const u32 ystride = MAP_BLOCKSIZE; @@ -536,6 +545,7 @@ private: int m_refcount = 0; MapNode data[nodecount]; + NodeTimerList m_node_timers; }; typedef std::vector MapBlockVect; diff --git a/src/server.cpp b/src/server.cpp index 5451e3833..10c41bc76 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1870,7 +1870,7 @@ void Server::SendSetLighting(session_t peer_id, const Lighting &lighting) { NetworkPacket pkt(TOCLIENT_SET_LIGHTING, 4, peer_id); - + pkt << lighting.shadow_intensity; Send(&pkt); @@ -2251,50 +2251,31 @@ void Server::fadeSound(s32 handle, float step, float gain) void Server::sendRemoveNode(v3s16 p, std::unordered_set *far_players, float far_d_nodes) { - float maxd = far_d_nodes * BS; v3f p_f = intToFloat(p, BS); v3s16 block_pos = getNodeBlockPos(p); NetworkPacket pkt(TOCLIENT_REMOVENODE, 6); pkt << p; - std::vector clients = m_clients.getClientIDs(); - ClientInterface::AutoLock clientlock(m_clients); - - for (session_t client_id : clients) { - RemoteClient *client = m_clients.lockedGetClientNoEx(client_id); - if (!client) - continue; - - RemotePlayer *player = m_env->getPlayer(client_id); - PlayerSAO *sao = player ? player->getPlayerSAO() : nullptr; - - // If player is far away, only set modified blocks not sent - if (!client->isBlockSent(block_pos) || (sao && - sao->getBasePosition().getDistanceFrom(p_f) > maxd)) { - if (far_players) - far_players->emplace(client_id); - else - client->SetBlockNotSent(block_pos); - continue; - } - - // Send as reliable - m_clients.send(client_id, 0, &pkt, true); - } + sendNodeChangePkt(pkt, block_pos, p_f, far_d_nodes, far_players); } void Server::sendAddNode(v3s16 p, MapNode n, std::unordered_set *far_players, float far_d_nodes, bool remove_metadata) { - float maxd = far_d_nodes * BS; v3f p_f = intToFloat(p, BS); v3s16 block_pos = getNodeBlockPos(p); NetworkPacket pkt(TOCLIENT_ADDNODE, 6 + 2 + 1 + 1 + 1); pkt << p << n.param0 << n.param1 << n.param2 << (u8) (remove_metadata ? 0 : 1); + sendNodeChangePkt(pkt, block_pos, p_f, far_d_nodes, far_players); +} +void Server::sendNodeChangePkt(NetworkPacket &pkt, v3s16 block_pos, + v3f p, float far_d_nodes, std::unordered_set *far_players) +{ + float maxd = far_d_nodes * BS; std::vector clients = m_clients.getClientIDs(); ClientInterface::AutoLock clientlock(m_clients); @@ -2308,7 +2289,7 @@ void Server::sendAddNode(v3s16 p, MapNode n, std::unordered_set *far_player // If player is far away, only set modified blocks not sent if (!client->isBlockSent(block_pos) || (sao && - sao->getBasePosition().getDistanceFrom(p_f) > maxd)) { + sao->getBasePosition().getDistanceFrom(p) > maxd)) { if (far_players) far_players->emplace(client_id); else diff --git a/src/server.h b/src/server.h index fdd64e851..668ce2898 100644 --- a/src/server.h +++ b/src/server.h @@ -479,6 +479,8 @@ private: void sendAddNode(v3s16 p, MapNode n, std::unordered_set *far_players = nullptr, float far_d_nodes = 100, bool remove_metadata = true); + void sendNodeChangePkt(NetworkPacket &pkt, v3s16 block_pos, + v3f p, float far_d_nodes, std::unordered_set *far_players); void sendMetadataChanged(const std::unordered_set &positions, float far_d_nodes = 100); diff --git a/src/serverenvironment.cpp b/src/serverenvironment.cpp index f893064de..864fe33a4 100644 --- a/src/serverenvironment.cpp +++ b/src/serverenvironment.cpp @@ -370,7 +370,7 @@ void ActiveBlockList::update(std::vector &active_players, // Go through new list for (v3s16 p : newlist) { // If not on old list, it's been added - if(m_list.find(p) == m_list.end()) + if (m_list.find(p) == m_list.end()) blocks_added.insert(p); } @@ -778,16 +778,16 @@ public: actual_interval = trigger_interval; } float chance = abm->getTriggerChance(); - if(chance == 0) + if (chance == 0) chance = 1; ActiveABM aabm; aabm.abm = abm; if (abm->getSimpleCatchUp()) { float intervals = actual_interval / trigger_interval; - if(intervals == 0) + if (intervals == 0) continue; aabm.chance = chance / intervals; - if(aabm.chance == 0) + if (aabm.chance == 0) aabm.chance = 1; } else { aabm.chance = chance; @@ -844,19 +844,17 @@ public: wider_unknown_count++; continue; } - wider += block2->m_static_objects.m_active.size() - + block2->m_static_objects.m_stored.size(); + wider += block2->m_static_objects.size(); } // Extrapolate - u32 active_object_count = block->m_static_objects.m_active.size(); - u32 wider_known_count = 3*3*3 - wider_unknown_count; + u32 active_object_count = block->m_static_objects.getActiveSize(); + u32 wider_known_count = 3 * 3 * 3 - wider_unknown_count; wider += wider_unknown_count * wider / wider_known_count; return active_object_count; - } void apply(MapBlock *block, int &blocks_scanned, int &abms_run, int &blocks_cached) { - if(m_aabms.empty()) + if (m_aabms.empty()) return; // Check the content type cache first @@ -980,7 +978,7 @@ void ServerEnvironment::activateBlock(MapBlock *block, u32 additional_dtime) // Remove stored static objects if clearObjects was called since block's timestamp if (stamp == BLOCK_TIMESTAMP_UNDEFINED || stamp < m_last_clear_objects_time) { - block->m_static_objects.m_stored.clear(); + block->m_static_objects.clearStored(); // do not set changed flag to avoid unnecessary mapblock writes } @@ -997,18 +995,9 @@ void ServerEnvironment::activateBlock(MapBlock *block, u32 additional_dtime) m_lbm_mgr.applyLBMs(this, block, stamp); // Run node timers - std::vector elapsed_timers = - block->m_node_timers.step((float)dtime_s); - if (!elapsed_timers.empty()) { - MapNode n; - for (const NodeTimer &elapsed_timer : elapsed_timers) { - n = block->getNodeNoEx(elapsed_timer.position); - v3s16 p = elapsed_timer.position + block->getPosRelative(); - if (m_script->node_on_timer(p, n, elapsed_timer.elapsed)) - block->setNodeTimer(NodeTimer(elapsed_timer.timeout, 0, - elapsed_timer.position)); - } - } + block->step((float)dtime_s, [&](v3s16 p, MapNode n, f32 d) -> bool { + return m_script->node_on_timer(p, n, d); + }); } void ServerEnvironment::addActiveBlockModifier(ActiveBlockModifier *abm) @@ -1138,7 +1127,7 @@ u8 ServerEnvironment::findSunlight(v3s16 pos) const m_map->emergeBlock(neighborPos, false); node = m_map->getNode(neighborPos, &is_position_ok); if (!is_position_ok) - continue; // not generated + continue; // not generated } const ContentFeatures &def = ndef->get(node); @@ -1258,14 +1247,10 @@ void ServerEnvironment::clearObjects(ClearObjectsMode mode) << "Failed to emerge block " << PP(p) << std::endl; continue; } - u32 num_stored = block->m_static_objects.m_stored.size(); - u32 num_active = block->m_static_objects.m_active.size(); - if (num_stored != 0 || num_active != 0) { - block->m_static_objects.m_stored.clear(); - block->m_static_objects.m_active.clear(); - block->raiseModified(MOD_STATE_WRITE_NEEDED, - MOD_REASON_CLEAR_ALL_OBJECTS); - num_objs_cleared += num_stored + num_active; + + u32 num_cleared = block->clearObjects(); + if (num_cleared > 0) { + num_objs_cleared += num_cleared; num_blocks_cleared++; } num_blocks_checked++; @@ -1440,19 +1425,9 @@ void ServerEnvironment::step(float dtime) MOD_REASON_BLOCK_EXPIRED); // Run node timers - std::vector elapsed_timers = block->m_node_timers.step(dtime); - if (!elapsed_timers.empty()) { - MapNode n; - v3s16 p2; - for (const NodeTimer &elapsed_timer: elapsed_timers) { - n = block->getNodeNoEx(elapsed_timer.position); - p2 = elapsed_timer.position + block->getPosRelative(); - if (m_script->node_on_timer(p2, n, elapsed_timer.elapsed)) { - block->setNodeTimer(NodeTimer( - elapsed_timer.timeout, 0, elapsed_timer.position)); - } - } - } + block->step(dtime, [&](v3s16 p, MapNode n, f32 d) -> bool { + return m_script->node_on_timer(p, n, d); + }); } } @@ -1530,7 +1505,7 @@ void ServerEnvironment::step(float dtime) u32 object_count = 0; - auto cb_state = [&] (ServerActiveObject *obj) { + auto cb_state = [&](ServerActiveObject *obj) { if (obj->isGone()) return; object_count++; @@ -1728,7 +1703,7 @@ void ServerEnvironment::setStaticForActiveObjectsInBlock( if (!block) return; - for (auto &so_it : block->m_static_objects.m_active) { + for (auto &so_it : block->m_static_objects.getAllActives()) { // Get the ServerActiveObject counterpart to this StaticObject ServerActiveObject *sao = m_ao_manager.getActiveObject(so_it.first); if (!sao) { @@ -1746,7 +1721,7 @@ void ServerEnvironment::setStaticForActiveObjectsInBlock( bool ServerEnvironment::getActiveObjectMessage(ActiveObjectMessage *dest) { - if(m_active_object_messages.empty()) + if (m_active_object_messages.empty()) return false; *dest = std::move(m_active_object_messages.front()); @@ -1821,8 +1796,8 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object, // Add to the block where the object is located in v3s16 blockpos = getNodeBlockPos(floatToInt(objectpos, BS)); MapBlock *block = m_map->emergeBlock(blockpos); - if(block){ - block->m_static_objects.m_active[object->getId()] = s_obj; + if (block) { + block->m_static_objects.setActive(object->getId(), s_obj); object->m_static_exists = true; object->m_static_block = blockpos; @@ -1847,7 +1822,7 @@ void ServerEnvironment::removeRemovedObjects() { ScopeProfiler sp(g_profiler, "ServerEnvironment::removeRemovedObjects()", SPT_AVG); - auto clear_cb = [this] (ServerActiveObject *obj, u16 id) { + auto clear_cb = [this](ServerActiveObject *obj, u16 id) { // This shouldn't happen but check it if (!obj) { errorstream << "ServerEnvironment::removeRemovedObjects(): " @@ -1869,22 +1844,15 @@ void ServerEnvironment::removeRemovedObjects() // If still known by clients, don't actually remove. On some future // invocation this will be 0, which is when removal will continue. - if(obj->m_known_by_count > 0) + if (obj->m_known_by_count > 0) return false; /* Move static data from active to stored if deactivated */ if (!obj->isPendingRemoval() && obj->m_static_exists) { - MapBlock *block = m_map->emergeBlock(obj->m_static_block, false); - if (block) { - const auto i = block->m_static_objects.m_active.find(id); - if (i != block->m_static_objects.m_active.end()) { - block->m_static_objects.m_stored.push_back(i->second); - block->m_static_objects.m_active.erase(id); - block->raiseModified(MOD_STATE_WRITE_NEEDED, - MOD_REASON_REMOVE_OBJECTS_DEACTIVATE); - } else { + if (MapBlock *block = m_map->emergeBlock(obj->m_static_block, false)) { + if (!block->storeActiveObject(id)) { warningstream << "ServerEnvironment::removeRemovedObjects(): " << "id=" << id << " m_static_exists=true but " << "static data doesn't actually exist in " @@ -1914,33 +1882,33 @@ void ServerEnvironment::removeRemovedObjects() static void print_hexdump(std::ostream &o, const std::string &data) { const int linelength = 16; - for(int l=0; ; l++){ + for (int l = 0;; l++) { int i0 = linelength * l; bool at_end = false; int thislinelength = linelength; - if(i0 + thislinelength > (int)data.size()){ + if (i0 + thislinelength > (int)data.size()) { thislinelength = data.size() - i0; at_end = true; } - for(int di=0; di= 32) - o<= 32) + o << data[i]; else - o<<"."; + o << "."; } - o<m_static_objects.m_stored.empty()) + if (!block->onObjectsActivation()) return; - verbosestream<<"ServerEnvironment::activateObjects(): " - <<"activating objects of block "<getPos()) - <<" ("<m_static_objects.m_stored.size() - <<" objects)"<m_static_objects.m_stored.size() > g_settings->getU16("max_objects_per_block")); - if (large_amount) { - errorstream<<"suspiciously large amount of objects detected: " - <m_static_objects.m_stored.size()<<" in " - <getPos()) - <<"; removing all of them."<m_static_objects.m_stored.clear(); - block->raiseModified(MOD_STATE_WRITE_NEEDED, - MOD_REASON_TOO_MANY_OBJECTS); - return; - } - // Activate stored objects std::vector new_stored; - for (const StaticObject &s_obj : block->m_static_objects.m_stored) { + for (const StaticObject &s_obj : block->m_static_objects.getAllStored()) { // Create an active object from the data - ServerActiveObject *obj = createSAO((ActiveObjectType) s_obj.type, s_obj.pos, - s_obj.data); + ServerActiveObject *obj = + createSAO((ActiveObjectType)s_obj.type, s_obj.pos, s_obj.data); // If couldn't create object, store static data back. if (!obj) { - errorstream<<"ServerEnvironment::activateObjects(): " - <<"failed to create active object from static object " - <<"in block "<m_static_objects.m_stored.size() - << " objects." << std::endl; - return false; - } - block->m_static_objects.insert(store_id, s_obj); - if (mod_reason != MOD_REASON_UNKNOWN) // Do not mark as modified if requested - block->raiseModified(MOD_STATE_WRITE_NEEDED, mod_reason); + if (!block->saveStaticObject(store_id, s_obj, mod_reason)) + return false; obj->m_static_exists = true; obj->m_static_block = blockpos; diff --git a/src/staticobject.cpp b/src/staticobject.cpp index f92995d0b..d728f5d10 100644 --- a/src/staticobject.cpp +++ b/src/staticobject.cpp @@ -99,6 +99,7 @@ void StaticObjectList::serialize(std::ostream &os) s_obj.serialize(os); } } + void StaticObjectList::deSerialize(std::istream &is) { if (m_active.size()) { @@ -121,3 +122,13 @@ void StaticObjectList::deSerialize(std::istream &is) } } +bool StaticObjectList::storeActiveObject(u16 id) +{ + const auto i = m_active.find(id); + if (i == m_active.end()) + return false; + + m_stored.push_back(i->second); + m_active.erase(id); + return true; +} diff --git a/src/staticobject.h b/src/staticobject.h index 03cd23cc8..eef090376 100644 --- a/src/staticobject.h +++ b/src/staticobject.h @@ -50,29 +50,24 @@ public: */ void insert(u16 id, const StaticObject &obj) { - if(id == 0) - { + if (id == 0) { m_stored.push_back(obj); - } - else - { - if(m_active.find(id) != m_active.end()) - { - dstream<<"ERROR: StaticObjectList::insert(): " - <<"id already exists"<& getAllStored() const { return m_stored; } + const std::map &getAllActives() const { return m_active; } + + inline void setActive(u16 id, const StaticObject &obj) { m_active[id] = obj; } + inline size_t getActiveSize() const { return m_active.size(); } + inline size_t getStoredSize() const { return m_stored.size(); } + inline void clearStored() { m_stored.clear(); } + void pushStored(const StaticObject &obj) { m_stored.push_back(obj); } + + bool storeActiveObject(u16 id); + + inline void clear() + { + m_active.clear(); + m_stored.clear(); + } + + inline size_t size() + { + return m_active.size() + m_stored.size(); + } + +private: /* NOTE: When an object is transformed to active, it is removed from m_stored and inserted to m_active. - The caller directly manipulates these containers. */ std::vector m_stored; std::map m_active; - -private: };