f140618e45
Trying to make it so that the map lower bound (via mapgen_limit) is solid to all built-in objects. Before, entities would fall into this space, remain until unloaded, and then be destroyed. Falling nodes appear to work correctly. Item ents still don't settle.
148 lines
4.3 KiB
Lua
148 lines
4.3 KiB
Lua
-- LUALOCALS < ---------------------------------------------------------
|
|
local ItemStack, math, minetest, nodecore, pairs, tonumber, type,
|
|
vector
|
|
= ItemStack, math, minetest, nodecore, pairs, tonumber, type,
|
|
vector
|
|
local math_floor, math_pi, math_random, math_sqrt
|
|
= math.floor, math.pi, math.random, math.sqrt
|
|
-- LUALOCALS > ---------------------------------------------------------
|
|
|
|
function minetest.spawn_falling_node(pos, node, meta)
|
|
node = node or minetest.get_node(pos)
|
|
if node.name == "air" or node.name == "ignore" then
|
|
return false
|
|
end
|
|
local obj = minetest.add_entity(pos, "__builtin:falling_node")
|
|
if obj then
|
|
obj:get_luaentity():set_node(node, meta or minetest.get_meta(pos):to_table())
|
|
minetest.remove_node(pos)
|
|
return obj
|
|
end
|
|
return false
|
|
end
|
|
|
|
function nodecore.stackentprops(stack, yaw, rotate, ss)
|
|
local props = {
|
|
hp_max = 1,
|
|
physical = false,
|
|
collide_with_objects = false,
|
|
collisionbox = {0, 0, 0, 0, 0, 0},
|
|
visual = "wielditem",
|
|
visual_size = {x = 0.4, y = 0.4},
|
|
textures = {""},
|
|
spritediv = {x = 1, y = 1},
|
|
initial_sprite_basepos = {x = 0, y = 0},
|
|
is_visible = false,
|
|
static_save = ss and true or false
|
|
}
|
|
local scale = 0
|
|
yaw = yaw or 0
|
|
if stack then
|
|
if type(stack) == "string" then stack = ItemStack(stack) end
|
|
props.is_visible = not stack:is_empty()
|
|
props.textures[1] = stack:get_name()
|
|
|
|
local ratio = stack:get_count() / stack:get_stack_max()
|
|
if ratio > 1 then ratio = 1 end
|
|
scale = math_sqrt(ratio) * 0.15 + 0.25
|
|
props.visual_size = {x = scale, y = scale}
|
|
|
|
props.automatic_rotate = rotate
|
|
and rotate * 2 / math_sqrt(math_sqrt(ratio)) or nil
|
|
|
|
if ratio == 1 then ratio = 1 - (stack:get_wear() / 65536) end
|
|
|
|
if ratio ~= 1 then yaw = yaw + 1/8 + 3/8 * (1 - ratio) end
|
|
yaw = yaw - 2 * math_floor(yaw / 2)
|
|
end
|
|
return props, scale, yaw * math_pi / 2
|
|
end
|
|
|
|
function nodecore.entity_staticdata_helpers(savedprops)
|
|
return function(self, data)
|
|
data = data and minetest.deserialize(data) or {}
|
|
for k in pairs(savedprops) do self[k] = data[k] end
|
|
end,
|
|
function(self)
|
|
local data = {}
|
|
for k in pairs(savedprops) do data[k] = self[k] end
|
|
return minetest.serialize(data)
|
|
end
|
|
end
|
|
|
|
local area_unloaded = {}
|
|
|
|
local maplimit = tonumber(minetest.get_mapgen_setting("mapgen_limit")) or 31000
|
|
local chunksize = tonumber(minetest.get_mapgen_setting("chunksize")) or 5
|
|
chunksize = chunksize * 16
|
|
maplimit = (-math_floor(maplimit / chunksize) + 0.5) * chunksize + 7.5
|
|
|
|
local function collides(pos)
|
|
if pos.y < maplimit then return {name = "ignore"} end
|
|
local node = minetest.get_node_or_nil(pos)
|
|
if not node then return area_unloaded end
|
|
local def = minetest.registered_nodes[node.name]
|
|
if not def then return node end
|
|
if def.walkable then return node end
|
|
end
|
|
|
|
local oldcheck = minetest.check_single_for_falling
|
|
function minetest.check_single_for_falling(...)
|
|
local oldget = minetest.get_node_or_nil
|
|
function minetest.get_node_or_nil(pos, ...)
|
|
if pos.y < maplimit then return end
|
|
return oldget(pos, ...)
|
|
end
|
|
local function helper(...)
|
|
minetest.get_node_or_nil = oldget
|
|
return ...
|
|
end
|
|
return helper(oldcheck(...))
|
|
end
|
|
|
|
function nodecore.entity_settle_check(on_settle, isnode)
|
|
return function(self)
|
|
local pos = self.object:get_pos()
|
|
|
|
if self.settle_oldpos and vector.distance(self.settle_oldpos, pos) < 1/16 then
|
|
local csize = self.collidesize or 0.5
|
|
pos.x = pos.x + (math_random() * 2 - 1) * csize
|
|
pos.z = pos.z + (math_random() * 2 - 1) * csize
|
|
else
|
|
self.settle_oldpos = pos
|
|
end
|
|
|
|
local yvel = self.object:get_velocity().y
|
|
local coll = (isnode or self.not_rising and yvel == 0)
|
|
and collides({x = pos.x, y = pos.y - 0.75, z = pos.z})
|
|
self.not_rising = yvel <= 0
|
|
if not coll then
|
|
if self.setvel then
|
|
self.object:set_velocity(self.vel)
|
|
self.setvel = nil
|
|
end
|
|
self.vel = self.object:get_velocity()
|
|
return nodecore.grav_air_accel_ent(self.object)
|
|
end
|
|
if coll == area_unloaded then
|
|
self.object:set_velocity({x = 0, y = 0, z = 0})
|
|
self.object:set_acceleration({x = 0, y = 0, z = 0})
|
|
self.setvel = true
|
|
return
|
|
end
|
|
pos = vector.round(pos)
|
|
|
|
if not on_settle(self, pos, collides) then return end
|
|
|
|
pos.y = pos.y + 1
|
|
for _, obj in pairs(nodecore.get_objects_at_pos(pos)) do
|
|
obj = obj.get_luaentity and obj:get_luaentity()
|
|
if obj and obj.settle_check then
|
|
obj:settle_check()
|
|
end
|
|
end
|
|
|
|
return nodecore.fallcheck(pos)
|
|
end
|
|
end
|