Compare commits

...

5 Commits

Author SHA1 Message Date
Aftermoth fac84ab480 Update details.txt 2017-04-28 09:51:15 +12:00
Aftermoth 5050b0c33d Remove old update announcement 2016-06-28 23:58:48 +12:00
Aftermoth 27b51a0a73 Update README.md 2016-05-29 20:05:32 +12:00
Aftermoth 2b3c715830 Update documentation
Reflect changes and explain more.
2016-05-29 19:59:29 +12:00
Aftermoth 4eeb4e2259 Significant rewrite
Switched to os.time() instead of faking mt.get_us_time() expensively.
Removed surplus vel/acc calls.
Simplified escape to be more correct and less ... creative?
Chunk/session reloading has been more thoroughly tested with no flaws apparent.
2016-05-29 19:56:41 +12:00
3 changed files with 38 additions and 88 deletions

View File

@ -1,7 +1,5 @@
Minetest mod: droplift
** May 1 -- Major changes -- Update strongly recommended **
==== Droplift ====
Droplift lifts drops out of solid blocks.

View File

@ -1,5 +1,5 @@
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.
Spaces closest to the nearest player are preferred.
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.
@ -7,9 +7,9 @@ Lift physics holds a drop for one second before moving it upwards by one node ev
Droplift does not distinguish between differently shaped node boxes, only what their 'walkable' setting is.
This makes it easy to manually entomb drops using simple node types like slabs and glass panes.
Entombed/free status is preserved across game reloads rather than retested. For example, a drop resting on a slab will remain at rest.
Entombed/free status is preserved across game reloads rather than retested. For example, a drop resting on a slab will remain at rest, although technically inside an obstructing node.
All drop velocities are zeroed on reload. This prevents buried drops from being sunk below their current floor.
ALL drop velocities are zeroed on reload. This prevents resting-buried drops from burrowing below their current floor as they do in the default game. This only affects mods, as it's not possible to manually produce this condition under droplift.
-------
* API *
@ -35,9 +35,11 @@ sync in [ false | 0 | seconds ]:
I.e. a lift must occur AFTER the call and BEFORE the target time so it can schedule its NEXT lift to occur at that time, otherwise the sync request is ignored. The initial standing period before the first lift cannot be modified.
Drops remain "entombed" while there is an outstanding sync time, regardless of whether they are actually buried, but will only receive calls while buried.
Drops remain "entombed" while there is an outstanding sync time, regardless of whether they are actually buried, but will only receive calls while buried. Lift will always exit on unburied drops, and a scheduled lift cannot be delayed by additional sync setting.
Sync info is not preserved across reloads.
Sync info is not preserved across reloads. Timing is approximate and variable.
Remember: Sync is primarily aesthetic, to ensure mod interactions display their activity nicely. Don't expect trickier uses to work perfectly.
----
To disable lift physics on a drop, use:

112
init.lua
View File

@ -21,17 +21,6 @@ droplift = {
--------------------------------------------------- Local
-- minetest.get_us_time is not defined in 0.4.10
local seconds = 0.0
if not minetest.get_us_time then
minetest.register_globalstep(function(dtime)
seconds = seconds + dtime
end)
minetest.get_us_time = function()
return seconds * 1000000
end
end
local function obstructed(p)
local n = minetest.get_node_or_nil(p)
return n and minetest.registered_nodes[n.name].walkable
@ -40,64 +29,32 @@ end
-- * Local escape *
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
return ( near < 8.5 and ppos )
end
local function usign(r)
return ( r < 0 and -1 ) or 1
local dist = function(p1,p2)
return ( (p1.y - p2.y)^2
+ (p1.x - p2.x)^2
+ (p1.z - p2.z)^2 )^0.5
end
local function 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
local q, p, ep, d, dd = pos
for _,player in ipairs(minetest.get_connected_players()) do
p = player:getpos(); p.y = p.y + 1
d = dist(p,pos)
if not dd or (d < dd) then dd, q = d, {x=p.x,y=p.y,z=p.z} 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}
for x = pos.x - 1, pos.x + 1 do
p.x = x; for y = pos.y - 1, pos.y + 1 do
p.y = y; for z = pos.z - 1, pos.z + 1 do
p.z = z
if not obstructed(p) then
ent.object:setacceleration({x=0,y=-10,z=0})
ent.object:setpos(p)
return p
d = dist(q,p)
if not ep or (d < dd) then dd, ep = d, {x=p.x,y=p.y,z=p.z} end
end
end
end
end
return false
if ep then ent.object:setpos(ep) end
return ep
end
@ -114,35 +71,30 @@ local function lift(obj)
local t = 1
local s1 = ent.sync1
if s1 then
local sd = ent.sync0+s1-minetest.get_us_time()
if sd > 0 then t = sd/1000000 end
local sd = ent.sync0+s1-os.time()
if sd > 0 then t = sd end
ent.sync0, ent.sync1 = nil, nil
end
-- Space
p = {x = p.x, y = math.floor(p.y - 0.5) + 1.800001, z = p.z}
obj:setpos(p)
if s1 or obstructed(p) then
obj:setvelocity({x = 0, y = 0, z = 0})
obj:setacceleration({x = 0, y = 0, z = 0})
minetest.after(t, lift, obj)
return
end
end -- if w
end
-- Void.
ent.is_entombed, ent.sync0, ent.sync1 = nil, nil, nil
end -- if p
end
end
-- ---------------- ASYNC
local counter = function()
local k = 0
return function()
k = (k==9973 and 1) or k+1
return k
end
local k = 0
local function newhash()
k = (k==32767 and 1) or k+1
return k
end
local newhash = counter()
local function async(obj, usync)
local p = obj:getpos()
@ -157,29 +109,26 @@ local function async(obj, usync)
ent.hash = nil
end
elseif usync > 0 then
ent.sync0 = minetest.get_us_time()
ent.sync0 = os.time()
ent.sync1 = usync
end
-- Space.
if hash == ent.hash then
obj:setpos({x = p.x, y = math.floor(p.y - 0.5) + 0.800001, z = p.z})
obj:setvelocity({x = 0, y = 0, z = 0})
obj:setacceleration({x = 0, y = 0, z = 0})
if not ent.is_entombed then
ent.is_entombed = true
minetest.after(1, lift, obj)
end
end
end -- if w
end
if hash == ent.hash then ent.hash = nil end
end -- if p
end
end
droplift.invoke = function(obj, sync)
async(obj, (sync and math.max(0,sync)*1000000))
async(obj, (sync and math.max(0,sync)))
end
-- * Events *
local function append_to_core_defns()
@ -192,10 +141,11 @@ local function append_to_core_defns()
if staticdata ~= "" then
if minetest.deserialize(staticdata).is_entombed then
ent.is_entombed = true
ent.object:setacceleration({x = 0, y = 0, z = 0}) -- Prevents 0.18m reload slippage. Not critical.
minetest.after(0.1, lift, ent.object)
end
end
ent.object:setvelocity({x = 0, y = 0, z = 0})
ent.object:setvelocity({x = 0, y = 0, z = 0}) -- Prevents resting-buried drops burrowing.
end
-- Preserve state across reloads