-- ticketer - a program to manage train destinations and print tickets-- You can see it in action on youtube.com/foreander -- -- Usage: Attach a train dispenser and a ticket machine to a computer, -- set the destinations and config variables below and run it. -- Enjoy your automatic train system. -- -- Version 4 -- -- Config variables below -- Label prefix for computer/ticket machine -- fahrtziele index of location will be added computer_label = "Fahrkartenautomat" -- numeric index for the "secret" maintenance menu maint_menu_nr = 99 -- table of destinations and other main menu entries fahrtziele = { [1] = "Spawn"; [2] = "1-Chunk-Basis"; [3] = "Trant0rs_Basis"; [4] = "Dunkler_Turm"; [5] = "Carthago"; [6] = "Baumhaus-Ruine"; [7] = "End-Portal"; [8] = "Keller_Spawn"; [9] = "Bergdorf"; [maint_menu_nr] = "Systemwartungsmenue" } -- table fahrtziele -- Note: Railcaft doesn't work with spaces in Destinations -- destination number of this ticketer's location num_here = 1 -- position of redstone connection redstone_cable = "top" -- time in seconds to display success messages success_timer = 5 -- default pattern for trains is one steam locomotive and -- one passenger cart, table keys use ["name"] field of -- inventory slots. set this to the same as the pattern -- in the train dispenser needed_carts = { ["cart.loco.steam.solid"] = 1; -- steam locomotive ["cart.loco.electric"] = 0; -- electric locomotive ["minecart"] = 1; -- (passenger) minecart ["chest_minecart"] = 0; -- chest minecart ["cart.tank"] = 0; -- tank cart ["cart.work"] = 0; -- work cart } -- table needed_carts -- display names for those needed carts -- I couldn't find a way to dynamically get them in game -- so hard coding them was the only way to get a nice display cart_names = { ["cart.loco.steam.solid"] = "Steam Locomotive"; ["cart.loco.electric"] = "Electrical Locomotive"; ["minecart"] = "Minecart"; ["chest_minecart"] = "Chest Minecart"; ["cart.tank"] = "Tank Cart"; ["cart.work"] = "Work Cart" } -- table cart_names -- End of config variables -- keeping track of which menu to display menu_mode = "main" -- automatically find and attach ticket printer and train dispenser ticket_printer = peripheral.find("openperipheral_ticketmachine") train_dispenser = peripheral.find("train_dispenser") -- set the computer's label os.setComputerLabel(computer_label.." ("..tostring(num_here)..")") -- displays and handles the main menu function main_menu() term.clear() print(" ***************") print(" FeluccaRail(tm)") print(" ***************") print("") -- check if enough carts and engines available if not check_train_dispenser_inventory() then print("") print("Fahrkartenausgabe eingestellt.") print("") end -- check if enough ink and paper in ticket_printer if not check_ticket_machine_inventory() then print("") print("Fahrkartenausgabe eingestellt.") print("") end print("Bitte Fahrtziel auswaehlen:") print("") for k,v in pairs(fahrtziele) do -- exclude the ticketer's location and the maintenance menu if k ~= num_here and k ~= maint_menu_nr then print(k .. " - " .. v) end end print("") io.write("Ziel: ") local ziel = tonumber(io.read()) print (" * Bearbeite Anfrage...") if ziel == maint_menu_nr then maintenance_menu() return -- this breaks out of main menu function early end if check_destination_validity(ziel) and check_train_dispenser_inventory(true) and check_ticket_machine_inventory(true) then if print_ticket(ziel) then start_train() success_screen("Zug nach " .. fahrtziele[ziel].. " faehrt in Kuerze ab.") end else error_screen("Ungueltiges Fahrtziel") end end -- function main_menu() -- displays and handles the maintenance menu function maintenance_menu() -- stay in maintenance menu until return to main is chosen menu_mode = "maint" term.clear() print(" *************") print(" Systemwartung") print(" *************") print("") print("Bitte Funktion auswaehlen:") print("") print("1 - Angeschlossene Peripherals") print("2 - Einstellungen anzeigen") if (ticket_printer) then print("3 - Inventar Ticket Printer") end if (train_dispenser) then print("4 - Inventar Train Dispenser (Display Names)") print("5 - Inventar Train Dispenser (Names)") end print("99 - Zurueck ins Hauptmenue") print("") io.write("Auswahl: ") local choice = tonumber(io.read()) if choice == 99 then menu_mode = "main" -- set menu back to main menu return elseif choice == 1 then list_peripherals() elseif choice == 2 then list_settings() elseif choice == 3 and (ticket_printer) then show_ticket_printer_inventory(true) elseif choice == 4 and (train_dispenser) then show_train_dispenser_inventory(true) elseif choice == 5 and (train_dispenser) then show_train_dispenser_inventory(false) end end -- function maintenance_menu -- list all connected peripherals function list_peripherals() term.clear() print("Angeschlossene Peripherals") print("") if ticket_printer then print("Aktiver Ticket Printer: "..ticket_printer.getInventoryName()) end if train_dispenser then print("Aktiver Train Dispenser: "..train_dispenser.getInventoryName()) end print("") local peris = peripheral.getNames() if not peris then print("Keine Peripherals vorhanden.") else print("Alle verfuegbaren Peripherals") print("Anschluss -> Geraet") for i = 1, #peris do print(peris[i].." -> "..peripheral.getType(peris[i])) end end wait_for_key() end -- function list_peripherals -- list all configurable settings function list_settings() term.clear() print("Einstellungen:") print("Standort: ("..num_here..") "..fahrtziele[num_here]) -- print("Anschluss Ticket Printer: "..ticket_printer_pos) print("Anschluss Redstone: "..redstone_cable) print("Anzeigedauer Erfolgsmeldung (s): "..tostring(success_timer)) wait_for_key() end -- function list_settings -- shows the ticket printers inventory -- use_display_names: boolean, if true show display names -- instead of internal names function show_ticket_printer_inventory(use_display_names) term.clear() print("Ticket Printer Inventar:") print("") print_inventory(ticket_printer.getAllStacks(), use_display_names) wait_for_key() end -- function show_ticket_printer_inventory -- shows the train dispensers inventory -- use_display_names: boolean, if true show display names -- instead of internal names function show_train_dispenser_inventory(use_display_names) term.clear() print("Train Dispenser Inventar:") print("") print_inventory(train_dispenser.getAllStacks(),use_display_names) wait_for_key() end -- function show_train_dispenser_inventory -- helper function to print a list of an inventory -- stacks: table, as returned from inventory.getAllStacks() -- use_display_names: boolean, if true show display names -- instead of internal names function print_inventory(stacks, use_display_names) for k,v in pairs(stacks) do io.write("Slot "..k.." -> ") local item = stacks[k].basic() if use_display_names then print(tostring(item["qty"]).."x "..item["display_name"]) else print(tostring(item["qty"]).."x "..item["name"]) end end end -- function print_inventory function success_screen(msg) -- prints a success message term.clear() print("") print(" ************") print(" Erfolgreich:") print(" ************") print("") print(msg) print("") os.sleep(success_timer) end -- function success_screen(msg) function error_screen(msg) -- prints an error message term.clear() print("") print(" *******") print(" Fehler:") print(" *******") print("") print(msg) wait_for_key() end -- function error_screen(msg) -- halts execution until user presses any key function wait_for_key() print("") print("Beliebige Taste druecken") while true do local evt = os.pullEvent("key") if evt == "key" then break end end end -- function wait_for_key -- checks if a given destination is valid function check_destination_validity(dest) if fahrtziele[dest] and dest ~= num_here then return true; else return false; end end -- function check_destination_validity(dest) function print_ticket(dest) -- print a ticket -- that's what error handling in lua looks like local status,err = pcall(ticket_printer.createTicket, fahrtziele[dest], 1) if not status then local error_msg = "Fehler beim Erzeugen des Tickets\n\n" if type(err) == "string" then -- cut out the unneccessary pcal prefix err = string.gsub(err,"pcall: ","") error_msg = error_msg .. err else -- api should alwas return string, just in case it doesn't error_msg = error_msg .. "Unbekannter Fehler" end error_screen(error_msg) return false else return true end end -- function print_ticket(dest) function start_train() -- put out redstone signal to assemble the train redstone.setOutput(redstone_cable,true) os.sleep(1) redstone.setOutput(redstone_cable,false) end -- functon start_train() -- check if train dispenser has enough carts and locomotives -- suppress_msg: boolean, if true no message will be printed function check_train_dispenser_inventory(suppress_msg) stacks = train_dispenser.getAllStacks() if not stacks then -- empty inventory if not suppress_msg then print ("Keine Carts oder Lokomotiven im Train Dispenser") end return false end -- get list of all available carts -- i.e. iterate over complete inventory and add up local available_carts = {} for k in pairs(stacks) do stack = stacks[k].basic() if available_carts[stack["name"]] then available_carts[stack["name"]] = available_carts[stack["name"]] + stack["qty"] else available_carts[stack["name"]] = stack["qty"] end end -- check if at least minimum of each needed cart is available local enough_carts = true for j,w in pairs(needed_carts) do if w > 0 and (not available_carts[j] or available_carts[j] < w) then enough_carts = false if not suppress_msg then print ("Nicht genuegend "..cart_names[j].." im Train Dispenser") end end end return enough_carts end -- function check_train_dispenser_inventory -- check if ticket machine has enough paper and ink -- suppress_msg: boolean, if true no message will be printed function check_ticket_machine_inventory(suppress_msg) stacks = ticket_printer.getAllStacks() local all_is_well = true if not stacks then -- empty inventory if not suppress_msg then print ("Weder Tinte noch Papier im Ticket Printer") end all_is_well = false end -- ticket printer has exactly two slots, one for paper (slot 1), -- one for ink (slot 2) if not stacks[1] then -- missing paper if not suppress_msg then print ("Kein Papier im Ticket Printer") end all_is_well = false end if not stacks[2] then -- missing ink if not suppress_msg then print ("Keine Tinte im Ticket Printer") end all_is_well = false end return all_is_well end -- function check_ticket_machine_inventory -- main loop while true do -- menu_mode determines which screen to display if menu_mode == "main" then main_menu() elseif menu_mode == "maint" then maintenance_menu() end end
Mitvierziger Gaming-Veteran mit Lets Play-Videos und gelegentlichem Livestream. Hauptsächlich Minecraft, zwischendurch aber auch Anderes. Hier gibt's Hintergrundinfos und Beschreibungen zu meinen Videos.
2016-02-18
Ticketer - Railcraft Tickets automatisch per ComputerCraft erstellen (Quellcode)
In der heutigen Episode habe ich versprochen, den Quelltext meines Fahrkartensystems hier zu veröffentlichen. Das System verwendet Railcraft, ComputerCraft und OpenPeripherals. Wie es genau zusammengebaut wird, zeige ich über mehrere Episoden verteilt in meiner Direwolf20-Minecraft-Serie.
Abonnieren
Posts (Atom)