70c5dcf191
- O(n) efficiency walk of item entities - Honor stack family merging, e.g. differing lux levels combine Since the new walk should be much more efficient, the need to handle "extremal" cases specially, e.g. creation of a multi-stack ent, is probably unnecessary. Remove it from the task list, barring any future evidence that it's still relevant.
94 lines
2.8 KiB
Lua
94 lines
2.8 KiB
Lua
-- LUALOCALS < ---------------------------------------------------------
|
|
local ItemStack, ipairs, math, minetest, nodecore, vector
|
|
= ItemStack, ipairs, math, minetest, nodecore, vector
|
|
local math_cos, math_pi, math_random, math_sin, math_sqrt
|
|
= math.cos, math.pi, math.random, math.sin, math.sqrt
|
|
-- LUALOCALS > ---------------------------------------------------------
|
|
|
|
nodecore.register_item_entity_step,
|
|
nodecore.registered_item_entity_steps
|
|
= nodecore.mkreg()
|
|
|
|
nodecore.register_item_entity_on_settle,
|
|
nodecore.registered_item_entity_on_settles
|
|
= nodecore.mkreg()
|
|
|
|
local function stub() end
|
|
|
|
local data_load, data_save = nodecore.entity_staticdata_helpers({
|
|
itemstring = true,
|
|
spin = true,
|
|
vel = true,
|
|
setvel = true
|
|
})
|
|
|
|
minetest.register_entity(":__builtin:item", {
|
|
initial_properties = {
|
|
physical = true,
|
|
is_visible = false,
|
|
collide_with_objects = false,
|
|
collisionbox = {0, 0, 0, 0, 0, 0}
|
|
},
|
|
|
|
set_item = function(self, item)
|
|
item = item and ItemStack(item):to_string()
|
|
if item and item ~= self.itemstring then
|
|
self.itemstring = item
|
|
self.object:set_yaw(math_random() * math_pi * 2)
|
|
end
|
|
if nodecore.item_is_virtual(self.itemstring) then return self.object:remove() end
|
|
self.spin = self.spin or math_random(1, 2) * 2 - 3
|
|
local p, s = nodecore.stackentprops(self.itemstring, 0, self.spin, true)
|
|
s = s / math_sqrt(2)
|
|
self.collidesize = s
|
|
p.collisionbox = {-s, -s, -s, s, s, s}
|
|
p.physical = true
|
|
return self.object:set_properties(p)
|
|
end,
|
|
|
|
get_staticdata = data_save,
|
|
|
|
on_activate = function(self, data)
|
|
self.object:set_armor_groups({immortal = 1})
|
|
data_load(self, data)
|
|
return self:set_item()
|
|
end,
|
|
|
|
on_punch = function(self, hitter)
|
|
local inv = hitter and hitter:get_inventory()
|
|
if inv then
|
|
local stack = ItemStack(self.itemstring)
|
|
stack = inv:add_item("main", stack)
|
|
if stack:is_empty() then return self.object:remove() end
|
|
self:set_item(stack)
|
|
end
|
|
local rho = math_random() * math_pi * 2
|
|
local y = math_sin(rho)
|
|
local xz = math_cos(rho)
|
|
local theta = math_random() * math_pi * 2
|
|
local x = math_cos(theta) * xz
|
|
local z = math_sin(theta) * xz
|
|
self.object:add_velocity(vector.multiply({x = x, y = y, z = z}, 5))
|
|
end,
|
|
|
|
try_merge_with = stub,
|
|
|
|
enable_physics = stub,
|
|
disable_physics = stub,
|
|
|
|
settle_check = nodecore.entity_settle_check(function(self, ...)
|
|
for _, func in ipairs(nodecore.registered_item_entity_on_settles) do
|
|
if func(self, ...) == true then return true end
|
|
end
|
|
end),
|
|
|
|
on_step = function(self, dtime, ...)
|
|
if not self.itemstring then return self.object:remove() end
|
|
if self:settle_check() then return end
|
|
|
|
for _, func in ipairs(nodecore.registered_item_entity_steps) do
|
|
if func(self, dtime, ...) == true then return end
|
|
end
|
|
end,
|
|
})
|