A way to connect my wiring system together

Hello, I am currently facing an issue where I have no clue how to connect every wire in my game.
It is hard to explain so I will just show a few pictures
image
I have 2 buttons here connected to one wire
image
But when I press one, it lights up one part
image
And when I press the other, it lights up the other part

I need these buttons to light up the entire circuit when one is pressed, not just a part of it and I don’t know how to go about doing this.

Here is my script (the player places down buttons and wires manually using a gui)

placeWireEvent.OnServerEvent:Connect(function(plr,wireCFrame,wireSize,mouseTarget,originTarget)
	
	local wire = Instance.new('Part')
	wire.Name = 'Wire'
	wire.Material = Enum.Material.Metal
	wire.Transparency = 0
	wire.Color = Color3.new(0.1,0.1,0.1)
	wire.Anchored = false
	wire.CFrame = wireCFrame
	wire.Size = wireSize
	wire.Parent = workspace.Wires
	
	-- this will allow for other wires to detect if the current one is turned on
	local Logistic = Instance.new('NumberValue')
	Logistic.Value = 0
	Logistic.Parent = wire
	Logistic.Name = 'Logistic'
	
	local weld = Instance.new('WeldConstraint')
	weld.Part0 = wire
	weld.Part1 = mouseTarget -- mouse target is the part that the player clicked on
	weld.Parent = wire

--mouseTarget is the final position the player clicked when setting the wire
-- originTarget is the first position the player clicked when setting a wire
	if mouseTarget.Name == 'LogisticPort' or originTarget.Name == 'LogisticPort' or
		originTarget.Parent.Name == 'Wires' or mouseTarget.Parent.Name == 'Wires' then
		-- every LogisticPort has a Logistic Number value, same with every wire, this value determines if the wire is on or off
		-- this just gets the logistic value of that the wire is touching etc
		local OtherLogisticValue
		
		if mouseTarget.Name == 'LogisticPort' or mouseTarget.Parent.Name == 'Wires' then
			
			OtherLogisticValue = mouseTarget.Logistic
			
		elseif originTarget.Name == 'LogisticPort' or originTarget.Parent.name == 'Wires' then
			
			OtherLogisticValue = originTarget.Logistic
			
		end

		Logistic.Value = OtherLogisticValue.Value
		
		--mousetarget is logisticport or wire, changes logistic value, if logistic value is changed then do a chain reaction to change it again?
		
		OtherLogisticValue.Changed:Connect(function(changed)
			
			Logistic.Value = changed
			wire.Color = Color3.new(0,1,1)
			delay(1,function()
				wire.Color = Color3.new(0.1,0.1,0.1)
			end)
		end)
	end

end)

I simply don’t know how to do this.
Should I do something with tags? Should I do something else? Any help is appreciated.

1 Like

in each wire store a list of connected wires. When the wire lights up, make it light up all adjacent wires except for the one that lit it up

1 Like

The way I see it, you need to create an interconnected graph. When something gets connected, you can give an object value (or equivalent) to both parts pointing to the other (since it’s a two way connection). Then when something that could power the circuit changes states, you’ll need to search the graph for power sources. If no power source connected anywhere on the graph is on then the entire graph can be traversed and powered off, otherwise the whole graph should be traversed and powered on.

When graphs get large, traversal for every update could be performance intensive. For such cases you can store the parts of the graph capable of supplying power directly so you can directly traverse that list instead. You’ll need to be careful about ensuring you remove them when the graph changes though which will still likely require a full traversal (with potential for early termination) but at a potentially reduced frequency.

You can of course split this up into multiple graphs which can help speed up calculations by localizing a lot of the problem. But this graph of graphs method does require a few more considerations to ensure consistent behavior depending on exactly how you are using the segments.

1 Like

I think what everyone is looking for here is known as a “linked” list. Where there is a head/tail value. Each wire is represented by 3 parts. A head, a tail, and the wire object. The head/tail hold the value of the wires they connect to or the power source they connect to. Or nothing if head/tail are not connected. Then its a simple traversal of the linked list. Beyond this you should take a look into various types of wiring diagrams to understand how circuits work.

Data Structure and Algorithms - Linked List (tutorialspoint.com)

1 Like

Thanks but I just still don’t understand how to make this at all, i’ve read a quite a bit of the data structure and algorithms - linked list tutorialspoint that you sent and tried to understand it but I just don’t get how I would implement this in game. Could I have a small sample of code to go off of? (sorry if i’m asking for code, I just don’t know where or how to start with making a linked list)

@tlr22

That does explain a bit of what to do but how would I actually go about this scripting wise? I’m sorry if I sound like an amateur in this, I just never made a connected system like this before so this is all quite new to me, also how would I make all of these objectvalues into a graph?

Wouldn’t the whole thing break if I removed a wire though? Since the list would have to be completely redone each time?

I am once again sorry for everyone, I just don’t know where to start as I never really used graphs or linked lists.

