ServerActiveObject *object = i->second;
if(object == NULL)
continue;
- // Discard if removed
- if(object->m_removed)
+ // Discard if removed or deactivating
+ if(object->m_removed || object->m_pending_deactivation)
continue;
if(object->unlimitedTransferDistance() == false){
// Discard if too far
continue;
}
- if(object->m_removed)
+ if(object->m_removed || object->m_pending_deactivation)
{
removed_objects.insert(id);
continue;
StaticObject s_obj(object->getType(), objectpos, staticdata);
// Add to the block where the object is located in
v3s16 blockpos = getNodeBlockPos(floatToInt(objectpos, BS));
- MapBlock *block = m_map->getBlockNoCreateNoEx(blockpos);
- if(block)
- {
+ MapBlock *block = m_map->emergeBlock(blockpos);
+ if(block){
block->m_static_objects.m_active[object->getId()] = s_obj;
object->m_static_exists = true;
object->m_static_block = blockpos;
if(set_changed)
block->raiseModified(MOD_STATE_WRITE_NEEDED,
"addActiveObjectRaw");
- }
- else{
+ } else {
v3s16 p = floatToInt(objectpos, BS);
errorstream<<"ServerEnvironment::addActiveObjectRaw(): "
- <<"could not find block for storing id="<<object->getId()
+ <<"could not emerge block for storing id="<<object->getId()
<<" statically (pos="<<PP(p)<<")"<<std::endl;
}
}
if (block) {
block->m_static_objects.remove(id);
block->raiseModified(MOD_STATE_WRITE_NEEDED,
- "removeRemovedObjects");
+ "removeRemovedObjects/remove");
obj->m_static_exists = false;
} else {
- infostream << "failed to emerge block from which "
- "an object to be removed was loaded from. id="<<id<<std::endl;
+ infostream<<"Failed to emerge block from which an object to "
+ <<"be removed was loaded from. id="<<id<<std::endl;
}
}
- // If m_known_by_count > 0, don't actually remove.
+ // If m_known_by_count > 0, 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)
continue;
-
+
+ /*
+ Move static data from active to stored if not marked as removed
+ */
+ if(obj->m_static_exists && !obj->m_removed){
+ MapBlock *block = m_map->emergeBlock(obj->m_static_block, false);
+ if (block) {
+ std::map<u16, StaticObject>::iterator 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,
+ "removeRemovedObjects/deactivate");
+ }
+ } else {
+ infostream<<"Failed to emerge block from which an object to "
+ <<"be deactivated was loaded from. id="<<id<<std::endl;
+ }
+ }
+
// Tell the object about removal
obj->removingFromEnvironment();
// Deregister in scripting api
"large amount of objects");
return;
}
- // A list for objects that couldn't be converted to active for some
- // reason. They will be stored back.
+
+ // Activate stored objects
std::list<StaticObject> new_stored;
- // Loop through stored static objects
for(std::list<StaticObject>::iterator
i = block->m_static_objects.m_stored.begin();
i != block->m_static_objects.m_stored.end(); ++i)
StaticObject &s_obj = *i;
block->m_static_objects.m_stored.push_back(s_obj);
}
+
+ // Turn the active counterparts of activated objects not pending for
+ // deactivation
+ for(std::map<u16, StaticObject>::iterator
+ i = block->m_static_objects.m_active.begin();
+ i != block->m_static_objects.m_active.end(); ++i)
+ {
+ u16 id = i->first;
+ ServerActiveObject *object = getActiveObject(id);
+ assert(object);
+ object->m_pending_deactivation = false;
+ }
+
/*
Note: Block hasn't really been modified here.
The objects have just been activated and moved from the stored
block = m_map->emergeBlock(blockpos);
} catch(InvalidPositionException &e){
// Handled via NULL pointer
+ // NOTE: emergeBlock's failure is usually determined by it
+ // actually returning NULL
}
if(block)
<<" Forcing delete."<<std::endl;
force_delete = true;
} else {
- // If static counterpart already exists, remove it first.
- // This shouldn't happen, but happens rarely for some
- // unknown reason. Unsuccessful attempts have been made to
- // find said reason.
+ // If static counterpart already exists in target block,
+ // remove it first.
+ // This shouldn't happen because the object is removed from
+ // the previous block before this according to
+ // obj->m_static_block, but happens rarely for some unknown
+ // reason. Unsuccessful attempts have been made to find
+ // said reason.
if(id && block->m_static_objects.m_active.find(id) != block->m_static_objects.m_active.end()){
infostream<<"ServerEnv: WARNING: Performing hack #83274"
<<std::endl;
block->m_static_objects.remove(id);
}
- //store static data
- block->m_static_objects.insert(0, s_obj);
+ // Store static data
+ u16 store_id = pending_delete ? id : 0;
+ block->m_static_objects.insert(store_id, s_obj);
// Only mark block as modified if data changed considerably
if(shall_be_written)