This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
theblackhatman's profile picture

Easier ways to create menus and call functions

Started by theblackhatman, 05 May 2012 - 09:55 PM
theblackhatman #1
Posted 05 May 2012 - 11:55 PM
Hello all,

I've recently picked up computercraft, and am working on a networked server login for a base that I've built. I have to be able to have several functions, such as locking down certain parts of the base, opening them back up, etc. The way I'm going about this is using wireless redstone mod along with computercraft, and I have one main room with the wireless redstone blocks stored with computers, for activation purposes. However, my coding is iffy. (I've picked it up pretty quick, but still.. : /) Here's the piece I'm currently working on (Not all parts are finished yet, will edit post when finished).
Any input on how to clean up the functions, rednet functions, etc?
Specifically, What I'm working on is having two options to start: Local login and Network Login. The local login would check variables stored on the computer against input variables for username/password combination. The networked login would save the read user/pass as var1 and var2 (That section isn't written in yet) then send them 1 at a time to the server with code to receive those variables. It would then check them against variables stored on the server and reply, either with Approved or Denied. the computer would wait for this response with a timeout, and if it didn't receive it in time or if the login failed, it would display such and give a chance to go back to the main menu. (To attempt another login). My questions are as such: How do I speed up the functions/ Clean up the code, and how do I make sure that the authentication reaches the server and then the server replies only to the computer who sent the authentication request?


