local y=game:GetService("\082\101\112\108\105\099\097\116\101\100\083\116\111\114\097\103\101")local g=game:GetService("\080\108\097\121\101\114\115")local H=require(y:FindFirstChild("\078\101\118\101\114\109\111\114\101"))local k=(H("\083\116\100")).rquery local o={}function o.FireExceptTo(y,H,...)for g,k in pairs(g:GetPlayers())do if k~=y then H:FireClient(k,...)end end end function o.GetOrCreateClientServerTopicCategory(g)local H=y:FindFirstChild("\069\118\101\110\116\084\111\112\105\099\115")if H==nil then H=k.CreateFolder("\069\118\101\110\116\084\111\112\105\099\115",y)end local o=H:FindFirstChild(g)if o==nil then o=k.CreateFolder(g,H)end return o end function o.GetOrCreateClientServerTopicInCategory(y,g)local H=o.GetOrCreateClientServerTopicCategory(y)local k=H:FindFirstChild(g)if k==nil or not k:IsA("\082\101\109\111\116\101\069\118\101\110\116")then k=Instance.new("\082\101\109\111\116\101\069\118\101\110\116")k.Name=g k.Parent=H end return k end function o.SubscribeServerToTopicEvent(y,g,H)print("\083\117\098\115\099\114\105\098\105\110\103 \116\111 \101\118\101\110\116 "..(g..(" \105\110 "..y)))local k=o.GetOrCreateClientServerTopicInCategory(y,g)k.OnServerEvent:Connect(H)return k end function o.ConnectEntityListenerFuncToTopic(y,g,H,k)local T=function(y,g)local H=function(H,k)if k~=nil and k==y then g(H,k)end end return H end local w=o.SubscribeServerToTopicEvent(g,H,T(y,k))return w end return o
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local PlayersService = game:GetService("Players")

local require = require(ReplicatedStorage:FindFirstChild("Nevermore"))
local rq = require("Std").rquery

local module = {}

-- local fireExceptToCheck = t.tuple(
-- 	t.instanceOf("Player"),
-- 	t.instanceOf("RemoteEvent")
--)

function module.FireExceptTo(player, event, ...)
	--assert(fireExceptToCheck(player, event))

	for _, other in pairs(PlayersService:GetPlayers()) do
		if other ~= player then
			event:FireClient(other, ...)
		end
	end
end
-- Create topic folder
function module.GetOrCreateClientServerTopicCategory( categoryName )
	local eventTopicFolder = ReplicatedStorage:FindFirstChild("EventTopics")
	if eventTopicFolder == nil then
		eventTopicFolder = rq.CreateFolder("EventTopics", ReplicatedStorage)
	end

	local categoryFolder = eventTopicFolder:FindFirstChild(categoryName)
	if categoryFolder == nil then
		categoryFolder = rq.CreateFolder(categoryName, eventTopicFolder)
	end

	return categoryFolder
end

-- Create ClientServer topic in folder
function module.GetOrCreateClientServerTopicInCategory(categoryName, topicName)
	local categoryFolder = module.GetOrCreateClientServerTopicCategory(categoryName)

	local topic = categoryFolder:FindFirstChild(topicName)
	if topic == nil or not topic:IsA("RemoteEvent") then
		topic = Instance.new("RemoteEvent")
		topic.Name = topicName
		topic.Parent = categoryFolder
	end
	return topic
end

-- Subscribe Server to event topic
-- callback params:
--  callback(playerWhoFiredTheEvent, argumentsTuplePassedByFireServer)
-- Receives events generated by RemoteEvent:FireServer()
function module.SubscribeServerToTopicEvent(categoryName, topicName, serverCallback)
	print("Subscribing to event " .. topicName .. " in " .. categoryName)
	local topic = module.GetOrCreateClientServerTopicInCategory(categoryName, topicName)
	topic.OnServerEvent:Connect(serverCallback)
	return topic
end

function module.ConnectEntityListenerFuncToTopic(entityId, categoryName, topic, listenerFunc)
	local gatekeeperClosure = function(listeningEntityId, wrappedListenerFunc)
		local wrapperFunc = function(sender, receiverEntityId)
			if (receiverEntityId ~= nil and receiverEntityId == listeningEntityId) then
				wrappedListenerFunc(sender, receiverEntityId)
			end
		end
		return wrapperFunc
	end

	local subscribedTopic = module.SubscribeServerToTopicEvent(categoryName, 
		topic,
		gatekeeperClosure(entityId, listenerFunc))
	return subscribedTopic
end

return module
