argument 1 missing or nil - lua

i am making a tower defense game but it keeps saying argument 1 missing or nil
when i try to spawn the tower
this is a module script
(error at line 11)
local PhysicsServive = game:GetService("PhysicsService")
local ServerStorage = game:GetService("ServerStorage")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local PhysicsService = game:GetService("PhysicsService")
local events = ReplicatedStorage:WaitForChild("Events")
local Tower = {}
local SpawnTowerEvent = events:WaitForChild("SpawnTower")
function Tower.Spawn(player, Name, CFrame)
local towerExists = ReplicatedStorage.Towers:FindFirstChild(Name)
if towerExists then
local newTower = towerExists:Clone()
newTower.HumanoidRootPart.CFrame = CFrame
newTower.Parent = workspace.Towers
newTower.HumanoidRootPart:SetNetworkOwner(nil)
for i, object in ipairs(newTower:GetDescendants()) do
if object:IsA("BasePart") then
PhysicsService:SetPartCollisionGroup(object, "Tower")
object.Material = Enum.Material.ForceField
end
end
else
warn("Missing:", Name)
end
end
SpawnTowerEvent.OnServerEvent:Connect(Tower.Spawn())
return Tower

SpawnTowerEvent.OnServerEvent:Connect(Tower.Spawn())
Connect expects a function value, not a function call (unless that function call resolves to a function value). Remove the call operator ().
SpawnTowerEvent.OnServerEvent:Connect(Tower.Spawn)
You call Tower.Spawn without any arguments. Therefor you call FindFirstChild(nil) which causes the observed error.
Also it does not return a function value.

Related

Can't get to a value inside a player in lua

Code I Tried
game.Workspace.burgerclick.OnServerEvent:Connect(function()
local playername = game.Workspace.ClickPlayer.Value
local player = game.Players:FindFirstChild(playername)
local playaname = player.Name
local fpval = game.Players[playaname].FP.Value
fpval = fpval + 1
end)
I am making a game and I wanted to have a button that updates the value of something called FP, in the workspace I have a stringvalue called ClickPLayer which updates to the player clicking the button. that works. I made a variable that is the value the stringvalue, but when I put the variable inside the line when I update the FP Value it says the variable is not a valid member of players. I'm not sure what to do.
I think the correct code should be something like:
game.Players[playaname].FP.Value = game.Players[playaname].FP.Value + 1
Because, when you do:
local fpval = game.Players[playaname].FP.Value
fpval = fpval + 1
You are copying the value of game.Players[playaname].FP.Valueto fpval and incrementing the copy (fpval = fpval + 1), not the value held by game.Players[playaname].FP.
The most correct and efficient code would be
local Players = game:GetService("Players")
local fpval
local plr
workspace.burgerclick.Activated:Connect(function()
plr = workspace.ClickPlayer.Value
fpval = Players[plr].FP
fpval.Value = fpval.Value + 1
end)
In the documentation of TextButtons and ImageButtons, there is an Activated event that can be used for this, instead of firing a server from a LocalScript which is what your script aims to do now. However, if the button is in the PlayerGui and you have an activation LocalScript for it, you probably want to use this code instead:
local fpval
workspace.burgerclick.OnServerEvent:Connect(function(plr)
fpval = plr.FP
fpval.Value = fpval.Value + 1
end)

Lua LGI unpack GLib.Variant object