************EDIT************************** (New code as I've continued working and implementing suggestions)
Just to explain a few more things, the random write("XX%") that are not part of functions are just indicators for me when running the program that everything is running smoothly. Other than that, I implemented the os.pullEvent() suggestion made. I should have a server copy posted by the end of tonight or tomorrow.

term.clear()
term.setCursorPos(1,1)
print("Defining Functions. Please Standby.")
write("0%")

function MainScreen()
term.clear()
term.setCursorPos(1,1)
print("This console has been locked by an Administrator.")
print("Please choose from the following options:")
print("1: Local Login.")
print("2: Network Login.")
print("Please Select the number for the option chosen.")
r = os.pullEvent("char")
if r == ("1") then
LocalLogin()
elseif r == ("2")
NetworkLogin()
end
end

term.clear()
term.setCursorPos(1,1)
write("10%")

function LocalLogin()
term.clear()
term.setCursorPos(1,1)
print("This console has been locked by an administrator.")
print("Please input your credentials.")
print("Username: ")
var1 = read()
print("Password: ")
var2 = read()
if var1 == ("LocalAdmin") and var2 ==("AdminBypass") then
LocalAccepted()
else
LoginFailed()
end
end

term.clear()
term.setCursorPos(1,1)
write("20%")

function LocalAccepted()
var0 = ("0")
print("Local login accepted. Some features have been disabled.")
print("Please choose from the following options: ")
print("1: Initiate Tunnel Lockdown Procedure.")
print("2: Initiate Tunnel Release Procedure.")
print("3: Log Out.")
print("4: Shutdown.")
print("Please enter the number of the chosen option.")
r = os.pullEvent("char")
if r == ("1") then
Close()
elseif r == ("2")
Open()
elseif r == ("3")
MainScreen()
elseif r == ("4")
Shutdown()
end
end

term.clear()
term.setCursorPos(1,1)
write("30%")

function NetworkLogin()
term.clear()
term.setCursorPos(1,1)
print("Please input your credentials for network login.")
print("Username: ")
var1 = read()
print("Password: ")
var2 = read()
rednet.open("top")
rednet.send(13, var1)
message = rednet.receive()
if message == ("Continue") then
rednet.send(13, var2)
else
LoginFailed()
end
message = rednet.receive()
if message == ("Approved") then
Menu()
else
LoginFailed()
end
end

term.clear()
term.setCursorPos(1,1)
write("40%")

function LoginFailed()
term.clear()
term.setCursorPos(1,1)
print("Login Failed. Try Again? Y/N")
r = os.pullEvent("char")
if r == ("y") then
MainScreen()
elseif r == ("n")
Shutdown()
end
end

term.clear()
term.setCursorPos(1,1)
write("50%")

function LogOut()
term.clear()
term.setCursorPos(1,1)
textutils.slowWrite("Initiating console lock sequence. stand by.")
sleep(3)
MainScreen()
end

term.clear()
term.setCursorPos(1,1)
write("60%")

function Menu()
term.clear()
term.setCursorPos(1,1)
var0 = ("1")
print("Network Login Accepted. Please choose from the following Options.")
print("1: Initiate Tunnel Lockdown Procedure.")
print("2: Initiate Tunnel Release Procedure.")
print("3: Broadcast alert sequence.")
print("4: shutdown alert sequence.")
print("5: Log Out.")
print("6: Shutdown.")
r = os.pullEvent("char")
if r == ("1") then
Close()
elseif r == ("2") then
Open()
elseif r == ("5") then
LogOut()
elseif r == ("6") then
Shutdown()
end
end

term.clear()
term.setCursorPos(1,1)
write("70%")

function Open()
textutils.slowPrint("Sending release codes. Stand by.")
rednet.open("top")
rednet.send(##, "open")
rednet.close("top")
if var0 = ("0") then
LocalAccepted()
elseif var0 = ("1") then
Menu()
end
end

term.clear()
term.setCursorPos(1,1)
write("80%")

function Close()
textutils.slowPrint("Sending lockdown code. Stand by.")
rednet.open("top")
rednet.send(##, "Close")
rednet.close("top")
if var0 = ("0") then
LocalAccepted()
elseif var0 = ("1") then
Menu()
end
end

term.clear()
term.setCursorPos(1,1)
write("90%")

function Shutdown()
term.clear()
term.setCursorPos(1,1)
textutils.slowPrint("Shutting down Operating System…")
sleep(1)
os.shutdown()
end

term.clear()
term.setCursorPos(1,1)
write("100%")
sleep(2)
MainScreen()
BigSHinyToys #2
Posted 06 May 2012 - 01:17 AM
http://pastebin.com/qXHFAtkf

New ver
http://pastebin.com/iHX19J5Y

this is a function it will return a number for witch of the options is selected.
how to make it call a function

local var = menu()
if var == 1 then
nameOfFunctionHere()
elseif var == 2 then
nameOfFunctionHere()
elseif var == 3 then
nameOfFunctionHere()
end
Noodle #3
Posted 06 May 2012 - 02:47 AM
Easier way
Do this!

function menu(id, text)
if x == id then
write (">>".. text)
else
write ("  ".. text)
end
function mainScreen()
menu(0, "Install")
end
while true do
event, key = os.pullEvent()
if event == "key" then
if key == 200 and x > 0 then
x = x - 1
mainScreen()
elseif key == 208 and x < (MAX NUMBER OF IDS) then -- The max number of ids you use for menu
x = x + 1
mainScreen()
else
mainScreen()
end
end
end
You add an enter key press then if x == 0 or x == 1 then
do whatever.
Edited on 06 May 2012 - 12:48 AM
Onionnion #4
Posted 06 May 2012 - 03:00 AM
Personally, for any type of menu usage, I'd use os.pullEvent("char").
BigSHinyToys #5
Posted 06 May 2012 - 03:07 AM
Easier way
Do this!
– sniped code –
You add an enter key press then if x == 0 or x == 1 then
do whatever.

any chance you could make a demo for that I'm not quite getting how this makes a menu??
Luanub #6
Posted 06 May 2012 - 03:41 AM
Easier way
Do this!
– sniped code –
You add an enter key press then if x == 0 or x == 1 then
do whatever.

any chance you could make a demo for that I'm not quite getting how this makes a menu??

He pretty much has its a basic cursor based menu very similar to the one listed in the tutorial. The only thing he is missing is to detect when the enter key is pressed and the execution of what was selected.

You could also use a couple of tables instead of the print commands to do it using the same method.

I'll get a demo put together here real quick and add it.

Here ya go, not tested of coarse as there is no code entered for the actions, but if you insert some it should work.

local option = {}
option[1] = Install
option[2] = Exit

local actions = {}
actions[1] = function()
print ("insert install coding")
end

actions[2] = function()
print ("insert exit coding")
end

function drawCursor()
term.setCursorPos(1, currentY)
write "->"
end

local currentY = 1
local select = 1

function printMenu()
while true do
shell.run("clear")
local num = table.maxn(option)
a = 1
for x=1, num do
print ("  "..option[a])
a = a + 1
end
drawCursor()
event, key = os.pullEvent()
if event == "key" then
if key == 200 and currentY > 1 then
currentY = currentY - 1
select = select -1
elseif key == 208 and currentY < num
currentY = currentY + 1
select = select + 1
elseif key == 28 then
actions[select]()
end
end
end
end

printMenu()
Edited on 06 May 2012 - 02:17 AM
BigSHinyToys #7
Posted 06 May 2012 - 04:03 AM
error


bios:206: [string "noodel"]:7: '=' expected
bios:206: [string "noodel"]:37: unexpected symbol
Luanub #8
Posted 06 May 2012 - 04:06 AM
Yeah I had some errors, it should be fixed.
BigSHinyToys #9
Posted 06 May 2012 - 04:14 AM
that code keeps erroring you should test it before posting. that goes for Noodle too
Luanub #10
Posted 06 May 2012 - 04:16 AM
Are you replacing the insert code here with code or leaving it as is? It will fail as is. I replaced the insert code with a print function to remind you…

It will work if you use it right….
BigSHinyToys #11
Posted 06 May 2012 - 04:19 AM
bios:206: [string "noodel"]:38: 'then' expected

and yes i was swaping them out for prints
Luanub #12
Posted 06 May 2012 - 04:22 AM
I suggest reading this if you dont understand how it works: http://www.computercraft.info/forums2/index.php?/topic/744-a-quick-guide-through-menu-making/


I missed an end for an extra if statement that I normally don't use as I filter my events. It should be added and correct now.
BigSHinyToys #13
Posted 06 May 2012 - 04:34 AM
1) On line 37 there needs to bve a then
2) options need to be strings so "" is required.
3) lines 25 to 30 could be replaced with

