Getting all parts in a mechanism / one part in each assembly?

I am trying to make a train turntable that welds parts to it to ensure things do not fall off when the table is turning. The things that are expected to be turned are mechanisms, and there will be large issues if the entire mechanism is not welded or the mechanism is partway on, partway off the turntable. If any of you have done the following before, I am interested in your implementation:

  • find all assemblies in a mechanism in PGS from a table of parts
  • ensure that all parts in the mechanism in included in a table of parts

Is this what you’re looking for? I might be misunderstanding what you mean

That works fine for Hinges, Motors, and Welds, but it does not take into account Constraints, which I need it to.

1 Like

Is a depth-first search not enough? According to the wiki, GetJoints will parts connected via joints and constrains, which is better than just checking for any child constraints.

Edit: Okay, this is confusing. According to the wiki, GetJoints() “Return all Joints or Constraints that is connected to this Part.”. but its return type is array<BasePart>. Hmmm…

I think I got it. Try this:

function GetFullAssembly(originPart)
	local result = {}
	local queue = {originPart}
	local touched = {[originPart] = true}
	local connectionChecked = {}
	local currentPart = originPart
	repeat
		-- Initialize surface joints.
		currentPart = table.remove(queue)
		currentPart:MakeJoints()
		table.insert(result, currentPart)
		for _, joint in pairs(currentPart:GetJoints()) do
			local part0, part1
			if joint:IsA("Constraint") then
				local attachment0 = joint.Attachment0
				local attachment1 = joint.Attachment1
				part0 = attachment0.Parent
				part1 = attachment1.Parent
			else
				part0 = joint.Part0
				part1 = joint.Part1
			end

			if not touched[part0] then
				touched[part0] = true
				table.insert(queue, part0)
			end
				
			if not touched[part1] then
				touched[part1] = true
				table.insert(queue, part1)
			end
		end	
		
		if not connectionChecked[currentPart] then
			connectionChecked[currentPart] = true
			for _, connectedPart in pairs(currentPart:GetConnectedParts(true)) do
				if not touched[connectedPart] then
					touched[connectedPart] = true
					connectionChecked[connectedPart] = true
					table.insert(queue, connectedPart)
				end
			end
		end
	until #queue <= 0

	return result
end

Edit: Bah. Doesn’t detect WeldConstraints. The wiki lied to me :(. It works for all other constraints and surfacejoints, though.

EditEdit: Apparently :GetJoints can’t find WeldConstraints but :GetConnectedParts will acknowledge them. I’ll update this asap.

EditEditEdit: Updated. This should find all connected parts, whether via Constrants, SurfaceJoints, or WeldConstraints.

More edit: Updated so that it’s more efficient. The previous queue would grow quadratically when parts were connected in series.

Final(?) edit: Reduced the number of :GetConnectedPart() checks drastically.

10 Likes