d514f8f56d
Instead of shuffling all the shells once for each tick used, shuffle only those shells actually used once per tick. This should save us more time in common cases where we need to only check a few shells to find a place to settle.
106 lines
2.5 KiB
Lua
106 lines
2.5 KiB
Lua
-- LUALOCALS < ---------------------------------------------------------
|
|
local ItemStack, math, minetest, nodecore, pairs, setmetatable, table,
|
|
vector
|
|
= ItemStack, math, minetest, nodecore, pairs, setmetatable, table,
|
|
vector
|
|
local math_random, table_sort
|
|
= math.random, table.sort
|
|
-- LUALOCALS > ---------------------------------------------------------
|
|
|
|
local settleorder = {}
|
|
do
|
|
local groups = {}
|
|
local keys = {}
|
|
for x = -5, 5 do
|
|
for y = -5, 5 do
|
|
for z = -5, 5 do
|
|
local p = {
|
|
x = x,
|
|
y = y,
|
|
z = z,
|
|
}
|
|
local d = vector.length(p)
|
|
if d <= 5 then
|
|
p.v = d + p.y / 100
|
|
local g = groups[p.v]
|
|
if not g then
|
|
g = {}
|
|
groups[p.v] = g
|
|
keys[#keys + 1] = p.v
|
|
end
|
|
g[#g + 1] = p
|
|
end
|
|
end
|
|
end
|
|
end
|
|
table_sort(keys)
|
|
for _, k in pairs(keys) do
|
|
local stamp = 0
|
|
local t = groups[k]
|
|
settleorder[#settleorder + 1] = function()
|
|
if stamp == nodecore.gametime then return t end
|
|
local n = #t
|
|
if n < 2 then return t end
|
|
for i = 1, n do
|
|
local j = math_random(1, n)
|
|
local x = t[i]
|
|
t[i] = t[j]
|
|
t[j] = x
|
|
end
|
|
stamp = nodecore.gametime
|
|
return t
|
|
end
|
|
end
|
|
end
|
|
|
|
local function settle(self)
|
|
local pos = vector.round(self.object:get_pos())
|
|
local item = ItemStack(self.itemstring)
|
|
for i = 1, #settleorder do
|
|
local grp = (settleorder[i])()
|
|
for j = 1, #grp do
|
|
local p = vector.add(pos, grp[j])
|
|
item = nodecore.stack_add(p, item)
|
|
if item:is_empty() then
|
|
self.itemstring = ""
|
|
self.object:remove()
|
|
return true
|
|
end
|
|
if nodecore.buildable_to(p) then
|
|
nodecore.place_stack(p, item)
|
|
self.itemstring = ""
|
|
self.object:remove()
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
self.itemstring = item:to_string()
|
|
end
|
|
|
|
local bii = minetest.registered_entities["__builtin:item"]
|
|
local newbii = {
|
|
on_step = function(self, dtime, ...)
|
|
bii.on_step(self, dtime, ...)
|
|
if not self.moving_state then
|
|
return settle(self)
|
|
end
|
|
end,
|
|
disable_physics = function(self, ...)
|
|
if settle(self) then return end
|
|
return bii.disable_physics(self, ...)
|
|
end,
|
|
on_punch = function(self, whom, ...)
|
|
if not nodecore.interact(whom) then return end
|
|
bii.on_punch(self, whom, ...)
|
|
if self.itemstring ~= "" then
|
|
local v = self.object:get_velocity()
|
|
v.x = v.x + math_random() * 5 - 2.5
|
|
v.y = v.y + math_random() * 5 - 2.5
|
|
v.z = v.z + math_random() * 5 - 2.5
|
|
self.object:set_velocity(v)
|
|
end
|
|
end
|
|
}
|
|
setmetatable(newbii, bii)
|
|
minetest.register_entity(":__builtin:item", newbii)
|