diff --git a/builtin/game/item.lua b/builtin/game/item.lua index 6628a4081..0f10af8ee 100644 --- a/builtin/game/item.lua +++ b/builtin/game/item.lua @@ -349,12 +349,16 @@ function core.item_drop(itemstack, dropper, pos) v.y = v.y*2 + 2 v.z = v.z*2 obj:setvelocity(v) + return itemstack end else - core.add_item(pos, itemstack) + if core.add_item(pos, itemstack) then + return itemstack + end end - return itemstack + -- If we reach this, adding the object to the + -- environment failed end function core.do_item_eat(hp_change, replace_with_item, itemstack, user, pointed_thing) diff --git a/builtin/game/item_entity.lua b/builtin/game/item_entity.lua index 6425a10aa..190473ceb 100644 --- a/builtin/game/item_entity.lua +++ b/builtin/game/item_entity.lua @@ -4,11 +4,14 @@ function core.spawn_item(pos, item) -- Take item in any format local stack = ItemStack(item) local obj = core.add_entity(pos, "__builtin:item") - obj:get_luaentity():set_item(stack:to_string()) + -- Don't use obj if it couldn't be added to the map. + if obj then + obj:get_luaentity():set_item(stack:to_string()) + end return obj end --- If item_entity_ttl is not set, enity will have default life time +-- If item_entity_ttl is not set, enity will have default life time -- Setting it to -1 disables the feature local time_to_live = tonumber(core.setting_get("item_entity_ttl")) @@ -81,7 +84,7 @@ core.register_entity(":__builtin:item", { if data and type(data) == "table" then self.itemstring = data.itemstring self.always_collect = data.always_collect - if data.age then + if data.age then self.age = data.age + dtime_s else self.age = dtime_s diff --git a/src/server.cpp b/src/server.cpp index 9b1b142eb..fbdaa5918 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -3263,10 +3263,6 @@ v3f Server::findSpawnPos() return nodeposf * BS; } - // Default position is static_spawnpoint - // We will return it if we don't found a good place - v3s16 nodepos(nodeposf.X, nodeposf.Y, nodeposf.Z); - s16 water_level = map.getWaterLevel(); bool is_good = false; @@ -3286,7 +3282,7 @@ v3f Server::findSpawnPos() if (groundheight > water_level + 6) // Don't go to high places continue; - nodepos = v3s16(nodepos2d.X, groundheight, nodepos2d.Y); + v3s16 nodepos(nodepos2d.X, groundheight, nodepos2d.Y); s32 air_count = 0; for (s32 i = 0; i < 10; i++) { @@ -3295,7 +3291,11 @@ v3f Server::findSpawnPos() content_t c = map.getNodeNoEx(nodepos).getContent(); if (c == CONTENT_AIR || c == CONTENT_IGNORE) { air_count++; - if (air_count >= 2){ + if (air_count >= 2) { + nodeposf = intToFloat(nodepos, BS); + // Don't spawn the player outside map boundaries + if (objectpos_over_limit(nodeposf)) + continue; is_good = true; break; } @@ -3304,7 +3304,7 @@ v3f Server::findSpawnPos() } } - return intToFloat(nodepos, BS); + return nodeposf; } PlayerSAO* Server::emergePlayer(const char *name, u16 peer_id, u16 proto_version) @@ -3353,6 +3353,16 @@ PlayerSAO* Server::emergePlayer(const char *name, u16 peer_id, u16 proto_version // Add player to environment m_env->addPlayer(player); + } else { + // If the player exists, ensure that they respawn inside legal bounds + // This fixes an assert crash when the player can't be added + // to the environment + if (objectpos_over_limit(player->getPosition())) { + actionstream << "Respawn position for player \"" + << name << "\" outside limits, resetting" << std::endl; + v3f pos = findSpawnPos(); + player->setPosition(pos); + } } // Create a new player active object