for x = 1 , #option do
print ("  "..option[x])
end

4) line 40 should be
return actions[select]()

code testing ensures quality. also i know how to make a menu look at my code posted above. it is cleaner more understandable and simpler to use

Spoiler

local option = {}
option[1] = "Install"
option[2] = "Exit"
local actions = {}
actions[1] = function()
print ("insert install coding")
end
actions[2] = function()
print ("insert exit coding")
end
local currentY = 1
local select = 1
function drawCursor()
term.setCursorPos(1, currentY)
write "->"
end
function printMenu()
while true do
shell.run("clear")
local num = table.maxn(option)
a = 1
for x=1, num do
print ("  "..option[a])
a = a + 1
end
drawCursor()
event, key = os.pullEvent()
if event == "key" then
if key == 200 and currentY > 1 then
currentY = currentY - 1
select = select -1
elseif key == 208 and currentY < num then
currentY = currentY + 1
select = select + 1
elseif key == 28 then
return actions[select]()
end
end
end
end
printMenu()
theblackhatman #14
Posted 06 May 2012 - 04:39 AM
So, something Like this?


char, r = os.pullEvent()
if r == ("1") then
LocalLogin()
elseif r == ("2")
NetworkLogin()
end
BigSHinyToys #15
Posted 06 May 2012 - 05:02 AM
here


local function LocalLogin()
print("function here")
end
local function NetworkLogin()
print("other function")
end
print("press 1 for local login or 2 for network login")
while true do
event,var = os.pullEvent()
if event == "char" then
  if var == "1" then
   LocalLogin()
   break
  elseif var == "2" then
   NetworkLogin()
   break
  end
end
end
Luanub #16
Posted 06 May 2012 - 05:34 AM
1) On line 37 there needs to bve a then
2) options need to be strings so "" is required.
3) lines 25 to 30 could be replaced with

for x = 1 , #option do
print ("  "..option[x])
end

4) line 40 should be
return actions[select]()

code testing ensures quality. also i know how to make a menu look at my code posted above. it is cleaner more understandable and simpler to use

#4 is not true, you can do just actions[select](), i do this all the time in my code and it works just fine.

I usually do test my codes. This one I did not feel that I need to as I've used it many many times. Also I'm unfortunately not able to test it with where I am at, but try to provide any help I can.

