environment.cpp 77 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849
  1. /*
  2. Minetest
  3. Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU Lesser General Public License as published by
  6. the Free Software Foundation; either version 2.1 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public License along
  13. with this program; if not, write to the Free Software Foundation, Inc.,
  14. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  15. */
  16. #include <fstream>
  17. #include "environment.h"
  18. #include "filesys.h"
  19. #include "porting.h"
  20. #include "collision.h"
  21. #include "content_mapnode.h"
  22. #include "mapblock.h"
  23. #include "serverobject.h"
  24. #include "content_sao.h"
  25. #include "settings.h"
  26. #include "log.h"
  27. #include "profiler.h"
  28. #include "scripting_game.h"
  29. #include "nodedef.h"
  30. #include "nodemetadata.h"
  31. #include "gamedef.h"
  32. #ifndef SERVER
  33. #include "clientmap.h"
  34. #include "localplayer.h"
  35. #include "mapblock_mesh.h"
  36. #include "event.h"
  37. #endif
  38. #include "server.h"
  39. #include "daynightratio.h"
  40. #include "map.h"
  41. #include "emerge.h"
  42. #include "util/serialize.h"
  43. #include "threading/mutex_auto_lock.h"
  44. #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
  45. #define LBM_NAME_ALLOWED_CHARS "abcdefghijklmnopqrstuvwxyz0123456789_:"
  46. // A number that is much smaller than the timeout for particle spawners should/could ever be
  47. #define PARTICLE_SPAWNER_NO_EXPIRY -1024.f
  48. Environment::Environment():
  49. m_time_of_day_speed(0),
  50. m_time_of_day(9000),
  51. m_time_of_day_f(9000./24000),
  52. m_time_conversion_skew(0.0f),
  53. m_enable_day_night_ratio_override(false),
  54. m_day_night_ratio_override(0.0f)
  55. {
  56. m_cache_enable_shaders = g_settings->getBool("enable_shaders");
  57. m_cache_active_block_mgmt_interval = g_settings->getFloat("active_block_mgmt_interval");
  58. m_cache_abm_interval = g_settings->getFloat("abm_interval");
  59. m_cache_nodetimer_interval = g_settings->getFloat("nodetimer_interval");
  60. }
  61. Environment::~Environment()
  62. {
  63. }
  64. u32 Environment::getDayNightRatio()
  65. {
  66. MutexAutoLock lock(this->m_time_lock);
  67. if (m_enable_day_night_ratio_override)
  68. return m_day_night_ratio_override;
  69. return time_to_daynight_ratio(m_time_of_day_f * 24000, m_cache_enable_shaders);
  70. }
  71. void Environment::setTimeOfDaySpeed(float speed)
  72. {
  73. m_time_of_day_speed = speed;
  74. }
  75. void Environment::setDayNightRatioOverride(bool enable, u32 value)
  76. {
  77. MutexAutoLock lock(this->m_time_lock);
  78. m_enable_day_night_ratio_override = enable;
  79. m_day_night_ratio_override = value;
  80. }
  81. void Environment::setTimeOfDay(u32 time)
  82. {
  83. MutexAutoLock lock(this->m_time_lock);
  84. if (m_time_of_day > time)
  85. m_day_count++;
  86. m_time_of_day = time;
  87. m_time_of_day_f = (float)time / 24000.0;
  88. }
  89. u32 Environment::getTimeOfDay()
  90. {
  91. MutexAutoLock lock(this->m_time_lock);
  92. return m_time_of_day;
  93. }
  94. float Environment::getTimeOfDayF()
  95. {
  96. MutexAutoLock lock(this->m_time_lock);
  97. return m_time_of_day_f;
  98. }
  99. void Environment::stepTimeOfDay(float dtime)
  100. {
  101. MutexAutoLock lock(this->m_time_lock);
  102. // Cached in order to prevent the two reads we do to give
  103. // different results (can be written by code not under the lock)
  104. f32 cached_time_of_day_speed = m_time_of_day_speed;
  105. f32 speed = cached_time_of_day_speed * 24000. / (24. * 3600);
  106. m_time_conversion_skew += dtime;
  107. u32 units = (u32)(m_time_conversion_skew * speed);
  108. bool sync_f = false;
  109. if (units > 0) {
  110. // Sync at overflow
  111. if (m_time_of_day + units >= 24000) {
  112. sync_f = true;
  113. m_day_count++;
  114. }
  115. m_time_of_day = (m_time_of_day + units) % 24000;
  116. if (sync_f)
  117. m_time_of_day_f = (float)m_time_of_day / 24000.0;
  118. }
  119. if (speed > 0) {
  120. m_time_conversion_skew -= (f32)units / speed;
  121. }
  122. if (!sync_f) {
  123. m_time_of_day_f += cached_time_of_day_speed / 24 / 3600 * dtime;
  124. if (m_time_of_day_f > 1.0)
  125. m_time_of_day_f -= 1.0;
  126. if (m_time_of_day_f < 0.0)
  127. m_time_of_day_f += 1.0;
  128. }
  129. }
  130. u32 Environment::getDayCount()
  131. {
  132. // Atomic<u32> counter
  133. return m_day_count;
  134. }
  135. /*
  136. ABMWithState
  137. */
  138. ABMWithState::ABMWithState(ActiveBlockModifier *abm_):
  139. abm(abm_),
  140. timer(0)
  141. {
  142. // Initialize timer to random value to spread processing
  143. float itv = abm->getTriggerInterval();
  144. itv = MYMAX(0.001, itv); // No less than 1ms
  145. int minval = MYMAX(-0.51*itv, -60); // Clamp to
  146. int maxval = MYMIN(0.51*itv, 60); // +-60 seconds
  147. timer = myrand_range(minval, maxval);
  148. }
  149. /*
  150. LBMManager
  151. */
  152. void LBMContentMapping::deleteContents()
  153. {
  154. for (std::vector<LoadingBlockModifierDef *>::iterator it = lbm_list.begin();
  155. it != lbm_list.end(); ++it) {
  156. delete *it;
  157. }
  158. }
  159. void LBMContentMapping::addLBM(LoadingBlockModifierDef *lbm_def, IGameDef *gamedef)
  160. {
  161. // Add the lbm_def to the LBMContentMapping.
  162. // Unknown names get added to the global NameIdMapping.
  163. INodeDefManager *nodedef = gamedef->ndef();
  164. lbm_list.push_back(lbm_def);
  165. for (std::set<std::string>::const_iterator it = lbm_def->trigger_contents.begin();
  166. it != lbm_def->trigger_contents.end(); ++it) {
  167. std::set<content_t> c_ids;
  168. bool found = nodedef->getIds(*it, c_ids);
  169. if (!found) {
  170. content_t c_id = gamedef->allocateUnknownNodeId(*it);
  171. if (c_id == CONTENT_IGNORE) {
  172. // Seems it can't be allocated.
  173. warningstream << "Could not internalize node name \"" << *it
  174. << "\" while loading LBM \"" << lbm_def->name << "\"." << std::endl;
  175. continue;
  176. }
  177. c_ids.insert(c_id);
  178. }
  179. for (std::set<content_t>::const_iterator iit =
  180. c_ids.begin(); iit != c_ids.end(); ++iit) {
  181. content_t c_id = *iit;
  182. map[c_id].push_back(lbm_def);
  183. }
  184. }
  185. }
  186. const std::vector<LoadingBlockModifierDef *> *
  187. LBMContentMapping::lookup(content_t c) const
  188. {
  189. container_map::const_iterator it = map.find(c);
  190. if (it == map.end())
  191. return NULL;
  192. // This first dereferences the iterator, returning
  193. // a std::vector<LoadingBlockModifierDef *>
  194. // reference, then we convert it to a pointer.
  195. return &(it->second);
  196. }
  197. LBMManager::~LBMManager()
  198. {
  199. for (std::map<std::string, LoadingBlockModifierDef *>::iterator it =
  200. m_lbm_defs.begin(); it != m_lbm_defs.end(); ++it) {
  201. delete it->second;
  202. }
  203. for (lbm_lookup_map::iterator it = m_lbm_lookup.begin();
  204. it != m_lbm_lookup.end(); ++it) {
  205. (it->second).deleteContents();
  206. }
  207. }
  208. void LBMManager::addLBMDef(LoadingBlockModifierDef *lbm_def)
  209. {
  210. // Precondition, in query mode the map isn't used anymore
  211. FATAL_ERROR_IF(m_query_mode == true,
  212. "attempted to modify LBMManager in query mode");
  213. if (!string_allowed(lbm_def->name, LBM_NAME_ALLOWED_CHARS)) {
  214. throw ModError("Error adding LBM \"" + lbm_def->name +
  215. "\": Does not follow naming conventions: "
  216. "Only chararacters [a-z0-9_:] are allowed.");
  217. }
  218. m_lbm_defs[lbm_def->name] = lbm_def;
  219. }
  220. void LBMManager::loadIntroductionTimes(const std::string &times,
  221. IGameDef *gamedef, u32 now)
  222. {
  223. m_query_mode = true;
  224. // name -> time map.
  225. // Storing it in a map first instead of
  226. // handling the stuff directly in the loop
  227. // removes all duplicate entries.
  228. // TODO make this std::unordered_map
  229. std::map<std::string, u32> introduction_times;
  230. /*
  231. The introduction times string consists of name~time entries,
  232. with each entry terminated by a semicolon. The time is decimal.
  233. */
  234. size_t idx = 0;
  235. size_t idx_new;
  236. while ((idx_new = times.find(";", idx)) != std::string::npos) {
  237. std::string entry = times.substr(idx, idx_new - idx);
  238. std::vector<std::string> components = str_split(entry, '~');
  239. if (components.size() != 2)
  240. throw SerializationError("Introduction times entry \""
  241. + entry + "\" requires exactly one '~'!");
  242. const std::string &name = components[0];
  243. u32 time = from_string<u32>(components[1]);
  244. introduction_times[name] = time;
  245. idx = idx_new + 1;
  246. }
  247. // Put stuff from introduction_times into m_lbm_lookup
  248. for (std::map<std::string, u32>::const_iterator it = introduction_times.begin();
  249. it != introduction_times.end(); ++it) {
  250. const std::string &name = it->first;
  251. u32 time = it->second;
  252. std::map<std::string, LoadingBlockModifierDef *>::iterator def_it =
  253. m_lbm_defs.find(name);
  254. if (def_it == m_lbm_defs.end()) {
  255. // This seems to be an LBM entry for
  256. // an LBM we haven't loaded. Discard it.
  257. continue;
  258. }
  259. LoadingBlockModifierDef *lbm_def = def_it->second;
  260. if (lbm_def->run_at_every_load) {
  261. // This seems to be an LBM entry for
  262. // an LBM that runs at every load.
  263. // Don't add it just yet.
  264. continue;
  265. }
  266. m_lbm_lookup[time].addLBM(lbm_def, gamedef);
  267. // Erase the entry so that we know later
  268. // what elements didn't get put into m_lbm_lookup
  269. m_lbm_defs.erase(name);
  270. }
  271. // Now also add the elements from m_lbm_defs to m_lbm_lookup
  272. // that weren't added in the previous step.
  273. // They are introduced first time to this world,
  274. // or are run at every load (introducement time hardcoded to U32_MAX).
  275. LBMContentMapping &lbms_we_introduce_now = m_lbm_lookup[now];
  276. LBMContentMapping &lbms_running_always = m_lbm_lookup[U32_MAX];
  277. for (std::map<std::string, LoadingBlockModifierDef *>::iterator it =
  278. m_lbm_defs.begin(); it != m_lbm_defs.end(); ++it) {
  279. if (it->second->run_at_every_load) {
  280. lbms_running_always.addLBM(it->second, gamedef);
  281. } else {
  282. lbms_we_introduce_now.addLBM(it->second, gamedef);
  283. }
  284. }
  285. // Clear the list, so that we don't delete remaining elements
  286. // twice in the destructor
  287. m_lbm_defs.clear();
  288. }
  289. std::string LBMManager::createIntroductionTimesString()
  290. {
  291. // Precondition, we must be in query mode
  292. FATAL_ERROR_IF(m_query_mode == false,
  293. "attempted to query on non fully set up LBMManager");
  294. std::ostringstream oss;
  295. for (lbm_lookup_map::iterator it = m_lbm_lookup.begin();
  296. it != m_lbm_lookup.end(); ++it) {
  297. u32 time = it->first;
  298. std::vector<LoadingBlockModifierDef *> &lbm_list = it->second.lbm_list;
  299. for (std::vector<LoadingBlockModifierDef *>::iterator iit = lbm_list.begin();
  300. iit != lbm_list.end(); ++iit) {
  301. // Don't add if the LBM runs at every load,
  302. // then introducement time is hardcoded
  303. // and doesn't need to be stored
  304. if ((*iit)->run_at_every_load)
  305. continue;
  306. oss << (*iit)->name << "~" << time << ";";
  307. }
  308. }
  309. return oss.str();
  310. }
  311. void LBMManager::applyLBMs(ServerEnvironment *env, MapBlock *block, u32 stamp)
  312. {
  313. // Precondition, we need m_lbm_lookup to be initialized
  314. FATAL_ERROR_IF(m_query_mode == false,
  315. "attempted to query on non fully set up LBMManager");
  316. v3s16 pos_of_block = block->getPosRelative();
  317. v3s16 pos;
  318. MapNode n;
  319. content_t c;
  320. lbm_lookup_map::const_iterator it = getLBMsIntroducedAfter(stamp);
  321. for (pos.X = 0; pos.X < MAP_BLOCKSIZE; pos.X++)
  322. for (pos.Y = 0; pos.Y < MAP_BLOCKSIZE; pos.Y++)
  323. for (pos.Z = 0; pos.Z < MAP_BLOCKSIZE; pos.Z++)
  324. {
  325. n = block->getNodeNoEx(pos);
  326. c = n.getContent();
  327. for (LBMManager::lbm_lookup_map::const_iterator iit = it;
  328. iit != m_lbm_lookup.end(); ++iit) {
  329. const std::vector<LoadingBlockModifierDef *> *lbm_list =
  330. iit->second.lookup(c);
  331. if (!lbm_list)
  332. continue;
  333. for (std::vector<LoadingBlockModifierDef *>::const_iterator iit =
  334. lbm_list->begin(); iit != lbm_list->end(); ++iit) {
  335. (*iit)->trigger(env, pos + pos_of_block, n);
  336. }
  337. }
  338. }
  339. }
  340. /*
  341. ActiveBlockList
  342. */
  343. void fillRadiusBlock(v3s16 p0, s16 r, std::set<v3s16> &list)
  344. {
  345. v3s16 p;
  346. for(p.X=p0.X-r; p.X<=p0.X+r; p.X++)
  347. for(p.Y=p0.Y-r; p.Y<=p0.Y+r; p.Y++)
  348. for(p.Z=p0.Z-r; p.Z<=p0.Z+r; p.Z++)
  349. {
  350. // Set in list
  351. list.insert(p);
  352. }
  353. }
  354. void ActiveBlockList::update(std::vector<v3s16> &active_positions,
  355. s16 radius,
  356. std::set<v3s16> &blocks_removed,
  357. std::set<v3s16> &blocks_added)
  358. {
  359. /*
  360. Create the new list
  361. */
  362. std::set<v3s16> newlist = m_forceloaded_list;
  363. for(std::vector<v3s16>::iterator i = active_positions.begin();
  364. i != active_positions.end(); ++i)
  365. {
  366. fillRadiusBlock(*i, radius, newlist);
  367. }
  368. /*
  369. Find out which blocks on the old list are not on the new list
  370. */
  371. // Go through old list
  372. for(std::set<v3s16>::iterator i = m_list.begin();
  373. i != m_list.end(); ++i)
  374. {
  375. v3s16 p = *i;
  376. // If not on new list, it's been removed
  377. if(newlist.find(p) == newlist.end())
  378. blocks_removed.insert(p);
  379. }
  380. /*
  381. Find out which blocks on the new list are not on the old list
  382. */
  383. // Go through new list
  384. for(std::set<v3s16>::iterator i = newlist.begin();
  385. i != newlist.end(); ++i)
  386. {
  387. v3s16 p = *i;
  388. // If not on old list, it's been added
  389. if(m_list.find(p) == m_list.end())
  390. blocks_added.insert(p);
  391. }
  392. /*
  393. Update m_list
  394. */
  395. m_list.clear();
  396. for(std::set<v3s16>::iterator i = newlist.begin();
  397. i != newlist.end(); ++i)
  398. {
  399. v3s16 p = *i;
  400. m_list.insert(p);
  401. }
  402. }
  403. /*
  404. ServerEnvironment
  405. */
  406. ServerEnvironment::ServerEnvironment(ServerMap *map,
  407. GameScripting *scriptIface, IGameDef *gamedef,
  408. const std::string &path_world) :
  409. m_map(map),
  410. m_script(scriptIface),
  411. m_gamedef(gamedef),
  412. m_path_world(path_world),
  413. m_send_recommended_timer(0),
  414. m_active_block_interval_overload_skip(0),
  415. m_game_time(0),
  416. m_game_time_fraction_counter(0),
  417. m_last_clear_objects_time(0),
  418. m_recommended_send_interval(0.1),
  419. m_max_lag_estimate(0.1)
  420. {
  421. }
  422. ServerEnvironment::~ServerEnvironment()
  423. {
  424. // Clear active block list.
  425. // This makes the next one delete all active objects.
  426. m_active_blocks.clear();
  427. // Convert all objects to static and delete the active objects
  428. deactivateFarObjects(true);
  429. // Drop/delete map
  430. m_map->drop();
  431. // Delete ActiveBlockModifiers
  432. for (std::vector<ABMWithState>::iterator
  433. i = m_abms.begin(); i != m_abms.end(); ++i){
  434. delete i->abm;
  435. }
  436. // Deallocate players
  437. for (std::vector<RemotePlayer *>::iterator i = m_players.begin();
  438. i != m_players.end(); ++i) {
  439. delete (*i);
  440. }
  441. }
  442. Map & ServerEnvironment::getMap()
  443. {
  444. return *m_map;
  445. }
  446. ServerMap & ServerEnvironment::getServerMap()
  447. {
  448. return *m_map;
  449. }
  450. RemotePlayer *ServerEnvironment::getPlayer(const u16 peer_id)
  451. {
  452. for (std::vector<RemotePlayer *>::iterator i = m_players.begin();
  453. i != m_players.end(); ++i) {
  454. RemotePlayer *player = *i;
  455. if (player->peer_id == peer_id)
  456. return player;
  457. }
  458. return NULL;
  459. }
  460. RemotePlayer *ServerEnvironment::getPlayer(const char* name)
  461. {
  462. for (std::vector<RemotePlayer *>::iterator i = m_players.begin();
  463. i != m_players.end(); ++i) {
  464. RemotePlayer *player = *i;
  465. if (strcmp(player->getName(), name) == 0)
  466. return player;
  467. }
  468. return NULL;
  469. }
  470. void ServerEnvironment::addPlayer(RemotePlayer *player)
  471. {
  472. DSTACK(FUNCTION_NAME);
  473. /*
  474. Check that peer_ids are unique.
  475. Also check that names are unique.
  476. Exception: there can be multiple players with peer_id=0
  477. */
  478. // If peer id is non-zero, it has to be unique.
  479. if (player->peer_id != 0)
  480. FATAL_ERROR_IF(getPlayer(player->peer_id) != NULL, "Peer id not unique");
  481. // Name has to be unique.
  482. FATAL_ERROR_IF(getPlayer(player->getName()) != NULL, "Player name not unique");
  483. // Add.
  484. m_players.push_back(player);
  485. }
  486. void ServerEnvironment::removePlayer(RemotePlayer *player)
  487. {
  488. for (std::vector<RemotePlayer *>::iterator it = m_players.begin();
  489. it != m_players.end(); ++it) {
  490. if ((*it) == player) {
  491. delete *it;
  492. m_players.erase(it);
  493. return;
  494. }
  495. }
  496. }
  497. bool ServerEnvironment::line_of_sight(v3f pos1, v3f pos2, float stepsize, v3s16 *p)
  498. {
  499. float distance = pos1.getDistanceFrom(pos2);
  500. //calculate normalized direction vector
  501. v3f normalized_vector = v3f((pos2.X - pos1.X)/distance,
  502. (pos2.Y - pos1.Y)/distance,
  503. (pos2.Z - pos1.Z)/distance);
  504. //find out if there's a node on path between pos1 and pos2
  505. for (float i = 1; i < distance; i += stepsize) {
  506. v3s16 pos = floatToInt(v3f(normalized_vector.X * i,
  507. normalized_vector.Y * i,
  508. normalized_vector.Z * i) +pos1,BS);
  509. MapNode n = getMap().getNodeNoEx(pos);
  510. if(n.param0 != CONTENT_AIR) {
  511. if (p) {
  512. *p = pos;
  513. }
  514. return false;
  515. }
  516. }
  517. return true;
  518. }
  519. void ServerEnvironment::kickAllPlayers(AccessDeniedCode reason,
  520. const std::string &str_reason, bool reconnect)
  521. {
  522. for (std::vector<RemotePlayer *>::iterator it = m_players.begin();
  523. it != m_players.end(); ++it) {
  524. RemotePlayer *player = dynamic_cast<RemotePlayer *>(*it);
  525. ((Server*)m_gamedef)->DenyAccessVerCompliant(player->peer_id,
  526. player->protocol_version, reason, str_reason, reconnect);
  527. }
  528. }
  529. void ServerEnvironment::saveLoadedPlayers()
  530. {
  531. std::string players_path = m_path_world + DIR_DELIM "players";
  532. fs::CreateDir(players_path);
  533. for (std::vector<RemotePlayer *>::iterator it = m_players.begin();
  534. it != m_players.end();
  535. ++it) {
  536. if ((*it)->checkModified()) {
  537. (*it)->save(players_path, m_gamedef);
  538. }
  539. }
  540. }
  541. void ServerEnvironment::savePlayer(RemotePlayer *player)
  542. {
  543. std::string players_path = m_path_world + DIR_DELIM "players";
  544. fs::CreateDir(players_path);
  545. player->save(players_path, m_gamedef);
  546. }
  547. RemotePlayer *ServerEnvironment::loadPlayer(const std::string &playername, PlayerSAO *sao)
  548. {
  549. bool newplayer = false;
  550. bool found = false;
  551. std::string players_path = m_path_world + DIR_DELIM "players" DIR_DELIM;
  552. std::string path = players_path + playername;
  553. RemotePlayer *player = getPlayer(playername.c_str());
  554. if (!player) {
  555. player = new RemotePlayer("", m_gamedef->idef());
  556. newplayer = true;
  557. }
  558. for (u32 i = 0; i < PLAYER_FILE_ALTERNATE_TRIES; i++) {
  559. //// Open file and deserialize
  560. std::ifstream is(path.c_str(), std::ios_base::binary);
  561. if (!is.good())
  562. continue;
  563. player->deSerialize(is, path, sao);
  564. is.close();
  565. if (player->getName() == playername) {
  566. found = true;
  567. break;
  568. }
  569. path = players_path + playername + itos(i);
  570. }
  571. if (!found) {
  572. infostream << "Player file for player " << playername
  573. << " not found" << std::endl;
  574. if (newplayer)
  575. delete player;
  576. return NULL;
  577. }
  578. if (newplayer) {
  579. addPlayer(player);
  580. }
  581. player->setModified(false);
  582. return player;
  583. }
  584. void ServerEnvironment::saveMeta()
  585. {
  586. std::string path = m_path_world + DIR_DELIM "env_meta.txt";
  587. // Open file and serialize
  588. std::ostringstream ss(std::ios_base::binary);
  589. Settings args;
  590. args.setU64("game_time", m_game_time);
  591. args.setU64("time_of_day", getTimeOfDay());
  592. args.setU64("last_clear_objects_time", m_last_clear_objects_time);
  593. args.setU64("lbm_introduction_times_version", 1);
  594. args.set("lbm_introduction_times",
  595. m_lbm_mgr.createIntroductionTimesString());
  596. args.setU64("day_count", m_day_count);
  597. args.writeLines(ss);
  598. ss<<"EnvArgsEnd\n";
  599. if(!fs::safeWriteToFile(path, ss.str()))
  600. {
  601. infostream<<"ServerEnvironment::saveMeta(): Failed to write "
  602. <<path<<std::endl;
  603. throw SerializationError("Couldn't save env meta");
  604. }
  605. }
  606. void ServerEnvironment::loadMeta()
  607. {
  608. std::string path = m_path_world + DIR_DELIM "env_meta.txt";
  609. // Open file and deserialize
  610. std::ifstream is(path.c_str(), std::ios_base::binary);
  611. if (!is.good()) {
  612. infostream << "ServerEnvironment::loadMeta(): Failed to open "
  613. << path << std::endl;
  614. throw SerializationError("Couldn't load env meta");
  615. }
  616. Settings args;
  617. if (!args.parseConfigLines(is, "EnvArgsEnd")) {
  618. throw SerializationError("ServerEnvironment::loadMeta(): "
  619. "EnvArgsEnd not found!");
  620. }
  621. try {
  622. m_game_time = args.getU64("game_time");
  623. } catch (SettingNotFoundException &e) {
  624. // Getting this is crucial, otherwise timestamps are useless
  625. throw SerializationError("Couldn't load env meta game_time");
  626. }
  627. setTimeOfDay(args.exists("time_of_day") ?
  628. // set day to morning by default
  629. args.getU64("time_of_day") : 9000);
  630. m_last_clear_objects_time = args.exists("last_clear_objects_time") ?
  631. // If missing, do as if clearObjects was never called
  632. args.getU64("last_clear_objects_time") : 0;
  633. std::string lbm_introduction_times = "";
  634. try {
  635. u64 ver = args.getU64("lbm_introduction_times_version");
  636. if (ver == 1) {
  637. lbm_introduction_times = args.get("lbm_introduction_times");
  638. } else {
  639. infostream << "ServerEnvironment::loadMeta(): Non-supported"
  640. << " introduction time version " << ver << std::endl;
  641. }
  642. } catch (SettingNotFoundException &e) {
  643. // No problem, this is expected. Just continue with an empty string
  644. }
  645. m_lbm_mgr.loadIntroductionTimes(lbm_introduction_times, m_gamedef, m_game_time);
  646. m_day_count = args.exists("day_count") ?
  647. args.getU64("day_count") : 0;
  648. }
  649. void ServerEnvironment::loadDefaultMeta()
  650. {
  651. m_lbm_mgr.loadIntroductionTimes("", m_gamedef, m_game_time);
  652. }
  653. struct ActiveABM
  654. {
  655. ActiveBlockModifier *abm;
  656. int chance;
  657. std::set<content_t> required_neighbors;
  658. };
  659. class ABMHandler
  660. {
  661. private:
  662. ServerEnvironment *m_env;
  663. std::map<content_t, std::vector<ActiveABM> > m_aabms;
  664. public:
  665. ABMHandler(std::vector<ABMWithState> &abms,
  666. float dtime_s, ServerEnvironment *env,
  667. bool use_timers):
  668. m_env(env)
  669. {
  670. if(dtime_s < 0.001)
  671. return;
  672. INodeDefManager *ndef = env->getGameDef()->ndef();
  673. for(std::vector<ABMWithState>::iterator
  674. i = abms.begin(); i != abms.end(); ++i) {
  675. ActiveBlockModifier *abm = i->abm;
  676. float trigger_interval = abm->getTriggerInterval();
  677. if(trigger_interval < 0.001)
  678. trigger_interval = 0.001;
  679. float actual_interval = dtime_s;
  680. if(use_timers){
  681. i->timer += dtime_s;
  682. if(i->timer < trigger_interval)
  683. continue;
  684. i->timer -= trigger_interval;
  685. actual_interval = trigger_interval;
  686. }
  687. float chance = abm->getTriggerChance();
  688. if(chance == 0)
  689. chance = 1;
  690. ActiveABM aabm;
  691. aabm.abm = abm;
  692. if(abm->getSimpleCatchUp()) {
  693. float intervals = actual_interval / trigger_interval;
  694. if(intervals == 0)
  695. continue;
  696. aabm.chance = chance / intervals;
  697. if(aabm.chance == 0)
  698. aabm.chance = 1;
  699. } else {
  700. aabm.chance = chance;
  701. }
  702. // Trigger neighbors
  703. std::set<std::string> required_neighbors_s
  704. = abm->getRequiredNeighbors();
  705. for(std::set<std::string>::iterator
  706. i = required_neighbors_s.begin();
  707. i != required_neighbors_s.end(); ++i)
  708. {
  709. ndef->getIds(*i, aabm.required_neighbors);
  710. }
  711. // Trigger contents
  712. std::set<std::string> contents_s = abm->getTriggerContents();
  713. for(std::set<std::string>::iterator
  714. i = contents_s.begin(); i != contents_s.end(); ++i)
  715. {
  716. std::set<content_t> ids;
  717. ndef->getIds(*i, ids);
  718. for(std::set<content_t>::const_iterator k = ids.begin();
  719. k != ids.end(); ++k)
  720. {
  721. content_t c = *k;
  722. std::map<content_t, std::vector<ActiveABM> >::iterator j;
  723. j = m_aabms.find(c);
  724. if(j == m_aabms.end()){
  725. std::vector<ActiveABM> aabmlist;
  726. m_aabms[c] = aabmlist;
  727. j = m_aabms.find(c);
  728. }
  729. j->second.push_back(aabm);
  730. }
  731. }
  732. }
  733. }
  734. // Find out how many objects the given block and its neighbours contain.
  735. // Returns the number of objects in the block, and also in 'wider' the
  736. // number of objects in the block and all its neighbours. The latter
  737. // may an estimate if any neighbours are unloaded.
  738. u32 countObjects(MapBlock *block, ServerMap * map, u32 &wider)
  739. {
  740. wider = 0;
  741. u32 wider_unknown_count = 0;
  742. for(s16 x=-1; x<=1; x++)
  743. for(s16 y=-1; y<=1; y++)
  744. for(s16 z=-1; z<=1; z++)
  745. {
  746. MapBlock *block2 = map->getBlockNoCreateNoEx(
  747. block->getPos() + v3s16(x,y,z));
  748. if(block2==NULL){
  749. wider_unknown_count++;
  750. continue;
  751. }
  752. wider += block2->m_static_objects.m_active.size()
  753. + block2->m_static_objects.m_stored.size();
  754. }
  755. // Extrapolate
  756. u32 active_object_count = block->m_static_objects.m_active.size();
  757. u32 wider_known_count = 3*3*3 - wider_unknown_count;
  758. wider += wider_unknown_count * wider / wider_known_count;
  759. return active_object_count;
  760. }
  761. void apply(MapBlock *block)
  762. {
  763. if(m_aabms.empty())
  764. return;
  765. ServerMap *map = &m_env->getServerMap();
  766. u32 active_object_count_wider;
  767. u32 active_object_count = this->countObjects(block, map, active_object_count_wider);
  768. m_env->m_added_objects = 0;
  769. v3s16 p0;
  770. for(p0.X=0; p0.X<MAP_BLOCKSIZE; p0.X++)
  771. for(p0.Y=0; p0.Y<MAP_BLOCKSIZE; p0.Y++)
  772. for(p0.Z=0; p0.Z<MAP_BLOCKSIZE; p0.Z++)
  773. {
  774. MapNode n = block->getNodeNoEx(p0);
  775. content_t c = n.getContent();
  776. v3s16 p = p0 + block->getPosRelative();
  777. std::map<content_t, std::vector<ActiveABM> >::iterator j;
  778. j = m_aabms.find(c);
  779. if(j == m_aabms.end())
  780. continue;
  781. for(std::vector<ActiveABM>::iterator
  782. i = j->second.begin(); i != j->second.end(); ++i) {
  783. if(myrand() % i->chance != 0)
  784. continue;
  785. // Check neighbors
  786. if(!i->required_neighbors.empty())
  787. {
  788. v3s16 p1;
  789. for(p1.X = p.X-1; p1.X <= p.X+1; p1.X++)
  790. for(p1.Y = p.Y-1; p1.Y <= p.Y+1; p1.Y++)
  791. for(p1.Z = p.Z-1; p1.Z <= p.Z+1; p1.Z++)
  792. {
  793. if(p1 == p)
  794. continue;
  795. MapNode n = map->getNodeNoEx(p1);
  796. content_t c = n.getContent();
  797. std::set<content_t>::const_iterator k;
  798. k = i->required_neighbors.find(c);
  799. if(k != i->required_neighbors.end()){
  800. goto neighbor_found;
  801. }
  802. }
  803. // No required neighbor found
  804. continue;
  805. }
  806. neighbor_found:
  807. // Call all the trigger variations
  808. i->abm->trigger(m_env, p, n);
  809. i->abm->trigger(m_env, p, n,
  810. active_object_count, active_object_count_wider);
  811. // Count surrounding objects again if the abms added any
  812. if(m_env->m_added_objects > 0) {
  813. active_object_count = countObjects(block, map, active_object_count_wider);
  814. m_env->m_added_objects = 0;
  815. }
  816. }
  817. }
  818. }
  819. };
  820. void ServerEnvironment::activateBlock(MapBlock *block, u32 additional_dtime)
  821. {
  822. // Reset usage timer immediately, otherwise a block that becomes active
  823. // again at around the same time as it would normally be unloaded will
  824. // get unloaded incorrectly. (I think this still leaves a small possibility
  825. // of a race condition between this and server::AsyncRunStep, which only
  826. // some kind of synchronisation will fix, but it at least reduces the window
  827. // of opportunity for it to break from seconds to nanoseconds)
  828. block->resetUsageTimer();
  829. // Get time difference
  830. u32 dtime_s = 0;
  831. u32 stamp = block->getTimestamp();
  832. if (m_game_time > stamp && stamp != BLOCK_TIMESTAMP_UNDEFINED)
  833. dtime_s = m_game_time - stamp;
  834. dtime_s += additional_dtime;
  835. /*infostream<<"ServerEnvironment::activateBlock(): block timestamp: "
  836. <<stamp<<", game time: "<<m_game_time<<std::endl;*/
  837. // Remove stored static objects if clearObjects was called since block's timestamp
  838. if (stamp == BLOCK_TIMESTAMP_UNDEFINED || stamp < m_last_clear_objects_time) {
  839. block->m_static_objects.m_stored.clear();
  840. // do not set changed flag to avoid unnecessary mapblock writes
  841. }
  842. // Set current time as timestamp
  843. block->setTimestampNoChangedFlag(m_game_time);
  844. /*infostream<<"ServerEnvironment::activateBlock(): block is "
  845. <<dtime_s<<" seconds old."<<std::endl;*/
  846. // Activate stored objects
  847. activateObjects(block, dtime_s);
  848. /* Handle LoadingBlockModifiers */
  849. m_lbm_mgr.applyLBMs(this, block, stamp);
  850. // Run node timers
  851. std::vector<NodeTimer> elapsed_timers =
  852. block->m_node_timers.step((float)dtime_s);
  853. if (!elapsed_timers.empty()) {
  854. MapNode n;
  855. for (std::vector<NodeTimer>::iterator
  856. i = elapsed_timers.begin();
  857. i != elapsed_timers.end(); ++i){
  858. n = block->getNodeNoEx(i->position);
  859. v3s16 p = i->position + block->getPosRelative();
  860. if (m_script->node_on_timer(p, n, i->elapsed))
  861. block->setNodeTimer(NodeTimer(i->timeout, 0, i->position));
  862. }
  863. }
  864. /* Handle ActiveBlockModifiers */
  865. ABMHandler abmhandler(m_abms, dtime_s, this, false);
  866. abmhandler.apply(block);
  867. }
  868. void ServerEnvironment::addActiveBlockModifier(ActiveBlockModifier *abm)
  869. {
  870. m_abms.push_back(ABMWithState(abm));
  871. }
  872. void ServerEnvironment::addLoadingBlockModifierDef(LoadingBlockModifierDef *lbm)
  873. {
  874. m_lbm_mgr.addLBMDef(lbm);
  875. }
  876. bool ServerEnvironment::setNode(v3s16 p, const MapNode &n)
  877. {
  878. INodeDefManager *ndef = m_gamedef->ndef();
  879. MapNode n_old = m_map->getNodeNoEx(p);
  880. // Call destructor
  881. if (ndef->get(n_old).has_on_destruct)
  882. m_script->node_on_destruct(p, n_old);
  883. // Replace node
  884. if (!m_map->addNodeWithEvent(p, n))
  885. return false;
  886. // Update active VoxelManipulator if a mapgen thread
  887. m_map->updateVManip(p);
  888. // Call post-destructor
  889. if (ndef->get(n_old).has_after_destruct)
  890. m_script->node_after_destruct(p, n_old);
  891. // Call constructor
  892. if (ndef->get(n).has_on_construct)
  893. m_script->node_on_construct(p, n);
  894. return true;
  895. }
  896. bool ServerEnvironment::removeNode(v3s16 p)
  897. {
  898. INodeDefManager *ndef = m_gamedef->ndef();
  899. MapNode n_old = m_map->getNodeNoEx(p);
  900. // Call destructor
  901. if (ndef->get(n_old).has_on_destruct)
  902. m_script->node_on_destruct(p, n_old);
  903. // Replace with air
  904. // This is slightly optimized compared to addNodeWithEvent(air)
  905. if (!m_map->removeNodeWithEvent(p))
  906. return false;
  907. // Update active VoxelManipulator if a mapgen thread
  908. m_map->updateVManip(p);
  909. // Call post-destructor
  910. if (ndef->get(n_old).has_after_destruct)
  911. m_script->node_after_destruct(p, n_old);
  912. // Air doesn't require constructor
  913. return true;
  914. }
  915. bool ServerEnvironment::swapNode(v3s16 p, const MapNode &n)
  916. {
  917. if (!m_map->addNodeWithEvent(p, n, false))
  918. return false;
  919. // Update active VoxelManipulator if a mapgen thread
  920. m_map->updateVManip(p);
  921. return true;
  922. }
  923. void ServerEnvironment::getObjectsInsideRadius(std::vector<u16> &objects, v3f pos, float radius)
  924. {
  925. for (ActiveObjectMap::iterator i = m_active_objects.begin();
  926. i != m_active_objects.end(); ++i) {
  927. ServerActiveObject* obj = i->second;
  928. u16 id = i->first;
  929. v3f objectpos = obj->getBasePosition();
  930. if (objectpos.getDistanceFrom(pos) > radius)
  931. continue;
  932. objects.push_back(id);
  933. }
  934. }
  935. void ServerEnvironment::clearObjects(ClearObjectsMode mode)
  936. {
  937. infostream << "ServerEnvironment::clearObjects(): "
  938. << "Removing all active objects" << std::endl;
  939. std::vector<u16> objects_to_remove;
  940. for (ActiveObjectMap::iterator i = m_active_objects.begin();
  941. i != m_active_objects.end(); ++i) {
  942. ServerActiveObject* obj = i->second;
  943. if (obj->getType() == ACTIVEOBJECT_TYPE_PLAYER)
  944. continue;
  945. u16 id = i->first;
  946. // Delete static object if block is loaded
  947. if (obj->m_static_exists) {
  948. MapBlock *block = m_map->getBlockNoCreateNoEx(obj->m_static_block);
  949. if (block) {
  950. block->m_static_objects.remove(id);
  951. block->raiseModified(MOD_STATE_WRITE_NEEDED,
  952. MOD_REASON_CLEAR_ALL_OBJECTS);
  953. obj->m_static_exists = false;
  954. }
  955. }
  956. // If known by some client, don't delete immediately
  957. if (obj->m_known_by_count > 0) {
  958. obj->m_pending_deactivation = true;
  959. obj->m_removed = true;
  960. continue;
  961. }
  962. // Tell the object about removal
  963. obj->removingFromEnvironment();
  964. // Deregister in scripting api
  965. m_script->removeObjectReference(obj);
  966. // Delete active object
  967. if (obj->environmentDeletes())
  968. delete obj;
  969. // Id to be removed from m_active_objects
  970. objects_to_remove.push_back(id);
  971. }
  972. // Remove references from m_active_objects
  973. for (std::vector<u16>::iterator i = objects_to_remove.begin();
  974. i != objects_to_remove.end(); ++i) {
  975. m_active_objects.erase(*i);
  976. }
  977. // Get list of loaded blocks
  978. std::vector<v3s16> loaded_blocks;
  979. infostream << "ServerEnvironment::clearObjects(): "
  980. << "Listing all loaded blocks" << std::endl;
  981. m_map->listAllLoadedBlocks(loaded_blocks);
  982. infostream << "ServerEnvironment::clearObjects(): "
  983. << "Done listing all loaded blocks: "
  984. << loaded_blocks.size()<<std::endl;
  985. // Get list of loadable blocks
  986. std::vector<v3s16> loadable_blocks;
  987. if (mode == CLEAR_OBJECTS_MODE_FULL) {
  988. infostream << "ServerEnvironment::clearObjects(): "
  989. << "Listing all loadable blocks" << std::endl;
  990. m_map->listAllLoadableBlocks(loadable_blocks);
  991. infostream << "ServerEnvironment::clearObjects(): "
  992. << "Done listing all loadable blocks: "
  993. << loadable_blocks.size() << std::endl;
  994. } else {
  995. loadable_blocks = loaded_blocks;
  996. }
  997. infostream << "ServerEnvironment::clearObjects(): "
  998. << "Now clearing objects in " << loadable_blocks.size()
  999. << " blocks" << std::endl;
  1000. // Grab a reference on each loaded block to avoid unloading it
  1001. for (std::vector<v3s16>::iterator i = loaded_blocks.begin();
  1002. i != loaded_blocks.end(); ++i) {
  1003. v3s16 p = *i;
  1004. MapBlock *block = m_map->getBlockNoCreateNoEx(p);
  1005. assert(block != NULL);
  1006. block->refGrab();
  1007. }
  1008. // Remove objects in all loadable blocks
  1009. u32 unload_interval = U32_MAX;
  1010. if (mode == CLEAR_OBJECTS_MODE_FULL) {
  1011. unload_interval = g_settings->getS32("max_clearobjects_extra_loaded_blocks");
  1012. unload_interval = MYMAX(unload_interval, 1);
  1013. }
  1014. u32 report_interval = loadable_blocks.size() / 10;
  1015. u32 num_blocks_checked = 0;
  1016. u32 num_blocks_cleared = 0;
  1017. u32 num_objs_cleared = 0;
  1018. for (std::vector<v3s16>::iterator i = loadable_blocks.begin();
  1019. i != loadable_blocks.end(); ++i) {
  1020. v3s16 p = *i;
  1021. MapBlock *block = m_map->emergeBlock(p, false);
  1022. if (!block) {
  1023. errorstream << "ServerEnvironment::clearObjects(): "
  1024. << "Failed to emerge block " << PP(p) << std::endl;
  1025. continue;
  1026. }
  1027. u32 num_stored = block->m_static_objects.m_stored.size();
  1028. u32 num_active = block->m_static_objects.m_active.size();
  1029. if (num_stored != 0 || num_active != 0) {
  1030. block->m_static_objects.m_stored.clear();
  1031. block->m_static_objects.m_active.clear();
  1032. block->raiseModified(MOD_STATE_WRITE_NEEDED,
  1033. MOD_REASON_CLEAR_ALL_OBJECTS);
  1034. num_objs_cleared += num_stored + num_active;
  1035. num_blocks_cleared++;
  1036. }
  1037. num_blocks_checked++;
  1038. if (report_interval != 0 &&
  1039. num_blocks_checked % report_interval == 0) {
  1040. float percent = 100.0 * (float)num_blocks_checked /
  1041. loadable_blocks.size();
  1042. infostream << "ServerEnvironment::clearObjects(): "
  1043. << "Cleared " << num_objs_cleared << " objects"
  1044. << " in " << num_blocks_cleared << " blocks ("
  1045. << percent << "%)" << std::endl;
  1046. }
  1047. if (num_blocks_checked % unload_interval == 0) {
  1048. m_map->unloadUnreferencedBlocks();
  1049. }
  1050. }
  1051. m_map->unloadUnreferencedBlocks();
  1052. // Drop references that were added above
  1053. for (std::vector<v3s16>::iterator i = loaded_blocks.begin();
  1054. i != loaded_blocks.end(); ++i) {
  1055. v3s16 p = *i;
  1056. MapBlock *block = m_map->getBlockNoCreateNoEx(p);
  1057. assert(block);
  1058. block->refDrop();
  1059. }
  1060. m_last_clear_objects_time = m_game_time;
  1061. infostream << "ServerEnvironment::clearObjects(): "
  1062. << "Finished: Cleared " << num_objs_cleared << " objects"
  1063. << " in " << num_blocks_cleared << " blocks" << std::endl;
  1064. }
  1065. void ServerEnvironment::step(float dtime)
  1066. {
  1067. DSTACK(FUNCTION_NAME);
  1068. //TimeTaker timer("ServerEnv step");
  1069. /* Step time of day */
  1070. stepTimeOfDay(dtime);
  1071. // Update this one
  1072. // NOTE: This is kind of funny on a singleplayer game, but doesn't
  1073. // really matter that much.
  1074. static const float server_step = g_settings->getFloat("dedicated_server_step");
  1075. m_recommended_send_interval = server_step;
  1076. /*
  1077. Increment game time
  1078. */
  1079. {
  1080. m_game_time_fraction_counter += dtime;
  1081. u32 inc_i = (u32)m_game_time_fraction_counter;
  1082. m_game_time += inc_i;
  1083. m_game_time_fraction_counter -= (float)inc_i;
  1084. }
  1085. /*
  1086. Handle players
  1087. */
  1088. {
  1089. ScopeProfiler sp(g_profiler, "SEnv: handle players avg", SPT_AVG);
  1090. for (std::vector<RemotePlayer *>::iterator i = m_players.begin();
  1091. i != m_players.end(); ++i) {
  1092. RemotePlayer *player = dynamic_cast<RemotePlayer *>(*i);
  1093. assert(player);
  1094. // Ignore disconnected players
  1095. if(player->peer_id == 0)
  1096. continue;
  1097. // Move
  1098. player->move(dtime, this, 100*BS);
  1099. }
  1100. }
  1101. /*
  1102. Manage active block list
  1103. */
  1104. if (m_active_blocks_management_interval.step(dtime, m_cache_active_block_mgmt_interval)) {
  1105. ScopeProfiler sp(g_profiler, "SEnv: manage act. block list avg per interval", SPT_AVG);
  1106. /*
  1107. Get player block positions
  1108. */
  1109. std::vector<v3s16> players_blockpos;
  1110. for (std::vector<RemotePlayer *>::iterator i = m_players.begin();
  1111. i != m_players.end(); ++i) {
  1112. RemotePlayer *player = dynamic_cast<RemotePlayer *>(*i);
  1113. assert(player);
  1114. // Ignore disconnected players
  1115. if (player->peer_id == 0)
  1116. continue;
  1117. PlayerSAO *playersao = player->getPlayerSAO();
  1118. assert(playersao);
  1119. v3s16 blockpos = getNodeBlockPos(
  1120. floatToInt(playersao->getBasePosition(), BS));
  1121. players_blockpos.push_back(blockpos);
  1122. }
  1123. /*
  1124. Update list of active blocks, collecting changes
  1125. */
  1126. static const s16 active_block_range = g_settings->getS16("active_block_range");
  1127. std::set<v3s16> blocks_removed;
  1128. std::set<v3s16> blocks_added;
  1129. m_active_blocks.update(players_blockpos, active_block_range,
  1130. blocks_removed, blocks_added);
  1131. /*
  1132. Handle removed blocks
  1133. */
  1134. // Convert active objects that are no more in active blocks to static
  1135. deactivateFarObjects(false);
  1136. for(std::set<v3s16>::iterator
  1137. i = blocks_removed.begin();
  1138. i != blocks_removed.end(); ++i) {
  1139. v3s16 p = *i;
  1140. /* infostream<<"Server: Block " << PP(p)
  1141. << " became inactive"<<std::endl; */
  1142. MapBlock *block = m_map->getBlockNoCreateNoEx(p);
  1143. if(block==NULL)
  1144. continue;
  1145. // Set current time as timestamp (and let it set ChangedFlag)
  1146. block->setTimestamp(m_game_time);
  1147. }
  1148. /*
  1149. Handle added blocks
  1150. */
  1151. for(std::set<v3s16>::iterator
  1152. i = blocks_added.begin();
  1153. i != blocks_added.end(); ++i)
  1154. {
  1155. v3s16 p = *i;
  1156. MapBlock *block = m_map->getBlockOrEmerge(p);
  1157. if(block==NULL){
  1158. m_active_blocks.m_list.erase(p);
  1159. continue;
  1160. }
  1161. activateBlock(block);
  1162. /* infostream<<"Server: Block " << PP(p)
  1163. << " became active"<<std::endl; */
  1164. }
  1165. }
  1166. /*
  1167. Mess around in active blocks
  1168. */
  1169. if (m_active_blocks_nodemetadata_interval.step(dtime, m_cache_nodetimer_interval)) {
  1170. ScopeProfiler sp(g_profiler, "SEnv: mess in act. blocks avg per interval", SPT_AVG);
  1171. float dtime = m_cache_nodetimer_interval;
  1172. for(std::set<v3s16>::iterator
  1173. i = m_active_blocks.m_list.begin();
  1174. i != m_active_blocks.m_list.end(); ++i)
  1175. {
  1176. v3s16 p = *i;
  1177. /*infostream<<"Server: Block ("<<p.X<<","<<p.Y<<","<<p.Z
  1178. <<") being handled"<<std::endl;*/
  1179. MapBlock *block = m_map->getBlockNoCreateNoEx(p);
  1180. if(block==NULL)
  1181. continue;
  1182. // Reset block usage timer
  1183. block->resetUsageTimer();
  1184. // Set current time as timestamp
  1185. block->setTimestampNoChangedFlag(m_game_time);
  1186. // If time has changed much from the one on disk,
  1187. // set block to be saved when it is unloaded
  1188. if(block->getTimestamp() > block->getDiskTimestamp() + 60)
  1189. block->raiseModified(MOD_STATE_WRITE_AT_UNLOAD,
  1190. MOD_REASON_BLOCK_EXPIRED);
  1191. // Run node timers
  1192. std::vector<NodeTimer> elapsed_timers =
  1193. block->m_node_timers.step((float)dtime);
  1194. if (!elapsed_timers.empty()) {
  1195. MapNode n;
  1196. for (std::vector<NodeTimer>::iterator i = elapsed_timers.begin();
  1197. i != elapsed_timers.end(); ++i) {
  1198. n = block->getNodeNoEx(i->position);
  1199. p = i->position + block->getPosRelative();
  1200. if (m_script->node_on_timer(p, n, i->elapsed)) {
  1201. block->setNodeTimer(NodeTimer(
  1202. i->timeout, 0, i->position));
  1203. }
  1204. }
  1205. }
  1206. }
  1207. }
  1208. if (m_active_block_modifier_interval.step(dtime, m_cache_abm_interval))
  1209. do{ // breakable
  1210. if(m_active_block_interval_overload_skip > 0){
  1211. ScopeProfiler sp(g_profiler, "SEnv: ABM overload skips");
  1212. m_active_block_interval_overload_skip--;
  1213. break;
  1214. }
  1215. ScopeProfiler sp(g_profiler, "SEnv: modify in blocks avg per interval", SPT_AVG);
  1216. TimeTaker timer("modify in active blocks per interval");
  1217. // Initialize handling of ActiveBlockModifiers
  1218. ABMHandler abmhandler(m_abms, m_cache_abm_interval, this, true);
  1219. for(std::set<v3s16>::iterator
  1220. i = m_active_blocks.m_list.begin();
  1221. i != m_active_blocks.m_list.end(); ++i)
  1222. {
  1223. v3s16 p = *i;
  1224. /*infostream<<"Server: Block ("<<p.X<<","<<p.Y<<","<<p.Z
  1225. <<") being handled"<<std::endl;*/
  1226. MapBlock *block = m_map->getBlockNoCreateNoEx(p);
  1227. if(block == NULL)
  1228. continue;
  1229. // Set current time as timestamp
  1230. block->setTimestampNoChangedFlag(m_game_time);
  1231. /* Handle ActiveBlockModifiers */
  1232. abmhandler.apply(block);
  1233. }
  1234. u32 time_ms = timer.stop(true);
  1235. u32 max_time_ms = 200;
  1236. if(time_ms > max_time_ms){
  1237. warningstream<<"active block modifiers took "
  1238. <<time_ms<<"ms (longer than "
  1239. <<max_time_ms<<"ms)"<<std::endl;
  1240. m_active_block_interval_overload_skip = (time_ms / max_time_ms) + 1;
  1241. }
  1242. }while(0);
  1243. /*
  1244. Step script environment (run global on_step())
  1245. */
  1246. m_script->environment_Step(dtime);
  1247. /*
  1248. Step active objects
  1249. */
  1250. {
  1251. ScopeProfiler sp(g_profiler, "SEnv: step act. objs avg", SPT_AVG);
  1252. //TimeTaker timer("Step active objects");
  1253. g_profiler->avg("SEnv: num of objects", m_active_objects.size());
  1254. // This helps the objects to send data at the same time
  1255. bool send_recommended = false;
  1256. m_send_recommended_timer += dtime;
  1257. if(m_send_recommended_timer > getSendRecommendedInterval())
  1258. {
  1259. m_send_recommended_timer -= getSendRecommendedInterval();
  1260. send_recommended = true;
  1261. }
  1262. for(ActiveObjectMap::iterator i = m_active_objects.begin();
  1263. i != m_active_objects.end(); ++i) {
  1264. ServerActiveObject* obj = i->second;
  1265. // Don't step if is to be removed or stored statically
  1266. if(obj->m_removed || obj->m_pending_deactivation)
  1267. continue;
  1268. // Step object
  1269. obj->step(dtime, send_recommended);
  1270. // Read messages from object
  1271. while(!obj->m_messages_out.empty())
  1272. {
  1273. m_active_object_messages.push(
  1274. obj->m_messages_out.front());
  1275. obj->m_messages_out.pop();
  1276. }
  1277. }
  1278. }
  1279. /*
  1280. Manage active objects
  1281. */
  1282. if(m_object_management_interval.step(dtime, 0.5))
  1283. {
  1284. ScopeProfiler sp(g_profiler, "SEnv: remove removed objs avg /.5s", SPT_AVG);
  1285. /*
  1286. Remove objects that satisfy (m_removed && m_known_by_count==0)
  1287. */
  1288. removeRemovedObjects();
  1289. }
  1290. /*
  1291. Manage particle spawner expiration
  1292. */
  1293. if (m_particle_management_interval.step(dtime, 1.0)) {
  1294. for (UNORDERED_MAP<u32, float>::iterator i = m_particle_spawners.begin();
  1295. i != m_particle_spawners.end(); ) {
  1296. //non expiring spawners
  1297. if (i->second == PARTICLE_SPAWNER_NO_EXPIRY) {
  1298. ++i;
  1299. continue;
  1300. }
  1301. i->second -= 1.0f;
  1302. if (i->second <= 0.f)
  1303. m_particle_spawners.erase(i++);
  1304. else
  1305. ++i;
  1306. }
  1307. }
  1308. }
  1309. u32 ServerEnvironment::addParticleSpawner(float exptime)
  1310. {
  1311. // Timers with lifetime 0 do not expire
  1312. float time = exptime > 0.f ? exptime : PARTICLE_SPAWNER_NO_EXPIRY;
  1313. u32 id = 0;
  1314. for (;;) { // look for unused particlespawner id
  1315. id++;
  1316. UNORDERED_MAP<u32, float>::iterator f = m_particle_spawners.find(id);
  1317. if (f == m_particle_spawners.end()) {
  1318. m_particle_spawners[id] = time;
  1319. break;
  1320. }
  1321. }
  1322. return id;
  1323. }
  1324. u32 ServerEnvironment::addParticleSpawner(float exptime, u16 attached_id)
  1325. {
  1326. u32 id = addParticleSpawner(exptime);
  1327. m_particle_spawner_attachments[id] = attached_id;
  1328. if (ServerActiveObject *obj = getActiveObject(attached_id)) {
  1329. obj->attachParticleSpawner(id);
  1330. }
  1331. return id;
  1332. }
  1333. void ServerEnvironment::deleteParticleSpawner(u32 id, bool remove_from_object)
  1334. {
  1335. m_particle_spawners.erase(id);
  1336. UNORDERED_MAP<u32, u16>::iterator it = m_particle_spawner_attachments.find(id);
  1337. if (it != m_particle_spawner_attachments.end()) {
  1338. u16 obj_id = (*it).second;
  1339. ServerActiveObject *sao = getActiveObject(obj_id);
  1340. if (sao != NULL && remove_from_object) {
  1341. sao->detachParticleSpawner(id);
  1342. }
  1343. m_particle_spawner_attachments.erase(id);
  1344. }
  1345. }
  1346. ServerActiveObject* ServerEnvironment::getActiveObject(u16 id)
  1347. {
  1348. ActiveObjectMap::iterator n = m_active_objects.find(id);
  1349. return (n != m_active_objects.end() ? n->second : NULL);
  1350. }
  1351. bool isFreeServerActiveObjectId(u16 id, ActiveObjectMap &objects)
  1352. {
  1353. if (id == 0)
  1354. return false;
  1355. return objects.find(id) == objects.end();
  1356. }
  1357. u16 getFreeServerActiveObjectId(ActiveObjectMap &objects)
  1358. {
  1359. //try to reuse id's as late as possible
  1360. static u16 last_used_id = 0;
  1361. u16 startid = last_used_id;
  1362. for(;;)
  1363. {
  1364. last_used_id ++;
  1365. if(isFreeServerActiveObjectId(last_used_id, objects))
  1366. return last_used_id;
  1367. if(last_used_id == startid)
  1368. return 0;
  1369. }
  1370. }
  1371. u16 ServerEnvironment::addActiveObject(ServerActiveObject *object)
  1372. {
  1373. assert(object); // Pre-condition
  1374. m_added_objects++;
  1375. u16 id = addActiveObjectRaw(object, true, 0);
  1376. return id;
  1377. }
  1378. /*
  1379. Finds out what new objects have been added to
  1380. inside a radius around a position
  1381. */
  1382. void ServerEnvironment::getAddedActiveObjects(PlayerSAO *playersao, s16 radius,
  1383. s16 player_radius,
  1384. std::set<u16> &current_objects,
  1385. std::queue<u16> &added_objects)
  1386. {
  1387. f32 radius_f = radius * BS;
  1388. f32 player_radius_f = player_radius * BS;
  1389. if (player_radius_f < 0)
  1390. player_radius_f = 0;
  1391. /*
  1392. Go through the object list,
  1393. - discard m_removed objects,
  1394. - discard objects that are too far away,
  1395. - discard objects that are found in current_objects.
  1396. - add remaining objects to added_objects
  1397. */
  1398. for (ActiveObjectMap::iterator i = m_active_objects.begin();
  1399. i != m_active_objects.end(); ++i) {
  1400. u16 id = i->first;
  1401. // Get object
  1402. ServerActiveObject *object = i->second;
  1403. if (object == NULL)
  1404. continue;
  1405. // Discard if removed or deactivating
  1406. if(object->m_removed || object->m_pending_deactivation)
  1407. continue;
  1408. f32 distance_f = object->getBasePosition().
  1409. getDistanceFrom(playersao->getBasePosition());
  1410. if (object->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
  1411. // Discard if too far
  1412. if (distance_f > player_radius_f && player_radius_f != 0)
  1413. continue;
  1414. } else if (distance_f > radius_f)
  1415. continue;
  1416. // Discard if already on current_objects
  1417. std::set<u16>::iterator n;
  1418. n = current_objects.find(id);
  1419. if(n != current_objects.end())
  1420. continue;
  1421. // Add to added_objects
  1422. added_objects.push(id);
  1423. }
  1424. }
  1425. /*
  1426. Finds out what objects have been removed from
  1427. inside a radius around a position
  1428. */
  1429. void ServerEnvironment::getRemovedActiveObjects(PlayerSAO *playersao, s16 radius,
  1430. s16 player_radius,
  1431. std::set<u16> &current_objects,
  1432. std::queue<u16> &removed_objects)
  1433. {
  1434. f32 radius_f = radius * BS;
  1435. f32 player_radius_f = player_radius * BS;
  1436. if (player_radius_f < 0)
  1437. player_radius_f = 0;
  1438. /*
  1439. Go through current_objects; object is removed if:
  1440. - object is not found in m_active_objects (this is actually an
  1441. error condition; objects should be set m_removed=true and removed
  1442. only after all clients have been informed about removal), or
  1443. - object has m_removed=true, or
  1444. - object is too far away
  1445. */
  1446. for(std::set<u16>::iterator
  1447. i = current_objects.begin();
  1448. i != current_objects.end(); ++i)
  1449. {
  1450. u16 id = *i;
  1451. ServerActiveObject *object = getActiveObject(id);
  1452. if (object == NULL) {
  1453. infostream << "ServerEnvironment::getRemovedActiveObjects():"
  1454. << " object in current_objects is NULL" << std::endl;
  1455. removed_objects.push(id);
  1456. continue;
  1457. }
  1458. if (object->m_removed || object->m_pending_deactivation) {
  1459. removed_objects.push(id);
  1460. continue;
  1461. }
  1462. f32 distance_f = object->getBasePosition().getDistanceFrom(playersao->getBasePosition());
  1463. if (object->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
  1464. if (distance_f <= player_radius_f || player_radius_f == 0)
  1465. continue;
  1466. } else if (distance_f <= radius_f)
  1467. continue;
  1468. // Object is no longer visible
  1469. removed_objects.push(id);
  1470. }
  1471. }
  1472. void ServerEnvironment::setStaticForActiveObjectsInBlock(
  1473. v3s16 blockpos, bool static_exists, v3s16 static_block)
  1474. {
  1475. MapBlock *block = m_map->getBlockNoCreateNoEx(blockpos);
  1476. if (!block)
  1477. return;
  1478. for (std::map<u16, StaticObject>::iterator
  1479. so_it = block->m_static_objects.m_active.begin();
  1480. so_it != block->m_static_objects.m_active.end(); ++so_it) {
  1481. // Get the ServerActiveObject counterpart to this StaticObject
  1482. ActiveObjectMap::iterator ao_it = m_active_objects.find(so_it->first);
  1483. if (ao_it == m_active_objects.end()) {
  1484. // If this ever happens, there must be some kind of nasty bug.
  1485. errorstream << "ServerEnvironment::setStaticForObjectsInBlock(): "
  1486. "Object from MapBlock::m_static_objects::m_active not found "
  1487. "in m_active_objects";
  1488. continue;
  1489. }
  1490. ServerActiveObject *sao = ao_it->second;
  1491. sao->m_static_exists = static_exists;
  1492. sao->m_static_block = static_block;
  1493. }
  1494. }
  1495. ActiveObjectMessage ServerEnvironment::getActiveObjectMessage()
  1496. {
  1497. if(m_active_object_messages.empty())
  1498. return ActiveObjectMessage(0);
  1499. ActiveObjectMessage message = m_active_object_messages.front();
  1500. m_active_object_messages.pop();
  1501. return message;
  1502. }
  1503. /*
  1504. ************ Private methods *************
  1505. */
  1506. u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
  1507. bool set_changed, u32 dtime_s)
  1508. {
  1509. assert(object); // Pre-condition
  1510. if(object->getId() == 0){
  1511. u16 new_id = getFreeServerActiveObjectId(m_active_objects);
  1512. if(new_id == 0)
  1513. {
  1514. errorstream<<"ServerEnvironment::addActiveObjectRaw(): "
  1515. <<"no free ids available"<<std::endl;
  1516. if(object->environmentDeletes())
  1517. delete object;
  1518. return 0;
  1519. }
  1520. object->setId(new_id);
  1521. }
  1522. else{
  1523. verbosestream<<"ServerEnvironment::addActiveObjectRaw(): "
  1524. <<"supplied with id "<<object->getId()<<std::endl;
  1525. }
  1526. if(!isFreeServerActiveObjectId(object->getId(), m_active_objects)) {
  1527. errorstream<<"ServerEnvironment::addActiveObjectRaw(): "
  1528. <<"id is not free ("<<object->getId()<<")"<<std::endl;
  1529. if(object->environmentDeletes())
  1530. delete object;
  1531. return 0;
  1532. }
  1533. if (objectpos_over_limit(object->getBasePosition())) {
  1534. v3f p = object->getBasePosition();
  1535. errorstream << "ServerEnvironment::addActiveObjectRaw(): "
  1536. << "object position (" << p.X << "," << p.Y << "," << p.Z
  1537. << ") outside maximum range" << std::endl;
  1538. if (object->environmentDeletes())
  1539. delete object;
  1540. return 0;
  1541. }
  1542. /*infostream<<"ServerEnvironment::addActiveObjectRaw(): "
  1543. <<"added (id="<<object->getId()<<")"<<std::endl;*/
  1544. m_active_objects[object->getId()] = object;
  1545. verbosestream<<"ServerEnvironment::addActiveObjectRaw(): "
  1546. <<"Added id="<<object->getId()<<"; there are now "
  1547. <<m_active_objects.size()<<" active objects."
  1548. <<std::endl;
  1549. // Register reference in scripting api (must be done before post-init)
  1550. m_script->addObjectReference(object);
  1551. // Post-initialize object
  1552. object->addedToEnvironment(dtime_s);
  1553. // Add static data to block
  1554. if(object->isStaticAllowed())
  1555. {
  1556. // Add static object to active static list of the block
  1557. v3f objectpos = object->getBasePosition();
  1558. std::string staticdata = object->getStaticData();
  1559. StaticObject s_obj(object->getType(), objectpos, staticdata);
  1560. // Add to the block where the object is located in
  1561. v3s16 blockpos = getNodeBlockPos(floatToInt(objectpos, BS));
  1562. MapBlock *block = m_map->emergeBlock(blockpos);
  1563. if(block){
  1564. block->m_static_objects.m_active[object->getId()] = s_obj;
  1565. object->m_static_exists = true;
  1566. object->m_static_block = blockpos;
  1567. if(set_changed)
  1568. block->raiseModified(MOD_STATE_WRITE_NEEDED,
  1569. MOD_REASON_ADD_ACTIVE_OBJECT_RAW);
  1570. } else {
  1571. v3s16 p = floatToInt(objectpos, BS);
  1572. errorstream<<"ServerEnvironment::addActiveObjectRaw(): "
  1573. <<"could not emerge block for storing id="<<object->getId()
  1574. <<" statically (pos="<<PP(p)<<")"<<std::endl;
  1575. }
  1576. }
  1577. return object->getId();
  1578. }
  1579. /*
  1580. Remove objects that satisfy (m_removed && m_known_by_count==0)
  1581. */
  1582. void ServerEnvironment::removeRemovedObjects()
  1583. {
  1584. std::vector<u16> objects_to_remove;
  1585. for(ActiveObjectMap::iterator i = m_active_objects.begin();
  1586. i != m_active_objects.end(); ++i) {
  1587. u16 id = i->first;
  1588. ServerActiveObject* obj = i->second;
  1589. // This shouldn't happen but check it
  1590. if(obj == NULL)
  1591. {
  1592. infostream<<"NULL object found in ServerEnvironment"
  1593. <<" while finding removed objects. id="<<id<<std::endl;
  1594. // Id to be removed from m_active_objects
  1595. objects_to_remove.push_back(id);
  1596. continue;
  1597. }
  1598. /*
  1599. We will delete objects that are marked as removed or thatare
  1600. waiting for deletion after deactivation
  1601. */
  1602. if (!obj->m_removed && !obj->m_pending_deactivation)
  1603. continue;
  1604. /*
  1605. Delete static data from block if is marked as removed
  1606. */
  1607. if(obj->m_static_exists && obj->m_removed)
  1608. {
  1609. MapBlock *block = m_map->emergeBlock(obj->m_static_block, false);
  1610. if (block) {
  1611. block->m_static_objects.remove(id);
  1612. block->raiseModified(MOD_STATE_WRITE_NEEDED,
  1613. MOD_REASON_REMOVE_OBJECTS_REMOVE);
  1614. obj->m_static_exists = false;
  1615. } else {
  1616. infostream<<"Failed to emerge block from which an object to "
  1617. <<"be removed was loaded from. id="<<id<<std::endl;
  1618. }
  1619. }
  1620. // If m_known_by_count > 0, don't actually remove. On some future
  1621. // invocation this will be 0, which is when removal will continue.
  1622. if(obj->m_known_by_count > 0)
  1623. continue;
  1624. /*
  1625. Move static data from active to stored if not marked as removed
  1626. */
  1627. if(obj->m_static_exists && !obj->m_removed){
  1628. MapBlock *block = m_map->emergeBlock(obj->m_static_block, false);
  1629. if (block) {
  1630. std::map<u16, StaticObject>::iterator i =
  1631. block->m_static_objects.m_active.find(id);
  1632. if(i != block->m_static_objects.m_active.end()){
  1633. block->m_static_objects.m_stored.push_back(i->second);
  1634. block->m_static_objects.m_active.erase(id);
  1635. block->raiseModified(MOD_STATE_WRITE_NEEDED,
  1636. MOD_REASON_REMOVE_OBJECTS_DEACTIVATE);
  1637. }
  1638. } else {
  1639. infostream<<"Failed to emerge block from which an object to "
  1640. <<"be deactivated was loaded from. id="<<id<<std::endl;
  1641. }
  1642. }
  1643. // Tell the object about removal
  1644. obj->removingFromEnvironment();
  1645. // Deregister in scripting api
  1646. m_script->removeObjectReference(obj);
  1647. // Delete
  1648. if(obj->environmentDeletes())
  1649. delete obj;
  1650. // Id to be removed from m_active_objects
  1651. objects_to_remove.push_back(id);
  1652. }
  1653. // Remove references from m_active_objects
  1654. for(std::vector<u16>::iterator i = objects_to_remove.begin();
  1655. i != objects_to_remove.end(); ++i) {
  1656. m_active_objects.erase(*i);
  1657. }
  1658. }
  1659. static void print_hexdump(std::ostream &o, const std::string &data)
  1660. {
  1661. const int linelength = 16;
  1662. for(int l=0; ; l++){
  1663. int i0 = linelength * l;
  1664. bool at_end = false;
  1665. int thislinelength = linelength;
  1666. if(i0 + thislinelength > (int)data.size()){
  1667. thislinelength = data.size() - i0;
  1668. at_end = true;
  1669. }
  1670. for(int di=0; di<linelength; di++){
  1671. int i = i0 + di;
  1672. char buf[4];
  1673. if(di<thislinelength)
  1674. snprintf(buf, 4, "%.2x ", data[i]);
  1675. else
  1676. snprintf(buf, 4, " ");
  1677. o<<buf;
  1678. }
  1679. o<<" ";
  1680. for(int di=0; di<thislinelength; di++){
  1681. int i = i0 + di;
  1682. if(data[i] >= 32)
  1683. o<<data[i];
  1684. else
  1685. o<<".";
  1686. }
  1687. o<<std::endl;
  1688. if(at_end)
  1689. break;
  1690. }
  1691. }
  1692. /*
  1693. Convert stored objects from blocks near the players to active.
  1694. */
  1695. void ServerEnvironment::activateObjects(MapBlock *block, u32 dtime_s)
  1696. {
  1697. if(block == NULL)
  1698. return;
  1699. // Ignore if no stored objects (to not set changed flag)
  1700. if(block->m_static_objects.m_stored.empty())
  1701. return;
  1702. verbosestream<<"ServerEnvironment::activateObjects(): "
  1703. <<"activating objects of block "<<PP(block->getPos())
  1704. <<" ("<<block->m_static_objects.m_stored.size()
  1705. <<" objects)"<<std::endl;
  1706. bool large_amount = (block->m_static_objects.m_stored.size() > g_settings->getU16("max_objects_per_block"));
  1707. if (large_amount) {
  1708. errorstream<<"suspiciously large amount of objects detected: "
  1709. <<block->m_static_objects.m_stored.size()<<" in "
  1710. <<PP(block->getPos())
  1711. <<"; removing all of them."<<std::endl;
  1712. // Clear stored list
  1713. block->m_static_objects.m_stored.clear();
  1714. block->raiseModified(MOD_STATE_WRITE_NEEDED,
  1715. MOD_REASON_TOO_MANY_OBJECTS);
  1716. return;
  1717. }
  1718. // Activate stored objects
  1719. std::vector<StaticObject> new_stored;
  1720. for (std::vector<StaticObject>::iterator
  1721. i = block->m_static_objects.m_stored.begin();
  1722. i != block->m_static_objects.m_stored.end(); ++i) {
  1723. StaticObject &s_obj = *i;
  1724. // Create an active object from the data
  1725. ServerActiveObject *obj = ServerActiveObject::create
  1726. ((ActiveObjectType) s_obj.type, this, 0, s_obj.pos, s_obj.data);
  1727. // If couldn't create object, store static data back.
  1728. if(obj == NULL) {
  1729. errorstream<<"ServerEnvironment::activateObjects(): "
  1730. <<"failed to create active object from static object "
  1731. <<"in block "<<PP(s_obj.pos/BS)
  1732. <<" type="<<(int)s_obj.type<<" data:"<<std::endl;
  1733. print_hexdump(verbosestream, s_obj.data);
  1734. new_stored.push_back(s_obj);
  1735. continue;
  1736. }
  1737. verbosestream<<"ServerEnvironment::activateObjects(): "
  1738. <<"activated static object pos="<<PP(s_obj.pos/BS)
  1739. <<" type="<<(int)s_obj.type<<std::endl;
  1740. // This will also add the object to the active static list
  1741. addActiveObjectRaw(obj, false, dtime_s);
  1742. }
  1743. // Clear stored list
  1744. block->m_static_objects.m_stored.clear();
  1745. // Add leftover failed stuff to stored list
  1746. for(std::vector<StaticObject>::iterator
  1747. i = new_stored.begin();
  1748. i != new_stored.end(); ++i) {
  1749. StaticObject &s_obj = *i;
  1750. block->m_static_objects.m_stored.push_back(s_obj);
  1751. }
  1752. // Turn the active counterparts of activated objects not pending for
  1753. // deactivation
  1754. for(std::map<u16, StaticObject>::iterator
  1755. i = block->m_static_objects.m_active.begin();
  1756. i != block->m_static_objects.m_active.end(); ++i)
  1757. {
  1758. u16 id = i->first;
  1759. ServerActiveObject *object = getActiveObject(id);
  1760. assert(object);
  1761. object->m_pending_deactivation = false;
  1762. }
  1763. /*
  1764. Note: Block hasn't really been modified here.
  1765. The objects have just been activated and moved from the stored
  1766. static list to the active static list.
  1767. As such, the block is essentially the same.
  1768. Thus, do not call block->raiseModified(MOD_STATE_WRITE_NEEDED).
  1769. Otherwise there would be a huge amount of unnecessary I/O.
  1770. */
  1771. }
  1772. /*
  1773. Convert objects that are not standing inside active blocks to static.
  1774. If m_known_by_count != 0, active object is not deleted, but static
  1775. data is still updated.
  1776. If force_delete is set, active object is deleted nevertheless. It
  1777. shall only be set so in the destructor of the environment.
  1778. If block wasn't generated (not in memory or on disk),
  1779. */
  1780. void ServerEnvironment::deactivateFarObjects(bool force_delete)
  1781. {
  1782. std::vector<u16> objects_to_remove;
  1783. for(ActiveObjectMap::iterator i = m_active_objects.begin();
  1784. i != m_active_objects.end(); ++i) {
  1785. ServerActiveObject* obj = i->second;
  1786. assert(obj);
  1787. // Do not deactivate if static data creation not allowed
  1788. if(!force_delete && !obj->isStaticAllowed())
  1789. continue;
  1790. // If pending deactivation, let removeRemovedObjects() do it
  1791. if(!force_delete && obj->m_pending_deactivation)
  1792. continue;
  1793. u16 id = i->first;
  1794. v3f objectpos = obj->getBasePosition();
  1795. // The block in which the object resides in
  1796. v3s16 blockpos_o = getNodeBlockPos(floatToInt(objectpos, BS));
  1797. // If object's static data is stored in a deactivated block and object
  1798. // is actually located in an active block, re-save to the block in
  1799. // which the object is actually located in.
  1800. if(!force_delete &&
  1801. obj->m_static_exists &&
  1802. !m_active_blocks.contains(obj->m_static_block) &&
  1803. m_active_blocks.contains(blockpos_o))
  1804. {
  1805. v3s16 old_static_block = obj->m_static_block;
  1806. // Save to block where object is located
  1807. MapBlock *block = m_map->emergeBlock(blockpos_o, false);
  1808. if(!block){
  1809. errorstream<<"ServerEnvironment::deactivateFarObjects(): "
  1810. <<"Could not save object id="<<id
  1811. <<" to it's current block "<<PP(blockpos_o)
  1812. <<std::endl;
  1813. continue;
  1814. }
  1815. std::string staticdata_new = obj->getStaticData();
  1816. StaticObject s_obj(obj->getType(), objectpos, staticdata_new);
  1817. block->m_static_objects.insert(id, s_obj);
  1818. obj->m_static_block = blockpos_o;
  1819. block->raiseModified(MOD_STATE_WRITE_NEEDED,
  1820. MOD_REASON_STATIC_DATA_ADDED);
  1821. // Delete from block where object was located
  1822. block = m_map->emergeBlock(old_static_block, false);
  1823. if(!block){
  1824. errorstream<<"ServerEnvironment::deactivateFarObjects(): "
  1825. <<"Could not delete object id="<<id
  1826. <<" from it's previous block "<<PP(old_static_block)
  1827. <<std::endl;
  1828. continue;
  1829. }
  1830. block->m_static_objects.remove(id);
  1831. block->raiseModified(MOD_STATE_WRITE_NEEDED,
  1832. MOD_REASON_STATIC_DATA_REMOVED);
  1833. continue;
  1834. }
  1835. // If block is active, don't remove
  1836. if(!force_delete && m_active_blocks.contains(blockpos_o))
  1837. continue;
  1838. verbosestream<<"ServerEnvironment::deactivateFarObjects(): "
  1839. <<"deactivating object id="<<id<<" on inactive block "
  1840. <<PP(blockpos_o)<<std::endl;
  1841. // If known by some client, don't immediately delete.
  1842. bool pending_delete = (obj->m_known_by_count > 0 && !force_delete);
  1843. /*
  1844. Update the static data
  1845. */
  1846. if(obj->isStaticAllowed())
  1847. {
  1848. // Create new static object
  1849. std::string staticdata_new = obj->getStaticData();
  1850. StaticObject s_obj(obj->getType(), objectpos, staticdata_new);
  1851. bool stays_in_same_block = false;
  1852. bool data_changed = true;
  1853. if (obj->m_static_exists) {
  1854. if (obj->m_static_block == blockpos_o)
  1855. stays_in_same_block = true;
  1856. MapBlock *block = m_map->emergeBlock(obj->m_static_block, false);
  1857. if (block) {
  1858. std::map<u16, StaticObject>::iterator n =
  1859. block->m_static_objects.m_active.find(id);
  1860. if (n != block->m_static_objects.m_active.end()) {
  1861. StaticObject static_old = n->second;
  1862. float save_movem = obj->getMinimumSavedMovement();
  1863. if (static_old.data == staticdata_new &&
  1864. (static_old.pos - objectpos).getLength() < save_movem)
  1865. data_changed = false;
  1866. } else {
  1867. errorstream<<"ServerEnvironment::deactivateFarObjects(): "
  1868. <<"id="<<id<<" m_static_exists=true but "
  1869. <<"static data doesn't actually exist in "
  1870. <<PP(obj->m_static_block)<<std::endl;
  1871. }
  1872. }
  1873. }
  1874. bool shall_be_written = (!stays_in_same_block || data_changed);
  1875. // Delete old static object
  1876. if(obj->m_static_exists)
  1877. {
  1878. MapBlock *block = m_map->emergeBlock(obj->m_static_block, false);
  1879. if(block)
  1880. {
  1881. block->m_static_objects.remove(id);
  1882. obj->m_static_exists = false;
  1883. // Only mark block as modified if data changed considerably
  1884. if(shall_be_written)
  1885. block->raiseModified(MOD_STATE_WRITE_NEEDED,
  1886. MOD_REASON_STATIC_DATA_CHANGED);
  1887. }
  1888. }
  1889. // Add to the block where the object is located in
  1890. v3s16 blockpos = getNodeBlockPos(floatToInt(objectpos, BS));
  1891. // Get or generate the block
  1892. MapBlock *block = NULL;
  1893. try{
  1894. block = m_map->emergeBlock(blockpos);
  1895. } catch(InvalidPositionException &e){
  1896. // Handled via NULL pointer
  1897. // NOTE: emergeBlock's failure is usually determined by it
  1898. // actually returning NULL
  1899. }
  1900. if(block)
  1901. {
  1902. if (block->m_static_objects.m_stored.size() >= g_settings->getU16("max_objects_per_block")) {
  1903. warningstream << "ServerEnv: Trying to store id = " << obj->getId()
  1904. << " statically but block " << PP(blockpos)
  1905. << " already contains "
  1906. << block->m_static_objects.m_stored.size()
  1907. << " objects."
  1908. << " Forcing delete." << std::endl;
  1909. force_delete = true;
  1910. } else {
  1911. // If static counterpart already exists in target block,
  1912. // remove it first.
  1913. // This shouldn't happen because the object is removed from
  1914. // the previous block before this according to
  1915. // obj->m_static_block, but happens rarely for some unknown
  1916. // reason. Unsuccessful attempts have been made to find
  1917. // said reason.
  1918. if(id && block->m_static_objects.m_active.find(id) != block->m_static_objects.m_active.end()){
  1919. warningstream<<"ServerEnv: Performing hack #83274"
  1920. <<std::endl;
  1921. block->m_static_objects.remove(id);
  1922. }
  1923. // Store static data
  1924. u16 store_id = pending_delete ? id : 0;
  1925. block->m_static_objects.insert(store_id, s_obj);
  1926. // Only mark block as modified if data changed considerably
  1927. if(shall_be_written)
  1928. block->raiseModified(MOD_STATE_WRITE_NEEDED,
  1929. MOD_REASON_STATIC_DATA_CHANGED);
  1930. obj->m_static_exists = true;
  1931. obj->m_static_block = block->getPos();
  1932. }
  1933. }
  1934. else{
  1935. if(!force_delete){
  1936. v3s16 p = floatToInt(objectpos, BS);
  1937. errorstream<<"ServerEnv: Could not find or generate "
  1938. <<"a block for storing id="<<obj->getId()
  1939. <<" statically (pos="<<PP(p)<<")"<<std::endl;
  1940. continue;
  1941. }
  1942. }
  1943. }
  1944. /*
  1945. If known by some client, set pending deactivation.
  1946. Otherwise delete it immediately.
  1947. */
  1948. if(pending_delete && !force_delete)
  1949. {
  1950. verbosestream<<"ServerEnvironment::deactivateFarObjects(): "
  1951. <<"object id="<<id<<" is known by clients"
  1952. <<"; not deleting yet"<<std::endl;
  1953. obj->m_pending_deactivation = true;
  1954. continue;
  1955. }
  1956. verbosestream<<"ServerEnvironment::deactivateFarObjects(): "
  1957. <<"object id="<<id<<" is not known by clients"
  1958. <<"; deleting"<<std::endl;
  1959. // Tell the object about removal
  1960. obj->removingFromEnvironment();
  1961. // Deregister in scripting api
  1962. m_script->removeObjectReference(obj);
  1963. // Delete active object
  1964. if(obj->environmentDeletes())
  1965. delete obj;
  1966. // Id to be removed from m_active_objects
  1967. objects_to_remove.push_back(id);
  1968. }
  1969. // Remove references from m_active_objects
  1970. for(std::vector<u16>::iterator i = objects_to_remove.begin();
  1971. i != objects_to_remove.end(); ++i) {
  1972. m_active_objects.erase(*i);
  1973. }
  1974. }
  1975. #ifndef SERVER
  1976. #include "clientsimpleobject.h"
  1977. /*
  1978. ClientEnvironment
  1979. */
  1980. ClientEnvironment::ClientEnvironment(ClientMap *map, scene::ISceneManager *smgr,
  1981. ITextureSource *texturesource, IGameDef *gamedef,
  1982. IrrlichtDevice *irr):
  1983. m_map(map),
  1984. m_local_player(NULL),
  1985. m_smgr(smgr),
  1986. m_texturesource(texturesource),
  1987. m_gamedef(gamedef),
  1988. m_irr(irr)
  1989. {
  1990. char zero = 0;
  1991. memset(attachement_parent_ids, zero, sizeof(attachement_parent_ids));
  1992. }
  1993. ClientEnvironment::~ClientEnvironment()
  1994. {
  1995. // delete active objects
  1996. for (UNORDERED_MAP<u16, ClientActiveObject*>::iterator i = m_active_objects.begin();
  1997. i != m_active_objects.end(); ++i) {
  1998. delete i->second;
  1999. }
  2000. for(std::vector<ClientSimpleObject*>::iterator
  2001. i = m_simple_objects.begin(); i != m_simple_objects.end(); ++i) {
  2002. delete *i;
  2003. }
  2004. // Drop/delete map
  2005. m_map->drop();
  2006. }
  2007. Map & ClientEnvironment::getMap()
  2008. {
  2009. return *m_map;
  2010. }
  2011. ClientMap & ClientEnvironment::getClientMap()
  2012. {
  2013. return *m_map;
  2014. }
  2015. void ClientEnvironment::setLocalPlayer(LocalPlayer *player)
  2016. {
  2017. DSTACK(FUNCTION_NAME);
  2018. /*
  2019. It is a failure if already is a local player
  2020. */
  2021. FATAL_ERROR_IF(m_local_player != NULL,
  2022. "Local player already allocated");
  2023. m_local_player = player;
  2024. }
  2025. void ClientEnvironment::step(float dtime)
  2026. {
  2027. DSTACK(FUNCTION_NAME);
  2028. /* Step time of day */
  2029. stepTimeOfDay(dtime);
  2030. // Get some settings
  2031. bool fly_allowed = m_gamedef->checkLocalPrivilege("fly");
  2032. bool free_move = fly_allowed && g_settings->getBool("free_move");
  2033. // Get local player
  2034. LocalPlayer *lplayer = getLocalPlayer();
  2035. assert(lplayer);
  2036. // collision info queue
  2037. std::vector<CollisionInfo> player_collisions;
  2038. /*
  2039. Get the speed the player is going
  2040. */
  2041. bool is_climbing = lplayer->is_climbing;
  2042. f32 player_speed = lplayer->getSpeed().getLength();
  2043. /*
  2044. Maximum position increment
  2045. */
  2046. //f32 position_max_increment = 0.05*BS;
  2047. f32 position_max_increment = 0.1*BS;
  2048. // Maximum time increment (for collision detection etc)
  2049. // time = distance / speed
  2050. f32 dtime_max_increment = 1;
  2051. if(player_speed > 0.001)
  2052. dtime_max_increment = position_max_increment / player_speed;
  2053. // Maximum time increment is 10ms or lower
  2054. if(dtime_max_increment > 0.01)
  2055. dtime_max_increment = 0.01;
  2056. // Don't allow overly huge dtime
  2057. if(dtime > 0.5)
  2058. dtime = 0.5;
  2059. f32 dtime_downcount = dtime;
  2060. /*
  2061. Stuff that has a maximum time increment
  2062. */
  2063. u32 loopcount = 0;
  2064. do
  2065. {
  2066. loopcount++;
  2067. f32 dtime_part;
  2068. if(dtime_downcount > dtime_max_increment)
  2069. {
  2070. dtime_part = dtime_max_increment;
  2071. dtime_downcount -= dtime_part;
  2072. }
  2073. else
  2074. {
  2075. dtime_part = dtime_downcount;
  2076. /*
  2077. Setting this to 0 (no -=dtime_part) disables an infinite loop
  2078. when dtime_part is so small that dtime_downcount -= dtime_part
  2079. does nothing
  2080. */
  2081. dtime_downcount = 0;
  2082. }
  2083. /*
  2084. Handle local player
  2085. */
  2086. {
  2087. // Apply physics
  2088. if(!free_move && !is_climbing)
  2089. {
  2090. // Gravity
  2091. v3f speed = lplayer->getSpeed();
  2092. if(!lplayer->in_liquid)
  2093. speed.Y -= lplayer->movement_gravity * lplayer->physics_override_gravity * dtime_part * 2;
  2094. // Liquid floating / sinking
  2095. if(lplayer->in_liquid && !lplayer->swimming_vertical)
  2096. speed.Y -= lplayer->movement_liquid_sink * dtime_part * 2;
  2097. // Liquid resistance
  2098. if(lplayer->in_liquid_stable || lplayer->in_liquid)
  2099. {
  2100. // How much the node's viscosity blocks movement, ranges between 0 and 1
  2101. // Should match the scale at which viscosity increase affects other liquid attributes
  2102. const f32 viscosity_factor = 0.3;
  2103. v3f d_wanted = -speed / lplayer->movement_liquid_fluidity;
  2104. f32 dl = d_wanted.getLength();
  2105. if(dl > lplayer->movement_liquid_fluidity_smooth)
  2106. dl = lplayer->movement_liquid_fluidity_smooth;
  2107. dl *= (lplayer->liquid_viscosity * viscosity_factor) + (1 - viscosity_factor);
  2108. v3f d = d_wanted.normalize() * dl;
  2109. speed += d;
  2110. }
  2111. lplayer->setSpeed(speed);
  2112. }
  2113. /*
  2114. Move the lplayer.
  2115. This also does collision detection.
  2116. */
  2117. lplayer->move(dtime_part, this, position_max_increment,
  2118. &player_collisions);
  2119. }
  2120. }
  2121. while(dtime_downcount > 0.001);
  2122. //std::cout<<"Looped "<<loopcount<<" times."<<std::endl;
  2123. for(std::vector<CollisionInfo>::iterator i = player_collisions.begin();
  2124. i != player_collisions.end(); ++i) {
  2125. CollisionInfo &info = *i;
  2126. v3f speed_diff = info.new_speed - info.old_speed;;
  2127. // Handle only fall damage
  2128. // (because otherwise walking against something in fast_move kills you)
  2129. if(speed_diff.Y < 0 || info.old_speed.Y >= 0)
  2130. continue;
  2131. // Get rid of other components
  2132. speed_diff.X = 0;
  2133. speed_diff.Z = 0;
  2134. f32 pre_factor = 1; // 1 hp per node/s
  2135. f32 tolerance = BS*14; // 5 without damage
  2136. f32 post_factor = 1; // 1 hp per node/s
  2137. if(info.type == COLLISION_NODE)
  2138. {
  2139. const ContentFeatures &f = m_gamedef->ndef()->
  2140. get(m_map->getNodeNoEx(info.node_p));
  2141. // Determine fall damage multiplier
  2142. int addp = itemgroup_get(f.groups, "fall_damage_add_percent");
  2143. pre_factor = 1.0 + (float)addp/100.0;
  2144. }
  2145. float speed = pre_factor * speed_diff.getLength();
  2146. if(speed > tolerance)
  2147. {
  2148. f32 damage_f = (speed - tolerance)/BS * post_factor;
  2149. u16 damage = (u16)(damage_f+0.5);
  2150. if(damage != 0){
  2151. damageLocalPlayer(damage, true);
  2152. MtEvent *e = new SimpleTriggerEvent("PlayerFallingDamage");
  2153. m_gamedef->event()->put(e);
  2154. }
  2155. }
  2156. }
  2157. /*
  2158. A quick draft of lava damage
  2159. */
  2160. if(m_lava_hurt_interval.step(dtime, 1.0))
  2161. {
  2162. v3f pf = lplayer->getPosition();
  2163. // Feet, middle and head
  2164. v3s16 p1 = floatToInt(pf + v3f(0, BS*0.1, 0), BS);
  2165. MapNode n1 = m_map->getNodeNoEx(p1);
  2166. v3s16 p2 = floatToInt(pf + v3f(0, BS*0.8, 0), BS);
  2167. MapNode n2 = m_map->getNodeNoEx(p2);
  2168. v3s16 p3 = floatToInt(pf + v3f(0, BS*1.6, 0), BS);
  2169. MapNode n3 = m_map->getNodeNoEx(p3);
  2170. u32 damage_per_second = 0;
  2171. damage_per_second = MYMAX(damage_per_second,
  2172. m_gamedef->ndef()->get(n1).damage_per_second);
  2173. damage_per_second = MYMAX(damage_per_second,
  2174. m_gamedef->ndef()->get(n2).damage_per_second);
  2175. damage_per_second = MYMAX(damage_per_second,
  2176. m_gamedef->ndef()->get(n3).damage_per_second);
  2177. if(damage_per_second != 0)
  2178. {
  2179. damageLocalPlayer(damage_per_second, true);
  2180. }
  2181. }
  2182. /*
  2183. Drowning
  2184. */
  2185. if(m_drowning_interval.step(dtime, 2.0))
  2186. {
  2187. v3f pf = lplayer->getPosition();
  2188. // head
  2189. v3s16 p = floatToInt(pf + v3f(0, BS*1.6, 0), BS);
  2190. MapNode n = m_map->getNodeNoEx(p);
  2191. ContentFeatures c = m_gamedef->ndef()->get(n);
  2192. u8 drowning_damage = c.drowning;
  2193. if(drowning_damage > 0 && lplayer->hp > 0){
  2194. u16 breath = lplayer->getBreath();
  2195. if(breath > 10){
  2196. breath = 11;
  2197. }
  2198. if(breath > 0){
  2199. breath -= 1;
  2200. }
  2201. lplayer->setBreath(breath);
  2202. updateLocalPlayerBreath(breath);
  2203. }
  2204. if(lplayer->getBreath() == 0 && drowning_damage > 0){
  2205. damageLocalPlayer(drowning_damage, true);
  2206. }
  2207. }
  2208. if(m_breathing_interval.step(dtime, 0.5))
  2209. {
  2210. v3f pf = lplayer->getPosition();
  2211. // head
  2212. v3s16 p = floatToInt(pf + v3f(0, BS*1.6, 0), BS);
  2213. MapNode n = m_map->getNodeNoEx(p);
  2214. ContentFeatures c = m_gamedef->ndef()->get(n);
  2215. if (!lplayer->hp){
  2216. lplayer->setBreath(11);
  2217. }
  2218. else if(c.drowning == 0){
  2219. u16 breath = lplayer->getBreath();
  2220. if(breath <= 10){
  2221. breath += 1;
  2222. lplayer->setBreath(breath);
  2223. updateLocalPlayerBreath(breath);
  2224. }
  2225. }
  2226. }
  2227. // Update lighting on local player (used for wield item)
  2228. u32 day_night_ratio = getDayNightRatio();
  2229. {
  2230. // Get node at head
  2231. // On InvalidPositionException, use this as default
  2232. // (day: LIGHT_SUN, night: 0)
  2233. MapNode node_at_lplayer(CONTENT_AIR, 0x0f, 0);
  2234. v3s16 p = lplayer->getLightPosition();
  2235. node_at_lplayer = m_map->getNodeNoEx(p);
  2236. u16 light = getInteriorLight(node_at_lplayer, 0, m_gamedef->ndef());
  2237. u8 day = light & 0xff;
  2238. u8 night = (light >> 8) & 0xff;
  2239. finalColorBlend(lplayer->light_color, day, night, day_night_ratio);
  2240. }
  2241. /*
  2242. Step active objects and update lighting of them
  2243. */
  2244. g_profiler->avg("CEnv: num of objects", m_active_objects.size());
  2245. bool update_lighting = m_active_object_light_update_interval.step(dtime, 0.21);
  2246. for (UNORDERED_MAP<u16, ClientActiveObject*>::iterator i = m_active_objects.begin();
  2247. i != m_active_objects.end(); ++i) {
  2248. ClientActiveObject* obj = i->second;
  2249. // Step object
  2250. obj->step(dtime, this);
  2251. if(update_lighting)
  2252. {
  2253. // Update lighting
  2254. u8 light = 0;
  2255. bool pos_ok;
  2256. // Get node at head
  2257. v3s16 p = obj->getLightPosition();
  2258. MapNode n = m_map->getNodeNoEx(p, &pos_ok);
  2259. if (pos_ok)
  2260. light = n.getLightBlend(day_night_ratio, m_gamedef->ndef());
  2261. else
  2262. light = blend_light(day_night_ratio, LIGHT_SUN, 0);
  2263. obj->updateLight(light);
  2264. }
  2265. }
  2266. /*
  2267. Step and handle simple objects
  2268. */
  2269. g_profiler->avg("CEnv: num of simple objects", m_simple_objects.size());
  2270. for(std::vector<ClientSimpleObject*>::iterator
  2271. i = m_simple_objects.begin(); i != m_simple_objects.end();) {
  2272. std::vector<ClientSimpleObject*>::iterator cur = i;
  2273. ClientSimpleObject *simple = *cur;
  2274. simple->step(dtime);
  2275. if(simple->m_to_be_removed) {
  2276. delete simple;
  2277. i = m_simple_objects.erase(cur);
  2278. }
  2279. else {
  2280. ++i;
  2281. }
  2282. }
  2283. }
  2284. void ClientEnvironment::addSimpleObject(ClientSimpleObject *simple)
  2285. {
  2286. m_simple_objects.push_back(simple);
  2287. }
  2288. GenericCAO* ClientEnvironment::getGenericCAO(u16 id)
  2289. {
  2290. ClientActiveObject *obj = getActiveObject(id);
  2291. if (obj && obj->getType() == ACTIVEOBJECT_TYPE_GENERIC)
  2292. return (GenericCAO*) obj;
  2293. else
  2294. return NULL;
  2295. }
  2296. ClientActiveObject* ClientEnvironment::getActiveObject(u16 id)
  2297. {
  2298. UNORDERED_MAP<u16, ClientActiveObject*>::iterator n = m_active_objects.find(id);
  2299. if (n == m_active_objects.end())
  2300. return NULL;
  2301. return n->second;
  2302. }
  2303. bool isFreeClientActiveObjectId(const u16 id,
  2304. UNORDERED_MAP<u16, ClientActiveObject*> &objects)
  2305. {
  2306. if(id == 0)
  2307. return false;
  2308. return objects.find(id) == objects.end();
  2309. }
  2310. u16 getFreeClientActiveObjectId(UNORDERED_MAP<u16, ClientActiveObject*> &objects)
  2311. {
  2312. //try to reuse id's as late as possible
  2313. static u16 last_used_id = 0;
  2314. u16 startid = last_used_id;
  2315. for(;;) {
  2316. last_used_id ++;
  2317. if (isFreeClientActiveObjectId(last_used_id, objects))
  2318. return last_used_id;
  2319. if (last_used_id == startid)
  2320. return 0;
  2321. }
  2322. }
  2323. u16 ClientEnvironment::addActiveObject(ClientActiveObject *object)
  2324. {
  2325. assert(object); // Pre-condition
  2326. if(object->getId() == 0)
  2327. {
  2328. u16 new_id = getFreeClientActiveObjectId(m_active_objects);
  2329. if(new_id == 0)
  2330. {
  2331. infostream<<"ClientEnvironment::addActiveObject(): "
  2332. <<"no free ids available"<<std::endl;
  2333. delete object;
  2334. return 0;
  2335. }
  2336. object->setId(new_id);
  2337. }
  2338. if (!isFreeClientActiveObjectId(object->getId(), m_active_objects)) {
  2339. infostream<<"ClientEnvironment::addActiveObject(): "
  2340. <<"id is not free ("<<object->getId()<<")"<<std::endl;
  2341. delete object;
  2342. return 0;
  2343. }
  2344. infostream<<"ClientEnvironment::addActiveObject(): "
  2345. <<"added (id="<<object->getId()<<")"<<std::endl;
  2346. m_active_objects[object->getId()] = object;
  2347. object->addToScene(m_smgr, m_texturesource, m_irr);
  2348. { // Update lighting immediately
  2349. u8 light = 0;
  2350. bool pos_ok;
  2351. // Get node at head
  2352. v3s16 p = object->getLightPosition();
  2353. MapNode n = m_map->getNodeNoEx(p, &pos_ok);
  2354. if (pos_ok)
  2355. light = n.getLightBlend(getDayNightRatio(), m_gamedef->ndef());
  2356. else
  2357. light = blend_light(getDayNightRatio(), LIGHT_SUN, 0);
  2358. object->updateLight(light);
  2359. }
  2360. return object->getId();
  2361. }
  2362. void ClientEnvironment::addActiveObject(u16 id, u8 type,
  2363. const std::string &init_data)
  2364. {
  2365. ClientActiveObject* obj =
  2366. ClientActiveObject::create((ActiveObjectType) type, m_gamedef, this);
  2367. if(obj == NULL)
  2368. {
  2369. infostream<<"ClientEnvironment::addActiveObject(): "
  2370. <<"id="<<id<<" type="<<type<<": Couldn't create object"
  2371. <<std::endl;
  2372. return;
  2373. }
  2374. obj->setId(id);
  2375. try
  2376. {
  2377. obj->initialize(init_data);
  2378. }
  2379. catch(SerializationError &e)
  2380. {
  2381. errorstream<<"ClientEnvironment::addActiveObject():"
  2382. <<" id="<<id<<" type="<<type
  2383. <<": SerializationError in initialize(): "
  2384. <<e.what()
  2385. <<": init_data="<<serializeJsonString(init_data)
  2386. <<std::endl;
  2387. }
  2388. addActiveObject(obj);
  2389. }
  2390. void ClientEnvironment::removeActiveObject(u16 id)
  2391. {
  2392. verbosestream<<"ClientEnvironment::removeActiveObject(): "
  2393. <<"id="<<id<<std::endl;
  2394. ClientActiveObject* obj = getActiveObject(id);
  2395. if (obj == NULL) {
  2396. infostream<<"ClientEnvironment::removeActiveObject(): "
  2397. <<"id="<<id<<" not found"<<std::endl;
  2398. return;
  2399. }
  2400. obj->removeFromScene(true);
  2401. delete obj;
  2402. m_active_objects.erase(id);
  2403. }
  2404. void ClientEnvironment::processActiveObjectMessage(u16 id, const std::string &data)
  2405. {
  2406. ClientActiveObject *obj = getActiveObject(id);
  2407. if (obj == NULL) {
  2408. infostream << "ClientEnvironment::processActiveObjectMessage():"
  2409. << " got message for id=" << id << ", which doesn't exist."
  2410. << std::endl;
  2411. return;
  2412. }
  2413. try {
  2414. obj->processMessage(data);
  2415. } catch (SerializationError &e) {
  2416. errorstream<<"ClientEnvironment::processActiveObjectMessage():"
  2417. << " id=" << id << " type=" << obj->getType()
  2418. << " SerializationError in processMessage(): " << e.what()
  2419. << std::endl;
  2420. }
  2421. }
  2422. /*
  2423. Callbacks for activeobjects
  2424. */
  2425. void ClientEnvironment::damageLocalPlayer(u8 damage, bool handle_hp)
  2426. {
  2427. LocalPlayer *lplayer = getLocalPlayer();
  2428. assert(lplayer);
  2429. if (handle_hp) {
  2430. if (lplayer->hp > damage)
  2431. lplayer->hp -= damage;
  2432. else
  2433. lplayer->hp = 0;
  2434. }
  2435. ClientEnvEvent event;
  2436. event.type = CEE_PLAYER_DAMAGE;
  2437. event.player_damage.amount = damage;
  2438. event.player_damage.send_to_server = handle_hp;
  2439. m_client_event_queue.push(event);
  2440. }
  2441. void ClientEnvironment::updateLocalPlayerBreath(u16 breath)
  2442. {
  2443. ClientEnvEvent event;
  2444. event.type = CEE_PLAYER_BREATH;
  2445. event.player_breath.amount = breath;
  2446. m_client_event_queue.push(event);
  2447. }
  2448. /*
  2449. Client likes to call these
  2450. */
  2451. void ClientEnvironment::getActiveObjects(v3f origin, f32 max_d,
  2452. std::vector<DistanceSortedActiveObject> &dest)
  2453. {
  2454. for (UNORDERED_MAP<u16, ClientActiveObject*>::iterator i = m_active_objects.begin();
  2455. i != m_active_objects.end(); ++i) {
  2456. ClientActiveObject* obj = i->second;
  2457. f32 d = (obj->getPosition() - origin).getLength();
  2458. if(d > max_d)
  2459. continue;
  2460. DistanceSortedActiveObject dso(obj, d);
  2461. dest.push_back(dso);
  2462. }
  2463. }
  2464. ClientEnvEvent ClientEnvironment::getClientEvent()
  2465. {
  2466. ClientEnvEvent event;
  2467. if(m_client_event_queue.empty())
  2468. event.type = CEE_NONE;
  2469. else {
  2470. event = m_client_event_queue.front();
  2471. m_client_event_queue.pop();
  2472. }
  2473. return event;
  2474. }
  2475. #endif // #ifndef SERVER