Update init.lua (#3)
* Update init.lua Implements quick escape for newly buried drops. * Update init.lua Added param to distinguish resting and newly buried drops, restoring reload consistency. Pruned a pointless cond. * Update init.lua (feature complete) Added one public function for other mods to invoke mechanism in cases droplift ignores. Restored fix for default sink-on-load behaviour of buried drops. * More precise and specific information. * Reduce MT-specific terminologymaster
parent
d71b073c98
commit
684b0f2475
|
@ -1,10 +1,10 @@
|
|||
|
||||
==== Droplift ====
|
||||
|
||||
Droplift lifts drops out of walkable nodes. ("drop" = "__builtin:item")
|
||||
Droplift lifts drops out of solid blocks.
|
||||
This mod adds no in-world items or blocks, just additional physics.
|
||||
|
||||
Droplift also prevents "entombed" drops from sinking below the floor
|
||||
Droplift also prevents buried drops from sinking below the floor
|
||||
when the game reloads.
|
||||
|
||||
Goals:
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
Upon burial, drops may escape to one of the 26 surrounding nodes if any are non-obstructing ('walkable'==false).
|
||||
If the nearest player is within 8.5 nodes (by taxicab metric), spaces closer to that player are preferred, otherwise they are prioritised by +x, +y, +z.
|
||||
|
||||
If no such spaces are found, the drop is "entombed," and remains subject to lift physics until free of obstructing nodes.
|
||||
Lift physics holds a drop for one second before moving it upwards by one node every step, and does not seek other escape routes.
|
||||
|
||||
Droplift does not distinguish between differently shaped node boxes, only what their 'walkable' setting is.
|
||||
This makes it easy to manually entomb drops using common node types like slabs and glass panes.
|
||||
|
||||
Entombed/free status is preserved across game reloads rather than retested.
|
||||
|
||||
All drop velocities are zeroed on reload. This is to prevent buried drops from being sunk below their current floor.
|
||||
|
||||
-------
|
||||
* API *
|
||||
-------
|
||||
|
||||
In general, drops are expected to spawn in non-obstructing nodes, like 'air.'
|
||||
Therefore droplift ignores newly spawned drops, and only checks them when they are newly buried.
|
||||
|
||||
|
||||
|
||||
If you want droplift to handle drops spawned inside obstructing nodes, use:
|
||||
|
||||
droplift.invoke(dropObject, entomb)
|
||||
|
||||
entomb = <boolean> Bypass initial escape phase and use only lift physics, otherwise follow normal burial behaviour.
|
||||
|
||||
|
||||
|
||||
** Drops that are already being lifted should not be called again with invoke. **
|
||||
That would produce multiple unsyncronized handlers for the same object. It will speed things up, but it might also go wrong.
|
||||
|
||||
|
||||
|
||||
...However,
|
||||
If you want to force an entombed drop to break free, AND you're sure it has an escape space, you can:
|
||||
|
||||
dropEntity.is_entombed = false
|
||||
droplift.invoke(dropObject, false)
|
||||
|
||||
If nothing weird happens, the handlers will be cleared from the newly freed drop.
|
||||
But if that's what you need, it may be preferable to refine the code accordingly.
|
112
init.lua
112
init.lua
|
@ -1,4 +1,4 @@
|
|||
|
||||
|
||||
--[[
|
||||
|
||||
Copyright (C) 2016 Aftermoth, Zolan Davis
|
||||
|
@ -13,6 +13,7 @@ http://www.gnu.org/licenses/lgpl-2.1.html
|
|||
|
||||
--]]
|
||||
|
||||
droplift = {}
|
||||
|
||||
local function in_walkable(p)
|
||||
local n = minetest.get_node_or_nil(p)
|
||||
|
@ -20,8 +21,77 @@ local function in_walkable(p)
|
|||
end
|
||||
|
||||
|
||||
-- Update drop physics and flags.
|
||||
local function disentomb(obj)
|
||||
-- * Local escape *
|
||||
|
||||
-- get nearest player in range (taxicab)
|
||||
local function near_player(dpos)
|
||||
local near = 8.5
|
||||
local pp, d, ppos
|
||||
for _,player in ipairs(minetest.get_connected_players()) do
|
||||
pp = player:getpos()
|
||||
pp.y = pp.y + 1
|
||||
d = math.abs(pp.x-dpos.x) + math.abs(pp.y-dpos.y) + math.abs(pp.z-dpos.z)
|
||||
if d < near then
|
||||
near = d
|
||||
ppos = pp
|
||||
end
|
||||
end
|
||||
if near < 8.5 then return ppos else return false end
|
||||
end
|
||||
|
||||
|
||||
local function usign(r)
|
||||
if r < 0 then return -1 else return 1 end
|
||||
end
|
||||
|
||||
|
||||
local function quick_escape(ent,pos)
|
||||
|
||||
local bias = {x = 1, y = 1, z = 1}
|
||||
local o = {a="x", b="y", c="z"}
|
||||
|
||||
local pref = near_player(pos)
|
||||
if pref then
|
||||
bias = {x = usign(pref.x - pos.x), y = usign(pref.y - pos.y), z = usign(pref.z - pos.z)}
|
||||
local mag={x=math.abs(pref.x - pos.x), y=math.abs(pref.y - pos.y), z=math.abs(pref.z - pos.z)}
|
||||
if mag.z > mag.y then
|
||||
if mag.y > mag.x then
|
||||
o={a="z",b="y",c="x"}
|
||||
elseif mag.z > mag.x then
|
||||
o={a="z",b="x",c="y"}
|
||||
else
|
||||
o={a="x",b="z",c="y"}
|
||||
end
|
||||
else
|
||||
if mag.z > mag.x then
|
||||
o={a="y",b="z",c="x"}
|
||||
elseif mag.y > mag.x then
|
||||
o={a="y",b="x",c="z"}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local p
|
||||
for a = pos[o.a] + bias[o.a], pos[o.a] - bias[o.a], -bias[o.a] do
|
||||
for b = pos[o.b] + bias[o.b], pos[o.b] - bias[o.b], -bias[o.b] do
|
||||
for c = pos[o.c] + bias[o.c], pos[o.c] - bias[o.c], -bias[o.c] do
|
||||
p = {[o.a]=a, [o.b]=b, [o.c]=c}
|
||||
if not in_walkable(p) then
|
||||
ent.object:setpos(p)
|
||||
return p
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
-- * Entombment physics *
|
||||
|
||||
|
||||
local function disentomb(obj, reset)
|
||||
local p = obj:getpos()
|
||||
if p then
|
||||
|
||||
|
@ -36,22 +106,27 @@ local function disentomb(obj)
|
|||
obj:setpos(p2)
|
||||
end
|
||||
ent.is_entombed = in_walkable(p2)
|
||||
else
|
||||
if w then
|
||||
obj:setpos({x = p.x, y = brace, z = p.z})
|
||||
ent.is_entombed = true
|
||||
end
|
||||
elseif w and not (reset and quick_escape(ent,p)) then
|
||||
obj:setpos({x = p.x, y = brace, z = p.z})
|
||||
ent.is_entombed = true
|
||||
end
|
||||
|
||||
if ent.is_entombed then
|
||||
obj:setvelocity({x = 0, y = 0, z = 0})
|
||||
obj:setacceleration({x = 0, y = 0, z = 0})
|
||||
minetest.after(1.0, disentomb, obj)
|
||||
minetest.after(1.0, disentomb, obj, false)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
function droplift.invoke(obj, entomb)
|
||||
disentomb(obj, not entomb)
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- * Events *
|
||||
|
||||
|
||||
-- Poll until defaults are ready before continuing.
|
||||
|
@ -63,13 +138,10 @@ local function wait_itemstring(ent, c)
|
|||
return
|
||||
end
|
||||
|
||||
if ent.is_entombed then
|
||||
disentomb(ent.object)
|
||||
end
|
||||
disentomb(ent.object, false)
|
||||
end
|
||||
|
||||
|
||||
|
||||
local function append_to_core_defns()
|
||||
local dropentity=minetest.registered_entities["__builtin:item"]
|
||||
|
||||
|
@ -77,10 +149,14 @@ local function append_to_core_defns()
|
|||
local on_activate_copy = dropentity.on_activate
|
||||
dropentity.on_activate = function(ent, staticdata, dtime_s)
|
||||
on_activate_copy(ent, staticdata, dtime_s)
|
||||
if staticdata ~= "" then
|
||||
ent.is_entombed = minetest.deserialize(staticdata).is_entombed
|
||||
if staticdata ~= "" then
|
||||
if minetest.deserialize(staticdata).is_entombed then
|
||||
ent.is_entombed = true
|
||||
minetest.after(0.1, wait_itemstring, ent, 1)
|
||||
else
|
||||
ent.object:setvelocity({x = 0, y = 0, z = 0})
|
||||
end
|
||||
end
|
||||
wait_itemstring(ent, 0)
|
||||
end
|
||||
|
||||
-- Preserve state across reloads
|
||||
|
@ -98,7 +174,7 @@ local function append_to_core_defns()
|
|||
return s
|
||||
end
|
||||
|
||||
-- Update drops inside newly placed (including fallen) nodes.
|
||||
-- Update drops inside newly placed nodes.
|
||||
local add_node_copy = minetest.add_node
|
||||
minetest.add_node = function(pos,node)
|
||||
add_node_copy(pos, node)
|
||||
|
@ -106,7 +182,7 @@ local function append_to_core_defns()
|
|||
for _,obj in ipairs(a) do
|
||||
local ent = obj:get_luaentity()
|
||||
if ent and ent.name == "__builtin:item" then
|
||||
disentomb(obj)
|
||||
disentomb(obj, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue