Thanks! Now it doesn't give me the error… but it doesn't call the cart or tell me one is coming. It shifts around the sensor cards but doesn't make the elevator work.
Spoiler
os.loadAPI("ocs/apis/sensor")
local theSensor = sensor.wrap("left")
rednet.open("right")
local config = dofile("elevator.config")
local floors = {}
local selectedFloor = 1
local cartDispenserId = nil
local lastError = nil
local expectingCart = false
local expectingArrival = false
local needCart = true
local gotCartResponse = false
local inUse = false
local inventorySlot = 1
local proximitySlot = 2
local function switchToInventorySensor()
if turtle.getItemCount(inventorySlot) > 0 then
turtle.select(16)
turtle.transferTo(proximitySlot)
turtle.select(inventorySlot)
turtle.transferTo(16)
end
end
local function switchToProximitySensor()
if turtle.getItemCount(proximitySlot) > 0 then
turtle.select(16)
turtle.transferTo(inventorySlot)
turtle.select(proximitySlot)
turtle.transferTo(16)
end
end
local function checkIfCart()
local rtn = false
local targetName = nil
switchToInventorySensor()
for name,target in pairs(theSensor.getTargets()) do
if target.type == "railcraft.common.blocks.machine.gamma.TileDispenserCart" then
targetName = name
break
end
end
if targetName then
local inventoryData = theSensor.getTargetDetails(targetName)
for slot, item in pairs(inventoryData) do
if item.Size > 0 then
rtn = true
break
end
end
end
return rtn
end
local function dispenseCart(floor)
if checkIfCart() then
expectingCart = true
rednet.send(cartDispenserId, textutils.serialize{type="elevator", sender="main", id=config.id, command="dispense"})
else
rednet.broadcast(textutils.serialize{type="elevator", sender="main", id=config.id, command="needCart"})
needCart = true
end
end
local function handleCancel()
inUse = false
needCart = false
gotCartResponse = false
expectingCart = false
expectingArrival = false
rs.setOutput("front", false)
lastError = nil
end
local function chooseFloor()
lastError = nil
if cartDispenserId then
if not expectingCart then
local floor = floors[selectedFloor]
dispenseCart(floor)
end
else
lastError = "Cannot find the cart dispenser!"
end
end
local function addFloor(message)
local found = false
for index, floor in ipairs(floors) do
if floor.id == message.id then
floors[index] = { id=message.id, shortcut = message.shortcut, description = message.description }
found = true
break
end
end
if not found then
table.insert(floors, { id=message.id, shortcut = message.shortcut, description = message.description })
end
table.sort(floors, function(a,B)/>/> return tonumber(a.id) < tonumber(b.id) end)
end
local function handleMain(senderId, message)
if message.command == "announce" then
rednet.send(senderId, textutils.serialize{type="elevator", sender = "main", id=config.id, command="ack", shortcut=config.shortcut, description=config.description})
addFloor(message)
elseif message.command == "ack" then
addFloor(message)
elseif message.command == "floorSelect" then
inUse = true
if message.floorId == config.id then
rs.setOutput("front", true)
expectingArrival = true
end
elseif message.command == "cancel" then
handleCancel()
elseif message.command == "gotCart" then
if needCart and not gotCartResponse then
gotCartResponse = true
expectingCart = true
rs.setOutput("front", true)
rednet.send(senderId, textutils.serialize{type="elevator", sender="main", id = config.id, command="sendCart"})
end
elseif message.command == "sendCart" then
rednet.send(cartDispenserId, textutils.serialize{type="elevator", sender="main", id=config.id, command="sendCart"})
elseif message.command == "needCart" then
if checkIfCart() then
rednet.send(senderId, textutils.serialize{type="elevator", sender="main", id=config.id, command="gotCart"})
end
end
end
local function handleDispenser(senderId, message)
if message.command == "announce" then
if message.id == config.id then
rednet.send(senderId, textutils.serialize{type="elevator", sender = "main", id=config.id, command="ack", shortcut=config.shortcut, description=config.description})
cartDispenserId = senderId
end
elseif message.command == "ack" then
cartDispenserId = senderId
end
end
local function doScan()
while true do
if expectingCart or expectingArrival then
switchToProximitySensor()
local targets = theSensor.getTargets()
for name, target in pairs(targets) do
if (target.Position.X == config.embarkedCoords.x) and (target.Position.Y == config.embarkedCoords.y) and (target.Position.Z == config.embarkedCoords.z) then
rs.setOutput("front", false)
if expectingCart then
inUse = true
rednet.broadcast(textutils.serialize{type="elevator", sender="main", id=config.id, command="floorSelect", floorId=floors[selectedFloor].id})
sleep(.5)
rednet.send(cartDispenserId, textutils.serialize{type="elevator", sender="main", id=config.id, command="launch"})
elseif expectingArrival then
inUse = false
rednet.broadcast(textutils.serialize{type="elevator", sender="main", id=config.id, command="cancel"})
rednet.send(cartDispenserId, textutils.serialize{type="elevator", sender="main", id=config.id, command="dispense"})
handleCancel()
end
expectingArrival = false
expectingCart = false
end
end
end
sleep(.1)
end
end
local function doNetwork()
print("Starting network...")
rednet.broadcast(textutils.serialize{type="elevator", sender = "main", id=config.id, command="announce", shortcut = config.shortcut, description=config.description })
while true do
local event, senderId, data, distance = os.pullEvent("rednet_message")
local message = textutils.unserialize(data)
if message and message.type == "elevator" then
if message.sender == "main" then
handleMain(senderId, message)
elseif message.sender == "dispenser" then
handleDispenser(senderId, message)
end
end
end
end
local function displayFloorSelection()
print("Floors available: ")
for index, floor in ipairs(floors) do
if index == selectedFloor then
print(string.format("[ %s: %s ]", floor.shortcut, floor.description))
else
print(string.format(" %s: %s ", floor.shortcut, floor.description))
end
end
end
local function displayCart()
if not needCart then
print("Your cart is ready!")
else
print("Use cart when arrives.")
end
end
local function displayInUse()
print("Cart system in use!")
end
local function displayNeedCart()
print("Waiting for cart...")
end
local function displayMenu()
term.clear()
term.setCursorPos(1,1)
if expectingCart then
displayCart()
elseif inUse then
displayInUse()
else
displayFloorSelection()
end
if lastError then print(lastError) end
print("Press Q to exit C to Cancel Request")
end
local function doMenu()
print("Displaying menu...")
while true do
sleep(1)
displayMenu()
end
end
local function doKeyboard()
print("Starting keyboard handler...")
while true do
local event, key = os.pullEvent()
if event == "char" then
if string.lower(key) == "q" then
break
elseif string.lower(key) == "c" then
rednet.broadcast(textutils.serialize{type="elevator", sender="main", id=config.id, command="cancel"})
handleCancel()
else
local keyToCompare = string.lower(key)
for index, floor in ipairs(floors) do
if keyToCompare == floor.shortcut then
selectedFloor = index
displayMenu()
chooseFloor()
break
end
end
end
elseif event == "key" then
if key == 200 then
if selectedFloor > 1 then -- up arrow
selectedFloor = selectedFloor - 1
displayMenu()
end
elseif key == 208 then
if selectedFloor < #floors then -- down arrow
selectedFloor = selectedFloor + 1
displayMenu()
end
elseif key == 28 then -- enter
chooseFloor()
end
end
end
end
local function startup()
term.clear()
term.setCursorPos(1,1)
return parallel.waitForAny(doNetwork, doKeyboard, doMenu, doScan)
end
local rtn, error = pcall(startup)
if not rtn then
print("Elevator failed: " .. error)
end
print("Exiting.")