So, I'm getting an error that looks like: [ERROR] addons/itemstore/lua/itemstore/lua/itemsure/vgui/container.lua:43 'for' limit must be a number
Here is container.lua
local PANEL = {}
AccessorFunc( PANEL, "ContainerID", "ContainerID" )
AccessorFunc( PANEL, "Rows", "Rows" )
AccessorFunc( PANEL, "Columns", "Columns" )
function PANEL:Init()
self.Items = {}
table.insert( itemstore.containers.Panels, self )
end
function PANEL:Refresh()
local container = itemstore.containers.Get( self:GetContainerID() )
if ( container ) then
for i = 1, container.Size do
if ( not self.Items[ i ] ) then
self.Items[ i ] = self:Add( "ItemStoreSlot" )
end
local panel = self.Items[ i ]
panel:SetItem( container:GetItem( i ) )
panel:SetContainerID( self:GetContainerID() )
panel:SetSlot( i )
panel:InvalidateLayout()
end
self:InvalidateLayout()
end
end
function PANEL:SetContainerID( containerid )
self.ContainerID = containerid
self:Refresh()
end
function PANEL:PerformLayout()
self:SetSpaceX( 1 )
self:SetSpaceY( 1 )
local container = itemstore.containers.Get( self:GetContainerID() )
if ( container ) then
for i = 1, container.Size do
local panel = self.Items[ i ]
if ( panel ) then
panel:SetSize( unpack( itemstore.config.SlotSize ) )
end
end
end
self.BaseClass.PerformLayout( self )
end
vgui.Register( "ItemStoreContainer", PANEL, "DIconLayout" )
Any solutions anybody can think of? I can't think of anything because to me, it should be working fine?
The error is pretty clear. In line 43 you have a for statement that uses container.Size as its limit, which in your case is not a number.
Solution:
use a number as the for limit. If you have to use container.Size and it comes from "outside", find out why it is not a number and what you can do about it. If you cannot make sure its a number then you cannot use it as your for limit.
So put your for loop inside an if type(container.Size) == "number" then statement or similar.
Related
I have been following the tutorials on corona website and everything has been going well so far.
But in the tutorial "Displaying and saving score" i seem to have the following runtime error.
attempt to call field setPreferences' (a nil value)
This is the code of score.lua
local M = {}
M.score = 0
function M.init( options )
local customOptions = options or {} -- nice use of "or" operator
local opt = {}
opt.fontSize = customOptions.fontSize or 24
opt.font = customOptions.font or native.systemFont
opt.x = customOptions.x or display.contentCenterX
opt.y = customOptions.y or opt.fontSize*0.5 -- such that the score is positioned at the top, half of its font size.
opt.maxDigits = customOptions.maxDigits or 6
opt.leadingZeros = customOptions.leadingZeros or false
local prefix = ""
if ( opt.leadingZeros ) then
prefix = "0"
end
M.format = "%" .. prefix .. opt.maxDigits .. "d" -- so that its accesible in other modules.
-- Create the score display object
M.scoreText = display.newText( string.format( M.format, 0 ), opt.x, opt.y, opt.font, opt.fontSize ) -- string.format() works like printf and scanf statements
M.scoreText:setFillColor(1,0,0)
return M.scoreText
end
function M.set( value )
M.score = tonumber(value)
M.scoreText.text = string.format( M.format, M.score )
end
function M.get()
return M.score
end
function M.add( amount )
M.score = M.score + tonumber(amount)
M.scoreText.text = string.format( M.format, M.score )
end
function M.save()
print (" the score is " .. M.score)
local saved = system.setPreferences( "app", { currentScore=M.score } )
if ( saved == false) then
print ( "ERROR: could not save score" )
end
end
function M.load()
local score = system.getPreference( "app", "currentScore", "number" )
if ( score ) then
return tonumber(score)
else
print( "ERROR: could not load score (score may not exist in storage)" )
end
end
return M
This is the code of main.lua
local score = require( "score" )
local scoreText = score.init(
{
fontSize = 20,
font = "CoolCustomFont.ttf",
x = display.contentCenterX,
y = 30,
maxDigits = 7,
leadingZeros = true
})
local savedScore = score.load()
score.set( 1000 ) -- Sets the score to value
score.save()
I am aware there are other ways of keeping score, but I want to know what the problem is in my code. I googled everywhere but couldn't come up with any solution. Maybe I have made a mistake somewhere that I'm not able to identify.
Even tried a build on my smart phone, but ended up getting the same error.
From corona docs
Syntax
system.setPreferences( category, preferences )
category (required)
String. Indicates which set of preferences should be accessed on the system. Currently, only the "app" category is supported — this is the application's custom preferences defined by the Corona app developer.
preferences (required)
Table. Table of preferences to be written to storage. This table should contain key-value pairs where the key is the unique name of the preference and its value is either a boolean, number, or string.
if your M.score is nil then you might get an error
try this
local saved = system.setPreferences( "app", { currentScore=M.score or 0 } )
I would like to display all the variables of Lua code using some debugger functions, but i can't get the exacte size of the tables, and also i can't retrieve the element of some tables (value, name, etc).
The following code illustrate what i did :
local name, value;
local NIL = {} -- to represent nil variables
local locals = {}
local a = 9
local i = 1
local tab ={1,2,3,4,4,4}
local tab2 = {22,22,22,22}
local tab4 = {'X', 'Y','Z'}
while( true ) do
name, value = debug.getlocal( 1, i )
if ( name == nil ) then break end
locals[ name ] = value == nil and NIL or value
i = i + 1
end
for k, v in pairs( locals ) do
if(type(v) ~= "table") then -- if it's a simple variable
print( k, v )
else
print("tabel : "..k) -- if it's a table, display it's element
print("size : "..#k)
-- I want to diplay all the elements of the table !!
for x, y in pairs(v) do
print(y)
end
end
end
you can use inspect library (useful to print nested tables) or print_r function
I just want to make a simple script that prints a colored text in the chat of the sender after executing a specific command.
First the console gave me an error [attempt to index global 'chat' (a nil value)]. After reloading the Singleplayer and opening the script it didn't do anything.
Current Code:
local ply = LocalPlayer()
local function Test( ply, text, team )
if string.sub( text, 1, 8 ) == "!command" then
chat.AddText( Color( 100, 100, 255 ), "Test" )
end
end
hook.Add( "PlayerSay", "Test", Test )
I hope that someone could help me.
You're using LocalPlayer() (which is only called client-side) as well as chat.AddText() (again, only called client-side) inside of a "PlayerSay" hook (which is a server-side hook). You'd need something else, like ChatPrint()
EDIT: Just realized ChatPrint() doesn't accept Color() arguments in it... you could always try sending a net message:
if SERVER then
util.AddNetworkString( "SendColouredChat" )
function SendColouredChat( ply, text )
if string.sub( text, 1, 8 ) == "!command" then
net.Start( "SendColouredChat" )
net.WriteTable( Color( 255, 0, 0, 255 ) )
net.WriteString( "Test" )
net.Send( ply )
end
end
hook.Add( "PlayerSay", "SendColouredChat", SendColouredChat )
end
if CLIENT then
function ReceiveColouredChat()
local color = net.ReadTable()
local str = net.ReadString()
chat.AddText( color, str )
end
net.Receive( "SendColouredChat", ReceiveColouredChat )
end
EDIT: Returned to this question after a few years. For anyone else who may run into this later on, it's much simpler to just use the GM:OnPlayerChat hook.
local function Command(ply, text, teamOnly, dead)
if text:sub(1, 8) == "!command" then
chat.AddText(Color(100, 100, 255), "Test")
end
end
hook.Add("OnPlayerChat", "TestCommand", Command)
hello I have this json data
"bookinfo": { "result1":{"page":"1","text":"aa","audio":"1.mp3"},
"result2":{"page":"1","text":"bb","audio":"2.mp3"},
"result3":{"page":"1","text":"cc.","audio":"3.mp3"} }
and I use this code
local function networkListener( event )
if ( event.isError ) then
print ( "ERROR!" )
else
local jsonContent = json.decode(event.response).bookinfo
print(jsonContent[1].text )
end
end
json data don't have only have 3 result1,2,3 ... but hundreds, this where the difficulty come from.
My question is jsonContent[1].text don't work, how to access sub-elements without knowing their names ? just by indexing?
** note : I'm sure this is not a duplicate of any question in stackoverflow, thanks a lot.
I found a dirty workaround that at least works in my case, printing the dictionary elements get's un-ordered... so I followed this approach.
I added this function to main
function tablelength(T)
local count = 0
for _ in pairs(T) do count = count + 1 end
return count
end
then I used this
local count = 0
local function networkListener( event )
if (event.isError) then
print ( "ERROR!" )
else
local jsonContent = json.decode(event.response)
count = tablelength(jsonContent.bookinfo); print(count)
local content = jsonContent
local texts = {}
for i=1,count do texts[i] = jsonContent.bookinfo["result"..i].text end
end
end
if you have a better solution please let us know.
Is it faster to check whether a number is equivalent to another, or to look up the number in a table?
I have a program where commands sent from a server are received as numbers. Commands are sent frequently: anywhere from 1/second to 30+/second. Certain commands are ignored while others trigger various events. Would it be better to determine which event to trigger by doing this:
function incoming_integer(n)
if n == 33 then
print('a')
elseif n == 44 then
print('b')
elseif n == 567 then
print('c')
... (the actual list is occasionally pretty long: upwards of ten valid numbers)
end
end
or this:
functions = {
[33] = function() print('a') end,
[44] = function() print('b') end,
[567] = function() print('c') end,
...
}
relevant_commands = {[33]= true, [44]=true, [567]=true ...}
function incoming_integer(n)
if relevant_commands[n] then
functions[n]()
end
end
Is there a point at which one method becomes more efficient?
What if the commands were instead sent as strings?
For your throughput, I would suggest that the overhead for either mechanism is likely to be negligible.
I ran very quick and dirty test of the overhead of the table lookup for both string and numeric keys. See below. Even with a large number of keys and a high hit rate, I struggled to get >1us overhead even on the slowest box I could find.
f = {}
function incoming_integer(n)
local t = f[n]
return t and t()
end
SIZE = 10000
RAN = 20000
REPEAT = 10000000
for i =1,SIZE do
--f[math.random(RAN)] = function() return "z" end
f[tostring(math.random(RAN))] = function() return "z" end
end
tm = os.time()
for i = 1,REPEAT do
--math.random(RAN)
tostring(math.random(RAN))
end
print(os.difftime(os.time(),tm))
tm = os.time()
for i = 1,REPEAT do
--incoming_integer(math.random(RAN))
incoming_integer(tostring(math.random(RAN)))
end
print(os.difftime(os.time(),tm))
If you want to trigger different events with the returned numbers, I would use this way...
function trigger( value )
if ( value == "..." ) then
triggerThis()
elseif ( value == "..." ) then
triggerElse()
-- and so on
end
end
function incoming_integer(n)
if ( n ) then -- check if variable is incoming to prevent errors
trigger( n )
else
alert( "noop, there is nothing here" )
end
end
Maybe you could try keys. Didn't tested it just an example.
http://lua-users.org/wiki/TablesTutorial
table = { [33]="a", [44]="b", [567]="c" }
function onCall( value ) -- if 33
if ( table[value] ) then
return( table[value] ) -- then if exists return a
end
end
onCall( 33 ) -- now it will search in table and get key
EDIT: You could name the triggered functions like the number, so you can directly trigger them. This would save a lot of time!
functions = {[33] = function() print('a') end, etc...}
setmetatable(functions, {__index = function() return function() end end}) -- return empty function if no defined function is found
Usage:
functions[32]() -- ignores
functions[33]() -- does defined function