-- 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
foreander spielt - Das Blog zum Film
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.
2015-05-18
Foreander in Felucca E66 - Schwarzpulver und fast eine Uhr - Minecraft Leben (Let's Play)
Manchmal hat man einfach nicht die Zeit, einen tiefen Schluck aus der Pulle zu nehmen. Zaubertränke sind eine feine Sache, aber im Eifer des Gefechts einfach zu langsam. Zum Glück kann man so gut wie alle Tränke auch als Splash Potions brauen, die man nur auf die Erde werfen muß.
Dabei verliert man zwar einiges an Wirkungszeit, die einfache Handhabung und der sofortige Effekt machen das aber durchaus wett. Außerdem kann man so die Tränke auch auf andere Spieler oder Mobs werfen, was zusätzliche Möglichkeiten eröffnet.
Ein Schalter, um Gunpowder (Schwarzpulver) hinzuzufügen ist nur eine kleine Änderung an meiner automatischen Brauerei. Ein wenig schiweriger stellt sich dann die Uhr heraus, mit der ich die automatische Extraktion aus dem Braustand steuern will.
Dabei verliert man zwar einiges an Wirkungszeit, die einfache Handhabung und der sofortige Effekt machen das aber durchaus wett. Außerdem kann man so die Tränke auch auf andere Spieler oder Mobs werfen, was zusätzliche Möglichkeiten eröffnet.
Ein Schalter, um Gunpowder (Schwarzpulver) hinzuzufügen ist nur eine kleine Änderung an meiner automatischen Brauerei. Ein wenig schiweriger stellt sich dann die Uhr heraus, mit der ich die automatische Extraktion aus dem Braustand steuern will.
2015-05-15
Foreander in Felucca E65 - Zutatenmixer - Minecraft Leben (Let's Play)
Die Auswahllogik für die verschiedenen Tränke funktioniert. Jetzt müssen die Zutaten auf eine Art zusammengebracht werden, die sicherstellt, das sie in der richtigen Reihenfolge im Brautisch landen. Außerdem fehlen noch Redstone und Glowstone für einige der Rezepte, ich will natürlich gleich die am längsten oder stärksten wirkenden Tränke brauen.
Eine lange Reihe von Trichtern verbindet die Dropper so, das am Ende alles in einen zentralen Brautisch münden kann und von dort später weiter transportiert werden kann.
Eine lange Reihe von Trichtern verbindet die Dropper so, das am Ende alles in einen zentralen Brautisch münden kann und von dort später weiter transportiert werden kann.
2015-05-14
Squishy the suicidal pig E04 - Sisyphus, der Vogeljäger :: Playthrough
Wenn man gerade denkt, so langsam kennt man die Steuerung und die Kniffe im Spiel, kommt so ein Level daher. Anstatt nach der Möglichkeit, sich umzubringen zu suchen, muß man in diesem Level am Leben bleiben. Ein Vogel hat den Schlüssel zum Tor, das die nächsten Level freischaltet.
Weil nichts in diesem Spiel einfach ist, muß man den Vogel erwischen, bevor er das Level-Ende erreicht. Klingt simpel, ist es aber beileibe nicht. Viele Fallen versperren den Weg und es kommt auf sehr exaktes Timing an. Kein Wunder, das ich hier ein wenig in Bedrängnis gerate.
Weil nichts in diesem Spiel einfach ist, muß man den Vogel erwischen, bevor er das Level-Ende erreicht. Klingt simpel, ist es aber beileibe nicht. Viele Fallen versperren den Weg und es kommt auf sehr exaktes Timing an. Kein Wunder, das ich hier ein wenig in Bedrängnis gerate.
2015-05-13
Foreander in Felucca E64 - Gatterlogik in kompakt - Minecraft Leben (Let's Play)
Für die Redstone-Schaltung an der automatischen Tränke-Brauerei brauche einige geschickt miteinander verschaltete Logik-Gatter. Um nicht allzu viel Platz zu verbrauchen, liegen die diversen Dropper nahe beieinander, auch das Signal aus dem Auswahlschalter ist auf engstem Raum konzentriert.
Mit einer großzügigen Portion Kletterei lassen sich diese Gatter und Verbindungen aber relativ einfach dreidimensional verteilen. So lange man aufpasst, das sich keine Signale kreuzen, bekommt man am Ende eine komfortable Achtfach-Schaltung, mit der sich alle gewünschten Tränke einstellen lassen.
Mit einer großzügigen Portion Kletterei lassen sich diese Gatter und Verbindungen aber relativ einfach dreidimensional verteilen. So lange man aufpasst, das sich keine Signale kreuzen, bekommt man am Ende eine komfortable Achtfach-Schaltung, mit der sich alle gewünschten Tränke einstellen lassen.
2015-05-12
Squishy the suicidal pig E03 - Schlüsseljagd :: Playthrough
Zur Abwechslung mal ein Level, in dem man ziemlich einfach sterben kann. Dummerweise werden hier die Regeln auf den Kopf gestellt und das Ziel ist es, lebendig durch den Level zu kommen.
Noch dazu muß man einen Vogel verfolgen, der einen Schlüssel trägt. Mit diesem Schlüssel kann man das Tor zu den folgenden Leveln aufschließen.
Noch dazu muß man einen Vogel verfolgen, der einen Schlüssel trägt. Mit diesem Schlüssel kann man das Tor zu den folgenden Leveln aufschließen.
2015-05-11
Foreander in Felucca E63 - Testaufbau Brauerei - Minecraft Leben
Eine meiner lange vor sich hin gärenden Ideen ist, eine automatische Braustation für die diversen Tränke, die man in Minecraft so braucht, zu bauen. In früheren Welten habe ich da die eine oder andere Brauerei gebaut, aber bis jetzt noch keine so richtig komfortable. Das soll sich jetzt ändern.
Neben dem Baumarkt ist reichlich Platz, so daß ich im Ausläufer der Wüste einen Testaufbau machen kann. Die zentrale Schaltstelle für diese automatische Brauerei soll ein Drehschalter sein, über den man auswählen kann, welche Tränke gebraut werden sollen.
Das ist schon ein wenig fortgeschrittene Redstone-Elektronik, deshalb baue ich die erste Version in Cobblestone. Ästhetik ist erst mal nicht so wichtig, Funktionalität ist Trumpf.
Neben dem Baumarkt ist reichlich Platz, so daß ich im Ausläufer der Wüste einen Testaufbau machen kann. Die zentrale Schaltstelle für diese automatische Brauerei soll ein Drehschalter sein, über den man auswählen kann, welche Tränke gebraut werden sollen.
Das ist schon ein wenig fortgeschrittene Redstone-Elektronik, deshalb baue ich die erste Version in Cobblestone. Ästhetik ist erst mal nicht so wichtig, Funktionalität ist Trumpf.
Abonnieren
Posts (Atom)