EDIT: or should I make a GetTouchingParts system like in this post? I am really at a loss.

So a graph is any set of nodes with connections to other nodes. A linked list would be a subset of a graph. Here is a general picture of a graph.

small_undirected_network_labeled-3831100630

Hopefully you can see the parallels between this and your problem. Basically each node, just needs a reference to another node. For the example given we can use object values. Each node will have children that are object values that reference the other nodes it can connect to from any given node, so if you were to start at the top left node in the above picture, it would have 1 object value that points to the node to the east. That would effectively be the edge. Now you can look to that node that was connected to the first and see it has 3 object values. One goes back west, one goes to the southwest and the other to the south east. Now you can just keep going through this whole list item by item by searching what it’s connected to until you hit what you are looking for. Keep in mind you will need some way to stop processing nodes that you’ve already searched otherwise you will get caught in loops.

But basically, when a new node is added, you’ll have to add an object value referencing each of its neighbors and you’ll have to add an object value representing your new node to each of the neighbors. When a node is removed, you’ll have to clean up references to it from each of its neighbors.

2 Likes

The actual setup of the graph I will leave to you (though feel free to ask if you need further help there).

But for traversal, you’ll want to have an open list and a closed list.
Hopefully you are familiar with dictionaries, if not, this would be a beneficial read Intro to Dictionaries | Documentation - Roblox Creator Hub

--Consider this a function or something.  Exact implementation varies
local closedList = {} --This one is a dictionary, but the open list is an array
local openList = {game.Workspace.EntryNode} --You will have to somehow place the first node in the openList, this is just a default value for the example

while #openList > 0 do
    local curNode = table.remove(openList) --We are picking the last one even though the first would be more intuitive because picking the first one would require the entire list to be shifted.  table.remove without the second argument will return the last item in the list after it removes it from the list
    closedList[curNode] = true --Add the node we are presently processing to the closed list so we know we have searched it
    for _, child in ipairs(curNode:GetChildren()) do
        if child.ClassName == "ObjectValue" then
            if not closedList[child.Value] then --We don't want to get caught in a loop, so if the value has been went through already, we don't want it back in the open list
                table.insert(openList, child.Value)
            end
        end

    --Do whatever else you need to do in traversal here.  Such as checking if it's a power source and that this node is powered.  Feel free to return early if you found what you were looking for (a single active power source is enough to terminate if you are checking if the graph is powered.  You can also light up parts or whatever so long as it makes sense
    end
end
2 Likes

Thanks for all the help! I just want to ask one question, is this script compatible with multiple different 'openList’s (or wire networks)? As this looks to only work with one graph or one wire network, I may be wrong though.

Yeah, it should be. Any given graph is defined by what it’s connected to. So if you give a reference to a node in one graph it will only have access to that graph for traversal since it has no way to enter another graph. So you can use it independently on multiple graphs

To be slightly more clear

function traverseGraph(startingNode)
    local closedList = {} --This one is a dictionary, but the open list is an array
    local openList = {startingNode}

    while #openList > 0 do
        local curNode = table.remove(openList) --We are picking the last one even though the first would be more intuitive because picking the first one would require the entire list to be shifted.  table.remove without the second argument will return the last item in the list after it removes it from the list
        closedList[curNode] = true --Add the node we are presently processing to the closed list so we know we have searched it
        for _, child in ipairs(curNode:GetChildren()) do
            if child.ClassName == "ObjectValue" then
                if not closedList[child.Value] then --We don't want to get caught in a loop, so if the value has been went through already, we don't want it back in the open list
                    table.insert(openList, child.Value)
                end
            end

    --Do whatever else you need to do in traversal here.  Such as checking if it's a power source and that this node is powered.  Feel free to return early if you found what you were looking for (a single active power source is enough to terminate if you are checking if the graph is powered.  You can also light up parts or whatever so long as it makes sense
        end
    end
end
1 Like

Final question i’ve been at this for about 1h now, how would I actually make the objectvalue for each wire/node?

local function traverseGraph(startingNode)
	local closedList = {} --This one is a dictionary, but the open list is an array
	local openList = {startingNode}

	while #openList > 0 do
		local curNode = table.remove(openList) --We are picking the last one even though the first would be more intuitive because picking the first one would require the entire list to be shifted.  table.remove without the second argument will return the last item in the list after it removes it from the list
		closedList[curNode] = true --Add the node we are presently processing to the closed list so we know we have searched it
		for _, child in ipairs(curNode:GetChildren()) do
			if child.ClassName == "ObjectValue" then
				if not closedList[child.Value] then --We don't want to get caught in a loop, so if the value has been went through already, we don't want it back in the open list
					table.insert(openList, child.Value)
				end
			end

			--Do whatever else you need to do in traversal here.  Such as checking if it's a power source and that this node is powered.  Feel free to return early if you found what you were looking for (a single active power source is enough to terminate if you are checking if the graph is powered.  You can also light up parts or whatever so long as it makes sense

			for _,wire in pairs(openList) do

				if string.find(wire.Name,'Wire') then

					wire.Color = Color3.new(0,1,1)

					delay(1,function()
						wire.Color = Color3.new(0.1,0.1,0.1)
					end)
				end
			end

		end
	end
