summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcheapie <no-email-for-you@example.com>2024-05-31 23:26:37 -0500
committercheapie <no-email-for-you@example.com>2024-05-31 23:26:37 -0500
commitbf31b4384e9eb52288dc4c3d60d075843ecd6422 (patch)
tree282d3d500182d8afae8ab9905df42220345ab76f
parentdeee7a747c9d9c5fefb17dbb1914077bd3ec6a7d (diff)
downloadcelevator-bf31b4384e9eb52288dc4c3d60d075843ecd6422.tar
celevator-bf31b4384e9eb52288dc4c3d60d075843ecd6422.tar.gz
celevator-bf31b4384e9eb52288dc4c3d60d075843ecd6422.tar.bz2
celevator-bf31b4384e9eb52288dc4c3d60d075843ecd6422.tar.xz
celevator-bf31b4384e9eb52288dc4c3d60d075843ecd6422.zip
Add destination-based dispatching
Still uses a crude ETA algorithm for now and is missing some features, but it is working and usable at a basic level
-rw-r--r--controllerfw.lua4
-rw-r--r--crafts.lua9
-rw-r--r--dbdkiosk.lua171
-rw-r--r--dispatcher.lua3
-rw-r--r--dispatcherfw.lua67
-rw-r--r--init.lua1
-rw-r--r--textures/celevator_dbdkiosk.pngbin0 -> 815 bytes
7 files changed, 254 insertions, 1 deletions
diff --git a/controllerfw.lua b/controllerfw.lua
index 26aabf2..3392179 100644
--- a/controllerfw.lua
+++ b/controllerfw.lua
@@ -734,6 +734,10 @@ elseif event.type == "dispatchermsg" then
mem.groupupcalls[event.msg] = nil
elseif event.channel == "groupdncancel" then
mem.groupdncalls[event.msg] = nil
+ elseif event.channel == "swingupcall" and mem.carstate == "normal" then
+ mem.swingupcalls[event.msg] = true
+ elseif event.channel == "swingdncall" and mem.carstate == "normal" then
+ mem.swingdncalls[event.msg] = true
elseif event.channel == "carcall" and mem.carstate == "normal" then
mem.carcalls[event.msg] = true
send(event.source,"status",mem)
diff --git a/crafts.lua b/crafts.lua
index dd4b796..fd4390d 100644
--- a/crafts.lua
+++ b/crafts.lua
@@ -287,3 +287,12 @@ minetest.register_craft({
"basic_materials:steel_strip",
},
})
+
+minetest.register_craft({
+ output = "celevator:dbdkiosk",
+ recipe = {
+ {"basic_materials:steel_strip","basic_materials:ic","default:glass"},
+ {"basic_materials:steel_strip","mesecons_lightstone:lightstone_white_off","default:glass"},
+ {"basic_materials:steel_strip","","default:glass"},
+ },
+})
diff --git a/dbdkiosk.lua b/dbdkiosk.lua
new file mode 100644
index 0000000..7f5996f
--- /dev/null
+++ b/dbdkiosk.lua
@@ -0,0 +1,171 @@
+celevator.dbdkiosk = {}
+
+function celevator.dbdkiosk.checkprot(pos,name)
+ if minetest.is_protected(pos,name) and not minetest.check_player_privs(name,{protection_bypass=true}) then
+ minetest.chat_send_player(name,"Can't open cabinet - cabinet is locked.")
+ minetest.record_protection_violation(pos,name)
+ return false
+ end
+ return true
+end
+
+function celevator.dbdkiosk.updatefields(pos)
+ if minetest.get_node(pos).name ~= "celevator:dbdkiosk" then return end
+ local meta = minetest.get_meta(pos)
+ local screenstate = meta:get_string("screenstate")
+ if screenstate == "connect" then
+ meta:set_string("formspec","formspec_version[7]size[8,5]field[0.5,0.5;7,1;carid;Dispatcher ID;]field[0.5,2;7,1;landing;Landing Number;]button[3,3.5;2,1;save;Save]")
+ elseif screenstate == "main" then
+ local landing = meta:get_int("landing")
+ local fs = "formspec_version[7]"
+ fs = fs.."size[8,14]"
+ fs = fs.."label[3,0.5;Please select a floor\\:]"
+ local floornames = minetest.deserialize(meta:get_string("floornames"))
+ local floorsavailable = minetest.deserialize(meta:get_string("floorsavailable"))
+ local showfloors = {}
+ for i=1,#floornames,1 do
+ if floorsavailable[i] then
+ table.insert(showfloors,i)
+ end
+ end
+ local startfloor = (meta:get_int("screenpage")-1)*10+1
+ for i=1,10,1 do
+ local floornum = showfloors[startfloor+i-1]
+ local floorname = floornum and floornames[floornum]
+ if floorname and floornum ~= landing then
+ fs = fs..string.format("button[2,%f;4,1;floor%d;%s]",12-i,floornum,minetest.formspec_escape(floorname))
+ end
+ end
+ if startfloor > 1 then
+ fs = fs.."button[3.75,12.2;0.8,0.8;scrolldown;vvv]"
+ end
+ if startfloor+9 < #showfloors then
+ fs = fs.."button[3.75,1;0.8,0.8;scrollup;^^^]"
+ end
+ meta:set_string("formspec",fs)
+ elseif screenstate == "assignment" then
+ local fs = "formspec_version[7]"
+ fs = fs.."size[8,14]"
+ fs = fs.."label[3,3;Please use elevator]"
+ fs = fs.."style_type[label;font_size=*4]"
+ fs = fs.."label[3.5,5;"..meta:get_string("assignedcar").."]"
+ meta:set_string("formspec",fs)
+ elseif screenstate == "error" then
+ local fs = "formspec_version[7]"
+ fs = fs.."size[8,14]"
+ fs = fs.."label[3.5,0.5;ERROR]"
+ fs = fs.."label[2.5,3;Could not find a suitable elevator]"
+ fs = fs.."label[2.5,3.5;Please try again later]"
+ meta:set_string("formspec",fs)
+ end
+end
+
+function celevator.dbdkiosk.handlefields(pos,_,fields,player)
+ local name = player:get_player_name()
+ local meta = minetest.get_meta(pos)
+ local screenstate = meta:get_string("screenstate")
+ if screenstate == "connect" then
+ if not (fields.save and celevator.dbdkiosk.checkprot(pos,name)) then return end
+ if not (tonumber(fields.carid) and tonumber(fields.landing)) then return end
+ local carinfo = minetest.deserialize(celevator.storage:get_string(string.format("car%d",fields.carid)))
+ if not carinfo then return end
+ if not (carinfo.dispatcherpos and celevator.dispatcher.isdispatcher(carinfo.dispatcherpos)) then return end
+ local dmem = minetest.deserialize(minetest.get_meta(carinfo.dispatcherpos):get_string("mem"))
+ if not dmem then return end
+ local floornames = dmem.params.floornames
+ local floorsavailable = {}
+ for i=1,#floornames,1 do
+ floorsavailable[i] = true
+ end
+ meta:set_string("floornames",minetest.serialize(floornames))
+ meta:set_string("floorsavailable",minetest.serialize(floorsavailable))
+ meta:set_int("screenpage",1)
+ meta:set_string("screenstate","main")
+ meta:set_int("carid",tonumber(fields.carid))
+ meta:set_int("landing",tonumber(fields.landing))
+ celevator.dbdkiosk.updatefields(pos)
+ elseif screenstate == "main" then
+ for k,v in pairs(fields) do
+ if v and string.sub(k,1,5) == "floor" then
+ local floor = tonumber(string.sub(k,6,-1))
+ if not floor then return end
+ local carid = meta:get_int("carid")
+ local carinfo = minetest.deserialize(celevator.storage:get_string(string.format("car%d",carid)))
+ if not carinfo then return end
+ if not (carinfo.dispatcherpos and celevator.dispatcher.isdispatcher(carinfo.dispatcherpos)) then return end
+ local dmem = minetest.deserialize(minetest.get_meta(carinfo.dispatcherpos):get_string("mem"))
+ if dmem then
+ local floornames = dmem.params.floornames
+ meta:set_string("floornames",minetest.serialize(floornames))
+ end
+ local event = {
+ type = "dbdkiosk",
+ source = minetest.hash_node_position(pos),
+ player = name,
+ srcfloor = meta:get_int("landing"),
+ destfloor = floor,
+ }
+ celevator.dispatcher.run(carinfo.dispatcherpos,event)
+ end
+ end
+ if fields.scrollup then
+ local page = meta:get_int("screenpage")
+ meta:set_int("screenpage",page+1)
+ elseif fields.scrolldown then
+ local page = meta:get_int("screenpage")
+ meta:set_int("screenpage",math.max(1,page-1))
+ end
+ celevator.dbdkiosk.updatefields(pos)
+ elseif screenstate == "assignment" or screenstate == "error" then
+ meta:set_string("screenstate","main")
+ celevator.dbdkiosk.updatefields(pos)
+ end
+end
+
+function celevator.dbdkiosk.showassignment(pos,assignment)
+ local meta = minetest.get_meta(pos)
+ if meta:get_string("screenstate") == "main" then
+ local carnames = {"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P"}
+ if carnames[assignment] then
+ meta:set_string("screenstate","assignment")
+ meta:set_string("assignedcar",carnames[assignment])
+ else
+ meta:set_string("screenstate","error")
+ end
+ celevator.dbdkiosk.updatefields(pos)
+ minetest.after(5,function()
+ meta:set_string("screenstate","main")
+ celevator.dbdkiosk.updatefields(pos)
+ end)
+ end
+end
+
+minetest.register_node("celevator:dbdkiosk",{
+ description = "Elevator Destination Entry Kiosk",
+ drawtype = "nodebox",
+ paramtype = "light",
+ paramtype2 = "4dir",
+ groups = {
+ cracky = 1,
+ },
+ node_box = {
+ type = "fixed",
+ fixed = {
+ {-0.2,-0.5,0.4,0.2,0.1,0.5},
+ },
+ },
+ tiles = {
+ "celevator_cabinet_sides.png",
+ "celevator_cabinet_sides.png",
+ "celevator_cabinet_sides.png",
+ "celevator_cabinet_sides.png",
+ "celevator_cabinet_sides.png",
+ "celevator_cabinet_sides.png^celevator_dbdkiosk.png",
+ },
+ on_construct = function(pos)
+ local meta = minetest.get_meta(pos)
+ meta:set_string("screenstate","connect")
+ celevator.dbdkiosk.updatefields(pos)
+ end,
+ on_receive_fields = celevator.dbdkiosk.handlefields,
+})
diff --git a/dispatcher.lua b/dispatcher.lua
index b58c6eb..a8bcf1c 100644
--- a/dispatcher.lua
+++ b/dispatcher.lua
@@ -345,6 +345,9 @@ function celevator.dispatcher.finish(pos,mem,changedinterrupts)
})
end
end
+ for _,message in ipairs(mem.kioskmessages) do
+ celevator.dbdkiosk.showassignment(minetest.get_position_from_hash(message.pos),message.car)
+ end
meta:set_string("mem",minetest.serialize(mem))
if node.name == "celevator:dispatcher_open" then meta:set_string("formspec",mem.formspec or "") end
meta:set_string("formspec_hidden",mem.formspec or "")
diff --git a/dispatcherfw.lua b/dispatcherfw.lua
index 318a69d..6489944 100644
--- a/dispatcherfw.lua
+++ b/dispatcherfw.lua
@@ -8,7 +8,9 @@ local function interrupt(time,iid)
end
mem.messages = {}
+mem.kioskmessages = {}
if not mem.powerstate then mem.powerstate = "awake" end
+if not mem.dbdcalls then mem.dbdcalls = {} end
local function getpos(carid)
local floormap = {}
@@ -98,6 +100,14 @@ local function send(carid,channel,message)
})
end
+local function kiosksend(kioskpos,carnum)
+ table.insert(mem.kioskmessages,{
+ pos = kioskpos,
+ type = "assigned",
+ car = carnum,
+ })
+end
+
local function getnextcallabove(carid,dir,startpos,carcalls,upcalls,dncalls)
for i=(startpos or getpos(carid)),#mem.params.floorheights,1 do
if not dir then
@@ -299,6 +309,7 @@ if event.type == "program" then
mem.assigneddn = {}
mem.upeta = {}
mem.dneta = {}
+ mem.dbdcalls = {}
if not mem.params then
mem.params = {
carids = {},
@@ -750,7 +761,48 @@ elseif event.type == "abm" or event.type == "remotewake" or (event.iid == "run"
for floor,carid in pairs(mem.assigneddn) do
mem.dneta[floor] = calculateeta(carid,floor,"down")
end
- if busy or event.type == "remotewake" then
+ for k,call in ipairs(mem.dbdcalls) do
+ if call.assigned then
+ local carstate = mem.carstatus[call.assigned].state
+ local doorstate = mem.carstatus[call.assigned].doorstate
+ local direction = mem.carstatus[call.assigned].direction
+ local desireddir = (call.srcfloor < call.destfloor and "up" or "down")
+ if direction == desireddir and doorstate ~= "closed" then
+ if carstate == "normal" then send(call.assigned,"carcall",realtocarfloor(call.assigned,call.destfloor)) end
+ table.remove(mem.dbdcalls,k)
+ end
+ else
+ local direction = (call.srcfloor < call.destfloor and "up" or "down")
+ local eligiblecars = {}
+ local revcarids = {}
+ for carnum,carid in pairs(mem.params.carids) do
+ if mem.carstatus[carid].state == "normal" and mem.params.floorsserved[carid][call.srcfloor] and mem.params.floorsserved[carid][call.destfloor] then
+ table.insert(eligiblecars,carid)
+ end
+ revcarids[carid] = carnum
+ end
+ local besteta = 999
+ local bestcar
+ if #eligiblecars > 0 then
+ for _,carid in pairs(eligiblecars) do
+ local eta = calculateeta(carid,call.srcfloor,direction)
+ if eta < besteta then
+ besteta = eta
+ bestcar = carid
+ end
+ end
+ end
+ if bestcar then
+ call.assigned = bestcar
+ send(bestcar,(direction == "up" and "swingupcall" or "swingdncall"),realtocarfloor(bestcar,call.srcfloor))
+ kiosksend(call.kioskpos,revcarids[bestcar])
+ else
+ table.remove(mem.dbdcalls,k)
+ kiosksend(call.kioskpos,-1)
+ end
+ end
+ end
+ if busy or event.type == "remotewake" or #mem.dbdcalls > 0 then
mem.powerstate = "awake"
interrupt(nil,"sleep")
interrupt(1,"run")
@@ -809,6 +861,19 @@ elseif event.type == "remotemsg" then
send(mem.params.carids[event.car],"carcall",event.floor)
end
end
+elseif event.type == "dbdkiosk" then
+ if mem.powerstate == "asleep" then
+ mem.powerstate = "awake"
+ interrupt(0,"getstatus")
+ interrupt(1,"run")
+ elseif mem.powerstate == "timing" then
+ mem.powerstate = "awake"
+ end
+ table.insert(mem.dbdcalls,{
+ srcfloor = event.srcfloor,
+ destfloor = event.destfloor,
+ kioskpos = event.source,
+ })
end
if not (mem.screenstate == "status" or mem.screenstate == "menu") then
diff --git a/init.lua b/init.lua
index 9b794e9..7cc2a30 100644
--- a/init.lua
+++ b/init.lua
@@ -9,6 +9,7 @@ local components = {
"pilantern",
"fs1switch",
"dispatcher",
+ "dbdkiosk",
"decorations",
"crafts",
}
diff --git a/textures/celevator_dbdkiosk.png b/textures/celevator_dbdkiosk.png
new file mode 100644
index 0000000..87b64a7
--- /dev/null
+++ b/textures/celevator_dbdkiosk.png
Binary files differ