Some map border related fixes
authorest31 <MTest31@outlook.com>
Tue, 29 Sep 2015 15:26:07 +0000 (17:26 +0200)
committerest31 <MTest31@outlook.com>
Tue, 29 Sep 2015 21:06:15 +0000 (23:06 +0200)
1. Check for entity addition success in spawn_item implementation
2. Check for success in item_drop callback, so that the player
doesn't lose the item if they are outside bounds and try to drop it.
3. When existing player joins game, check that their position is inside
map bounds. If not, set their position to the return value of findSpawnPos().
4. Make findSpawnPos() respect the border

2 fixes a lua crash if a player drops an item outside map bounds.
3 fixes an assertion crash if a player leaves when being outside map bounds,
and then rejoins.

builtin/game/item.lua
builtin/game/item_entity.lua
src/server.cpp

index 6628a40813ffef0be47561b11fb609800d1c97b2..0f10af8ee172414b13749700ed19a891d1c6403e 100644 (file)
@@ -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)
index 6425a10aab6cd7b6d4db8582b6e3878bdbf02c18..190473ceb5dca2f76ed6b5929df7b8fa3abbdd06 100644 (file)
@@ -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
index 9b1b142ebe9a8df6ef7c9afe374dcf7c5281e35f..fbdaa59180a66679a92f93defafc8d2f26429bf3 100644 (file)
@@ -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