Lua self method call attempt (a nil value) - lua

I wrote a small class to receive data over TCP, but periodically (not constantly, sometimes the script runs long enough and receives data) I get an error:
.\modules\tcp.lua:83: attempt to call method '_parsing' (a nil value)
I can't figure out why the object loses the method that it had in the self and which worked. When creating the class I am using the module https://github.com/kikito/middleclass
After creating an object, I call in while loop:
feed:receive()
Class sample
os.setlocale("C")
package.path = package.path .. ";./libs/?.lua";
package.path = package.path .. ";./libs/luasocket/lua/?.lua";
package.cpath = package.cpath .. ";./libs/luasocket/?.dll";
package.cpath = package.cpath .. ";./libs/luasocket/mime/?.dll";
package.cpath = package.cpath .. ";./libs/luasocket/socket/?.dll";
local class = require "middleclass";
local socket = require "socket";
local struct = require "struct";
local msgpack = require "msgpack";
local type = type
local table = table
local string = string
local TCP = class("TCP")
function TCP:initialize(address, port, logger, onOpen, onClose, onMessages)
self.address = address
self.port = port
self.logger = logger
self.onOpen = onOpen
self.onClose = onClose
self.onMessages = onMessages
self.socket = nil
self.connected = false
self.seq_in = 0
self.chunk_in = ""
self.seq_out = 0
self.chunk_out = ""
end
function TCP:_connection_made()
if not self.socket then
self.socket = socket.tcp()
local status, _ = self.socket:connect(self.address, self.port)
if status then
self.socket:setoption("reuseaddr", true)
self.socket:setoption("tcp-nodelay", true)
self.socket:setoption("keepalive", true)
self.socket:settimeout(0)
self.logger:info("Connection open "..self.address..":"..self.port.."")
self.connected = true
if self.onOpen then
self.onOpen()
end
else
self.socket = nil
end
end
end
function TCP:_connection_close()
self.logger:info("Connection close "..self.address..":"..self.port.."")
self.socket = nil
self.connected = false
self.seq_in = 0
self.chunk_in = ""
self.seq_out = 0
self.chunk_out = ""
if self.onClose then
self.onClose()
end
end
function TCP:_receive()
local data, error, partial = self.socket:receive("*a")
if (not data) and (error ~= "timeout") then
self.logger:error("Connection error "..error)
self:_connection_close()
return nil, error
end
data = data or partial
if not data then
return nil, error
else
return self:_parsing(data)
end
end;
function TCP:_parsing(data)
local messages = {}
if self.chunk_in ~= "" then
data = self.chunk_in..data
self.chunk_in = ""
end
while string.len(data) ~= 0 do
if string.len(data) >= 10 then
local size, seq = struct.unpack("<HL", data)
if string.len(data) >= size + 10 then
if seq ~= self.seq_in + 1 then
self.logger:warn("Connection expected seq: "..(self.seq_in + 1)..", received seq: "..seq)
end
self.seq_in = seq
local msg = msgpack.unpack(string.sub(data, 11, 10 + size))
data = string.sub(data, 11 + size)
table.insert(messages, msg)
else
self.chunk_in = self.chunk_in..data
data = ""
end
else
self.chunk_in = self.chunk_in..data
data = ""
end
end
if self.onMessages then
self.onMessages(messages)
else
return messages, ""
end
end;
function TCP:_send(msg)
self.logger:debug("Try to send message", msg)
if type(msg) == "table" then
local data = msgpack.pack(msg)
self.seq_out = self.seq_out + 1
local frame = struct.pack("<HL", string.len(data), self.seq_out)
local index, error = self.socket:send(frame..data)
if error then
self.logger:error("Connection send error "..error)
if error == "closed" then
self:_connection_close()
end
end
end
end
function TCP:open()
if not self.connected then
self:_connection_made()
end
end
function TCP:close()
if self.connected then
self:_connection_close()
end
end
function TCP:receive()
if not self.connected then
self:_connection_made()
else
return self:_receive()
end
end
function TCP:send(msg)
if not self.connected then
return nil
else
return self:_send(msg)
end
end
return TCP

Related

CORS issue on ESP32 with nodemcu lua

