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

[LUA][Question] Saved variables after server restart

Started by remiX, 06 October 2012 - 05:14 AM
remiX #1
Posted 06 October 2012 - 07:14 AM
Hey guys, I was wondering if you can set variables to a string and keep them saved to that. Because after a server restart the variables for my codes restart.

My variable settings
--Variables
local sPassword = "xxx"
local sBypasspw = "yyy"
local sStatus = "OFFLINE"
local selection = ""
local sRedstoneSignal = ""

The base setting for sStatus is offline, so after a server restart the directed redstone signal is offline. If i had selected it to be online while the server is up its fine but after a restart it will default back to offline. Is there a way to save the variable?

Thanks
Luanub #2
Posted 06 October 2012 - 07:19 AM
Yes save them to a file and then load them when the programs starts.
remiX #3
Posted 06 October 2012 - 07:40 AM
Yes save them to a file and then load them when the programs starts.

Hmm, cant believe I didn't think of that :D/>/> Could you give me quick steps on how to use save and load? Busy googling it too now.

Another question: How do i make a code go somewhere specifically within the code? Ex: After entering the password for my code and then doing an action it will go back to 'Please enter the password'. How do i make it go to the point after entering the password?
Luanub #4
Posted 06 October 2012 - 07:53 AM
Here's how to save a var.

local sStatus = "OFFLINE" -- i'll use this for example

--check to make sure file exists, good to do at start of the program
if not fs.exists("status") then
  local file = io.open("status", "w") -- open file in write mode
  file:write()
  file:close() -- always close the handle.
end

