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

API Load not working

Started by gknova61, 28 November 2012 - 03:35 PM
gknova61 #1
Posted 28 November 2012 - 04:35 PM
I've had this problems on allot of my programs that load an API that does some higher-level things, what am I doing wrong?
Program:
http://pastebin.com/XR9C8z75

And the API it uses (must be in the apis/config path on your computer (it's where osloadapi is pointed to), not the rom!):
http://pastebin.com/fkcMT9CE

I keep getting the attempt to call nil error on the program when i'm using os load api and yes i've made sure that the config api is in my apis/config folder on my computer. The only way i can even use an API currently is to put it in my rom but i don't wana get into the habit of that since i normally play on a server without FTP access ;)/>

And for anyone with extra time, my other thread in 'Ask a Pro' on an unrelated problem with what looks to be the fs api is not exactly answered yet :(/>:
http://www.computerc...n-this-program/
Cranium #2
Posted 28 November 2012 - 06:48 PM
I see that you are trying to write to the "apis" folder. That's part of ROM, so it can't be modified with script. If you want to have an updateable API, you need to have it either go into root, or a designated directory that you create. And yes, you can do that, just lead the full path when loading the API. (such as: os.loadAPI("testDir/config"), and it will still retain the proper function call.)

I did fix your program, and it will run. The problem was that you were trying to write to the ROM….
Spoiler



local function printUsage()
print( "Usage:" )
print( shell.getRunningProgram().." <interval> (config)" )
print("Parameters:")
print("<> = required")
print("() = optional")
end

local x,y = term.getSize()

local function cPrint( txt )
    local function printC( text )
        x2,y2 = term.getCursorPos()
        term.setCursorPos(math.ceil((x / 2) - (text:len() / 2)), y2)
        write(text.. "\n")
    end

    if type(txt) == "string" then
        printC( txt )
    elseif type(txt) == "table" then
        for i=1,#txt do
printC( txt[i] )
        end
    end
end

local function autoUpdate()
local programName = shell.getRunningProgram()
    term.clear()
    term.setCursorPos(1,6)
    cPrint("+--------------------+")
    cPrint("|     Loading...     |")
    cPrint("| ||||||             |") 
    cPrint("+--------------------+")
    while true do
        local downloadedFile = http.request("http://pastebin.com/raw.php?i=XR9C8z75")
        local event, url, body = os.pullEvent()
        if event == "http_success" then
            _tBody = body.readAll()
            break
        elseif event == "http_failed" then
            break
        end
    end
    term.clear()
    term.setCursorPos(1,6)
    cPrint("+--------------------+")
    cPrint("|     Loading...     |")
    cPrint("| ||||||||||||       |")
    cPrint("+--------------------+")
    file = fs.open(programName, "r")
    _fBody = file.readAll()
    file.close()
    sleep(0.5)
    term.clear()
    term.setCursorPos(1,6)
    cPrint("+--------------------+")
    cPrint("|     Loading...     |")
    cPrint("| |||||||||||||||||| |")
    cPrint("+--------------------+")
    sleep(0.5)
    local selection = 1
    --[[if _fBody ~= _tBody then
cPrint("+--------------------+")
cPrint("|     Updating...    |")
cPrint("+--------------------+")
sleep(2)
        fs.delete(programName)
        file = fs.open(programName, "w")
        file.write(_tBody)
        file.close()
        shell.run(programName, sInterval)
        error()
end]]
end
autoUpdate()

if not fs.exists("config") then         --NON WORKING CODDE NEEDS A FIXXXXXXXX
local sCode = "fkcMT9CE"
local sFile = "config"
local sPath = shell.resolve(sFile)
    local response = http.get(
    "http://pastebin.com/raw.php?i="..textutils.urlEncode( sCode )
    )    
    if response then
local sResponse = response.readAll()
response.close()
local file = fs.open( sPath, "w" )
        file.write( sResponse )
   file.close()
    end    
end
if not fs.exists("config") then
shell.run("pastebin","get","fkcMT9CE","config")
os.reboot()
end
os.loadAPI("config")

local function editConfig()
term.clear()
term.setCursorPos(1,1)
fs.delete("configs")
cPrint("Interactive Configuration Editor (I.C.E.)")
config.load("configs","Timer.cfg")
term.setCursorPos(1,3)
print("Please set a computer id to receive all the rednet messages")
local sMid = read("*")
config.writeVal("mId",sMid)
print("Please type out the sides you'd like to output redstone on (one at a time and leave blank for nil)")
for i=1,rs.getSides() do
redstoneSide[i] = read()
if redstoneSide[i] ~= nil then
if checkValidSide(input) then 
table.insert(redstoneSides,i,redstoneSide[i])
config.writeVal("redstoneSide"..tostring(i),redstoneSide[i])
elseif not checkValidSide(input) then
print("Not a valid side!")
i=i-1
end
elseif redstoneSide[i] == nil then
config.writeVal("numOfActiveSides",tostring((i-1)))
break
end
end
config.save()
print("Success, please restart your timer")
sleep(2)
end

local function checkValidSide(input)
local availableRedstoneSides = rs.getSides()
for i2=1,#availableRedstoneSides do
if input == availableRedstoneSides[i] then
return true
end
end
return false
end

local function readConfig()
redstoneSides = {}
config.load("configs","Timer.cfg")
mId = tonumber(config.readVal(mId))
sInterval = tonumber(config.readVal(sInterval))
if tonumber(config.readVal(numOfActiveSides)) == nil then
local activeSides = 6
else
local activeSides = tonumber(config.readVal(numOfActiveSides)) 
end
for i=1,activeSides do
redstoneSide[i] = tostring(config.readVal(redstoneSide[i]))
end
config.save()
end

local function redstoneOut(boolean)
for i=1,#redstoneSides do
redstone.setOutput(redstoneSides[i],boolean)
end
end

local function pWrapper()
local bOpen, sFreeSide = false, nil
for n,sSide in pairs(rs.getSides()) do 
if peripheral.getType( sSide ) == "modem" then
sFreeSide = sSide
if rednet.isOpen( sSide ) then
bOpen = true
break
end
end
end

if not bOpen then
if sFreeSide then
term.clear()
term.setCursorPos(1,1)
   cPrint("+------------------------------------+")
   cPrint("| Opening Modem on "..sFreeSide.." |")
   cPrint("+------------------------------------+")
rednet.open( sFreeSide )
sOpenedSide = sFreeSide
sleep(2)
return true
else
print( "No modem attached. Please try again." )
sleep(2)
os.reboot()
end
end
return true
end

if sConfig == "config" then editConfig()
end

local tArgs = { ... }
local sOpenedSide = nil
local sInterval = tonumber(tArgs[1])
local sConfig = tArgs[2]
config.load("configs","Timer.cfg")
if #tArgs < 1 and config.readVal("sInterval") == nil then 
config.save()
    printUsage()
    return false
end
config.save()

if mId == nil then
mId = 0
end

if tArgs[1] ~= nil then
config.load("configs","Timer.cfg")
config.writeVal("sInterval",tArgs[1])
config.save()
end

if not rednet.broadcast("PING") then pWrapper() end
readConfig()
term.clear()
term.setCursorPos(1,1)
    cPrint("+--------------------+")
    cPrint("| Triggers Done: 0 |")
    cPrint("+--------------------+")
local spaceTimerLength, spaceTimer, pulseTimer, pulseCount = 0.8, nil, nil, 0
local updateInterval, updateTarget = 100, mId
rednet.send(updateTarget,"timer_check_in_"..os.computerID())
os.unloadAPI("config")
while true do
        e, p1, p2 = os.pullEvent()
        if e == "timer" then
            if p1 == spaceTimer then
                redstone.setOutput("back", true)
                pulseTimer = os.startTimer(0.1)
            elseif p1 == pulseTimer then
                redstone.setOutput("back", false)
                spaceTimer = os.startTimer(spaceTimerLength)
                pulseCount = pulseCount + 1
term.setCursorPos(1,2)
term.clearLine()
cPrint("| Triggers Done: "..pulseCount.." |")
                if pulseCount % updateInterval == 0 then
rednet.send(updateTarget, tostring(pulseCount / updateInterval))
                end
            end
        elseif e == "rednet_message" then
            if p1 == updateTarget and p2 == "reset_"..os.computerID() then
                pulseCount = 0
term.setCursorPos(1,2)
term.clearLine()
cPrint("| Triggers Done: "..pulseCount.." |")
            elseif p1 == updateTarget and p2 == "stop_"..os.computerID() then
                spaceTimer = nil
                pulseTimer = nil
                redstone.setOutput("back", false)
            elseif p1 == updateTarget and p2 == "start_"..os.computerID() then
                spaceTimer = os.startTimer(0)
             end
        end
end
Lyqyd #3
Posted 28 November 2012 - 06:56 PM
What? rom/apis is part of rom, but a folder called apis in the root of the drive isn't.
Cranium #4
Posted 28 November 2012 - 07:03 PM
I think that since apis is an alias for rom/apis, it might be having that problem. The program ran just fine without doing that. Although, my sleepless mind just realized that I did not test if apis was an existing directory. What you should do, if going through a user created apis foler, is this block of code somewhere before checking if apis/config exists:

if not fs.exists(apis) then
    fs.mkDir("apis")
end
Luanub #5
Posted 28 November 2012 - 08:40 PM
Once the folder is created another good idea would be to use "/apis/config" as the path instead of "apis/config". That will ensure that it is pointing to the correct path.