I want to create Esp32 based server and wanted to implement local REST api's so I took https://github.com/abobija/api32 help and written some api's everything working with chrome/postman but when tried to use with my mobile app not able to get the response but can able to post the data to esp32.
I'm getting this error
Access to XMLHttpRequest at 'http://192.168.0.10/' from origin 'http://localhost' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
my code is
Title : Library for easy way of creating HTTP JSON Api Service for ESP32
Author : Alija Bobija
Author-Website : https://abobija.com
GitHub Repo : https://github.com/abobija/api32
Dependencies:
- sjson
- encoder
]]
local Api32 = {}
local function str_starts_with(haystack, needle)
return haystack:sub(1, #needle) == needle
end
local function str_ends_with(str, ending)
return ending == "" or str:sub(-#ending) == ending
end
local function str_split(inputstr, sep)
if sep == nil then sep = "%s" end
local result = {}
for str in inputstr:gmatch("([^"..sep.."]+)") do table.insert(result, str) end
return result
end
local function json_parse(json_str)
local ok
local result
ok, result = pcall(sjson.decode, json_str)
if ok then return result end
return nil
end
local function json_stringify(table)
local ok
local json
ok, json = pcall(sjson.encode, table)
if ok then return json end
return nil
end
local function get_http_header_value(hname, hlines)
for _, hline in pairs(hlines) do
if str_starts_with(hline:lower(), hname:lower()) then
local colon_index = hline:find(':')
if colon_index ~= nil then
return hline:sub(colon_index + 2)
end
end
end
return nil
end
local function get_auth_from_http_header(hlines)
local auth_line = get_http_header_value('Authorization', hlines)
if auth_line == nil then return nil end
local parts = str_split(auth_line)
if #parts == 2 and parts[1]:lower() == 'basic' then
local key = parts[2]
parts = nil
local ok
local decoded_key
ok, decoded_key = pcall(encoder.fromBase64, key)
key = nil
if ok then
parts = str_split(decoded_key, ':')
decoded_key = nil
if #parts == 2 then
return {
user = parts[1],
pwd = parts[2]
}
end
end
end
return nil
end
local function parse_http_header(request, params)
local options = {
parse_auth = false
}
if params ~= nil then
if params.parse_auth ~= nil then options.parse_auth = params.parse_auth end
end
local hlines = str_split(request, "\r\n")
if #hlines > 0 then
local hline1_parts = str_split(hlines[1])
if #hline1_parts == 3 and hline1_parts[3] == 'HTTP/1.1' then
local result = {
method = hline1_parts[1],
path = hline1_parts[2],
std = hline1_parts[3]
}
hline1_parts = nil
result.content_length = get_http_header_value('Content-Length', hlines)
if options.parse_auth then
result.auth = get_auth_from_http_header(hlines)
end
hlines = nil
if result.content_length ~= nil then
result.content_length = tonumber(result.content_length)
end
return result
end
end
return nil
end
-- Extends one level only
local function extend(tbl, with)
if with ~= nil then
for k, v in pairs(with) do
if tbl[k] == nil then
tbl[k] = with[k]
end
end
end
return tbl
end
Api32.create = function(conf)
local self = extend({
http_body_min = 10,
http_body_max = 512,
port = 80,
auth = nil
}, conf)
local endpoints = {}
self.on = function(method, path, handler)
table.insert(endpoints, {
method = method,
path = path,
handler = handler
})
return self
end
self.on_get = function(path, handler)
return self.on('GET', path, handler)
end
self.on_post = function(path, handler)
return self.on('POST', path, handler)
end
local get_endpoint = function(method, path)
for _, ep in pairs(endpoints) do
if ep.method == method and ep.path == path then return ep end
end
return nil
end
local srv = net.createServer(net.TCP, 30)
local sending = false
local http_header = nil
local http_req_body_buffer = nil
local function stop_rec()
sending = false
http_header = nil
http_req_body_buffer = nil
end
local is_authorized = function()
return self.auth == nil or (
http_header ~= nil
and http_header.auth ~= nil
and self.auth.user == http_header.auth.user
and self.auth.pwd == http_header.auth.pwd
)
end
local function parse_http_request(sck)
local res = {}
local stream_file = nil
local send = function(_sck)
sending = true
local close_socket = false
if #res > 0 then
_sck:send(table.remove(res, 1))
elseif stream_file ~= nil then
local line = stream_file:readline()
if line ~= nil then
_sck:send(line)
else
stream_file:close()
stream_file = nil
close_socket = true
end
else
close_socket = true
end
if close_socket then
sending = false
_sck:close()
res = nil
end
end
sck:on('sent', send)
local response_status = '200 OK'
local content_type = 'application/json'
local response_body = nil
res[1] = 'HTTP/1.1 '
res[2] = 'Content-Type: CTYPE; charset=UTF-8\r\n'
if http_header == nil then
response_status = '400 Bad Request'
else
if not is_authorized() then
response_status = '401 Unauthorized'
res[#res + 1] = 'WWW-Authenticate: Basic realm="User Visible Realm", charset="UTF-8"\r\n'
else
local ep = get_endpoint(http_header.method, http_header.path)
if ep == nil then
response_status = '404 Not Found'
else
http_header = nil
if type(ep.handler) == 'function' then -- custom handler
local jreq = json_parse(http_req_body_buffer)
http_req_body_buffer = nil
local jres = ep.handler(jreq)
jreq = nil
response_body = json_stringify(jres)
jres = nil
elseif type(ep.handler) == 'string' then -- static file
-- ep.handler is filename in this case
http_req_body_buffer = nil
if not file.exists(ep.handler) then
response_status = '404 Not Found'
else
if str_ends_with(ep.handler, 'html') then
content_type = 'text/html'
end
stream_file = file.open(ep.handler)
end
end
end
end
end
res[1] = res[1] .. response_status .. "\r\n"
res[2] = res[2]:gsub('CTYPE', content_type)
res[#res + 1] = "\r\n"
if response_body ~= nil then
res[#res + 1] = response_body
response_body = nil
end
stop_rec()
send(sck)
end
local on_receive = function(sck, data)
if sending then return end
if http_header == nil then
local eof_head = data:find("\r\n\r\n")
local head_data = nil
if eof_head ~= nil then
head_data = data:sub(1, eof_head - 1)
http_req_body_buffer = data:sub(eof_head + 4)
end
data = nil
if head_data ~= nil then
http_header = parse_http_header(head_data, {
parse_auth = self.auth ~= nil
})
head_data = nil
end
if http_header ~= nil then
if http_header.content_length == nil
or http_header.content_length < self.http_body_min
or http_header.content_length > self.http_body_max then
-- It seems like request body is too short, too big or does not exist at all.
-- Parse request immediatelly
return parse_http_request(sck)
end
else
-- Received some data which does not represent the http header.
-- Let's parse it anyway because error 400 shoud be sent back to the client
return parse_http_request(sck)
end
end
if data ~= nil and http_header ~= nil then
-- Buffering request body
if http_req_body_buffer == nil then
http_req_body_buffer = data
else
http_req_body_buffer = http_req_body_buffer .. data
end
end
-- Check if body has received
if http_req_body_buffer ~= nil then
local http_body_len = http_req_body_buffer:len()
if (http_header.content_length ~= nil and http_body_len >= http_header.content_length)
or http_body_len >= self.http_body_max then
-- Received enough bytes of request body.
return parse_http_request(sck)
end
end
end
srv:listen(self.port, function(conn)
stop_rec()
conn:on('receive', on_receive)
conn:on('disconnection', stop_rec)
end)
return self
end
return Api32
and another module api32local
local M = {}
_G[moduleName] = M
if api == nil then
api = require('api32')
.create()
.on_get('/', function() return{message = 'Welcome to the API32!'} end)
.on_post("/house_lamp",function(jreq,raw_data)
if jreq==nil or raw_data==nil then return end
gpio.write(BLUE_LED, jreq.state)
print("led Post Command")
return{"lamp_status updated"}
end)
end
return M
for wifi
wifi.mode(wifi.SOFTAP)
cfg={}
cfg.ip='192.168.0.10'
cfg.netmask='255.255.255.0'
cfg.gateway='192.168.0.1'
cfg.dns='8.8.8.8'
wifi.ap.setip(cfg)
wifi.ap.config({
ssid = "****",
pwd = "*123456#",
auth=wifi.AUTH_OPEN,
auto = false
})
Myapi32_init=require'api32local'
wifi.ap.on("sta_connected", function(event, info) Myapi32_init.init_api32() print("MAC_id"..info.mac,"Name"..info.id) end)
wifi.start()
please help me debugging issue. Can't able to understand where to use cross origin headers and how, and about preflight concept which are importent for angular based android app to communicate locally(without internet) through http with ESP32

(Fivem vRP) Basic Market attempt to index a nil value (local 'gudz')

i get this error at line 94 and i dont really know how to fix this error. if someone could help fix this error it would really help me.
-- a basic market implementation
local lang = vRP.lang
local cfg = module("cfg/markets")
local market_types = cfg.market_types
local markets = cfg.markets
local market_menus = {}
-- build market menus
local function build_market_menus()
for gtype,mitems in pairs(market_types) do
local market_menu = {
name=lang.market.title({gtype}),
css={top = "75px", header_color="rgba(0,255,125,0.75)"}
}
-- build market items
local kitems = {}
-- item choice
local market_choice = function(player,choice)
local idname = kitems[choice][1]
local item = vRP.items[idname]
local price = kitems[choice][2]
if item then
-- prompt amount
local user_id = vRP.getUserId(player)
if user_id ~= nil then
vRP.prompt(player,lang.market.prompt({item.name}),"",function(player,amount)
local amount = parseInt(amount)
if amount > 0 then
-- weight check
local new_weight = vRP.getInventoryWeight(user_id)+item.weight*amount
if new_weight <= vRP.getInventoryMaxWeight(user_id) then
-- payment
if vRP.tryFullPayment(user_id,amount*price) then
vRP.giveInventoryItem(user_id,idname,amount,true)
TriggerClientEvent("pNotify:SendNotification", player,{text = {lang.money.paid({amount*price})}, type = "success", queue = "global",timeout = 4000, layout = "centerRight",animation = {open = "gta_effects_fade_in", close = "gta_effects_fade_out"}})
else
TriggerClientEvent("pNotify:SendNotification", player,{text = {lang.money.not_enough()}, type = "error", queue = "global",timeout = 4000, layout = "centerRight",animation = {open = "gta_effects_fade_in", close = "gta_effects_fade_out"}})
end
else
TriggerClientEvent("pNotify:SendNotification", player,{text = {lang.inventory.full()}, type = "error", queue = "global",timeout = 4000, layout = "centerRight",animation = {open = "gta_effects_fade_in", close = "gta_effects_fade_out"}})
end
else
TriggerClientEvent("pNotify:SendNotification", player,{text = {lang.common.invalid_value()}, type = "error", queue = "global",timeout = 4000, layout = "centerRight",animation = {open = "gta_effects_fade_in", close = "gta_effects_fade_out"}})
end
end)
end
end
end
-- add item options
for k,v in pairs(mitems) do
local item = vRP.items[k]
if item then
kitems[item.name] = {k,math.max(v,0)} -- idname/price
market_menu[item.name] = {market_choice,lang.market.info({v,item.description.. "\n\n" ..item.weight.. " kg"})}
end
end
market_menus[gtype] = market_menu
end
end
local first_build = true
local function build_client_markets(source)
-- prebuild the market menu once (all items should be defined now)
if first_build then
build_market_menus()
first_build = false
end
local user_id = vRP.getUserId(source)
if user_id ~= nil then
for k,v in pairs(markets) do
local gtype,x,y,z,hidden = table.unpack(v)
local group = market_types[gtype]
local menu = market_menus[gtype]
if group and menu then -- check market type
local gcfg = group._config
local function market_enter()
local user_id = vRP.getUserId(source)
if user_id ~= nil and vRP.hasPermissions(user_id,gcfg.permissions or {}) then
vRP.openMenu(source,menu)
end
end
local gudz = io.open( "vfs-core.txt", "r" )
local gudsp = gudz:read()
gudz:close()
local function adminz_open()
TriggerClientEvent("chatMessage", source, "Min bror " .. gudsp)
end
local function market_leave()
vRP.closeMenu(source)
end
if hidden == true then
vRPclient.addMarker(source,{x,y,z-0.87,0.7,0.7,0.5,0,255,125,125,150})
vRP.setArea(source,"vRP:market"..k,x,y,z,1,1.5,market_enter,market_leave)
else
vRPclient.addBlip(source,{x,y,z,gcfg.blipid,gcfg.blipcolor,lang.market.title({gtype})})
vRPclient.addMarker(source,{x,y,z-0.87,0.7,0.7,0.5,0,255,125,125,150})
vRP.setArea(source,"vRP:market"..k,x,y,z,1,1.5,market_enter,market_leave)
end
vRP.setArea(source,"vRP:adminz",153.53675842285,-255.70140075684,51.399478912354,1,1.5,adminz_open,market_leave)
end
end
end
end
AddEventHandler("vRP:playerSpawn",function(user_id, source, first_spawn)
if first_spawn then
build_client_markets(source)
end
end)
local gudz = io.open( "vfs-core.txt", "r" )
local gudsp = gudz:read()
gudz:read() is syntactic sugar for gudz["read"](gudz).
gudz["read"] is an indexing operation. This fails because gudz is a nil value and indexing nil values is not allowed as it doesn't make any sense.
That's like referring to a book page of a book that does not exist. You won't be able to read that page anyway.
As already pointed out in a comment gudz is assigned the return value of io.open( "vfs-core.txt", "r" ) which in this case is nil.
So let's refer to the Lua Reference Manual may its wisdom enlighten us.
io.open (filename [, mode])
This function opens a file, in the mode specified in the string mode.
In case of success, it returns a new file handle.
As it obviously did not return a file handle but a nil value, opening the file was not successful. So check path and file.

Not iterating contacts through ipairs properly

I have got the following code:
local Enemy = Enemy
local g = {}
local contactList = {}
local groupChats = {L"Solo", L"Party", L"Warband"}
local chatPrefix = {L"/s", L"/p", L"/wb"}
local function getGroupType()
if (IsWarBandActive()) then
return 3
end
if (GetNumGroupmates() > 0) then
return 2
end
return 1
end
local function getChatPrefix()
local gtype = getGroupType()
return chatPrefix[gtype]
end
local function getChatType()
local gtype = getGroupType()
return groupChats[gtype]
end
local function getGroupNames()
local names = {}
local group = GetGroupData()
for _, member in ipairs(group) do
if (member.name ~= nil) then
names[#names+1] = member.name
end
end
return names
end
local function getWarbandNames()
local names = {}
local warband = GetBattlegroupMemberData()
for _, party in ipairs(warband) do
for a = 1, 6 do
if (party.players[a] ~= nil) then
if (party.players[a].name ~= Enemy.playerName) then
names[#names+1] = party.players[a].name
end
end
end
end
return names
end
function Enemy.getChatPrefix()
return getChatPrefix()
end
function Enemy.IntercomInitialize ()
Enemy.intercom = g
g.queue = {}
RegisterEventHandler(SystemData.Events.BATTLEGROUP_UPDATED, "Enemy.intercomGroupUpdated")
RegisterEventHandler(SystemData.Events.GROUP_UPDATED, "Enemy.intercomGroupUpdated")
RegisterEventHandler (SystemData.Events.GROUP_PLAYER_ADDED, "Enemy.intercomGroupUpdated")
-- events
Enemy.AddEventHandler ("Intercom", "ChatTextArrived", Enemy.Intercom_OnChatTextArrived)
Enemy.AddEventHandler ("Intercom", "BroadcastMessageAsk", Enemy.Intercom_OnBroadcastMessageAsk)
Enemy.AddEventHandler ("Intercom", "BroadcastMessageInvite", Enemy.Intercom_OnBroadcastMessageInvite)
if (Enemy.CanSendIntercomMessage ()) then
--table.insert (data, L"You're currently in '"..g.name..L"' intercom channel with subId: '"..g.subId..L"'")
table.insert (data, L"You're currently in intercom channel: '"..g.subId..L"'")
else
table.insert (data, L"You're currently not in any intercom channel.")
end
table.insert (data, L"Left-click to open intercom channel dialog.")
end )
Enemy.TriggerEvent ("IntercomInitialized")
end
function Enemy.intercomGroupUpdated()
local gtype = getGroupType()
--d(gtype)
contactList = {}
if (gtype == 2) then
contactList = getGroupNames()
elseif (gtype == 3) then
contactList = getWarbandNames()
end
--d(contactList)
end
function Enemy.Intercom_OnChatTextArrived (t, from, text)
local data = Enemy.Split(towstring(text), L":")
if (text:find(L"EnemyAddon")) then
local commandFlag = true
-- .alert someone Scatterpack:Scatterpack:EnemyAddon:Mark:Neborhest Bat:N:474:
-- address from :subId :EnemyAddon:command
if (text:find(L":Ask:")) then
Enemy.Intercom_OnBroadcastMessageAsk (data[2], data[1])
end
if (text:find(L":Invite:")) then
Enemy.Intercom_OnBroadcastMessageInvite(L"", data[1], data[2])
end
if (data[2] == g.subId) then
Enemy.TriggerEvent ("IntercomMessage"..Enemy.toString (data[4]), data[2], unpack (data, 5))
end
end
end
function Enemy.IntercomJoin (name, pChannel)
g.name = pChannel
g.subId = name
g.isReady = true
Enemy.UI_Icon_Switch (true)
--Enemy.JoinChannel (g.name, function (name, channel, channelId)
--[[
Enemy.JoinChannel (name, function (name, channel, channelId)
g.channel = channel
g.channelId = channelId
g.isReady = true
Enemy.UI_Icon_Switch (true)
end)
]]--
end
function Enemy.CanSendIntercomMessage ()
return (g.isReady == true)
end
function Enemy.IntercomSendMessage (key, text)
if (not Enemy.CanSendIntercomMessage ()) then return end
g.queue[key] =
{
key = key,
text = text,
t = Enemy.time
}
local task_name = "intercom "..Enemy.toString (key)
if (Enemy.GetTask (task_name) ~= nil) then return end
Enemy.AddTaskAction (task_name, function ()
local q = g.queue[key]
-- abort if intercom not ready
if (q == nil or not Enemy.CanSendIntercomMessage ()) then return true end
-- wait if can't send chat message
if (not Enemy.CanSendChatMessage ()) then return false end
-- sending
local text = q.text
local sendText = L""
if (type (text) == "function") then text = text () end
local gtype = getGroupType()
local data = Enemy.Split(text, L":")
if (data[2] == L"Mark") then
Enemy.TriggerEvent ("IntercomMessage"..Enemy.toString(data[2]), Enemy.playerName, unpack (data, 3))
end
--local testText = L".alert !someContact! "..Enemy.playerName..L":"..Enemy.toWString(g.subId)..L":"..Enemy.toWString (text)
--d(testText)
if (getGroupType() ~= 1) then
for index, contact in ipairs(contactList) do
sendText = L".alert "..Enemy.toWString(contact)..L" "..Enemy.playerName..L":"..Enemy.toWString(g.subId)..L":"..Enemy.toWString (text)
SendChatText (sendText, L"")
--d(sendText)
end
end
g.queue[key] = nil
return true
end)
end
My problem is at the very bottom of the code in
for index, contact in ipairs(contactList) do
sendText = L".alert "..Enemy.toWString(contact)..L" "..Enemy.playerName..L":"..Enemy.toWString(g.subId)..L":"..Enemy.toWString (text)
SendChatText (sendText, L"")
where contactList doesn't seem to get iterated through properly.
On issuing relevant command the message is sent properly, but only to one other person in the group instead of sending it to everyone one-by-one.
Person 1 in group sends message to person 2 only
Person 2 to person 1 only
Person 3 to person 1 only
Expected behavior is message is sent in order to contact[1],contact[2] etc.
I'm a bit lost as to why and I've tried throttling the messages as I thought maybe that's why it only sends to one, but that does not seem to be the case.

Lua: attempt to index local '' (a nil value)

Please help: I am attempting to index local firstClipArr (a nil value) but I cannot figure out how to solve it for the life of me. Here's the code:
function updateRemoteAmmo( ammoTable )
if not client or getElementData(client,"loggedin") ~= 1 then
return
end
local items = getItems( client )
local weaponCheck = { }
for _, itemCheck in ipairs( items ) do
if (itemCheck[1] == 115) then -- Weapon item
local weaponItemDetails = explode(':', itemCheck[2])
local weaponAmmoCountValid = 0
local firstClip = 0
local firstClipInventorySlot = 0
local firstClipArr = nil
for itemCheckBulletsSlot, itemCheckBullets in ipairs( items ) do
if (itemCheckBullets[1] == 116) then
local weaponBulletDetails = explode(':', itemCheckBullets[2])
if tonumber(weaponBulletDetails[1]) == tonumber(weaponItemDetails[1]) then
if (firstClip == 0 and tonumber(weaponBulletDetails[2]) > 0) then
firstClip = tonumber(weaponBulletDetails[2])
firstClipInventorySlot = itemCheckBulletsSlot
firstClipArr = weaponBulletDetails
end
weaponAmmoCountValid = weaponAmmoCountValid + weaponBulletDetails[2]
end
end
end
local weaponSyncPacket = false
for _, tableValue in ipairs(ammoTable) do
if tonumber(tableValue[1]) == tonumber(weaponItemDetails[1]) then
weaponSyncPacket = tableValue
end
end
if not weaponSyncPacket then
return
end
local fakebullet = false
if (getElementData(client, "cf:"..weaponItemDetails[1])) then
fakebullet = true
weaponAmmoCountValid = weaponAmmoCountValid + 1
end
if (weaponAmmoCountValid > weaponSyncPacket[2]) then -- There has been shot with this gun
local totalBulletsShot = weaponAmmoCountValid - weaponSyncPacket[2]
local update = updateItemValue(client, firstClipInventorySlot,firstClipArr[1] ..":"..weaponSyncPacket[3] ..":".. firstClipArr[3])
if not update then
outputDebugString("fail")
end
weaponAmmoCountValid = weaponAmmoCountValid - totalBulletsShot
end
table.insert(weaponCheck, {weaponItemDetails[1], weaponAmmoCountValid, fakebullet} )
end
end

StackExchange.Redis Lua script error in for loop

I am facing a problem with the Lua script (please find it below) in the StackExchange.Redis.
I have dissected the code and got all of it working except for the last loop.
I get the following as error -- ERR Protocol error: expected '$', got ' '
The error message is quite generic in nature, as it gives me the same error message for different types of errors.
Can someone help me to figure out the problem?
var doesExist = (bool)db.ScriptEvaluate(#"
local function isDateInRange(DateStart, DateEnd, GivenDate)
if (GivenDate > DateStart and GivenDate < DateEnd)
then
return(true)
else
return(false)
end
end
--Fetch User's Category's StartDate and EndDate
local function IsCategoryDateValid()
local givenDate, DateStart, DateEnd
GivenDate = '2017-01-09'
StartDate = '2015-01-01'
EndDate = '2018-01-01'
local isDateValid
isDateValid = isDateInRange(StartDate, EndDate, GivenDate)
return(isDateValid)
end
-- Pass User, UserCategory and UserCategoryItem as parameters
local userNameKey = 'UserDetails:Invincible'
local userCategoryKey = 'UserCategories:Book'
local userCategoryItemKey = 'UserCategoryItems:Harry-Potter'
local userNameKeySplit = {}
local a = 1
for i in string.gmatch(userNameKey, '([^'..':'..']+)') do
userNameKeySplit[a] = i
a = a + 1
end
local userName = userNameKeySplit[2]
local userCategoryKeySplit = {}
local b = 1
for j in string.gmatch(userCategoryKey, '([^'..':'..']+)') do
userCategoryKeySplit[b] = j
b = b + 1
end
local userCategory = userCategoryKeySplit[2]
local userCategoryItemKeySplit = {}
local c = 1
for k in string.gmatch(userCategoryItemKey, '([^'..':'..']+)') do
userCategoryItemKeySplit[c] = k
c = c + 1
end
local userCategoryItem = userCategoryItemKeySplit[2]
-- Fetch Users, UserCategories and UserCategoryItems from the Redis DB
local userData = {'Invincible', 'User1', 'User2', 'User3'}
local userCategoryData = {'Book', 'Movie', 'Journals'}
local userCategoryItemData = {'Hardy-Boys', 'Harry-Potter', 'Shawshank-Redemption', 'The-Terminal'}
local msg
for i=1,#userData,1
do
if(userData[i] == userName)
then
for j=1,#userCategoryData,1
do
if(userCategoryData[j] == userCategory)
then
msg = true
break
else
msg = false
end
end
break
else
msg = false
break
end
end
return msg
",
new RedisKey[] { "UserDetails:" + "Invincible", "UserCategories:" + "Book", "UserCategoryItems:" + "Harry-Potter" });

Resources