virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n) { ServerMap *map = &env->getServerMap(); if (map->transforming_liquid_size() < 500) map->transforming_liquid_add(p); //if ((*map).m_transforming_liquid.size() < 500) (*map).m_transforming_liquid.push_back(p); }
// L-System tree LUA spawner treegen::error spawn_ltree(ServerEnvironment *env, v3s16 p0, INodeDefManager *ndef, TreeDef tree_definition) { ServerMap *map = &env->getServerMap(); std::map<v3s16, MapBlock*> modified_blocks; ManualMapVoxelManipulator vmanip(map); v3s16 tree_blockp = getNodeBlockPos(p0); treegen::error e; vmanip.initialEmerge(tree_blockp - v3s16(1,1,1), tree_blockp + v3s16(1,3,1)); e = make_ltree (vmanip, p0, ndef, tree_definition); if (e != SUCCESS) return e; vmanip.blitBackAll(&modified_blocks); // update lighting std::map<v3s16, MapBlock*> lighting_modified_blocks; lighting_modified_blocks.insert(modified_blocks.begin(), modified_blocks.end()); map->updateLighting(lighting_modified_blocks, modified_blocks); // Send a MEET_OTHER event MapEditEvent event; event.type = MEET_OTHER; for(std::map<v3s16, MapBlock*>::iterator i = modified_blocks.begin(); i != modified_blocks.end(); ++i) { event.modified_blocks.insert(i->first); } map->dispatchEvent(&event); return SUCCESS; }
int LuaVoxelManip::l_write_to_map(lua_State *L) { MAP_LOCK_REQUIRED; LuaVoxelManip *o = checkobject(L, 1); bool update_light = !lua_isboolean(L, 2) || lua_toboolean(L, 2); GET_ENV_PTR; ServerMap *map = &(env->getServerMap()); if (o->is_mapgen_vm || !update_light) { o->vm->blitBackAll(&(o->modified_blocks)); } else { voxalgo::blit_back_with_light(map, o->vm, &(o->modified_blocks)); } MapEditEvent event; event.type = MEET_OTHER; for (const auto &modified_block : o->modified_blocks) event.modified_blocks.insert(modified_block.first); map->dispatchEvent(&event); o->modified_blocks.clear(); return 0; }
bool EmergeThread::getBlockOrStartGen(v3s16 p, MapBlock **b, BlockMakeData *data, bool allow_gen) { #if !ENABLE_THREADS auto lock = map->m_nothread_locker.lock_unique_rec(); #endif MapBlock *block; { //envlock: usually takes <=1ms, sometimes 90ms or ~400ms to acquire //JMutexAutoLock envlock(m_server->m_env_mutex); // Attempt to load block block = map->getBlockNoCreateNoEx(p); if (!block || block->isDummy()) { EMERGE_DBG_OUT("not in memory, attempting to load from disk ag="<<allow_gen<<" block="<<block<<" p="<<p); block = map->loadBlock(p); if (block && block->isGenerated()) map->prepareBlock(block); } } // If could not load and allowed to generate, // start generation inside this same envlock if (allow_gen && (!block)) { EMERGE_DBG_OUT("generating b="<<block); *b = block; return map->initBlockMake(data, p); } *b = block; return false; }
bool EmergeThread::getBlockOrStartGen(v3s16 p, MapBlock **b, BlockMakeData *data, bool allow_gen) { v2s16 p2d(p.X, p.Z); //envlock: usually takes <=1ms, sometimes 90ms or ~400ms to acquire JMutexAutoLock envlock(m_server->m_env_mutex); // Load sector if it isn't loaded if (map->getSectorNoGenerateNoEx(p2d) == NULL) map->loadSectorMeta(p2d); // Attempt to load block MapBlock *block = map->getBlockNoCreateNoEx(p); if (!block || block->isDummy() || !block->isGenerated()) { EMERGE_DBG_OUT("not in memory, attempting to load from disk"); block = map->loadBlock(p); } // If could not load and allowed to generate, // start generation inside this same envlock if (allow_gen && (block == NULL || !block->isGenerated())) { EMERGE_DBG_OUT("generating"); *b = block; return map->initBlockMake(data, p); } *b = block; return false; }
bool EmergeThread::getBlockOrStartGen(v3s16 p, MapBlock **b, BlockMakeData *data, bool allow_gen) { //envlock: usually takes <=1ms, sometimes 90ms or ~400ms to acquire //JMutexAutoLock envlock(m_server->m_env_mutex); // Attempt to load block MapBlock *block = map->getBlockNoCreateNoEx(p); if (!block || block->isDummy()) { EMERGE_DBG_OUT("not in memory, attempting to load from disk ag="<<allow_gen<<" block="<<block<<" p="<<p); block = map->loadBlock(p); if(block) { // block->pushElementsToCircuit(m_circuit); // m_circuit->processElementsQueue(*map, map->getNodeDefManager()); } if (block && block->isGenerated()) map->prepareBlock(block); } // If could not load and allowed to generate, // start generation inside this same envlock if (allow_gen && (!block)) { EMERGE_DBG_OUT("generating b="<<block); *b = block; return map->initBlockMake(data, p); } *b = block; return false; }
virtual void trigger(ServerEnvironment *env, v3POS p, MapNode n, u32 active_object_count, u32 active_object_count_wider, MapNode neighbor, bool activate) { ServerMap *map = &env->getServerMap(); INodeDefManager *ndef = env->getGameDef()->ndef(); int cold = ((ItemGroupList) ndef->get(neighbor).groups)["cold"]; int freeze = ((ItemGroupList) ndef->get(n).groups)["freeze"]; if (cold < freeze) { n.freeze_melt(ndef, -1); map->setNode(p, n); } }
MapBlock *EmergeThread::finishGen(v3s16 pos, BlockMakeData *bmdata, std::map<v3s16, MapBlock *> *modified_blocks) { //MutexAutoLock envlock(m_server->m_env_mutex); ScopeProfiler sp(g_profiler, "EmergeThread: after Mapgen::makeChunk", SPT_AVG); /* Perform post-processing on blocks (invalidate lighting, queue liquid transforms, etc.) to finish block make */ m_map->finishBlockMake(bmdata, modified_blocks); MapBlock *block = m_map->getBlockNoCreateNoEx(pos, false, true); if (!block) { errorstream << "EmergeThread::finishGen: Couldn't grab block we " "just generated: " << PP(pos) << std::endl; return NULL; } v3s16 minp = bmdata->blockpos_min * MAP_BLOCKSIZE; v3s16 maxp = bmdata->blockpos_max * MAP_BLOCKSIZE + v3s16(1,1,1) * (MAP_BLOCKSIZE - 1); // Ignore map edit events, they will not need to be sent // to anybody because the block hasn't been sent to anybody /* thread unsafe MapEditEventAreaIgnorer ign( &m_server->m_ignore_map_edit_events_area, VoxelArea(minp, maxp)); */ /* Run Lua on_generated callbacks */ try { MAP_NOTHREAD_LOCK(m_map); m_server->getScriptIface()->environment_OnGenerated( minp, maxp, m_mapgen->blockseed); } catch (LuaError &e) { m_server->setAsyncFatalError("Lua: " + std::string(e.what())); } EMERGE_DBG_OUT("ended up with: " << analyze_block(block)); /* Activate the block */ m_server->m_env->activateBlock(block, 0); return block; }
virtual void trigger(ServerEnvironment *env, v3POS p, MapNode n, u32 active_object_count, u32 active_object_count_wider, MapNode neighbor, bool activate) { ServerMap *map = &env->getServerMap(); INodeDefManager *ndef = env->getGameDef()->ndef(); int hot = ((ItemGroupList) ndef->get(neighbor).groups)["hot"]; int melt = ((ItemGroupList) ndef->get(n).groups)["melt"]; if (hot > melt) { n.freeze_melt(ndef, +1); map->setNode(p, n); env->nodeUpdate(p, 2); } }
virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n) { INodeDefManager *ndef = env->getGameDef()->ndef(); ServerMap *map = &env->getServerMap(); MapNode n_top = map->getNodeNoEx(p+v3s16(0,1,0)); if(!ndef->get(n_top).light_propagates || ndef->get(n_top).isLiquid()) { n.setContent(ndef->getId("dirt")); map->addNodeWithEvent(p, n); } }
virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n) { INodeDefManager *ndef = env->getGameDef()->ndef(); ServerMap *map = &env->getServerMap(); MapNode n_top = map->getNodeNoEx(p+v3s16(0,1,0)); if(ndef->get(n_top).light_propagates && !ndef->get(n_top).isLiquid() && n_top.getLightBlend(env->getDayNightRatio(), ndef) >= 13) { n.setContent(ndef->getId("dirt_with_grass")); map->addNodeWithEvent(p, n); } }
virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n, u32 active_object_count, u32 active_object_count_wider) { INodeDefManager *ndef = env->getGameDef()->ndef(); ServerMap *map = &env->getServerMap(); MapNode n_below = map->getNodeNoEx(p - v3s16(0, 1, 0)); if (n_below.getContent() != c_dirt && n_below.getContent() != c_dirt_with_grass) return; bool is_jungle_tree = n.getContent() == c_junglesapling; actionstream <<"A " << (is_jungle_tree ? "jungle " : "") << "sapling grows into a tree at " << PP(p) << std::endl; std::map<v3s16, MapBlock*> modified_blocks; v3s16 tree_p = p; ManualMapVoxelManipulator vmanip(map); v3s16 tree_blockp = getNodeBlockPos(tree_p); vmanip.initialEmerge(tree_blockp - v3s16(1,1,1), tree_blockp + v3s16(1,1,1)); if (is_jungle_tree) { treegen::make_jungletree(vmanip, tree_p, ndef, myrand()); } else { bool is_apple_tree = myrand() % 4 == 0; treegen::make_tree(vmanip, tree_p, is_apple_tree, ndef, myrand()); } vmanip.blitBackAll(&modified_blocks); // update lighting std::map<v3s16, MapBlock*> lighting_modified_blocks; lighting_modified_blocks.insert(modified_blocks.begin(), modified_blocks.end()); map->updateLighting(lighting_modified_blocks, modified_blocks); // Send a MEET_OTHER event MapEditEvent event; event.type = MEET_OTHER; // event.modified_blocks.insert(modified_blocks.begin(), modified_blocks.end()); for(std::map<v3s16, MapBlock*>::iterator i = modified_blocks.begin(); i != modified_blocks.end(); ++i) { event.modified_blocks.insert(i->first); } map->dispatchEvent(&event); }
/*! Add a ServerSession to the manager; takes ownership of the object \param what ServerSession to add \return true if successful */ bool add(ServerSessionBase *what) { if (!what || !what->_server_sock) throw f8Exception("bad or missing server socket"); _servermap.insert({*what->_server_sock, what}); return true; }
/*! Check to see if there are any waiting inbound connections on any of the managed servers. Will only return the first ServerSession; select should be called continually to process all waiting sockets. \param timeout timespan (us, default 250 ms) to wait before returning (will return immediately if connection available) \return pointer to ServerSession that is ready to accept a connection or nullptr if timeout with none */ ServerSessionBase *select(const Poco::Timespan& timeout=Poco::Timespan(250000)) const { Poco::Net::Socket::SocketList readList, writeList, exceptList; for (auto& pp : _servermap) readList.push_back(pp.first); return Poco::Net::Socket::select(readList, writeList, exceptList, timeout) && !readList.empty() ? _servermap.find(readList[0])->second : nullptr; }
virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n, u32 active_object_count, u32 active_object_count_wider) { if(active_object_count_wider != 0) return; INodeDefManager *ndef = env->getGameDef()->ndef(); ServerMap *map = &env->getServerMap(); v3s16 p1 = p + v3s16(0,1,0); MapNode n1a = map->getNodeNoEx(p1+v3s16(0,0,0)); if(n1a.getLightBlend(env->getDayNightRatio(), ndef) <= 3){ MapNode n1b = map->getNodeNoEx(p1+v3s16(0,1,0)); if(n1a.getContent() == CONTENT_AIR && n1b.getContent() == CONTENT_AIR) { v3f pos = intToFloat(p1, BS); int i = myrand()%5; if(i == 0 || i == 1){ actionstream<<"A dungeon master spawns at " <<PP(p1)<<std::endl; Settings properties; getMob_dungeon_master(properties); ServerActiveObject *obj = new MobV2SAO( env, pos, &properties); env->addActiveObject(obj); } else if(i == 2 || i == 3){ actionstream<<"Rats spawn at " <<PP(p1)<<std::endl; for(int j=0; j<3; j++){ ServerActiveObject *obj = new RatSAO( env, pos); env->addActiveObject(obj); } } else { actionstream<<"An oerkki spawns at " <<PP(p1)<<std::endl; ServerActiveObject *obj = new Oerkki1SAO( env, pos); env->addActiveObject(obj); } } } }
EmergeAction EmergeThread::getBlockOrStartGen( v3s16 pos, bool allow_gen, MapBlock **block, BlockMakeData *bmdata) { //MutexAutoLock envlock(m_server->m_env_mutex); { MAP_NOTHREAD_LOCK(m_map); // 1). Attempt to fetch block from memory *block = m_map->getBlockNoCreateNoEx(pos, false, true); } if (*block && !(*block)->isDummy() && (*block)->isGenerated()) return EMERGE_FROM_MEMORY; { MAP_NOTHREAD_LOCK(m_map); // 2). Attempt to load block from disk *block = m_map->loadBlock(pos); } if (*block && (*block)->isGenerated()) { MAP_NOTHREAD_LOCK(m_map); m_map->prepareBlock(*block); return EMERGE_FROM_DISK; } { MAP_NOTHREAD_LOCK(m_map); // 3). Attempt to start generation if (allow_gen && m_map->initBlockMake(pos, bmdata)) return EMERGE_GENERATED; } /* verbosestream << "EmergeThread::getBlockOrStartGen : cancel pos=" << pos << " block="<< *block; if (*block) verbosestream << "dummy=" << (*block)->isDummy() << " generated="<< (*block)->isGenerated(); verbosestream << std::endl; */ // All attempts failed; cancel this block emerge return EMERGE_CANCELLED; }
virtual void trigger(ServerEnvironment *env, v3POS p, MapNode n, u32 active_object_count, u32 active_object_count_wider, MapNode neighbor, bool activate) { ServerMap *map = &env->getServerMap(); INodeDefManager *ndef = env->getGameDef()->ndef(); float heat = map->updateBlockHeat(env, p); //heater = rare content_t c = map->getNodeTry(p - v3POS(0, -1, 0 )).getContent(); // top //more chance to freeze if air at top static int water_level = g_settings->getS16("water_level"); bool top_liquid = ndef->get(n).liquid_type > LIQUID_NONE && p.Y > water_level; int freeze = ((ItemGroupList) ndef->get(n).groups)["freeze"]; if (heat <= freeze - 1 && ((!top_liquid && (activate || (heat <= freeze - 50))) || heat <= freeze - 50 || (myrand_range(freeze - 50, heat) <= (freeze + (top_liquid ? -42 : c == CONTENT_AIR ? -10 : -40))))) { content_t c_self = n.getContent(); // making freeze not annoying, do not freeze random blocks in center of ocean // todo: any block not water (dont freeze _source near _flowing) bool allow = activate || heat < freeze - 40; // todo: make for(...) if (!allow) { c = map->getNodeTry(p - v3POS(0, 1, 0 )).getContent(); // below if (c == CONTENT_AIR || c == CONTENT_IGNORE) if (ndef->get(n.getContent()).liquid_type == LIQUID_FLOWING || ndef->get(n.getContent()).liquid_type == LIQUID_SOURCE) return; // do not freeze when falling if (c != c_self && c != CONTENT_IGNORE) allow = 1; if (!allow) { c = map->getNodeTry(p - v3POS(1, 0, 0 )).getContent(); // right if (c != c_self && c != CONTENT_IGNORE) allow = 1; if (!allow) { c = map->getNodeTry(p - v3POS(-1, 0, 0 )).getContent(); // left if (c != c_self && c != CONTENT_IGNORE) allow = 1; if (!allow) { c = map->getNodeTry(p - v3POS(0, 0, 1 )).getContent(); // back if (c != c_self && c != CONTENT_IGNORE) allow = 1; if (!allow) { c = map->getNodeTry(p - v3POS(0, 0, -1)).getContent(); // front if (c != c_self && c != CONTENT_IGNORE) allow = 1; } } } } } if (allow) { n.freeze_melt(ndef, -1); map->setNode(p, n); } } }
virtual void trigger(ServerEnvironment *env, v3POS p, MapNode n, u32 active_object_count, u32 active_object_count_wider, MapNode neighbor, bool activate) { ServerMap *map = &env->getServerMap(); INodeDefManager *ndef = env->getGameDef()->ndef(); float heat = map->updateBlockHeat(env, p); content_t c = map->getNodeTry(p - v3POS(0, -1, 0 )).getContent(); // top int melt = ((ItemGroupList) ndef->get(n).groups)["melt"]; if (heat >= melt + 1 && (activate || heat >= melt + 40 || ((myrand_range(heat, melt + 40)) >= (c == CONTENT_AIR ? melt + 10 : melt + 20)))) { if (ndef->get(n.getContent()).liquid_type == LIQUID_FLOWING || ndef->get(n.getContent()).liquid_type == LIQUID_SOURCE) { c = map->getNodeTry(p - v3POS(0, 1, 0 )).getContent(); // below if (c == CONTENT_AIR || c == CONTENT_IGNORE) return; // do not melt when falling (dirt->dirt_with_grass on air) } n.freeze_melt(ndef, +1); map->setNode(p, n); env->nodeUpdate(p, 2); //enable after making FAST nodeupdate } }
/*! Check to see if there are any waiting inbound connections on any of the managed servers. Will add all ServerSession pointers to the supplied vector for all waiting sockets found. \param result vector to place results in; will empty before polling \param timeout timespan (us, default 250 ms) to wait before returning (will return immediately if connection available) \return number of active ServerSockets returned in vector */ size_t select_l(std::vector<ServerSessionBase *>& result, const Poco::Timespan& timeout=Poco::Timespan(250000)) const { result.clear(); Poco::Net::Socket::SocketList readList, writeList, exceptList; for (auto& pp : _servermap) readList.push_back(pp.first); if (Poco::Net::Socket::select(readList, writeList, exceptList, timeout) && !readList.empty()) std::for_each(readList.begin(), readList.end(), [&](decltype(readList)::value_type& pp) { result.push_back(_servermap.find(pp)->second); }); return result.size(); }
virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n, u32 active_object_count, u32 active_object_count_wider) { if(active_object_count_wider != 0) return; INodeDefManager *ndef = env->getGameDef()->ndef(); ServerMap *map = &env->getServerMap(); v3s16 p1 = p + v3s16(myrand_range(-2, 2), 0, myrand_range(-2, 2)); MapNode n1 = map->getNodeNoEx(p1); MapNode n1b = map->getNodeNoEx(p1+v3s16(0,-1,0)); if(n1b.getContent() == ndef->getId("dirt_with_grass") && n1.getContent() == CONTENT_AIR) { v3f pos = intToFloat(p1, BS); ServerActiveObject *obj = new RatSAO(env, pos); env->addActiveObject(obj); } }
virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n, u32 active_object_count, u32 active_object_count_wider) { INodeDefManager *ndef = env->getGameDef()->ndef(); ServerMap *map = &env->getServerMap(); actionstream<<"A sapling grows into a tree at " <<PP(p)<<std::endl; core::map<v3s16, MapBlock*> modified_blocks; v3s16 tree_p = p; ManualMapVoxelManipulator vmanip(map); v3s16 tree_blockp = getNodeBlockPos(tree_p); vmanip.initialEmerge(tree_blockp - v3s16(1,1,1), tree_blockp + v3s16(1,1,1)); bool is_apple_tree = myrand()%4 == 0; mapgen::make_tree(vmanip, tree_p, is_apple_tree, ndef); vmanip.blitBackAll(&modified_blocks); // update lighting core::map<v3s16, MapBlock*> lighting_modified_blocks; for(core::map<v3s16, MapBlock*>::Iterator i = modified_blocks.getIterator(); i.atEnd() == false; i++) { lighting_modified_blocks.insert(i.getNode()->getKey(), i.getNode()->getValue()); } map->updateLighting(lighting_modified_blocks, modified_blocks); // Send a MEET_OTHER event MapEditEvent event; event.type = MEET_OTHER; for(core::map<v3s16, MapBlock*>::Iterator i = modified_blocks.getIterator(); i.atEnd() == false; i++) { v3s16 p = i.getNode()->getKey(); event.modified_blocks.insert(p, true); } map->dispatchEvent(&event); }
EmergeAction EmergeThread::getBlockOrStartGen( v3s16 pos, bool allow_gen, MapBlock **block, BlockMakeData *bmdata) { MutexAutoLock envlock(m_server->m_env_mutex); // 1). Attempt to fetch block from memory *block = m_map->getBlockNoCreateNoEx(pos); if (*block && !(*block)->isDummy() && (*block)->isGenerated()) return EMERGE_FROM_MEMORY; // 2). Attempt to load block from disk *block = m_map->loadBlock(pos); if (*block && (*block)->isGenerated()) return EMERGE_FROM_DISK; // 3). Attempt to start generation if (allow_gen && m_map->initBlockMake(pos, bmdata)) return EMERGE_GENERATED; // All attempts failed; cancel this block emerge return EMERGE_CANCELLED; }
int main(int argc, char const *[]) { std::string str="123456"; std::cout<<str<<std::endl; typedef std::map<std::string, CacheServer> ServerMap; ServerMap servers; Consistent::HashRing<std::string,std::string,SdbmHash> ring(4,SdbmHash()); //Create some cache servers servers["cach1.example.com"]=CacheServer(); servers["cach2.example.com"]=CacheServer(); servers["cach3.example.com"]=CacheServer(); //Add their host names to the hash ring for (ServerMap::const_iterator it = servers.begin();it != servers.end(); ++it) { std::cout << "Adding " << it->first << " with hash " << ring.AddNode(it->first) <<std::endl; } //Store some data const char* fruits[] = {"apple","pear","banana","orange","cherry","apricot"}; const char* colours[] = {"red","green","yellow","orange","black","pink"}; const unsigned int numfruits = sizeof(fruits)/sizeof(char*); //std::cout<< "sizeof(fruits):" <<sizeof(fruits) << " sizeof (char*):" <<sizeof(char*) <<std::endl; for (unsigned int f = 0; f<numfruits;f++) { std::string host = ring.GetNode(fruits[f]); std::cout << "Storing " <<fruits[f] << " on server " <<host <<std::endl; servers[host].Put(fruits[f],colours[f]); } //Read it back for (unsigned int f = 0; f< numfruits; f++) { std::string host = ring.GetNode(fruits[f]); std::string colour =servers[host].Get(fruits[f]); std::cout << "Found " << fruits[f] << " on server "<< host << " (" <<colour << ")" <<std::endl; } return 0; }
virtual void trigger(ServerEnvironment *env, v3POS p, MapNode n, u32 active_object_count, u32 active_object_count_wider, MapNode neighbor, bool activate) { ServerMap *map = &env->getServerMap(); if (map->transforming_liquid_size() > map->m_liquid_step_flow) return; if ( map->getNodeTry(p - v3POS(0, 1, 0 )).getContent() != CONTENT_AIR // below && map->getNodeTry(p - v3POS(1, 0, 0 )).getContent() != CONTENT_AIR // right && map->getNodeTry(p - v3POS(-1, 0, 0 )).getContent() != CONTENT_AIR // left && map->getNodeTry(p - v3POS(0, 0, 1 )).getContent() != CONTENT_AIR // back && map->getNodeTry(p - v3POS(0, 0, -1)).getContent() != CONTENT_AIR // front ) return; map->transforming_liquid_push_back(p); }
/// Dtor. virtual ~ServerManager() { std::for_each (_servermap.begin(), _servermap.end(), [](decltype(_servermap)::value_type& pp){ delete pp.second; }); }
void *EmergeThread::Thread() { ThreadStarted(); log_register_thread("EmergeThread" + itos(id)); DSTACK(__FUNCTION_NAME); BEGIN_DEBUG_EXCEPTION_HANDLER v3s16 last_tried_pos(-32768,-32768,-32768); // For error output v3s16 p; u8 flags = 0; map = (ServerMap *)&(m_server->m_env->getMap()); emerge = m_server->m_emerge; mapgen = emerge->mapgen[id]; enable_mapgen_debug_info = emerge->mapgen_debug_info; porting::setThreadName("EmergeThread"); while (!StopRequested()) try { if (!popBlockEmerge(&p, &flags)) { qevent.wait(); continue; } last_tried_pos = p; if (blockpos_over_limit(p)) continue; bool allow_generate = flags & BLOCK_EMERGE_ALLOWGEN; EMERGE_DBG_OUT("p=" PP(p) " allow_generate=" << allow_generate); /* Try to fetch block from memory or disk. If not found and asked to generate, initialize generator. */ BlockMakeData data; MapBlock *block = NULL; std::map<v3s16, MapBlock *> modified_blocks; if (getBlockOrStartGen(p, &block, &data, allow_generate) && mapgen) { { ScopeProfiler sp(g_profiler, "EmergeThread: Mapgen::makeChunk", SPT_AVG); TimeTaker t("mapgen::make_block()"); mapgen->makeChunk(&data); if (enable_mapgen_debug_info == false) t.stop(true); // Hide output } { //envlock: usually 0ms, but can take either 30 or 400ms to acquire JMutexAutoLock envlock(m_server->m_env_mutex); ScopeProfiler sp(g_profiler, "EmergeThread: after " "Mapgen::makeChunk (envlock)", SPT_AVG); map->finishBlockMake(&data, modified_blocks); block = map->getBlockNoCreateNoEx(p); if (block) { /* Do some post-generate stuff */ v3s16 minp = data.blockpos_min * MAP_BLOCKSIZE; v3s16 maxp = data.blockpos_max * MAP_BLOCKSIZE + v3s16(1,1,1) * (MAP_BLOCKSIZE - 1); // Ignore map edit events, they will not need to be sent // to anybody because the block hasn't been sent to anybody MapEditEventAreaIgnorer ign(&m_server->m_ignore_map_edit_events_area, VoxelArea(minp, maxp)); try { // takes about 90ms with -O1 on an e3-1230v2 m_server->getScriptIface()->environment_OnGenerated( minp, maxp, emerge->getBlockSeed(minp)); } catch(LuaError &e) { m_server->setAsyncFatalError(e.what()); } EMERGE_DBG_OUT("ended up with: " << analyze_block(block)); m_server->m_env->activateBlock(block, 0); } } } /* Set sent status of modified blocks on clients */ // Add the originally fetched block to the modified list if (block) modified_blocks[p] = block; if (modified_blocks.size() > 0) { m_server->SetBlocksNotSent(modified_blocks); } } catch (VersionMismatchException &e) { std::ostringstream err; err << "World data version mismatch in MapBlock "<<PP(last_tried_pos)<<std::endl; err << "----"<<std::endl; err << "\""<<e.what()<<"\""<<std::endl; err << "See debug.txt."<<std::endl; err << "World probably saved by a newer version of Minetest."<<std::endl; m_server->setAsyncFatalError(err.str()); } catch (SerializationError &e) { std::ostringstream err; err << "Invalid data in MapBlock "<<PP(last_tried_pos)<<std::endl; err << "----"<<std::endl; err << "\""<<e.what()<<"\""<<std::endl; err << "See debug.txt."<<std::endl; err << "You can ignore this using [ignore_world_load_errors = true]."<<std::endl; m_server->setAsyncFatalError(err.str()); } END_DEBUG_EXCEPTION_HANDLER(errorstream) log_deregister_thread(); return NULL; }
void LuaEntitySAO::step(float dtime, bool send_recommended) { if(!m_properties_sent) { m_properties_sent = true; std::string str = getPropertyPacket(); // create message and add to list ActiveObjectMessage aom(getId(), true, str); m_messages_out.push(aom); } // If attached, check that our parent is still there. If it isn't, detach. if(m_attachment_parent_id && !isAttached()) { m_attachment_parent_id = 0; m_attachment_bone = ""; m_attachment_position = v3f(0,0,0); m_attachment_rotation = v3f(0,0,0); sendPosition(false, true); } m_last_sent_position_timer += dtime; // Each frame, parent position is copied if the object is attached, otherwise it's calculated normally // If the object gets detached this comes into effect automatically from the last known origin if(isAttached()) { v3f pos = m_env->getActiveObject(m_attachment_parent_id)->getBasePosition(); m_base_position = pos; m_velocity = v3f(0,0,0); m_acceleration = v3f(0,0,0); } else { if(m_prop.physical){ aabb3f box = m_prop.collisionbox; box.MinEdge *= BS; box.MaxEdge *= BS; collisionMoveResult moveresult; f32 pos_max_d = BS*0.25; // Distance per iteration v3f p_pos = m_base_position; v3f p_velocity = m_velocity; v3f p_acceleration = m_acceleration; moveresult = collisionMoveSimple(m_env, m_env->getGameDef(), pos_max_d, box, m_prop.stepheight, dtime, &p_pos, &p_velocity, p_acceleration, this, m_prop.collideWithObjects); // Apply results m_base_position = p_pos; m_velocity = p_velocity; m_acceleration = p_acceleration; } else { m_base_position += dtime * m_velocity + 0.5 * dtime * dtime * m_acceleration; m_velocity += dtime * m_acceleration; } if((m_prop.automatic_face_movement_dir) && (fabs(m_velocity.Z) > 0.001 || fabs(m_velocity.X) > 0.001)) { float optimal_yaw = atan2(m_velocity.Z,m_velocity.X) * 180 / M_PI + m_prop.automatic_face_movement_dir_offset; float max_rotation_delta = dtime * m_prop.automatic_face_movement_max_rotation_per_sec; if ((m_prop.automatic_face_movement_max_rotation_per_sec > 0) && (fabs(m_yaw - optimal_yaw) > max_rotation_delta)) { m_yaw = optimal_yaw < m_yaw ? m_yaw - max_rotation_delta : m_yaw + max_rotation_delta; } else { m_yaw = optimal_yaw; } } } if(m_registered){ m_env->getScriptIface()->luaentity_Step(m_id, dtime); } // Remove LuaEntity beyond terrain edges { ServerMap *map = dynamic_cast<ServerMap *>(&m_env->getMap()); assert(map); if (!m_pending_deactivation && map->saoPositionOverLimit(m_base_position)) { infostream << "Remove SAO " << m_id << "(" << m_init_name << "), outside of limits" << std::endl; m_pending_deactivation = true; m_removed = true; return; } } if(send_recommended == false) return; if(!isAttached()) { // TODO: force send when acceleration changes enough? float minchange = 0.2*BS; if(m_last_sent_position_timer > 1.0){ minchange = 0.01*BS; } else if(m_last_sent_position_timer > 0.2){ minchange = 0.05*BS; } float move_d = m_base_position.getDistanceFrom(m_last_sent_position); move_d += m_last_sent_move_precision; float vel_d = m_velocity.getDistanceFrom(m_last_sent_velocity); if(move_d > minchange || vel_d > minchange || fabs(m_yaw - m_last_sent_yaw) > 1.0){ sendPosition(true, false); } } if(m_armor_groups_sent == false){ m_armor_groups_sent = true; std::string str = gob_cmd_update_armor_groups( m_armor_groups); // create message and add to list ActiveObjectMessage aom(getId(), true, str); m_messages_out.push(aom); } if(m_animation_sent == false){ m_animation_sent = true; std::string str = gob_cmd_update_animation( m_animation_range, m_animation_speed, m_animation_blend, m_animation_loop); // create message and add to list ActiveObjectMessage aom(getId(), true, str); m_messages_out.push(aom); } if(m_bone_position_sent == false){ m_bone_position_sent = true; for (UNORDERED_MAP<std::string, core::vector2d<v3f> >::const_iterator ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii){ std::string str = gob_cmd_update_bone_position((*ii).first, (*ii).second.X, (*ii).second.Y); // create message and add to list ActiveObjectMessage aom(getId(), true, str); m_messages_out.push(aom); } } if(m_attachment_sent == false){ m_attachment_sent = true; std::string str = gob_cmd_update_attachment(m_attachment_parent_id, m_attachment_bone, m_attachment_position, m_attachment_rotation); // create message and add to list ActiveObjectMessage aom(getId(), true, str); m_messages_out.push(aom); } }