aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBeha <shacknetisp@mail.com>2017-03-19 13:37:29 -0400
committerBeha <shacknetisp@mail.com>2017-03-19 13:37:29 -0400
commitaf7558eb542f1811e0283f9e9597c365f7153e29 (patch)
treed8fdef407537ed5fb5d8b2a09a672e210f4a3c4d
parent31d29756533c656eddd833e42f6065072203012a (diff)
downloadelevator-af7558eb542f1811e0283f9e9597c365f7153e29.tar.gz
elevator-af7558eb542f1811e0283f9e9597c365f7153e29.tar.bz2
elevator-af7558eb542f1811e0283f9e9597c365f7153e29.zip
Fixes
-rw-r--r--init.lua126
1 files changed, 86 insertions, 40 deletions
diff --git a/init.lua b/init.lua
index f3a3d6a..bfb246d 100644
--- a/init.lua
+++ b/init.lua
@@ -3,33 +3,97 @@ local ACCEL = 0.1
local VERSION = 8
local PTIMEOUT = 120
+-- Central "network" table.
local elevator = {
motors = {},
}
+-- Elevator boxes in action.
local boxes = {}
+-- Player formspecs.
local formspecs = {}
-local lastpp = {}
+-- Player near box timeout.
local lastboxes = {}
+-- Players riding boxes.
+local riding = {}
+-- Globalstep timer.
local time = 0
+
+-- Cause <sender> to ride <motorhash> beginning at <pos> and targetting <target>.
+local function create_box(motorhash, pos, target, sender)
+ -- First create the box.
+ local obj = minetest.add_entity(pos, "elevator:box")
+ obj:set_pos(pos)
+ -- Attach the player.
+ sender:set_pos(pos)
+ sender:set_attach(obj, "", {x=0, y=0, z=0}, {x=0, y=0, z=0})
+ sender:set_eye_offset({x=0, y=-9, z=0},{x=0, y=-9, z=0})
+ -- Set the box properties.
+ obj:get_luaentity().motor = motorhash
+ obj:get_luaentity().uid = math.floor(math.random() * 1000000)
+ obj:get_luaentity().attached = sender:get_player_name()
+ obj:get_luaentity().start = pos
+ obj:get_luaentity().target = target
+ obj:get_luaentity().halfway = {x=pos.x, y=(pos.y+target.y)/2, z=pos.z}
+ obj:get_luaentity().vmult = (target.y < pos.y) and -1 or 1
+ -- Set the speed.
+ obj:setvelocity({x=0, y=SPEED*obj:get_luaentity().vmult, z=0})
+ obj:setacceleration({x=0, y=ACCEL*obj:get_luaentity().vmult, z=0})
+ -- Set the tables.
+ boxes[motorhash] = obj
+ riding[sender:get_player_name()] = {
+ motor = motorhash,
+ pos = pos,
+ target = target,
+ box = obj,
+ }
+ return obj
+end
+
+local function teleport_player_from_elevator(player)
+ local function solid(pos)
+ if not minetest.registered_nodes[minetest.get_node(pos).name] then
+ return true
+ end
+ return minetest.registered_nodes[minetest.get_node(pos).name].walkable
+ end
+ local pos = vector.round(player:getpos())
+ local node = minetest.get_node(pos)
+ if node.name == "elevator:elevator_on" then
+ local front = vector.subtract(pos, minetest.facedir_to_dir(node.param2))
+ local front_above = vector.add(front, {x=0, y=1, z=0})
+ local front_below = vector.subtract(front, {x=0, y=1, z=0})
+ if not solid(front) and not solid(front_above) then
+ player:setpos(front)
+ end
+ end
+end
+
minetest.register_globalstep(function(dtime)
time = time + dtime
if time < 0.5 then
return
end
time = 0
- local aplayers = {}
- for motor,box in pairs(boxes) do
- if box and box.get_luaentity and box:get_luaentity() and box:get_luaentity().attached then
- aplayers[box:get_luaentity().attached] = true
- end
- end
+ local newriding = {}
for _,p in ipairs(minetest.get_connected_players()) do
local pos = p:getpos()
- if not aplayers[p:get_player_name()] and minetest.get_node(pos).name ~= "elevator:elevator_on" then
- lastpp[p:get_player_name()] = pos
+ newriding[p:get_player_name()] = riding[p:get_player_name()]
+ if newriding[p:get_player_name()] then
+ newriding[p:get_player_name()].pos = pos
+ end
+ end
+ riding = newriding
+ for name,r in pairs(riding) do
+ local ok = r.box and r.box.getpos and r.box:getpos() and r.box:get_luaentity() and r.box:get_luaentity().attached == name
+ if not ok then
+ minetest.log("action", "[elevator] "..minetest.pos_to_string(r.pos).." created due to lost rider.")
+ minetest.after(0, create_box, r.motor, r.pos, r.target, minetest.get_player_by_name(name))
end
end
for motor,obj in pairs(boxes) do
+ if type(obj) ~= "table" then
+ return
+ end
lastboxes[motor] = lastboxes[motor] and math.min(lastboxes[motor], PTIMEOUT) or PTIMEOUT
lastboxes[motor] = math.max(lastboxes[motor] - 1, 0)
local pos = obj:getpos()
@@ -45,14 +109,13 @@ minetest.register_globalstep(function(dtime)
boxes[motor] = false
end
else
+ minetest.log("action", "[elevator] "..minetest.pos_to_string(pos).." broke due to lack of position during player check.")
boxes[motor] = false
end
end
end)
minetest.register_on_leaveplayer(function(player)
- if lastpp[player:get_player_name()] and vector.distance(lastpp[player:get_player_name()], player:getpos()) < 20 then
- player:setpos(lastpp[player:get_player_name()])
- end
+ teleport_player_from_elevator(player)
end)
local elevator_file = minetest.get_worldpath() .. "/elevator"
@@ -352,25 +415,6 @@ minetest.register_node(nodename, {
})
end
-local function create_box(motorhash, pos, target, sender)
- local obj = minetest.add_entity(pos, "elevator:box")
- obj:set_pos(pos)
- sender:set_pos(pos)
- sender:set_attach(obj, "", {x=0, y=0, z=0}, {x=0, y=0, z=0})
- sender:set_eye_offset({x=0, y=-9, z=0},{x=0, y=-9, z=0})
- obj:get_luaentity().motor = motorhash
- obj:get_luaentity().uid = math.floor(math.random() * 1000000)
- obj:get_luaentity().attached = sender:get_player_name()
- obj:get_luaentity().start = pos
- obj:get_luaentity().target = target
- obj:get_luaentity().halfway = {x=pos.x, y=(pos.y+target.y)/2, z=pos.z}
- obj:get_luaentity().vmult = (target.y < pos.y) and -1 or 1
- obj:setvelocity({x=0, y=SPEED*obj:get_luaentity().vmult, z=0})
- obj:setacceleration({x=0, y=ACCEL*obj:get_luaentity().vmult, z=0})
- boxes[motorhash] = obj
- return obj
-end
-
minetest.register_on_player_receive_fields(function(sender, formname, fields)
if formname ~= "elevator:elevator" then
return
@@ -396,6 +440,7 @@ minetest.register_on_player_receive_fields(function(sender, formname, fields)
if fields.target then
local closeformspec = ""
local pi = minetest.get_player_information(sender:get_player_name())
+ -- HACK: With player information enabled, we can check if closing formspecs are now allowed. This is specifically used on Survival in Ethereal.
if (not (pi.major == 0 and pi.minor == 4 and pi.patch == 15)) and (pi.protocol_version or 29) < 29 then
closeformspec = "size[4,2] label[0,0;You are now using the elevator.\nUpgrade Minetest to avoid this dialog.] button_exit[0,1;4,1;close;Close]"
end
@@ -431,9 +476,9 @@ minetest.register_on_player_receive_fields(function(sender, formname, fields)
for _,p in ipairs(motor.elevators) do
local p = minetest.string_to_pos(p)
for _,object in ipairs(minetest.get_objects_inside_radius(p, 2)) do
- if object.is_player and object:is_player() and minetest.get_node(object:getpos()).name == "elevator:elevator_on" then
+ if object.is_player and object:is_player() then
if object:get_player_name() ~= obj:get_luaentity().attached then
- object:setpos(lastpp[sender:get_player_name()])
+ teleport_player_from_elevator(object)
end
end
end
@@ -582,6 +627,7 @@ local function detach(self, pos)
pl:setpos(p)
end, player, pos)
end
+ riding[self.attached] = nil
end
local box_entity = {
@@ -601,18 +647,12 @@ local box_entity = {
halfway = false,
vmult = 0,
- on_activate = function(self)
+ on_activate = function(self, staticdata)
self.object:set_armor_groups({immortal=1})
end,
on_step = function(self, dtime)
local pos = self.object:getpos()
- self.timer = (self.timer or 0) + dtime
- if self.timer > 5 and self.motor and self.target and self.attached and pos then
- self.object:remove()
- create_box(self.motor, pos, self.target, minetest.get_player_by_name(self.attached))
- return
- end
if boxes[self.motor] and boxes[self.motor] ~= self.object then
minetest.log("action", "[elevator] "..minetest.pos_to_string(pos).." broke due to duplication.")
self.object:remove()
@@ -667,6 +707,12 @@ local box_entity = {
end
end
end
+ self.timer = (self.timer or 0) + dtime
+ if self.timer > 5 and self.motor and self.target and self.attached and pos then
+ self.object:remove()
+ create_box(self.motor, pos, self.target, minetest.get_player_by_name(self.attached))
+ return
+ end
self.lastpos = pos
end,
}