build/.cmake/
# Gradle
.gradle
+# Clang
+.cache
## Files related to Minetest development cycle
/*.patch
}
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,
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)
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;
};
}
if (auto shadow = RenderingEngine::get_shadow_renderer())
- shadow->removeNodeFromShadowList(getSceneNode());
+ if (auto node = getSceneNode())
+ shadow->removeNodeFromShadowList(node);
if (m_meshnode) {
m_meshnode->remove();
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;
}
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) {
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
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();
m_driver->draw2DImage(shadowMapClientMap,
core::rect<s32>(0, 50 + 128, 128, 128 + 50 + 128),
core::rect<s32>({0, 0}, shadowMapTextureFinal->getSize()));
-
+
if (shadowMapTextureDynamicObjects)
m_driver->draw2DImage(shadowMapTextureDynamicObjects,
core::rect<s32>(0, 128 + 50 + 128, 128,
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<ClientMap *>(shadow_node.node);
+ ClientMap &map_node = static_cast<ClientMap &>(m_client->getEnv().getMap());
- 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);
- }
+ 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;
+ 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;
- }
+ 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());
+ 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;
+ 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;
- }
+ map_node.renderMapShadows(m_driver, material, pass, frame, total_frames);
}
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
/**
* @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.
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);
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;
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;
}
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;
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
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;
std::string current_field_enter_pending = "";
std::vector<std::string> m_hovered_item_tooltips;
+ void removeAll();
+
void parseElement(parserData* data, const std::string &element);
void parseSize(parserData* data, const std::string &element);
<<std::endl;
return NodeTimer();
}
- NodeTimer t = block->m_node_timers.get(p_rel);
+ NodeTimer t = block->getNodeTimer(p_rel);
NodeTimer nt(t.timeout, t.elapsed, p);
return nt;
}
return;
}
NodeTimer nt(t.timeout, t.elapsed, p_rel);
- block->m_node_timers.set(nt);
+ block->setNodeTimer(nt);
}
void Map::removeNodeTimer(v3s16 p)
<<std::endl;
return;
}
- block->m_node_timers.remove(p_rel);
+ block->removeNodeTimer(p_rel);
}
bool Map::determineAdditionalOcclusionCheck(const v3s16 &pos_camera,
#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
"unknown",
};
-
/*
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<bool(v3s16, MapNode, f32)> &on_timer_cb)
+{
+ // Run script callbacks for elapsed node_timers
+ std::vector<NodeTimer> 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)) {
/*
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);
}
// Static objects
m_static_objects.serialize(os);
- if(version < 29){
+ if (version < 29) {
// Timestamp
writeU32(os, getTimestamp());
nimap.serialize(os);
}
- if(version >= 25){
+ if (version >= 25) {
// Node timers
m_node_timers.serialize(os, version);
}
/*
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 "<<PP(getPos())
- <<": Node timers (ver==24)"<<std::endl);
+ if (version == 24) {
+ TRACESTREAM(<< "MapBlock::deSerialize " << PP(getPos())
+ << ": Node timers (ver==24)" << std::endl);
m_node_timers.deSerialize(is, version);
}
<<": Static objects"<<std::endl);
m_static_objects.deSerialize(is);
- if(version < 29) {
+ if (version < 29) {
// Timestamp
TRACESTREAM(<<"MapBlock::deSerialize "<<PP(getPos())
<<": Timestamp"<<std::endl);
}
}
+bool MapBlock::storeActiveObject(u16 id)
+{
+ if (m_static_objects.storeActiveObject(id)) {
+ raiseModified(MOD_STATE_WRITE_NEEDED,
+ MOD_REASON_REMOVE_OBJECTS_DEACTIVATE);
+ return true;
+ }
+
+ return false;
+}
+
+u32 MapBlock::clearObjects()
+{
+ u32 size = m_static_objects.size();
+ if (size > 0) {
+ m_static_objects.clear();
+ raiseModified(MOD_STATE_WRITE_NEEDED, MOD_REASON_CLEAR_ALL_OBJECTS);
+ }
+ return size;
+}
/*
Legacy serialization
*/
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
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; i<nodecount; i++)
- {
+ for (u32 i = 0; i < nodecount; i++) {
const ContentFeatures &f = nodedef->get(data[i].getContent());
// Mineral
if(nodedef->getId("default:stone") == data[i].getContent()
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;
}
data[i].setParam2(dir_new_format);
}
}
-
}
/*
*/
std::string analyze_block(MapBlock *block)
{
- if(block == NULL)
+ if (block == NULL)
return "NULL";
std::ostringstream desc;
return m_day_night_differs;
}
+ bool onObjectsActivation();
+ bool saveStaticObject(u16 id, const StaticObject &obj, u32 reason);
+
+ void step(float dtime, const std::function<bool(v3s16, MapNode, f32)> &on_timer_cb);
+
////
//// Timestamp (see m_timestamp)
////
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
#endif
NodeMetadataList m_node_metadata;
- NodeTimerList m_node_timers;
StaticObjectList m_static_objects;
static const u32 ystride = MAP_BLOCKSIZE;
int m_refcount = 0;
MapNode data[nodecount];
+ NodeTimerList m_node_timers;
};
typedef std::vector<MapBlock*> MapBlockVect;
{
NetworkPacket pkt(TOCLIENT_SET_LIGHTING,
4, peer_id);
-
+
pkt << lighting.shadow_intensity;
Send(&pkt);
void Server::sendRemoveNode(v3s16 p, std::unordered_set<u16> *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<session_t> 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<u16> *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<u16> *far_players)
+{
+ float maxd = far_d_nodes * BS;
std::vector<session_t> clients = m_clients.getClientIDs();
ClientInterface::AutoLock clientlock(m_clients);
// 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
void sendAddNode(v3s16 p, MapNode n,
std::unordered_set<u16> *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<u16> *far_players);
void sendMetadataChanged(const std::unordered_set<v3s16> &positions,
float far_d_nodes = 100);
// 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);
}
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;
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
// 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
}
m_lbm_mgr.applyLBMs(this, block, stamp);
// Run node timers
- std::vector<NodeTimer> 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)
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);
<< "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++;
MOD_REASON_BLOCK_EXPIRED);
// Run node timers
- std::vector<NodeTimer> 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);
+ });
}
}
u32 object_count = 0;
- auto cb_state = [&] (ServerActiveObject *obj) {
+ auto cb_state = [&](ServerActiveObject *obj) {
if (obj->isGone())
return;
object_count++;
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) {
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());
// 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;
{
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(): "
// 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 "
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<linelength; di++){
+ for (int di = 0; di < linelength; di++) {
int i = i0 + di;
char buf[4];
- if(di<thislinelength)
+ if (di < thislinelength)
porting::mt_snprintf(buf, sizeof(buf), "%.2x ", data[i]);
else
porting::mt_snprintf(buf, sizeof(buf), " ");
- o<<buf;
+ o << buf;
}
- o<<" ";
- for(int di=0; di<thislinelength; di++){
+ o << " ";
+ for (int di = 0; di < thislinelength; di++) {
int i = i0 + di;
- if(data[i] >= 32)
- o<<data[i];
+ if (data[i] >= 32)
+ o << data[i];
else
- o<<".";
+ o << ".";
}
- o<<std::endl;
- if(at_end)
+ o << std::endl;
+ if (at_end)
break;
}
}
*/
void ServerEnvironment::activateObjects(MapBlock *block, u32 dtime_s)
{
- if(block == NULL)
- return;
-
- // Ignore if no stored objects (to not set changed flag)
- if(block->m_static_objects.m_stored.empty())
+ if (block == NULL)
return;
- verbosestream<<"ServerEnvironment::activateObjects(): "
- <<"activating objects of block "<<PP(block->getPos())
- <<" ("<<block->m_static_objects.m_stored.size()
- <<" objects)"<<std::endl;
- bool large_amount = (block->m_static_objects.m_stored.size() > g_settings->getU16("max_objects_per_block"));
- if (large_amount) {
- errorstream<<"suspiciously large amount of objects detected: "
- <<block->m_static_objects.m_stored.size()<<" in "
- <<PP(block->getPos())
- <<"; removing all of them."<<std::endl;
- // Clear stored list
- block->m_static_objects.m_stored.clear();
- block->raiseModified(MOD_STATE_WRITE_NEEDED,
- MOD_REASON_TOO_MANY_OBJECTS);
+ if (!block->onObjectsActivation())
return;
- }
// Activate stored objects
std::vector<StaticObject> 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 "<<PP(s_obj.pos/BS)
- <<" type="<<(int)s_obj.type<<" data:"<<std::endl;
+ errorstream << "ServerEnvironment::activateObjects(): "
+ << "failed to create active object from static object "
+ << "in block " << PP(s_obj.pos / BS)
+ << " type=" << (int)s_obj.type << " data:" << std::endl;
print_hexdump(verbosestream, s_obj.data);
new_stored.push_back(s_obj);
continue;
}
- verbosestream<<"ServerEnvironment::activateObjects(): "
- <<"activated static object pos="<<PP(s_obj.pos/BS)
- <<" type="<<(int)s_obj.type<<std::endl;
+ verbosestream << "ServerEnvironment::activateObjects(): "
+ << "activated static object pos=" << PP(s_obj.pos / BS)
+ << " type=" << (int)s_obj.type << std::endl;
// This will also add the object to the active static list
addActiveObjectRaw(obj, false, dtime_s);
}
// Clear stored list
- block->m_static_objects.m_stored.clear();
+ block->m_static_objects.clearStored();
// Add leftover failed stuff to stored list
for (const StaticObject &s_obj : new_stored) {
- block->m_static_objects.m_stored.push_back(s_obj);
+ block->m_static_objects.pushStored(s_obj);
}
/*
*/
void ServerEnvironment::deactivateFarObjects(bool _force_delete)
{
- auto cb_deactivate = [this, _force_delete] (ServerActiveObject *obj, u16 id) {
+ auto cb_deactivate = [this, _force_delete](ServerActiveObject *obj, u16 id) {
// force_delete might be overriden per object
bool force_delete = _force_delete;
if (obj->m_static_block == blockpos_o)
stays_in_same_block = true;
- MapBlock *block = m_map->emergeBlock(obj->m_static_block, false);
-
- if (block) {
- const auto n = block->m_static_objects.m_active.find(id);
- if (n != block->m_static_objects.m_active.end()) {
+ if (MapBlock *block = m_map->emergeBlock(obj->m_static_block, false)) {
+ const auto n = block->m_static_objects.getAllActives().find(id);
+ if (n != block->m_static_objects.getAllActives().end()) {
StaticObject static_old = n->second;
float save_movem = obj->getMinimumSavedMovement();
<< " when saving static data of object to it. id=" << store_id << std::endl;
return false;
}
- if (block->m_static_objects.m_stored.size() >= g_settings->getU16("max_objects_per_block")) {
- warningstream << "ServerEnv: Trying to store id = " << store_id
- << " statically but block " << PP(blockpos)
- << " already contains "
- << 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;
s_obj.serialize(os);
}
}
+
void StaticObjectList::deSerialize(std::istream &is)
{
if (m_active.size()) {
}
}
+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;
+}
*/
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"<<std::endl;
+ } else {
+ if (m_active.find(id) != m_active.end()) {
+ dstream << "ERROR: StaticObjectList::insert(): "
+ << "id already exists" << std::endl;
FATAL_ERROR("StaticObjectList::insert()");
}
- m_active[id] = obj;
+ setActive(id, obj);
}
}
void remove(u16 id)
{
assert(id != 0); // Pre-condition
- if(m_active.find(id) == m_active.end())
- {
- warningstream<<"StaticObjectList::remove(): id="<<id
- <<" not found"<<std::endl;
+ if (m_active.find(id) == m_active.end()) {
+ warningstream << "StaticObjectList::remove(): id=" << id << " not found"
+ << std::endl;
return;
}
m_active.erase(id);
void serialize(std::ostream &os);
void deSerialize(std::istream &is);
+ // Never permit to modify outside of here. Only this object is responsible of m_stored and m_active modifications
+ const std::vector<StaticObject>& getAllStored() const { return m_stored; }
+ const std::map<u16, StaticObject> &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<StaticObject> m_stored;
std::map<u16, StaticObject> m_active;
-
-private:
};