I'm trying to get password from keyring for awesome-wm session (using DBus via lgi library).
I'm able to find keyring entry path, open communication session and unlock entry.
Then I call GetSecrets method and store result into secret variable.
According to the documentation it is supposed to be a struct Secret. Seems like lgi cannot handle this type and passes it as userdata type (at least I wasn't able to make it give access to struct fields). Is there a way to get struct Secret value field contents without writing custom C handler?
Here is the code:
local bus = Gio.bus_get_sync(Gio.BusType.SESSION, nil)
local attr = {}
attr[1] = {attribute = "value"} -- attribute-value pair to search for
-- search for secret path
local name = "org.freedesktop.secrets"
local object = "/org/freedesktop/secrets"
local interface = "org.freedesktop.Secret.Service"
local method = "SearchItems"
local message = Gio.DBusMessage.new_method_call(name, object, interface, method)
message:set_body(GLib.Variant("(a{ss})", attr))
local result, err = bus:send_message_with_reply_sync(message, Gio.DBusSendMessageFlags.NONE,
-1, nil)
local location
for _, l in result:get_body():pairs() do
if #l > 0 then location = l[1] end
end
print(location) -- returns "/org/freedesktop/secrets/collection/Default/1"
-- open session
local name = "org.freedesktop.secrets"
local object = "/org/freedesktop/secrets"
local interface = "org.freedesktop.Secret.Service"
local method = "OpenSession"
local message = Gio.DBusMessage.new_method_call(name, object, interface, method)
message:set_body(GLib.Variant("(sv)", {"plain", GLib.Variant("s", "")}))
local result, err = bus:send_message_with_reply_sync(message, Gio.DBusSendMessageFlags.NONE,
-1, nil)
local session = result:get_body()[2]
print(session) -- returns "/org/freedesktop/secrets/session/s4"
-- unlock key
local name = "org.freedesktop.secrets"
local object = "/org/freedesktop/secrets"
local interface = "org.freedesktop.Secret.Service"
local method = "Unlock"
local message = Gio.DBusMessage.new_method_call(name, object, interface, method)
message:set_body(GLib.Variant("(ao)", {{location}}))
local result, err = bus:send_message_with_reply_sync(message, Gio.DBusSendMessageFlags.NONE,
-1, nil)
-- at this point key property "Locked" if false. tested using d-feet
-- get secret
local name = "org.freedesktop.secrets"
local object = "/org/freedesktop/secrets"
local interface = "org.freedesktop.Secret.Service"
local method = "GetSecrets"
local message = Gio.DBusMessage.new_method_call(name, object, interface, method)
message:set_body(GLib.Variant("(aoo)", {{location},session}))
local result, err = bus:send_message_with_reply_sync(message, Gio.DBusSendMessageFlags.NONE,
-1, nil)
local secret = result:get_body()
print(#secret) -- returns "1"
print(secret) -- returns table address
print(type(secret)) -- returns "userdata"
-- lock key
local name = "org.freedesktop.secrets"
local object = "/org/freedesktop/secrets"
local interface = "org.freedesktop.Secret.Service"
local method = "Lock"
local message = Gio.DBusMessage.new_method_call(name, object, interface, method)
message:set_body(GLib.Variant("(ao)", {{location}}))
local result, err = bus:send_message_with_reply_sync(message, Gio.DBusSendMessageFlags.NONE,
-1, nil)
-- close session
local name = "org.freedesktop.secrets"
local object = location
local interface = "org.freedesktop.Secret.Session"
local method = "Close"
local message = Gio.DBusMessage.new_method_call(name, object, interface, method)
local result, err = bus:send_message_with_reply_sync(message, Gio.DBusSendMessageFlags.NONE,
-1, nil)
edit
When I do print(secret), lgi.rec 0x7f57d0014960:GLib.Variant is returned.
So, secret is an object. How can I retrieve value field from GLib.Variant object?
edit 2
secret:get_data_as_bytes():get_data() dumps struct in bytearray form; secret:print() returns formatted string of struct. I wonder if there's a better way.
edit 3
type of secret variable is (a{o(oayays)})
Code to recreate an object of that type:
local lgi = require 'lgi'
local Gio = lgi.require 'Gio'
local GLib = lgi.require 'GLib'
local var = GLib.Variant("(a{o(oayays)})", {{["/path/to/object"]={"/path/to/session","parameters","value","content_type"}}})
(Note that I didn't install this password manager or try any of this at all)
Last time I asked the author of LGI about such issue, the answer was:
I have submitted fix to Variant which restores this functionality. So
an example of use will be:
local function called_from_C(userdata)
local variant = GLib.Variant(userdata)
print(variant)
end
if you have to support older (well, released :) lgi versions, you can
use undocumented way:
local core = require 'lgi.core'
local function called_from_C(userdata)
local variant = core.record.new(GLib.Variant, userdata)
print(variant)
end
Note that there is other ways. To work around another such bugs, I also once created a C Lua plugin and just wrote that code in C. That's actually rather trivial with Lua [2].
Another way, if you use LuaJIT, is to use the built-in FFI to just-in-time compile the struct definition into a Lua object [1].
Finally, if the question is more about how to unpack "working" GVariant values once they are consumed properly by LGI, look at my code for this here https://github.com/Elv13/wirefu/blob/master/proxy.lua
[1] http://luajit.org/ext_ffi_api.html
[2] https://github.com/Elv13/lua_async_binding/blob/master/src/luabridge.c#L407
Finally I've found a solution. To unpack a value of a complex type, for example (a{o(oayays)}), one should use get_child_value function.
secret:get_child_value(0):get_child_value(0):get_child_value(1):get_child_value(2).value
Explanation: index tuple; index array; index dict; index tuple

ROBLOX sandboxing

I am new to sandboxing in Lua, and would like to learn how to filter stuff like :GetChildren() or :Kick().
This is what I have so far:
function safeGetChildren(obj)
local objs = {}
for _,v in pairs(obj) do
if not v.Name:match("^^") then
table.insert(objs, v.Name)
end
end
return objs
end
function safeClearAllChildren(obj)
if obj:IsA("Player") or obj:IsA("Players") or obj:IsA("Workspace") or obj:IsA("ServerScriptService") or obj:IsA("Lighting") or obj:IsA("ReplicatedStorage") or obj:IsA("StarterGui") then
return error("Cannot clear this object!");
else
obj:ClearAllChildren();
end
end
function safeRemoveObject(obj)
local name = obj.Name:lower();
if obj:IsA("Player") or name == "remoteevents" or obj.Parent == "RemoteEvents" or obj.Parent == "ReplicatedStorage" or obj.Parent == "StarterGui" or obj.Parent == "ServerScriptService" or obj.Parent == "TinySB" then
return error("Cannot destroy this object!");
else
obj:Destroy();
end
end
local Globals = {
-- Globals
workspace = workspace,
print = print,
error = error,
table = table,
pairs = pairs,
game = game,
string = string,
_G = _G,
getfenv = getfenv,
loadstring = loadstring,
ipairs = ipairs,
next = next,
os = os,
pcall = pcall,
rawequal = rawequal,
rawget = rawget,
rawset = rawset,
select = select,
setfenv = setfenv,
setmetatable = setmetatable,
tonumber = tonumber,
tostring = tostring,
type = type,
unpack = unpack,
_VERSION = _VERSION,
xpcall = xpcall,
collectgarbage = collectgarbage,
assert = assert,
gcinfo = gcinfo,
coroutine = coroutine,
string = string,
table = table,
math = math,
delay = delay,
LoadLibrary = LoadLibrary,
printidentity = printidentity,
spawn = spawn,
tick = tick,
time = time,
UserSettings = UserSettings,
Version = Version,
wait = wait,
warn = warn,
ypcall = ypcall,
PluginManager = PluginManager,
LoadRobloxLibrary = LoadRobloxLibrary,
settings = settings,
stats = stats,
-- Functions
["require"] = function(...)
return error("Cannot require object (API disabled)");
end,
["getchildren"] = function(...)
return safeGetChildren(...);
end,
['children'] = function(...)
return safeGetChildren(...);
end,
['clearallchildren'] = function(...)
return safeClearAllChildren(...);
end,
['destroy'] = function(...)
return safeRemoveObject(...);
end,
['remove'] = function(...)
return safeRemoveObject(...);
end,
['kick'] = function(...)
return safeRemoveObject(...);
end,
['saveplace'] = function(...)
return error("Cannot save place (API Disabled)");
end
}
setfenv(1, Globals)
table.foreach(workspace:GetChildren(), print)
I made this in a few hours but things like :GetChildren() aren't filtered in this environment. If anyone can help me with an explanation on what each part of the code required does will really help.
You're setting safe wrapper under name 'getchildren' in new environment. But later, when testing, you're calling 'GetChildren', taken from 'workspace' table, and not from global variable in new environment.
Replacing function in global environment doesn't mean replacing functions with same name in all tables/objects. For that to work, object must call function from current global environment, and not function from internal tables or lexical closures.

How to use Lua field extractor in Wireshark?

I have a protocol like this
"Packet" - A sequence of messages
{Head}{Content}{Head}{Content}...
"Head" - 1 byte
bit 1-7 : msg length
bit 8 : true msg or not
It is a udp communication, I have to use that bit 8 to determine if I need to skip the message.
Following is my toy parser, the Problem I am facing is how to extract the bool value helping me to make the decision.
TOY_proto = Proto("TOY", "TOY Protocol")
local isSkip = ProtoField.new("Is Skip?", "mytoy.isSkip", ftypes.BOOLEAN, {"Yes", "No"}, 8, 0x01)
local msgLen = ProroField.new("Message Length", "mytoy.msgLen", ftypes.UINT8, nil, base.DEC, 0xFE)
TOY_proto.fields = {isSkip, msgLen}
local isSkip_Field = Field.new("mytoy.isSkip")
local function getIsSkip()
return isSkip_Field()()
end
local msgLen_Field = Field.new("mytoy.msgLen")
local function getMsgLen()
return msgLen_Field()()
end
function TOY_proto.dissector(tvbuf, pktinfo, root)
pktinfo.cols.protocol = "TOY"
local pktlen = tvbuf:reported_length_remaining()
local pos = 0
while pos < pktlen do
local headTree = tree:add("Head")
headTree:add_le(isSkip, tvbuf:range(pos,1))
headTree:add_le(msgLen, tvbuf:range(pos,1))
if getIsSkip() then
pos = pos + getMsgLen()
else
-- do something else
end
end
end
udp_table = DissectorTable.get("udp.port")
udp_table:add(6628, TOY_proto)
The Problem is that in the first loop, every variable is doing right, but after the first loop, the value returned from getIsSkip() and getMsgLen() are always unchanged.
When you do this:
return isSkip_Field()()
What you're really doing is logically equivalent to this:
-- extract the FieldInfo object using the Field object "isSkip_Field"
local tempFieldInfo = isSkip_Field()
-- get the Lua boolean value of the FieldInfo object
local tempValue = tempFieldInfo()
-- return it
return tempValue
I mention the above to explain why you're getting what you're getting later in this answer...
When you invoke a field extractor (i.e., you call a Field object to get a FieldInfo object), you actually get back every FieldInfo object of that Field's type that exists in that packet at the time the extractor is invoked. Your packet contains multiple "messages" of your protocol, so in each loop you get back the previous loops' FieldInfo objects as well as the current one, for the same packet.
In other words, when your script executed this:
return isSkip_Field()()
...the first time for a packet, it got back one FieldInfo object, called that, and got the boolean. When it ran the second time, the call to isSkip_Field() actually returned two FieldInfo objects, but it discarded the second one because the code is logically equivalent to the code I wrote at the top of this answer, and instead only called the first instance, which of course rteturns the same boolean value as the first loop iteration; and when it ran a third time for the same packet it returned three FieldInfo objects, discarded the second two, called the first one, etc.
So what you really want to do is select the correct FieldInfo object each loop iteration - namely the most recent (last) one. You can do that one of two ways: (1) using the Lua select() function, or (2) put the returned FieldInfo objects into a table and retrieve the last entry.
For example, do this:
local isSkip_Field = Field.new("mytoy.isSkip")
local function getIsSkip(num)
return select(num, isSkip_Field())()
end
local msgLen_Field = Field.new("mytoy.msgLen")
local function getMsgLen(num)
return select(num, msgLen_Field())()
end
function TOY_proto.dissector(tvbuf, pktinfo, root)
pktinfo.cols.protocol = "TOY"
local pktlen = tvbuf:reported_length_remaining()
local pos = 0
local num = 1
while pos < pktlen do
local headTree = tree:add("Head")
headTree:add_le(isSkip, tvbuf:range(pos,1))
headTree:add_le(msgLen, tvbuf:range(pos,1))
if getIsSkip(num) then
pos = pos + getMsgLen(num)
else
-- do something else
end
num = num + 1
end
end
...or this:
local isSkip_Field = Field.new("mytoy.isSkip")
local function getIsSkip()
local tbl = { isSkip_Field() }
return tbl[#tbl]()
end
local msgLen_Field = Field.new("mytoy.msgLen")
local function getMsgLen()
local tbl = { msgLen_Field() }
return tbl[#tbl]()
end
function TOY_proto.dissector(tvbuf, pktinfo, root)
pktinfo.cols.protocol = "TOY"
local pktlen = tvbuf:reported_length_remaining()
local pos = 0
while pos < pktlen do
local headTree = tree:add("Head")
headTree:add_le(isSkip, tvbuf:range(pos,1))
headTree:add_le(msgLen, tvbuf:range(pos,1))
if getIsSkip() then
pos = pos + getMsgLen()
else
-- do something else
end
end
end
...or if there are going to be lots of Fields, this might be nicer:
local isSkip_Field = Field.new("mytoy.isSkip")
local msgLen_Field = Field.new("mytoy.msgLen")
local function getFieldValue(field)
local tbl = { field() }
return tbl[#tbl]()
end
function TOY_proto.dissector(tvbuf, pktinfo, root)
pktinfo.cols.protocol = "TOY"
local pktlen = tvbuf:reported_length_remaining()
local pos = 0
while pos < pktlen do
local headTree = tree:add("Head")
headTree:add_le(isSkip, tvbuf:range(pos,1))
headTree:add_le(msgLen, tvbuf:range(pos,1))
if getFieldValue(isSkip_Field) then
pos = pos + getFieldValue(msgLen_Field)
else
-- do something else
end
end
end

Trying to add a event listener fo a object which is part of an array in lua using corona

The main creates a simple 2d array. Now i want to create a addeventlistener for each object in the table. I presume i do this in the class? Although i have created a taps function and then defined addeventlistener but i ma getting errors.
--main.lua--
grid={}
for i =1,5 do
grid[i]= {}
for j =1,5 do
grid[i][j]=diceClass.new( ((i+2)/10),((j+2)/10))
end
end
--dice class--
local dice = {}
local dice_mt = { __index = dice } -- metatable
function dice.new( posx, posy) -- constructor
local a=math.random(1,6)
local b= true
local newdice = display.newText(a, display.contentWidth*posx,
display.contentHeight*posy, nil, 60)
--newdice:addEventListener("tap", taps(event))
return setmetatable( newdice, dice_mt )
end
function dice:taps(event)
self.b = false
print("works")
end
function dice:addEventListener("tap", taps(event))
This stumped me till today. The main problem is that you're making newdice a Corona display.newText object and then reassigning it to be a dice object. All the Corona objects act like ordinary tables, but they're actually special objects. So you have two options:
A. Don't use classes and OOP. As your code is now, there's no reason to have dice be a class. This is the option I'd go with unless you have some compelling reason to make dice a class. Here's how you would implement this option
--dice not a class--
local dice = {}
local function taps(event)
event.target.b = false
print("works")
end
function dice.new( posx, posy) -- constructor
local a=math.random(1,6)
--local b= true
local newdice = {}
newdice = display.newText(a, display.contentWidth*posx,
display.contentHeight*posy, nil, 60)
newdice:addEventListener("tap", taps)
newdice.b = true
return newdice
end
or B. Use a "has a" relationship instead of an "is a" relationship for the display object. Since you can't make them both a dice object and a display object, your dice object could contain a display object. Here's how that would look.
--dice class--
local dice = {}
local dice_mt = { __index = dice } -- metatable
local function taps(event)
event.target.b = false
print("works")
end
function dice.new( posx, posy) -- constructor
local a=math.random(1,6)
--local b= true
local newdice = {}
newdice.image = display.newText(a, display.contentWidth*posx,
display.contentHeight*posy, nil, 60)
newdice.image:addEventListener("tap", taps)
newdice.b = true
return setmetatable( newdice, dice_mt )
end
There were some other problems as well. In your taps function event handler you have to use event.target.b instead of self.b. Also, in dice.new b is a local variable so it's not a member of your dice class.
Remove the last line.
The addEventListener function should be called like this
newdice:addEventListener("tap", taps)

Resources