- }
- // If known by some client, don't delete immediately
- if(obj->m_known_by_count > 0){
- obj->m_pending_deactivation = true;
- obj->m_removed = true;
- continue;
- }
-
- // Tell the object about removal
- obj->removingFromEnvironment();
- // Deregister in scripting api
- scriptapi_rm_object_reference(m_lua, obj);
-
- // Delete active object
- if(obj->environmentDeletes())
- delete obj;
- // Id to be removed from m_active_objects
- objects_to_remove.push_back(id);
- }
- // Remove references from m_active_objects
- for(core::list<u16>::Iterator i = objects_to_remove.begin();
- i != objects_to_remove.end(); i++)
- {
- m_active_objects.remove(*i);
- }
-
- core::list<v3s16> loadable_blocks;
- infostream<<"ServerEnvironment::clearAllObjects(): "
- <<"Listing all loadable blocks"<<std::endl;
- m_map->listAllLoadableBlocks(loadable_blocks);
- infostream<<"ServerEnvironment::clearAllObjects(): "
- <<"Done listing all loadable blocks: "
- <<loadable_blocks.size()
- <<", now clearing"<<std::endl;
- u32 report_interval = loadable_blocks.size() / 10;
- u32 num_blocks_checked = 0;
- u32 num_blocks_cleared = 0;
- u32 num_objs_cleared = 0;
- for(core::list<v3s16>::Iterator i = loadable_blocks.begin();
- i != loadable_blocks.end(); i++)
- {
- v3s16 p = *i;
- MapBlock *block = m_map->emergeBlock(p, false);
- if(!block){
- errorstream<<"ServerEnvironment::clearAllObjects(): "
- <<"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,
- "clearAllObjects");
- num_objs_cleared += num_stored + num_active;
- num_blocks_cleared++;
- }
- num_blocks_checked++;
-
- if(num_blocks_checked % report_interval == 0){
- float percent = 100.0 * (float)num_blocks_checked /
- loadable_blocks.size();
- infostream<<"ServerEnvironment::clearAllObjects(): "
- <<"Cleared "<<num_objs_cleared<<" objects"
- <<" in "<<num_blocks_cleared<<" blocks ("
- <<percent<<"%)"<<std::endl;
- }
- }
- infostream<<"ServerEnvironment::clearAllObjects(): "
- <<"Finished: Cleared "<<num_objs_cleared<<" objects"
- <<" in "<<num_blocks_cleared<<" blocks"<<std::endl;
-}
-
-void ServerEnvironment::step(float dtime)
-{
- DSTACK(__FUNCTION_NAME);
-
- //TimeTaker timer("ServerEnv step");
-
- /* Step time of day */
- stepTimeOfDay(dtime);
-
- /*
- Increment game time
- */
- {
- m_game_time_fraction_counter += dtime;
- u32 inc_i = (u32)m_game_time_fraction_counter;
- m_game_time += inc_i;
- m_game_time_fraction_counter -= (float)inc_i;
- }
-
- /*
- Handle players
- */
- {
- ScopeProfiler sp(g_profiler, "SEnv: handle players avg", SPT_AVG);
- for(core::list<Player*>::Iterator i = m_players.begin();
- i != m_players.end(); i++)
- {
- Player *player = *i;
-
- // Ignore disconnected players
- if(player->peer_id == 0)
- continue;
-
- v3f playerpos = player->getPosition();
-
- // Move
- player->move(dtime, *m_map, 100*BS);
- }
- }
-
- /*
- Manage active block list
- */
- if(m_active_blocks_management_interval.step(dtime, 2.0))
- {
- ScopeProfiler sp(g_profiler, "SEnv: manage act. block list avg /2s", SPT_AVG);
- /*
- Get player block positions
- */
- core::list<v3s16> players_blockpos;
- for(core::list<Player*>::Iterator
- i = m_players.begin();
- i != m_players.end(); i++)
- {
- Player *player = *i;
- // Ignore disconnected players
- if(player->peer_id == 0)
- continue;
- v3s16 blockpos = getNodeBlockPos(
- floatToInt(player->getPosition(), BS));
- players_blockpos.push_back(blockpos);
- }
-
- /*
- Update list of active blocks, collecting changes
- */
- const s16 active_block_range = g_settings->getS16("active_block_range");
- core::map<v3s16, bool> blocks_removed;
- core::map<v3s16, bool> blocks_added;
- m_active_blocks.update(players_blockpos, active_block_range,
- blocks_removed, blocks_added);
-
- /*
- Handle removed blocks
- */
-
- // Convert active objects that are no more in active blocks to static
- deactivateFarObjects(false);
-
- for(core::map<v3s16, bool>::Iterator
- i = blocks_removed.getIterator();
- i.atEnd()==false; i++)
- {
- v3s16 p = i.getNode()->getKey();
-
- /*infostream<<"Server: Block ("<<p.X<<","<<p.Y<<","<<p.Z
- <<") became inactive"<<std::endl;*/
-
- MapBlock *block = m_map->getBlockNoCreateNoEx(p);
- if(block==NULL)
- continue;
-
- // Set current time as timestamp (and let it set ChangedFlag)
- block->setTimestamp(m_game_time);
- }
-
- /*
- Handle added blocks
- */
-
- for(core::map<v3s16, bool>::Iterator
- i = blocks_added.getIterator();
- i.atEnd()==false; i++)
- {
- v3s16 p = i.getNode()->getKey();
-
- /*infostream<<"Server: Block ("<<p.X<<","<<p.Y<<","<<p.Z
- <<") became active"<<std::endl;*/
-
- MapBlock *block = m_map->getBlockNoCreateNoEx(p);
- if(block==NULL){
- // Block needs to be fetched first
- m_emerger->queueBlockEmerge(p, false);
- m_active_blocks.m_list.remove(p);
- continue;
- }
-
- activateBlock(block);
- }
- }
-
- /*
- Mess around in active blocks
- */
- if(m_active_blocks_nodemetadata_interval.step(dtime, 1.0))
- {
- ScopeProfiler sp(g_profiler, "SEnv: mess in act. blocks avg /1s", SPT_AVG);
-
- float dtime = 1.0;
-
- for(core::map<v3s16, bool>::Iterator
- i = m_active_blocks.m_list.getIterator();
- i.atEnd()==false; i++)
- {
- v3s16 p = i.getNode()->getKey();
-
- /*infostream<<"Server: Block ("<<p.X<<","<<p.Y<<","<<p.Z
- <<") being handled"<<std::endl;*/
-
- MapBlock *block = m_map->getBlockNoCreateNoEx(p);
- if(block==NULL)
- continue;
-
- // Reset block usage timer
- block->resetUsageTimer();
-
- // Set current time as timestamp
- block->setTimestampNoChangedFlag(m_game_time);
- // If time has changed much from the one on disk,
- // set block to be saved when it is unloaded
- if(block->getTimestamp() > block->getDiskTimestamp() + 60)
- block->raiseModified(MOD_STATE_WRITE_AT_UNLOAD,
- "Timestamp older than 60s (step)");
-
- // Run node timers
- std::map<v3s16, NodeTimer> elapsed_timers =
- block->m_node_timers.step((float)dtime);
- if(!elapsed_timers.empty()){
- MapNode n;
- for(std::map<v3s16, NodeTimer>::iterator
- i = elapsed_timers.begin();
- i != elapsed_timers.end(); i++){
- n = block->getNodeNoEx(i->first);
- p = i->first + block->getPosRelative();
- if(scriptapi_node_on_timer(m_lua,p,n,i->second.elapsed))
- block->setNodeTimer(i->first,NodeTimer(i->second.timeout,0));
- }
- }
- }
- }
-
- const float abm_interval = 1.0;
- if(m_active_block_modifier_interval.step(dtime, abm_interval))
- do{ // breakable
- if(m_active_block_interval_overload_skip > 0){
- ScopeProfiler sp(g_profiler, "SEnv: ABM overload skips");
- m_active_block_interval_overload_skip--;
- break;
- }
- ScopeProfiler sp(g_profiler, "SEnv: modify in blocks avg /1s", SPT_AVG);
- TimeTaker timer("modify in active blocks");
-
- // Initialize handling of ActiveBlockModifiers
- ABMHandler abmhandler(m_abms, abm_interval, this, true);
-
- for(core::map<v3s16, bool>::Iterator
- i = m_active_blocks.m_list.getIterator();
- i.atEnd()==false; i++)
- {
- v3s16 p = i.getNode()->getKey();
-
- /*infostream<<"Server: Block ("<<p.X<<","<<p.Y<<","<<p.Z
- <<") being handled"<<std::endl;*/
-
- MapBlock *block = m_map->getBlockNoCreateNoEx(p);
- if(block==NULL)
- continue;
-
- // Set current time as timestamp
- block->setTimestampNoChangedFlag(m_game_time);
-
- /* Handle ActiveBlockModifiers */
- abmhandler.apply(block);
- }
-
- u32 time_ms = timer.stop(true);
- u32 max_time_ms = 200;
- if(time_ms > max_time_ms){
- infostream<<"WARNING: active block modifiers took "
- <<time_ms<<"ms (longer than "
- <<max_time_ms<<"ms)"<<std::endl;
- m_active_block_interval_overload_skip = (time_ms / max_time_ms) + 1;
- }
- }while(0);
-
- /*
- Step script environment (run global on_step())
- */
- scriptapi_environment_step(m_lua, dtime);
-
- /*
- Step active objects
- */
- {
- ScopeProfiler sp(g_profiler, "SEnv: step act. objs avg", SPT_AVG);
- //TimeTaker timer("Step active objects");
-
- g_profiler->avg("SEnv: num of objects", m_active_objects.size());
-
- // This helps the objects to send data at the same time
- bool send_recommended = false;
- m_send_recommended_timer += dtime;
- if(m_send_recommended_timer > getSendRecommendedInterval())
- {
- m_send_recommended_timer -= getSendRecommendedInterval();
- send_recommended = true;
- }
-
- for(core::map<u16, ServerActiveObject*>::Iterator
- i = m_active_objects.getIterator();
- i.atEnd()==false; i++)
- {
- ServerActiveObject* obj = i.getNode()->getValue();
- // Remove non-peaceful mobs on peaceful mode
- if(g_settings->getBool("only_peaceful_mobs")){
- if(!obj->isPeaceful())
- obj->m_removed = true;
- }
- // Don't step if is to be removed or stored statically
- if(obj->m_removed || obj->m_pending_deactivation)
- continue;
- // Step object
- obj->step(dtime, send_recommended);
- // Read messages from object
- while(obj->m_messages_out.size() > 0)
- {
- m_active_object_messages.push_back(
- obj->m_messages_out.pop_front());
- }
- }
- }
-
- /*
- Manage active objects
- */
- if(m_object_management_interval.step(dtime, 0.5))
- {
- ScopeProfiler sp(g_profiler, "SEnv: remove removed objs avg /.5s", SPT_AVG);
- /*
- Remove objects that satisfy (m_removed && m_known_by_count==0)
- */
- removeRemovedObjects();
- }
-}
-
-ServerActiveObject* ServerEnvironment::getActiveObject(u16 id)
-{
- core::map<u16, ServerActiveObject*>::Node *n;
- n = m_active_objects.find(id);
- if(n == NULL)
- return NULL;
- return n->getValue();
-}
-
-bool isFreeServerActiveObjectId(u16 id,
- core::map<u16, ServerActiveObject*> &objects)
-{
- if(id == 0)
- return false;
-
- for(core::map<u16, ServerActiveObject*>::Iterator
- i = objects.getIterator();
- i.atEnd()==false; i++)
- {
- if(i.getNode()->getKey() == id)
- return false;
- }
- return true;
-}
-
-u16 getFreeServerActiveObjectId(
- core::map<u16, ServerActiveObject*> &objects)
-{
- u16 new_id = 1;
- for(;;)
- {
- if(isFreeServerActiveObjectId(new_id, objects))
- return new_id;
-
- if(new_id == 65535)
- return 0;
-
- new_id++;
- }
-}
-
-u16 ServerEnvironment::addActiveObject(ServerActiveObject *object)
-{
- assert(object);
- u16 id = addActiveObjectRaw(object, true, 0);
- return id;
-}
-
-bool ServerEnvironment::addActiveObjectAsStatic(ServerActiveObject *obj)
-{
- assert(obj);
-
- v3f objectpos = obj->getBasePosition();
-
- // The block in which the object resides in
- v3s16 blockpos_o = getNodeBlockPos(floatToInt(objectpos, BS));
-
- /*
- Update the static data
- */
-
- // Create new static object
- std::string staticdata = obj->getStaticData();
- StaticObject s_obj(obj->getType(), objectpos, staticdata);
- // Add to the block where the object is located in
- v3s16 blockpos = getNodeBlockPos(floatToInt(objectpos, BS));
- // Get or generate the block
- MapBlock *block = m_map->emergeBlock(blockpos);
-
- bool succeeded = false;
-
- if(block)
- {
- block->m_static_objects.insert(0, s_obj);
- block->raiseModified(MOD_STATE_WRITE_AT_UNLOAD,
- "addActiveObjectAsStatic");
- succeeded = true;
- }
- else{
- infostream<<"ServerEnvironment::addActiveObjectAsStatic: "
- <<"Could not find or generate "
- <<"a block for storing static object"<<std::endl;
- succeeded = false;
- }
-
- if(obj->environmentDeletes())
- delete obj;
-
- return succeeded;
-}
-
-/*
- Finds out what new objects have been added to
- inside a radius around a position
-*/
-void ServerEnvironment::getAddedActiveObjects(v3s16 pos, s16 radius,
- core::map<u16, bool> ¤t_objects,
- core::map<u16, bool> &added_objects)
-{
- v3f pos_f = intToFloat(pos, BS);
- f32 radius_f = radius * BS;
- /*
- Go through the object list,
- - discard m_removed objects,
- - discard objects that are too far away,
- - discard objects that are found in current_objects.
- - add remaining objects to added_objects
- */
- for(core::map<u16, ServerActiveObject*>::Iterator
- i = m_active_objects.getIterator();
- i.atEnd()==false; i++)
- {
- u16 id = i.getNode()->getKey();
- // Get object
- ServerActiveObject *object = i.getNode()->getValue();
- if(object == NULL)
- continue;
- // Discard if removed
- if(object->m_removed)
- continue;
- if(object->unlimitedTransferDistance() == false){
- // Discard if too far
- f32 distance_f = object->getBasePosition().getDistanceFrom(pos_f);
- if(distance_f > radius_f)