And the menu thing might be simpler but not necessarily better. The cursor based looks better, and you can do more with it. I run multiple menu's in my OS using it all on one screen and at the same time.
BigSHinyToys #17
Posted 06 May 2012 - 05:46 AM
with out line #4 the program will run the menu after the function has ended this may or may not be a good thing depending on your program.in this case it makes the program unable to end.

My program can be switched to cursor based by editing two lines.

The main problem i have with you is that you consistently said there is no error while i repeatedly told you there was. If i was just some noob I would not have a clue where to start in fixing your code but i have enough experience to find your codes faults.

If you want to help people you have to make shore that your code works or else you will just confuse people.

also what can you do with your menu mine cant.

I am sorry for derailing your thread theblackhatman
theblackhatman #18
Posted 06 May 2012 - 05:50 AM
It's no problem, I'm learning, which makes me happy. :)/>/> I edited some of the original code, but with the os.pull thing, I enter the number I want and it just ends the program entirely. what did i do wrong there?
BigSHinyToys #19
Posted 06 May 2012 - 06:08 AM
I have looked at your code and made some changes take a look at this.

http://pastebin.com/P9nZ1jSh

use the menu i fixed as an example to fix the others if you have any other problems please post them here or PM me
Noodle #20
Posted 06 May 2012 - 06:25 AM
Didnt have enough time to read thru all ur code.
you can just do

while true do
event, key = os.pullEvent()
if event == "char" and key == "1" then
localLogin()
elsief event == "char" and key == "2" then
networkLogin()
end
end
theblackhatman #21
Posted 06 May 2012 - 07:07 AM
BigShiny, I officially love you! Your pastebin helps soooo much.
theblackhatman #22
Posted 06 May 2012 - 10:19 PM
Alrighty, now its time to post the server file!