--save the var
local file = io.open("status", "w')
file:write(sStatus)
file:close()

--read the var
local file = io.open("status", "r") --open in read mode
sStatus = file:read()
file:close()
For more info read up on the fs and io API's. Note that CC does not have all of the io functions available.

To make a code go run a specific task make it a function.

local function getPass()
write("Enter Password")
input = read("*")
end

getPass() -- to call it.

Make sure the function is above the code that is calling it or it will error.
brett122798 #5
Posted 06 October 2012 - 07:57 AM
Yes save them to a file and then load them when the programs starts.
Another question: How do i make a code go somewhere specifically within the code? Ex: After entering the password for my code and then doing an action it will go back to 'Please enter the password'. How do i make it go to the point after entering the password?
Functions. That is what you're looking for. Example:


function login()
write("Please Enter Password: ")
pass = read()
if pass = "mypass" then
stuff()
elseif
login()
end
end -- Ends the function login()

function stuff()
<Your Program, or whatever>
end -- Ends the function stuff()

login()
Sebra #6
Posted 06 October 2012 - 07:58 AM
Is it Direwolf20's turtle on forum? :D/>/>

FYI developers are making efforts for computers do not even sense server/chunk unload/load.
jag #7
Posted 06 October 2012 - 10:47 AM
SpoilerHere's how to save a var.

local sStatus = "OFFLINE" -- i'll use this for example

--check to make sure file exists, good to do at start of the program
if not fs.exists("status") then
  local file = io.open("status", "w") -- open file in write mode
  file:write()
  file:close() -- always close the handle.
end

--save the var
local file = io.open("status", "w')
file:write(sStatus)
file:close()

--read the var
local file = io.open("status", "r") --open in read mode
sStatus = file:read()
file:close()
For more info read up on the fs and io API's. Note that CC does not have all of the io functions available.
Well the wiki says file:read() only reads 1 byte at a time…
Luanub #8
Posted 06 October 2012 - 11:26 AM
Which wiki? Try it..


This is what I read about it, and seems to be the way it works..

file:read (…)
Reads the file file, according to the given formats, which specify what to read. For each format, the function returns a string (or a number) with the characters read, or nil if it cannot read data with the specified format. When called without formats, it uses a default format that reads the entire next line (see below).
remiX #9
Posted 06 October 2012 - 12:15 PM
Here's how to save a var.

local sStatus = "OFFLINE" -- i'll use this for example

--check to make sure file exists, good to do at start of the program
if not fs.exists("status") then
  local file = io.open("status", "w") -- open file in write mode
  file:write()
  file:close() -- always close the handle.
end

--save the var
local file = io.open("status", "w')
file:write(sStatus)
file:close()

--read the var
local file = io.open("status", "r") --open in read mode
sStatus = file:read()
file:close()
For more info read up on the fs and io API's. Note that CC does not have all of the io functions available.

To make a code go run a specific task make it a function.

local function getPass()
write("Enter Password")
input = read("*")
end

getPass() -- to call it.

Make sure the function is above the code that is calling it or it will error.

Thanks, going to try implement it now :D/>/>

Yes save them to a file and then load them when the programs starts.
Another question: How do i make a code go somewhere specifically within the code? Ex: After entering the password for my code and then doing an action it will go back to 'Please enter the password'. How do i make it go to the point after entering the password?
Functions. That is what you're looking for. Example:


function login()
write("Please Enter Password: ")
pass = read()
if pass = "mypass" then
stuff()
elseif
login()
end
end -- Ends the function login()

function stuff()
<Your Program, or whatever>
end -- Ends the function stuff()

login()

Yes i know how to do this, but i use a while true do.

This is my code now. If you guys could help me, after entering the password I wan't it to stay logged in until you manually logout yourself. So you don't have to re-enter the password after choosing an option.

-- Configuration
-- Strings
local sBypasspw = "xxx"
local sDoorpw = "derp"
local sDoorStatus = ""
local sRedstoneSideClose = "back"
local sRedstoneSideOpen = "bottom"
local sName = "The Sorting Facility"
local wp = "print"
-- Values
local nTimer = 1

-- Do not edit from here

-- Functions

local function menu(...)
    local sel = 1
    local list = {...}
    local offX,offY = term.getCursorPos()
    local curX,curY = term.getCursorPos()
    while true do
		    if sel > #list then sel = 1 end
		    if sel < 1 then sel = #list end
		    for i = 1,#list do
				    term.setCursorPos(offX,offY+i-1)
				    if sel == i then
						    print("["..list[i].."]") -- very customisible example print(">"..list[i])
				    else
						    print(" "..list[i].." ") -- very customisible
				    end
		    end
		    while true do
				    local e,e1,e2,e3,e4,e5 = os.pullEvent()
				    if e == "key" then
						    if e1 == 200 then -- up key
								    sel = sel-1
								    break
						    end
						    if e1 == 208 then -- down key
								    sel = sel+1
								    break
						    end
						    if e1 == 28 then
								    term.setCursorPos(curX,curY)
								    return list[sel],sel
						    end
				    end
		    end
    end
end

function clearPrint(string, x, y)
  if not x or x < 0 then x = 1 end
  if not y or y < 0 then y = 1 end
  term.clear()
  term.setCursorPos(x,y)
  print(string)
end

function skipLine()
    print(" ")
end

function Welcome(string)
    clearPrint("+-----------------------------------------------+")
    print("+----  Welcome to "..sName.."   ----+")
    print("+-----------------------------------------------+")
    skipLine()
    if wp == "print" then
        print(string)
    elseif wp == "write" then
        write(string)
    end
end

function Open()
    if sDoorStatus == "opened" then
        Welcome("The doors are already open!")
        sleep(1.5)
    elseif sDoorStatus == "closed" then
        Welcome("Opening doors...")
        while nTimer <=4 do
           rs.setOutput(sRedstoneSideOpen,true)
           sleep(.425)
           rs.setOutput(sRedstoneSideOpen,false)
           sleep(.425)
           nTimer = nTimer + 1
        end
        nTimer = 0
        Welcome("Doors have been opened!")
        sDoorStatus = "opened"
        sleep(1)
    else
        Welcome("ERROR.")
        print("CURRENT DOOR STATUS: "..sDoorStatus..". What is wrong. WHAT THE HELL IS WRONG?")
        sleep(60)
    end
end

function Close()
    Welcome("Closing garage doors...")
    sleep(1.5)
    if sDoorStatus == "closed" then
        Welcome("The doors are already closed!")
        sleep(1.5)
    elseif sDoorStatus == "opened" then
        Welcome("Closing doors...")
        while nTimer <=4 do
           rs.setOutput(sRedstoneSideClose,true)
           sleep(.425)
           rs.setOutput(sRedstoneSideClose,false)
           sleep(.425)
           nTimer = nTimer + 1
        end
        nTimer = 0
        Welcome("Doors have been closed!")
        sDoorStatus = "closed"
        sleep(1)
    else
        Welcome("ERROR.")
        print("CURRENT DOOR STATUS: "..sDoorStatus..". What is wrong. WHAT THE HELL IS WRONG?")
        sleep(60)
    end
end

function Logout()
    Welcome("Logging out...")
    sleep(1.5)
end

-- if statement

function checkPW(PW)
    if PW == sDoorpw then
        Welcome("Password correct!")
        sleep(1.5)
        Welcome("The door is currently "..sDoorStatus..".")
        print("Choose an option:")
         local selection = menu("Open", "Close", "Logout")
        if selection == "Open" then
            Open()
        elseif selection == "Close" then
            Close()
        elseif selection == "Logout" then
            Logout()
        end
            
    elseif PW == sBypasspw then
        Open()
    else
        Welcome("Password invalid.")
        sleep(1.5)
    end
end


while true do
    if sDoorStatus == "closed" or sDoorStatus == "opened" then
        wp = "write"
    Welcome("Enter password to access garage: ")
    local selection = ""
    wp = "print"
        if checkPW(read("*")) == sBypasspw then break end
    else
        Welcome("Door has an unknown status. opened or closed?")
        print(sDoorStatus)
        input = read()
        if input == "opened" or input == "closed" then
            sDoorStatus = input
        else
            Welcome("Unknown status.")
            sleep(2)
        end
    end
end
jag #10
Posted 06 October 2012 - 05:24 PM
Which wiki? Try it..


This is what I read about it, and seems to be the way it works..

file:read (…)
Reads the file file, according to the given formats, which specify what to read. For each format, the function returns a string (or a number) with the characters read, or nil if it cannot read data with the specified format. When called without formats, it uses a default format that reads the entire next line (see below).
Function h.read Syntax h.read() Returns int the byte read from the file, or nil if there are no more bytes Part of ComputerCraft API fs Description
Reads a single byte from the file and returns it

I don't know if I'm reading it wrong, but that is how I think it is…
MysticT #11
Posted 06 October 2012 - 06:51 PM
Function h.read Syntax h.read() Returns int the byte read from the file, or nil if there are no more bytes Part of ComputerCraft API fs Description
Reads a single byte from the file and returns it

I don't know if I'm reading it wrong, but that is how I think it is…
It depends on the open mode. If you use "r" (read mode) it reads a line, if you use "rb" (binary read mode) it reads a byte. Same for write modes, "w" and "a" writes strings, while "wb" and "ab" writes bytes.
jag #12
Posted 06 October 2012 - 07:26 PM
Spoiler
Function h.read Syntax h.read() Returns int the byte read from the file, or nil if there are no more bytes Part of ComputerCraft API fs Description
Reads a single byte from the file and returns it

I don't know if I'm reading it wrong, but that is how I think it is…
It depends on the open mode. If you use "r" (read mode) it reads a line, if you use "rb" (binary read mode) it reads a byte. Same for write modes, "w" and "a" writes strings, while "wb" and "ab" writes bytes.
Ah! I get it!
Luanub #13
Posted 07 October 2012 - 12:25 AM
Which wiki? Try it..


This is what I read about it, and seems to be the way it works..

file:read (…)
Reads the file file, according to the given formats, which specify what to read. For each format, the function returns a string (or a number) with the characters read, or nil if it cannot read data with the specified format. When called without formats, it uses a default format that reads the entire next line (see below).
Function h.read Syntax h.read() Returns int the byte read from the file, or nil if there are no more bytes Part of ComputerCraft API fs Description
Reads a single byte from the file and returns it

I don't know if I'm reading it wrong, but that is how I think it is…

Also notice you have h.read() which is the fs API. I'm using h:read() the io API. Notice its io.open() and not fs.open(), they are different.
jag #14
Posted 07 October 2012 - 03:44 AM
Which wiki? Try it..


This is what I read about it, and seems to be the way it works..

file:read (…)
Reads the file file, according to the given formats, which specify what to read. For each format, the function returns a string (or a number) with the characters read, or nil if it cannot read data with the specified format. When called without formats, it uses a default format that reads the entire next line (see below).
Function h.read Syntax h.read() Returns int the byte read from the file, or nil if there are no more bytes Part of ComputerCraft API fs Description
Reads a single byte from the file and returns it

I don't know if I'm reading it wrong, but that is how I think it is…

Also notice you have h.read() which is the fs API. I'm using h:read() the io API. Notice its io.open() and not fs.open(), they are different.
Oh, did not notice that!
remiX #15
Posted 07 October 2012 - 09:48 AM

local sStatus = "OFFLINE" -- i'll use this for example

--check to make sure file exists, good to do at start of the program
if not fs.exists("status") then
  local file = io.open("status", "w") -- open file in write mode
  file:write()
  file:close() -- always close the handle.
end

--save the var
local file = io.open("status", "w')
file:write(sStatus)
file:close()

--read the var
local file = io.open("status", "r") --open in read mode
sStatus = file:read()
file:close()
I tried to put this into my code but it does nothing. I put it in various place within my code and does nothing. Doesn't give an error nor does it create or put content to the file. Can anybody help me? ;3
Luanub #16
Posted 07 October 2012 - 10:12 AM
There's a typo here:

local file = io.open("status", "w')  -- change the ' to "
remiX #17
Posted 07 October 2012 - 02:27 PM
There's a typo here:

local file = io.open("status", "w')  -- change the ' to "

I did change that in my code but I just copied it from you where you had the typo :D/>/>
Exerro #18
Posted 07 October 2012 - 04:03 PM
you could do it a lot better…have it edit itself!

local var1 = "variable one"
local var2 = "variable two"
local editFile = true
if editFile == true then
tLines = {}
k = fs.open("program", "r")
while true do
  m = k.readLine()
  if m == "" or m == nil then
   break
  else
   table.insert(tLines, m)
  end
end
k.close()
tLines[3] = "local editFile = false"
tLines[2] = --what you want
tLines[1] = --what you want
k = fs.open("program", "w")
for i = 1,#tLines do
  k.writeLine(tLines[i])
end
k.close()
--code
else
--code
end
remiX #19
Posted 07 October 2012 - 04:54 PM
you could do it a lot better…have it edit itself!

local var1 = "variable one"
local var2 = "variable two"
local editFile = true
if editFile == true then
tLines = {}
k = fs.open("program", "r")
while true do
  m = k.readLine()
  if m == "" or m == nil then
   break
  else
   table.insert(tLines, m)
  end
end
k.close()
tLines[3] = "local editFile = false"
tLines[2] = --what you want
tLines[1] = --what you want
k = fs.open("program", "w")
for i = 1,#tLines do
  k.writeLine(tLines[i])
end
k.close()
--code
else
--code
end

Nice :D/>/> GOing to test it out now, while im doing this could you explain to me what each line does after 'while true do' please? ;)/>/>

Edit: Used this code and got error - save:15: attempt to index ? (a nil value) which is where it says it does k = m.readLine()

local editFile = true

function Clear(string)
  term.clear()
  term.setCursorPos(1,1)
  print(string)
end

if editFile == true then
tLines = {}
k = fs.open("program", "r")
while true do
  Clear("Set Door Status:")
  var1 = read()
  m = k.readLine()
  if m == "" or m == nil then
   break
  else
   table.insert(tLines, m)
  end
end
k.close()
tLines[2] = "local editFile = false"
tLines[1] = var1
k = fs.open("program", "w")
for i = 1,#tLines do
  k.writeLine(tLines[i])
end
k.close()
--code
else
--code
end
Exerro #20
Posted 07 October 2012 - 05:22 PM
the while true do loop is for getting all the lines of the program into a table…what is it you're trying to do exactly? say if a door is open or not and it will save even if the server reboots? If so then use this:
Spoiler

local editFile = true
local lightState = ""
function Clear(string, x, y)
if x == nil or y == nil then
  x, y = term.getCursorPos()
end
term.clear()
term.setCursorPos(x, y)
term.write(string)
end
if editFile == true then
tLines = {}
k = fs.open("nameOfThisProgram", "r") -- name of the program that you are running with this code
while true do
  m = k.readLine()
  if m == "" or m == nil then
   break
  else
   table.insert(tLines, m)
  end
end
k.close()
Clear("Set door status: ",1,1)
var1 = read()
tLines[2] = "local lightState = "..var1
tLines[1] = false
k = fs.open("nameOfThisProgram", "w") -- name of the program that you are running with this code
for i = 1,#tLines do
  k.writeLine(tLines[i])
end
k.close()
--code
else
--code
end
remiX #21
Posted 07 October 2012 - 05:45 PM
the while true do loop is for getting all the lines of the program into a table…what is it you're trying to do exactly? say if a door is open or not and it will save even if the server reboots? If so then use this:
Spoiler

local editFile = true
local lightState = ""
function Clear(string, x, y)
if x == nil or y == nil then
  x, y = term.getCursorPos()
end
term.clear()
term.setCursorPos(x, y)
term.write(string)
end
if editFile == true then
tLines = {}
k = fs.open("nameOfThisProgram", "r") -- name of the program that you are running with this code
while true do
  m = k.readLine()
  if m == "" or m == nil then
   break
  else
   table.insert(tLines, m)
  end
end
k.close()
Clear("Set door status: ",1,1)
var1 = read()
tLines[2] = "local lightState = "..var1
tLines[1] = false
k = fs.open("nameOfThisProgram", "w") -- name of the program that you are running with this code
for i = 1,#tLines do
  k.writeLine(tLines[i])
end
k.close()
--code
else
--code
end

i copied your code exactly and got the same error :X save:15: attempt to index ? (a nil value)
Exerro #22
Posted 07 October 2012 - 05:48 PM
the while true do loop is for getting all the lines of the program into a table…what is it you're trying to do exactly? say if a door is open or not and it will save even if the server reboots? If so then use this:
Spoiler

local editFile = true
local lightState = ""
function Clear(string, x, y)
if x == nil or y == nil then
  x, y = term.getCursorPos()
end
term.clear()
term.setCursorPos(x, y)
term.write(string)
end
if editFile == true then
tLines = {}
k = fs.open("nameOfThisProgram", "r") -- name of the program that you are running with this code
while true do
  m = k.readLine()
  if m == "" or m == nil then
   break
  else
   table.insert(tLines, m)
  end
end
k.close()
Clear("Set door status: ",1,1)
var1 = read()
tLines[2] = "local lightState = "..var1
tLines[1] = false
k = fs.open("nameOfThisProgram", "w") -- name of the program that you are running with this code
for i = 1,#tLines do
  k.writeLine(tLines[i])
end
k.close()
--code
else
--code
end

i copied your code exactly and got the same error :X save:15: attempt to index ? (a nil value)
yes you need to change "nameOfThisProgram" to the name of your program
remiX #23
Posted 07 October 2012 - 06:02 PM
the while true do loop is for getting all the lines of the program into a table…what is it you're trying to do exactly? say if a door is open or not and it will save even if the server reboots? If so then use this:
Spoiler

local editFile = true
local lightState = ""
function Clear(string, x, y)
if x == nil or y == nil then
  x, y = term.getCursorPos()
end
term.clear()
term.setCursorPos(x, y)
term.write(string)
end
if editFile == true then
tLines = {}
k = fs.open("nameOfThisProgram", "r") -- name of the program that you are running with this code
while true do
  m = k.readLine()
  if m == "" or m == nil then
   break
  else
   table.insert(tLines, m)
  end
end
k.close()
Clear("Set door status: ",1,1)
var1 = read()
tLines[2] = "local lightState = "..var1
tLines[1] = false
k = fs.open("nameOfThisProgram", "w") -- name of the program that you are running with this code
for i = 1,#tLines do
  k.writeLine(tLines[i])
end
k.close()
--code
else
--code
end

i copied your code exactly and got the same error :X save:15: attempt to index ? (a nil value)
yes you need to change "nameOfThisProgram" to the name of your program

Sorry for all the troubles :D/>/> But i still get the same error, am I doing everything right?
This code is within a file called 'save'.
Spoiler
 local editFile = true
local lightState = ""
function Clear(string, x, y)
if x == nil or y == nil then
  x, y = term.getCursorPos()
end
term.clear()
term.setCursorPos(x, y)
term.write(string)
end
if editFile == true then
tLines = {}
k = fs.open("save", "r") -- name of the program that you are running with this code
while true do
  m = k.readLine()
  if m == "" or m == nil then
   break
  else
   table.insert(tLines, m)
  end
end
k.close()
Clear("Set door status: ",1,1)
var1 = read()
tLines[2] = "local lightState = "..var1
tLines[1] = false
k = fs.open("nameOfThisProgram", "w") -- name of the program that you are running with this code
for i = 1,#tLines do
  k.writeLine(tLines[i])
end
k.close()
--code
else
--code
end
Exerro #24
Posted 07 October 2012 - 06:07 PM
i think the error is that it tries to read a nil line so try putting an extra blank line at the end of your code that should sort it…otherwise im really not sure sorry
Luanub #25
Posted 07 October 2012 - 11:22 PM
Edit: nevermind I read the code wrong. I've never tried having a program edit itself, I'll give it a go and see if I can't find whats wrong.
remiX #26
Posted 08 October 2012 - 12:23 AM
I got it to work
gtapokomon #27
Posted 09 December 2012 - 10:51 PM
i read this topic cause im trying to load and save variables myself, but im still confused. how exactly do you save the variable and then load it later. because the variable is called pass and im trying to make that changeable without going into the code so that a user can type in the new pass and that it says like that even after the computer has rebooted
KaoS #28
Posted 10 December 2012 - 02:11 AM
you create a file in which the password is stored. so when you change the password


print("Please enter your new password")
local pass=read()
local f=io,open("pass","w")
f:write(pass)
f:close()
that will create the file "pass" (or overwrite the existing one), the file will contain your password.

when you start up your program use

local f=io.open("pass","r")
local res=f:read()
local pass=res~="" and res or 0000
f:close
and that will restore your password.please note that so far it does not check if the file exists and will error if the file "pass" does not exist. I am sure you can put in an if fs.exists statement for that
gtapokomon #29
Posted 10 December 2012 - 09:30 PM
with the second bit that i use when starting the program it says: bios:206: [string "password"]:4: function arguments expected

oh and password is the name of the program btw
gtapokomon #30
Posted 10 December 2012 - 09:35 PM
nvm the f:close needed to be f:close()
gtapokomon #31
Posted 10 December 2012 - 09:52 PM
i have another problem, this is my code now:

fs.exists("pass")
if false then
print("hi")
sleep(2)
os.shutdown()
end

if true then
local f=io.open("pass", "r")
local res=f:read()
local pass=res~="" and res or 0000
f:close()

when i run it to test if it's working so far I get an error
the error i get is: password:10: attemt to call index ? (a nil value)

anyone know what the problem is?
KaoS #32
Posted 11 December 2012 - 02:44 AM
you are formatting your if statement wrong. here is the correct syntax


if not fs.exists("pass") then
  print("hi")
  sleep(2)
  os.shutdown()
else
  local f=io.open("pass", "r")
  local res=f:read()
  local pass=res~="" and res or 0000
  f:close()
end