end

local prevWire = nil

-- places wire down, received from Wiring TOol PreviewWireScript
placeWireEvent.OnServerEvent:Connect(function(plr,wireCFrame,wireSize,mouseTarget,originTarget)
	
	local wire = Instance.new('Part')
	wire.Name = 'Wire' .. tostring(math.random(1,10000))
	wire.Material = Enum.Material.Metal
	wire.Transparency = 0
	wire.Color = Color3.new(0.1,0.1,0.1)
	wire.Anchored = false
	wire.CFrame = wireCFrame
	wire.Size = wireSize
	wire.Parent = workspace.Wires
	
	-- this will allow for other wires to detect if 
	local Logistic = Instance.new('NumberValue')
	Logistic.Value = 0
	Logistic.Parent = wire
	Logistic.Name = 'Logistic'
	
	local weld = Instance.new('WeldConstraint')
	weld.Part0 = wire
	weld.Part1 = mouseTarget -- mouse target is the part that the player clicked on
	weld.Parent = wire

	--mouseTarget is the final position the player clicked when setting the wire
	-- originTarget is the first position the player clicked when setting a wire

	if originTarget == prevWire or mouseTarget == prevWire then

		local firstObject = Instance.new('ObjectValue')
		firstObject.Name = 'Previous'
		firstObject.Value = prevWire
		firstObject.Parent = wire
	else

		if originTarget.Parent.Name == 'Wires' or originTarget.Name == 'LogisticPort' then

			local secondObject = Instance.new('ObjectValue')
			secondObject.Name = 'Next'
			secondObject.Value = originTarget
			secondObject.Parent = wire
		end

		if mouseTarget.Parent.Name == 'Wires' or mouseTarget.Name == 'LogisticPort' then
 --LogisticPort is either the input/output part of an electronic containg a Logistic Number
--Value which gets carried over by the wire system to connected electronics
			local secondObject = Instance.new('ObjectValue')
			secondObject.Name = 'Next'
			secondObject.Value = mouseTarget
			secondObject.Parent = wire
		end

	end
	--originTarget.Name == 'LogisticPort' or mouseTarget.Name == 'LogisticPort'

	traverseGraph(wire)
	
	prevWire = wire
end)

Here is what I have so far, it barely functions and I have no clue how to do this, I feel like i’m asking for too much at this point as i’ve already received a ready graph traversal script, I just cannot figure out how I am supposed to detect every item that a node is connected to and make it into an objectvalue, i’ve tried everything, changing the if statement to various things, etc.

If this is too much I can make a seperate post about this and mark your answer down as the solution, as you’ve helped immensely already, thank you.

To be honest, I’m not entirely certain. I don’t quite have a full grasp on your wiring system which doesn’t make this easy. However, as far as I can tell, there should always be at least 2 object values created at every point. But if originTarget or mouseTarget = prevWire, only one is made. The present wire points to the previous wire, but the previous wire should also point back to the present wire I think? (the uncertainty ties back to my not quite understanding the wiring system as a whole)

	if originTarget == prevWire or mouseTarget == prevWire then

		local firstObject = Instance.new('ObjectValue')
		firstObject.Name = 'Previous'
		firstObject.Value = prevWire
		firstObject.Parent = wire

        local secondObject= Instance.new('ObjectValue')
		secondObject.Name = 'untitled_document' --Not entirely certain what you want this called so I picked a random name
		secondObject.Value = wire
		secondObject.Parent = wire
	else

Yeah, due to me not entirely understanding your wiring system I might be of limited help here. It can be useful to create some sort of way for you to see the neighbors you are creating though so you can debug the graph.

But overall when adding a wire to the system, the input should have an object value for both the source of the wire and the wire, and the future output of the wire when it gets connected to something should have an object in both the output and the wire

1 Like

I did make a way of debugging the graph, by making every child in openList turn into a cyan colour so I can see, also I made each wire have a random name so I can see if the objectvalues were correct. I have found zero solutions. I can’t really explain my wiring system better unless I invite you over to team create, and I can do just that if you want. I can also pay in upwards of 200 robux because of how much time i’ve wasted you.

I’d be willing to do that(no payment necessary), but I will be busy for the rest of the day so it would have to wait until tomorrow.

1 Like

Alright! Thank you so much, i’ll invite you over to team create so you can check it out when you have time , i’ll be available at around 16:00 gmt+1, also please don’t mind the name of the game when you do check it out, I didn’t name it that.

Edit: the game is called ‘Lol Land RP’ in the group ‘Double L Studios’

I apologize for the inconvenience, just group games are like that.

Edit 2: Alright! The owner of the group now gave you access to the game, please inform me on when you will finish looking at the game

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.