luaminecraftcomputercraft

ComputerCraft (Lua) Can "attempt to index a nil value"error be trapped to prevent the script from haulting


I've written a Lua script for ComputerCraft to control a mob farm. What I'm doing is checking the amount in specific Functional Storage drawers. The API for the mod has, at least to me, a weird quark that if the storage drawer is empty then the call to getItemDetail(num).count fails and returns "Attempt to index a nil value."

I was able to determine that if you just call getItemDetail(num), where num is the index of the drawer, and the drawer is empty then it returns nil. This works some of the time. It fails if that between calling getItemDetail(num) and getItemDetail(num).count the drawer's count goes from >0 to 0 it errors with "Attempt to index a nil value." At least this is my current working theory as to why it fails.

Is there any better way of trapping the index a nill value error so that the program doesn't error and hault?

This is how I'm currently trying to determine if the drawer has a 0 count or not.

data is table of class objects where I keep track of things like the location, index, of the drawers.

-- If you call getItemDetail and it returns nil, then the drawer is empty.
-- If you call getItemDetaiil(num).count it throws a error "Attempt to index a nill value."
if storage.getItemDetail(data[i]:getLocation()) ~= nil then
   storageamount = storage.getItemDetail(data[i]:getLocation()).count
else
   storageamount = 1
end

if storage.getItemLimit(data[i]:getLocation()) ~= nil then
   storagelimit = storage.getItemLimit(data[i]:getLocation())
else
   storagelimit = 1024
end

The code loops until the drawer is full and then moves on to the next item.

The class definition for clairity.

Class = {
        -- Constructor
        new = function(self)
                local new = {}
                setmetatable(new, {__index = self})
                return new
        end,
        
        -- Setters
        setName = function(self, name) --Tag of item in drawer
            self.name = name
        end,
        setLocation = function(self, location) -- Drawer location from Controller
            self.location = location
        end,
        setRSI = function(self, RSI) -- This is the side of the Computer of the RSI
            self.RSI = RSI
        end,
        setSide = function(self, Side) -- This is the side of RSI that will out RS signal
            self.Side = Side
        end,
        
        --Getters
        getName = function(self, name)
            return self.name
        end,
        getLocation = function(self,location)
            return self.location
        end,
        getRSI = function(self, RSI)
            return self.RSI
        end,
        getSide = function(self, Side)
            return self.Side
        end
        }

The code runs just fine as long as one of the drawers that I'm monitoring doesn't go to zero.

So I really want to be able to trap the error or prevent the program from haulting if encounters the index a nill value error.

Thanks,


Solution

  • You could just store the value of storage.getItemDetail(data[i]:getLocation()) in a variable, check if that variable is not Nil, and get the item's count, something like this:

    item = storage.getItemDetail(data[i]:getLocation())
    storagelimit = storage.getItemLimit(data[i]:getLocation())
    storageamount = 1
    
    if item ~= nil then
       storageamount = item.count
    end
    
    if storagelimit == nil then
       storagelimit = 1024
    end