summaryrefslogtreecommitdiff
path: root/drive_null.lua
diff options
context:
space:
mode:
Diffstat (limited to 'drive_null.lua')
-rw-r--r--drive_null.lua206
1 files changed, 206 insertions, 0 deletions
diff --git a/drive_null.lua b/drive_null.lua
new file mode 100644
index 0000000..17ed649
--- /dev/null
+++ b/drive_null.lua
@@ -0,0 +1,206 @@
+celevator.drives.null = {
+ name = "Null Drive",
+ description = "Simulation only, no movement, for testing and demonstration",
+ nname = "celevator:drive_null",
+ soundhandles = {},
+}
+
+local function update_ui(pos)
+ local meta = minetest.get_meta(pos)
+ local apos = tonumber(meta:get_string("apos")) or 0
+ local status = "Idle"
+ local vel = tonumber(meta:get_string("vel")) or 0
+ if vel > 0 then
+ status = string.format("Running: Up, %0.02f m/s",vel)
+ elseif vel < 0 then
+ status = string.format("Running: Down, %0.02f m/s",math.abs(vel))
+ end
+ meta:set_string("infotext",string.format("Null Drive - %s - Position: %0.02f m",status,apos))
+end
+
+local function playbuzz(pos)
+ local hash = minetest.hash_node_position(pos)
+ if celevator.drives.null.soundhandles[hash] == "cancel" then return end
+ celevator.drives.null.soundhandles[hash] = minetest.sound_play("celevator_drive_run",{
+ pos = pos,
+ loop = true,
+ gain = 0.4,
+ })
+end
+
+local function startbuzz(pos)
+ local hash = minetest.hash_node_position(pos)
+ if celevator.drives.null.soundhandles[hash] == "cancel" then
+ celevator.drives.null.soundhandles[hash] = nil
+ return
+ end
+ if celevator.drives.null.soundhandles[hash] then return end
+ celevator.drives.null.soundhandles[hash] = "pending"
+ minetest.after(0.5,playbuzz,pos)
+end
+
+local function stopbuzz(pos)
+ local hash = minetest.hash_node_position(pos)
+ if not celevator.drives.null.soundhandles[hash] then return end
+ if celevator.drives.null.soundhandles[hash] == "pending" then
+ celevator.drives.null.soundhandles[hash] = "cancel"
+ end
+ if type(celevator.drives.null.soundhandles[hash]) ~= "string" then
+ minetest.sound_stop(celevator.drives.null.soundhandles[hash])
+ celevator.drives.null.soundhandles[hash] = nil
+ end
+end
+
+minetest.register_node("celevator:drive_null",{
+ description = celevator.drives.null.name,
+ groups = {
+ cracky = 1,
+ },
+ tiles = {
+ "celevator_cabinet_sides.png",
+ "celevator_cabinet_sides.png",
+ "celevator_cabinet_sides.png",
+ "celevator_cabinet_sides.png",
+ "celevator_cabinet_sides.png",
+ "celevator_drive_front.png",
+ },
+ paramtype = "light",
+ paramtype2 = "facedir",
+ drawtype = "nodebox",
+ node_box = {
+ type = "fixed",
+ fixed = {
+ {-0.4,-0.4,-0.1,0.4,0.4,0.5},
+ {-0.5,-0.3,0.4,-0.4,-0.22,0.32},
+ {-0.5,0.22,0.4,-0.4,0.3,0.32},
+ },
+ },
+ _celevator_drive_type = "null",
+ after_place_node = function(pos)
+ local meta = minetest.get_meta(pos)
+ meta:set_string("apos","0")
+ meta:set_string("dpos","0")
+ meta:set_string("vel","0")
+ meta:set_string("maxvel","0.2")
+ update_ui(pos)
+ end,
+ on_destruct = stopbuzz,
+})
+
+function celevator.drives.null.step(dtime)
+ local nulldrives_running = minetest.deserialize(celevator.storage:get_string("nulldrives_running")) or {}
+ local save = false
+ for i,hash in ipairs(nulldrives_running) do
+ save = true
+ local pos = minetest.get_position_from_hash(hash)
+ local node = minetest.get_node(pos)
+ local sound = false
+ if node.name == "ignore" then
+ minetest.forceload_block(pos,true)
+ elseif node.name ~= "celevator:drive_null" then
+ table.remove(nulldrives_running,i)
+ else
+ local meta = minetest.get_meta(pos)
+ local apos = tonumber(meta:get_string("apos")) or 0
+ local dpos = tonumber(meta:get_string("dpos")) or 0
+ local maxvel = tonumber(meta:get_string("maxvel")) or 0.2
+ local dremain = math.abs(dpos-apos)
+ local vel = maxvel
+ if dremain < 0.5 then vel = math.min(0.2,vel) end
+ local stepdist = vel*dtime
+ if dpos > apos then
+ local newpos = apos + stepdist
+ if newpos < dpos then
+ meta:set_string("apos",tostring(newpos))
+ meta:set_string("vel",vel)
+ sound = true
+ else
+ meta:set_string("apos",tostring(dpos))
+ meta:set_string("vel",0)
+ sound = false
+ end
+ elseif dpos < apos then
+ local newpos = apos - stepdist
+ if newpos > dpos then
+ meta:set_string("apos",tostring(newpos))
+ meta:set_string("vel",0-vel)
+ sound = true
+ else
+ meta:set_string("apos",tostring(dpos))
+ meta:set_string("vel",0)
+ sound = false
+ end
+ else
+ table.remove(nulldrives_running,i)
+ end
+ end
+ update_ui(pos)
+ if sound then
+ startbuzz(pos)
+ else
+ stopbuzz(pos)
+ end
+ end
+ if save then
+ celevator.storage:set_string("nulldrives_running",minetest.serialize(nulldrives_running))
+ end
+end
+
+minetest.register_globalstep(celevator.drives.null.step)
+
+function celevator.drives.null.moveto(pos,target)
+ local meta = minetest.get_meta(pos)
+ meta:set_string("dpos",tostring(target))
+ local hash = minetest.hash_node_position(pos)
+ local nulldrives_running = minetest.deserialize(celevator.storage:get_string("nulldrives_running")) or {}
+ local running = false
+ for _,dhash in ipairs(nulldrives_running) do
+ if hash == dhash then
+ running = true
+ break
+ end
+ end
+ if not running then
+ table.insert(nulldrives_running,hash)
+ celevator.storage:set_string("nulldrives_running",minetest.serialize(nulldrives_running))
+ end
+end
+
+function celevator.drives.null.resetpos(pos)
+ celevator.drives.null.moveto(pos,0)
+end
+
+function celevator.drives.null.estop(pos)
+ local meta = minetest.get_meta(pos)
+ meta:set_string("dpos",meta:get_string("apos"))
+ meta:set_string("vel","0")
+end
+
+function celevator.drives.null.setmaxvel(pos,maxvel)
+ local meta = minetest.get_meta(pos)
+ meta:set_string("maxvel",tostring(maxvel))
+end
+
+function celevator.drives.null.rezero(pos)
+ celevator.drives.null.moveto(pos,0)
+end
+
+function celevator.drives.null.getstatus(pos,call2)
+ local node = minetest.get_node(pos)
+ if node.name == "ignore" and not call2 then
+ minetest.forceload_block(pos,true)
+ return celevator.drives.null.get_status(pos,true)
+ elseif node.name ~= "celevator:drive_null" then
+ minetest.log("error","[celevator] [null drive] Could not load drive status at "..minetest.pos_to_string(pos))
+ return
+ else
+ local meta = minetest.get_meta(pos)
+ local ret = {}
+ ret.apos = tonumber(meta:get_string("apos")) or 0
+ ret.dpos = tonumber(meta:get_string("dpos")) or 0
+ ret.vel = tonumber(meta:get_string("vel")) or 0
+ ret.maxvel = tonumber(meta:get_string("maxvel")) or 0.2
+ ret.neareststop = ret.apos
+ return ret
+ end
+end