term.clear()
term.setCursorPos(1,1)
print("Initiating Server protocols. Stand by.")
print("0%")
sleep(1)
function ServerMain()
term.clear()
term.setCursorPos(1,1)
print("***Welcome to Authentication Server v1.0. ***")
Print("***Please choose an operating mode. ***")
print("***1: Username Authentication. ***")
print("***2: Username and Password Authentication.***")
print("***3: Shutdown Server. ***")
event, key = os.pullEvent()
if event ==("char") and key == ("1") then
Username()
elseif event == ("char") and key == ("2") then
UserPass()
elseif event == ("char") and key == ("3") then
Shutdown()
else
ServerMain()
end
end
term.clear()
term.setCursorPos(1,1)
print("14%")
sleep(1)
function Username()
term.clear()
term.setCursorPos(1,1)
var0 = ("0")
print("Username Authentication Activated. Awaiting Authentication Request.")
rednet.open("top")
event, id, text = os.pullEvent()
if event == ("rednet_message") and text == ("Authenticate") then
message1 = (text)
ID1 = (id)
UsernameAuthentication()
else
Username()
end
end
term.clear()
term.setCursorPos(1,1)
print("28%")
sleep(1)
function UsernameAuthentication()
user1 = ("Administrator")
user2 = ("BlackHat")
user3 = ("Computercraft")
if text == (user1, user2, user3) and var0 = ("1") then
Password()
elseif text ==(user1, user2, user3) and var0= ("0") then
Approved()
else
Denied()
end
end
term.clear()
term.setCursorPos(1,1)
print(42%")
sleep(1)
function UserPass()
term.clear()
term.setCursorPos(1,1)
var0 = ("1")
print("Username and Password Authentication Activated. Awaiting Authentication Request.")
rednet.open("top")
event, id, text = os.pullEvent()
if event == ("rednet_message") and text == ("Authenticate") then
message1 = (text)
ID1 = (id)
UsernameAuthentication()
else
UserPass()
end
end
term.clear()
term.setCursorPos(1,1)
print(56%")
sleep(1)
function Password()
password1 = ("AdminBypass")
password2 = ("Hall")
password3 = ("Derp")
rednet.open("top")
rednet.send(ID1, "Continue")
event, id, text = os.pullEvent()
if event == ("rednet_message") and text == (password1, password2, password3) then
Approved()
else
Denied()
end
end
term.clear()
term.setCursorPos(1,1)
print(70%")
sleep(1)
function Approved()
rednet.send (ID1, "Approved")
sleep(1)
Username()
end
term.clear()
term.setCursorPos(1,1)
print(84%")
sleep(1)
function Denied()
rednet.send (ID1, "Denied")
sleep(1)
if var == ("0") then
Username()
else
UserPass()
end
end
ServerMain()

Alright, so, that's the server that runs to receive any rednet authentication stuff from the client.. I wanted to make it print to monitor and stuff too, but I can't seem to figure out how to do that at all. : /
ComputerCraftFan11 #23
Posted 06 May 2012 - 10:34 PM
Alrighty, now its time to post the server file!


term.clear()
term.setCursorPos(1,1)
print("Initiating Server protocols. Stand by.")
print("0%")
sleep(1)
function ServerMain()
term.clear()
term.setCursorPos(1,1)
print("***Welcome to Authentication Server v1.0. ***")
Print("***Please choose an operating mode. ***")
print("***1: Username Authentication. ***")
print("***2: Username and Password Authentication.***")
print("***3: Shutdown Server. ***")
event, key = os.pullEvent()
if event ==("char") and key == ("1") then
Username()
elseif event == ("char") and key == ("2") then
UserPass()
elseif event == ("char") and key == ("3") then
Shutdown()
else
ServerMain()
end
end
term.clear()
term.setCursorPos(1,1)
print("14%")
sleep(1)
function Username()
term.clear()
term.setCursorPos(1,1)
var0 = ("0")
print("Username Authentication Activated. Awaiting Authentication Request.")
rednet.open("top")
event, id, text = os.pullEvent()
if event == ("rednet_message") and text == ("Authenticate") then
message1 = (text)
ID1 = (id)
UsernameAuthentication()
else
Username()
end
end
term.clear()
term.setCursorPos(1,1)
print("28%")
sleep(1)
function UsernameAuthentication()
user1 = ("Administrator")
user2 = ("BlackHat")
user3 = ("Computercraft")
if text == (user1, user2, user3) and var0 = ("1") then
Password()
elseif text ==(user1, user2, user3) and var0= ("0") then
Approved()
else
Denied()
end
end
term.clear()
term.setCursorPos(1,1)
print(42%")
sleep(1)
function UserPass()
term.clear()
term.setCursorPos(1,1)
var0 = ("1")
print("Username and Password Authentication Activated. Awaiting Authentication Request.")
rednet.open("top")
event, id, text = os.pullEvent()
if event == ("rednet_message") and text == ("Authenticate") then
message1 = (text)
ID1 = (id)
UsernameAuthentication()
else
UserPass()
end
end
term.clear()
term.setCursorPos(1,1)
print(56%")
sleep(1)
function Password()
password1 = ("AdminBypass")
password2 = ("Hall")
password3 = ("Derp")
rednet.open("top")
rednet.send(ID1, "Continue")
event, id, text = os.pullEvent()
if event == ("rednet_message") and text == (password1, password2, password3) then
Approved()
else
Denied()
end
end
term.clear()
term.setCursorPos(1,1)
print(70%")
sleep(1)
function Approved()
rednet.send (ID1, "Approved")
sleep(1)
Username()
end
term.clear()
term.setCursorPos(1,1)
print(84%")
sleep(1)
function Denied()
rednet.send (ID1, "Denied")
sleep(1)
if var == ("0") then
Username()
else
UserPass()
end
end
ServerMain()

Alright, so, that's the server that runs to receive any rednet authentication stuff from the client.. I wanted to make it print to monitor and stuff too, but I can't seem to figure out how to do that at all. : /

Try this to print to a monitor

monitor = peripheral.wrap("side of the monitor")
function mPrint(text) --replace print("") with mPrint("") to print on monitor and terminal
  print(text)
  term.redirect(monitor) --Switch to monitor
  print(text)
  term.restore() --Switch back to computer
end
function lPrint(text) --replace print("") with mPrint("") to print on monitor only
  term.redirect(monitor)
  print(text)
  term.restore()
end

Example codes:

mPrint("Hi!")
will print "Hi!" on the monitor and computer