From 93be162fd7a880918090f973031c1165349988c7 Mon Sep 17 00:00:00 2001 From: norrbotten Date: Mon, 19 Aug 2019 12:22:54 +0200 Subject: [PATCH 1/2] fix infinite recursion when you link gearboxes in a loop --- lua/entities/acf_gearbox.lua | 47 +++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/lua/entities/acf_gearbox.lua b/lua/entities/acf_gearbox.lua index 6c2496e3d..5db5f88d3 100644 --- a/lua/entities/acf_gearbox.lua +++ b/lua/entities/acf_gearbox.lua @@ -937,6 +937,43 @@ function ENT:ChangeDrive(value) end +-- Searches the "tree" which gearbox-gearbox connections forms, if the source is found +-- anywhere in the targets link tree, this function will return true and the loop path +function ACF_SearchGearboxLinkTree(source, target) + local queue = { target } + local parent = { } + + -- search the link tree + while #queue > 0 do + local ent = table.remove(queue) + + if ent == source then + -- backtrack the loop + local nextInLoop = source:EntIndex() + local loop = { } + + while nextInLoop do + table.insert(loop, nextInLoop) + nextInLoop = parent[nextInLoop] + end + + loop = table.Reverse(loop) + + return true, loop + end + + if not ent.WheelLink then continue end + + -- add each link to the queue + for k, v in ipairs(ent.WheelLink) do + table.insert(queue, v.Ent) + parent[v.Ent:EntIndex()] = ent:EntIndex() + end + end + + return false +end + function ENT:Link( Target ) if not IsValid( Target ) or not table.HasValue( { "prop_physics", "acf_gearbox", "tire" }, Target:GetClass() ) then @@ -949,7 +986,15 @@ function ENT:Link( Target ) return false, "That is already linked to this gearbox!" end end - + + local hasLoop, loop = ACF_SearchGearboxLinkTree(self, Target) + if hasLoop then + local loopStr = string.format("%s (%i) (target) loops back to %s (%i) (source)", + ents.GetByIndex(loop[1]):GetClass(), loop[1], ents.GetByIndex(loop[#loop]):GetClass(), loop[#loop]) + + return false, "You cannot link gearboxes in a loop!\n" .. loopStr + end + -- make sure the angle is not excessive local InPos = Vector( 0, 0, 0 ) if Target.IsGeartrain then From 3c77dc40745e2f09ffb7a7b93d941ba53a3a35e3 Mon Sep 17 00:00:00 2001 From: norrbotten Date: Mon, 19 Aug 2019 12:49:24 +0200 Subject: [PATCH 2/2] source/target print was kinda unnecessary --- lua/entities/acf_gearbox.lua | 29 ++++++----------------------- 1 file changed, 6 insertions(+), 23 deletions(-) diff --git a/lua/entities/acf_gearbox.lua b/lua/entities/acf_gearbox.lua index 5db5f88d3..7e3b6f8b2 100644 --- a/lua/entities/acf_gearbox.lua +++ b/lua/entities/acf_gearbox.lua @@ -938,36 +938,23 @@ function ENT:ChangeDrive(value) end -- Searches the "tree" which gearbox-gearbox connections forms, if the source is found --- anywhere in the targets link tree, this function will return true and the loop path +-- anywhere in the targets link tree, this function will return true function ACF_SearchGearboxLinkTree(source, target) local queue = { target } - local parent = { } - + -- search the link tree while #queue > 0 do local ent = table.remove(queue) if ent == source then - -- backtrack the loop - local nextInLoop = source:EntIndex() - local loop = { } - - while nextInLoop do - table.insert(loop, nextInLoop) - nextInLoop = parent[nextInLoop] - end - - loop = table.Reverse(loop) - - return true, loop + return true end if not ent.WheelLink then continue end - + -- add each link to the queue for k, v in ipairs(ent.WheelLink) do table.insert(queue, v.Ent) - parent[v.Ent:EntIndex()] = ent:EntIndex() end end @@ -987,12 +974,8 @@ function ENT:Link( Target ) end end - local hasLoop, loop = ACF_SearchGearboxLinkTree(self, Target) - if hasLoop then - local loopStr = string.format("%s (%i) (target) loops back to %s (%i) (source)", - ents.GetByIndex(loop[1]):GetClass(), loop[1], ents.GetByIndex(loop[#loop]):GetClass(), loop[#loop]) - - return false, "You cannot link gearboxes in a loop!\n" .. loopStr + if ACF_SearchGearboxLinkTree(self, Target) then + return false, "You cannot link gearboxes in a loop!" end -- make sure the angle is not excessive