Excessive PlayerAdded events for Knit framework?

I am using the Knit framework by @sleitnick
Currently I have many services that are dedicated to a single purpose, of course, but some of these services have to handle when a player joins the game. I am wondering if I should either keep the excessive PlayerAdded events (which might be inefficient) or have a single module which communicates with the other services (although this is apparently a bad practice?) with only one PlayerAdded event in total.

Side-question (albeit irrelevant to the topic): If I wanted to handle purchases, and have to listen to certain events like PromptGamePassPurchaseFinished, is it best to have this as a standalone script, service, or module?

1 Like

I think you should keep it how it is. I don’t think its excessive at all. Its actually pretty normal to have many player added events for organization and such. Its not performance heavy at all to have many events. Having only one is extreme bad practice as you lose all forms of organization.

1 Like

I connect all mine to one PlayerAdded event. I have have a folder named “PlayerAdded” inside ServerScriptService. Inside that folder, are module scripts that return a function. It looks like th is:

game.Players.PlayerAdded:Connect(function(player)
	for i, module in pairs(SSS.Executables.PlayerAdded:GetChildren()) do
		if module:IsA("ModuleScript") then
			local s, e = pcall(function()
				coroutine.wrap(function()
					local m = require(module)
					m(player)
				end)()
			end)
			if e then error(e) end
		end
	end
end)

I do not recommend you do that. Your making things way more complicated then it is. I don’t see the problem why you can’t just create more the one playeradded event.

1 Like

Keeping them all in different services is fine.

The only reason why you’d want to combine them all together is if you need certain things to be loaded first (Like a saving system).

My solution (probably not the best one) is to have one service manage all PlayerAdded events to make sure that the ones I want loaded first do actually load first.

Here’s the script if you want to look at it for some reason. (this is sort of old so I suggest remaking it yourself)

local Knit = require(game:GetService("ReplicatedStorage").Knit)
local Players = game:GetService("Players")

local Thread 

local PlayerService = Knit.CreateService({
	["Name"] = "PlayerService";
	["Client"] = {},
	["__maxPriority"] = 1,
	["NumberOfPlayers"] = 0,
	["__playerAddedCallbacks"] = {},
	["__playerRemovedCallBacks"] = {},
})


local function firstAdded(player)
	PlayerService.NumberOfPlayers = #Players:GetPlayers()
end

local function firstRemoved(player)
	PlayerService.NumberOfPlayers = #Players:GetPlayers()
end

function PlayerService:__callCallbacks(callbacks,...)
	local args = {...}
	for index = 1,self.__maxPriority do
		local callback = callbacks[index]
		if callback then
			print(callback)
			print("[PlayerService]: Calling... ",index)
			callback(unpack(args))
		end
	end
end

function PlayerService:AddCallbackFor(eventName,priority,func)
	local callbacks = (eventName == "playerRemoved" and self.__playerRemovedCallBacks) or self.__playerAddedCallbacks
	priority = priority or (#callbacks + 1)
	self.__maxPriority = self.__maxPriority < priority and priority or self.__maxPriority
	callbacks[priority] = func

	--	print(string.format("[PlayerService]: Callback added to event: %s with priority of %d",eventName,priority))
	--	print(callbacks)
end

function PlayerService:KnitStart()	
	Thread = require(Knit.Shared.Lib.Thread)

	self:AddCallbackFor("playerRemoved",1,firstRemoved)
	self:AddCallbackFor("playerAdded",1,firstAdded)
	warn(self.__maxPriority)
	for _,player in pairs(game.Players:GetPlayers()) do
		self:__callCallbacks(self.__playerAddedCallbacks,player)
	end
	game.Players.PlayerAdded:Connect(function(player)
		self:__callCallbacks(self.__playerAddedCallbacks,player)
	end)
	game.Players.PlayerRemoving:Connect(function(player)
		self:__callCallbacks(self.__playerRemovedCallBacks,player)
	end)
end

function PlayerService:KnitInit()
end


return PlayerService
1 Like

It is not inefficient to have many PlayerAdded handles. That’s the whole point of event-driven programming: you can hook any code into something going on elsewhere, and drive your program from that. If you only use one handle, you essentially waive the benefits of event flow.

2 Likes

It’s not complicated at all. In fact, having 1000+ lines of code and multiple PlayerAdded events in one script is complicated. With this way, it’s split into a few module scripts. It’s easy to organize and split up based on things like data, etc.

2 Likes