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
This commit is contained in:
parent
deee7a747c
commit
bf31b4384e
@ -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)
|
||||
|
@ -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"},
|
||||
},
|
||||
})
|
||||
|
171
dbdkiosk.lua
Normal file
171
dbdkiosk.lua
Normal file
@ -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,
|
||||
})
|
@ -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 "")
|
||||
|
@ -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
|
||||
|
1
init.lua
1
init.lua
@ -9,6 +9,7 @@ local components = {
|
||||
"pilantern",
|
||||
"fs1switch",
|
||||
"dispatcher",
|
||||
"dbdkiosk",
|
||||
"decorations",
|
||||
"crafts",
|
||||
}
|
||||
|
BIN
textures/celevator_dbdkiosk.png
Normal file
BIN
textures/celevator_dbdkiosk.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 815 B |
Loading…
x
Reference in New Issue
Block a user