I have a STOOL that links two entities (in this particular case, air tanks) together. It works fine in singleplayer, but for some reason it seems to almost stutter and run some of the code more than it should, causing console errors. The toolgun seems to do its job, at least in the first cycle, as the objects appear to be linked together and are sharing resources. In subsequent cycles it encounters errors and the toolgun no longer functions.
The following is the toolgun's source, and following that the errors thrown in the console. Maybe a second set of eyes are all I really need...
[lua]
TOOL.Category = "Horizon"
TOOL.Name = "Link Tool"
TOOL.Command = nil
TOOL.ConfigName = ""
local timesFired = 0
local cycleComplete = false
local startPos
local endPos
function TOOL:LeftClick( tr )
if (!tr.Entity:IsValid(tr.Entity.linkable)) or (tr.Entity:IsPlayer()) then return end
startPos = tr.HitPos
if (timesFired == 0) then
entA = tr.Entity
print ("entA = " .. entA:GetClass())
timesFired = 1
if (CLIENT) then return true end
end
if (tr.Entity != entA) then
if cycleComplete == false then
entB = tr.Entity
print ("entB = " .. entB:GetClass())
if entA.networkID == nil and entB.networkID == nil then
print( "neither entities are networked" )
entA.networkID = GAMEMODE.nextNet
print(entA.connections)
table.insert(entA.connections, entB)
entB.networkID = GAMEMODE.nextNet
table.insert(entB.connections, entA)
newNetwork = {}
newNetwork[1] = {}
newNetwork[2] = entA
newNetwork[3] = entB
GAMEMODE.networks[GAMEMODE.nextNet] = newNetwork
--Now, let's add any new resources to the network's resource list
for _, ent in pairs( newNetwork ) do
if ent.deviceType == "storage" then
GAMEMODE:addToResourceList( ent )
end
end
--Next, we need to get a count of all resources on the network
GAMEMODE:updateResourceCount(GAMEMODE.nextNet)
-- Increment to next available network ID
GAMEMODE.nextNet = GAMEMODE.nextNet + 1
cycleComplete = true;
end
end
if entA.networkID != nil and entB.networkID == nil then
if cycleComplete == false then
print( "one entity (entA) is networked" )
--add each other to connections table
table.insert(entA.connections, entB)
table.insert(entB.connections, entA)
entB.networkID = entA.networkID
table.insert(GAMEMODE.networks[entA.networkID], entB)
if entB.deviceType == "storage" then
GAMEMODE:addToResourceList( entB )
end
GAMEMODE:updateResourceCount( entA.networkID )
cycleComplete = true
end
end
if entB.networkID != nil and entA.networkID == nil then
if cycleComplete == false then
print( "one entity (entB) is networked" )
--add each other to connections table
table.insert(entA.connections, entB)
table.insert(entB.connections, entA)
entA.networkID = entB.networkID
table.insert(GAMEMODE.networks[entB.networkID], entA)
if entA.deviceType == "storage" then
GAMEMODE:addToResourceList( entA )
end
GAMEMODE:updateResourceCount( entB.networkID )
cycleComplete = true
end
end
if entA.networkID !=nil and entB.networkID != nil then
if entA.networkID == entB.networkID and cycleComplete == false then
print("Entities are in the same network!")
table.insert(entA.connections, entB)
table.insert(entB.connections, entA)
cycleComplete = true
end
if cycleComplete == false then
print( "both entities are networked" )
table.insert(entA.connections, entB)
table.insert(entB.connections, entA)
local oldNetA = GAMEMODE.networks[entA.networkID]
local oldNetB = GAMEMODE.networks[entB.networkID]
local NetworkA = GAMEMODE.networks[entA.networkID]
local NetworkB = GAMEMODE.networks[entB.networkID]
local newNetwork = {}
newNetwork[1] = {}
for _, ent in pairs( NetworkA ) do
if ent.linkable == true then
ent.networkID = GAMEMODE.nextNet
table.insert(newNetwork, ent)
end
end
for _, ent in pairs( NetworkB ) do
if ent.linkable == true then
ent.networkID = GAMEMODE.nextNet
table.insert(newNetwork, ent)
end
end
GAMEMODE.networks[oldNetA] = nil
GAMEMODE.networks[oldNetB] = nil
GAMEMODE.networks[GAMEMODE.nextNet] = newNetwork
for _, ent in pairs( GAMEMODE.networks[GAMEMODE.nextNet]) do
if ent.deviceType == "storage" then
GAMEMODE:addToResourceList( ent )
end
end
GAMEMODE:updateResourceCount( GAMEMODE.nextNet )
GAMEMODE.nextNet = GAMEMODE.nextNet + 1
cycleComplete = true
end
end
endPos = tr.HitPos
// Get information we're about to use
local constraint, rope = constraint.Elastic( entA, entB, 0, 0, startPos, endPos, 0, 0, 0, "cable/cable2", 2, 0 )
timesFired = 0
cycleComplete = false
end
if (CLIENT) then return true end
return true
end
function TOOL:Reload( tr )
if tr.Entity.linkable == true then
if tr.Entity.networkID != nil then
GAMEMODE:unlinkDevice(tr.Entity)
end
if (CLIENT) then return true end
end
return true
end
[/lua]
Console output:
[code]
] ent_create test_tank
] ent_create test_tank
entA = test_tank
entA = test_tank
entB = test_tank
neither entities are networked
table: 2BDC3FC8
entB = test_tank
neither entities are networked
nil
[@weapons\gmod_tool\stools\link_tool.lua:40] bad argument #1 to 'insert' (table expected, got nil)
nilentB = test_tank
neither entities are networked
[@weapons\gmod_tool\stools\link_tool.lua:40] bad argument #1 to 'insert' (table expected, got nil)
entB = test_tank
neither entities are networked
nil
[@weapons\gmod_tool\stools\link_tool.lua:40] bad argument #1 to 'insert' (table expected, got nil)
entB = test_tank
neither entities are networked
nil
[@weapons\gmod_tool\stools\link_tool.lua:40] bad argument #1 to 'insert' (table expected, got nil)
[/code]
One small suggestion to reduce the clutter, make a link function on the entity itself as it seems quite complicated. This way you don't have to copy-paste it everywhere you need it.
As for the error: entA.connections is nil, make it equal to {} if its nil to fix it.
[QUOTE=CmdrMatthew;30774743]One small suggestion to reduce the clutter, make a link function on the entity itself as it seems quite complicated. This way you don't have to copy-paste it everywhere you need it.
As for the error: entA.connections is nil, make it equal to {} if its nil to fix it.[/QUOTE]
I'm not sure that would fix the problem- on the first run entA.connections isn't nil. It should only run through this sequence once, which it does in singleplayer. As you can see in the console output, it's running part of the sequence four additional times.
Anyone want to take a crack at it? Anyone at all...?
Is entA.connections a table or is entA a table :p
It's trying to add it to a table but that table doesn't exist so
Theory wise
[lua]
local entAT = {}
local entBT = {}
table.insert(entAT, entB.connections)
table.insert(entBT, entA.connections)
[/lua]
[QUOTE=RetTurtl3;30783673]Is entA.connections a table or is entA a table :p
It's trying to add it to a table but that table doesn't exist so
Theory wise
[lua]
local entAT = {}
local entBT = {}
table.insert(entAT, entB.connections)
table.insert(entBT, entA.connections)
[/lua][/QUOTE]
entA.connections is a table that exists on the entity. When the entity is selected by the toolgun, entA(or entB for that matter) becomes valid and their connections table is accessible to the tool.
The problem I'm having is not the 'Bad Argument' error in the console. That's only a symptom. The problem is the code running multiple times when it shouldn't be.
The only analogy I can think of is a gun. In singleplayer, it behaves like a semi-automatic. the script executes once, does its job and readies itself to fire again. In multiplayer, the same script tries to go full auto, executing the first time as it should, but then fires again without a valid entity selected, effectively jamming up. That's the point where it throws the console error.
I just want to know why this behavior would occur only in multiplayer?
Sorry, you need to Log In to post a reply to this thread.