While true do loop moment

This should work to my knowledge, the script suppose to check when the “queue input” value is changed then print out the value. Can yall explain why this didn’t work.

local Player = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local inputRequestFunction = ReplicatedStorage:WaitForChild("input")
local CollectionService = game:GetService("CollectionService")

Player.PlayerAdded:Connect(function(plr)
	local queuedInput
	while queuedInput == not nil do
		print("executed:", queuedInput)
		queuedInput = nil
		wait()
	end
	inputRequestFunction.OnServerInvoke = function(player, input)
		if input then
			queuedInput = input
		end
		return true
	end
end)
2 Likes

Try changing

while queuedInput == not nil do

To

while queuedInput do
1 Like

I’ve tried this before and it did not work. I think its something to do with the PlayerAdded Function

1 Like

On this line, you forgot to define the variable, you cant just leave it in blank or else it wont work, change the variable to be something.

Maybe set the queuedInput to false?

At the moment you have the while loop terminate before you connect to the event. This means the loop will terminate before queuedInput can be set to anything.

can you show me an example, i dont quite understand it.

I’ll just list the issues in the script below.
Dear god, I found a lot of issues with your coding style. I hope it helped:

local Player = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local inputRequestFunction = ReplicatedStorage:WaitForChild("input")
local CollectionService = game:GetService("CollectionService")

Player.PlayerAdded:Connect(function(plr)
	local queuedInput --variable not needed
	while queuedInput == not nil do --only runs once, while is not needed.
		--this can be done in the invoke function. also won't run anyways since ran once on join.
		print("executed:", queuedInput)
		queuedInput = nil
		wait() --task.wait() is a better option than this and can be used in parameters.
	end
	inputRequestFunction.OnServerInvoke = function(player, input)
		if input then
			queuedInput = input
		end
		return true --true not needed unless its for a specific parameter
	end
end)

Now, for the solution.

local Player = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local inputRequestFunction = ReplicatedStorage:WaitForChild("input")
local CollectionService = game:GetService("CollectionService")

Player.PlayerAdded:Connect(function(plr)
	inputRequestFunction.OnServerInvoke = function(player, input)
		if input then
			print("executed:", input)
			--insert firing a remote event here
		end
		return true
	end
end)
1 Like
local Player = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local inputRequestFunction = ReplicatedStorage:WaitForChild("input")
local CollectionService = game:GetService("CollectionService")

local queues = {}

local function processQueue(queue)
	-- Do whatever you need to do with a player's queue
	for i, element in ipairs(queue) do
		print(element)
	end
end

-- You only need to connect set this once rather than every time a player joins
inputRequestFunction.OnServerInvoke = function(player, _input)
	local queue = queues[player]
	if _input then
		table.insert(queue, _input)
		return processQueue(queue)
	end
	return false
end

Player.PlayerAdded:Connect(function(player)
	queues[player] = {}
end)

using the method you mention defeat the purpose of why im doing input and queued input separately. I dont want players to spam their mouse or button to make their attacks true.

Then just add a debounce:

local Player = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local inputRequestFunction = ReplicatedStorage:WaitForChild("input")
local CollectionService = game:GetService("CollectionService")

local debounce = os.clock()
local cooldown = 1 --your cooldown timer here

Player.PlayerAdded:Connect(function(plr)
	inputRequestFunction.OnServerInvoke = function(player, input)
		if input and debounce <= os.clock() then
			debounce = os.clock() + cooldown
			print("executed:", input)
			--insert firing a remote event here
		end
		return true
	end
end)

Code is executed line by line until the end of the file is reached, or execution is yielded. Your while loop is yielding the thread which prevents your OnServerInvoke event from being connected.

Simple fix :

local Player = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local inputRequestFunction = ReplicatedStorage:WaitForChild("input")
local CollectionService = game:GetService("CollectionService")

Player.PlayerAdded:Connect(function(plr)
	local queuedInput

    inputRequestFunction.OnServerInvoke = function(player, input)
		if input then
			queuedInput = input
		end
		return true
	end

	while queuedInput == not nil do
		print("executed:", queuedInput)
		queuedInput = nil
		wait()
	end
end)

I like this possible fix, but take into consideration that this event only runs once. This means that the while loop will not function.

1 Like

It isn’t working because everytime a player joins the .OnServerInvoke is overrided by the next player, therefore removing the functions for the previous player.

Try this instead:

--//Services
local Player = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local CollectionService = game:GetService("CollectionService")

--//Variables
local inputRequestFunction = ReplicatedStorage:WaitForChild("input")

--//Tables
local QueuedInputs = {}

--//Functions
Player.PlayerAdded:Connect(function(player)
	while QueuedInputs[player] do
		print("executed:", QueuedInputs[player])
		
		QueuedInputs[player] = nil
		
		task.wait()
	end
end)

inputRequestFunction.OnServerInvoke = function(player, input)
	if input then
		QueuedInputs[player] = input
	end
	
	return true
end
1 Like

The loop doesn’t start since queuedInput is nil so it passes it, replace it with a while wait() do loop and have an if statement inside.

2 Likes

The while loop will function as intended, because you’re only creating a connection prior to starting the while loop. When the event is fired, it will terminate your loop, which is what you’re trying to do.

Wait. Wouldn’t it just be better to combine the while loop into the server invoke, and just use the while loop’s code inside it? The while loop only runs once, which means it’s not needed.

If the code is only intended to run once, then possibly. However, I’m not here to try and figure out the intended use case of the provided code. I’m just here to provide a solution to why the code no work.

It will define it to nil if you don’t assign it to anything.

On a global variable without local, that’s a different story.

From my understanding, you are not able to send instances through a RemoteEvent or RemoteFunction.

Trust me, I did the exact same thing.

So, if you are doing so, you will need to implement this another way as that is impossible.

You cannot send non-replicated instances or functions through remotes.