local A=game:GetService("\082\101\112\108\105\099\097\116\101\100\083\116\111\114\097\103\101")local i=game:GetService("\082\117\110\083\101\114\118\105\099\101")local V={}local j="\082\111\112\111\115\116\069\118\101\110\116"local M=A:FindFirstChild(j)if not M then if i:IsServer()then M=Instance.new("\082\101\109\111\116\101\069\118\101\110\116")M.Name=j M.Parent=A else M=A:WaitForChild(j)end end local function K(A,i,V)return{channel=A;topic=i,timestamp=os.clock(),data=V}end function V.subscribe(A)local V,j,K=A.channel,A.topic,A.callback assert(type(V)=="\115\116\114\105\110\103","\073\110\118\097\108\105\100 \099\104\097\110\110\101\108\033")assert(type(j)=="\115\116\114\105\110\103","\073\110\118\097\108\105\100 \116\111\112\105\099\033")assert(type(K)=="\102\117\110\099\116\105\111\110","\073\110\118\097\108\105\100 \099\097\108\108\098\097\099\107\033")local E if i:IsServer()then E=M.OnServerEvent:connect(function(A,i)if i.channel==V and i.topic==j then i.player=A K(i.data,i)end end)else E=M.OnClientEvent:connect(function(A)if A.channel==V and A.topic==j then K(A.data,A)end end)end return function()E:disconnect()end end function V.publish(A)local V,j,E=A.channel,A.topic,A.data assert(type(V)=="\115\116\114\105\110\103","\073\110\118\097\108\105\100 \099\104\097\110\110\101\108\033")assert(type(j)=="\115\116\114\105\110\103","\073\110\118\097\108\105\100 \116\111\112\105\099\033")assert(type(E)=="\116\097\098\108\101","\073\110\118\097\108\105\100 \100\097\116\097\033")local C=K(V,j,E)if i:IsServer()then local i=A.players if i then for A,i in pairs(i)do M:FireClient(i,C)end else M:FireAllClients(C)end else M:FireServer(C)end end return V
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")

local RopostMethods = {}

local ROPOST_EVENT_NAME = "RopostEvent"
local remoteEvent = ReplicatedStorage:FindFirstChild(ROPOST_EVENT_NAME)
if not remoteEvent then
	if RunService:IsServer() then
		remoteEvent = Instance.new("RemoteEvent")
		remoteEvent.Name = ROPOST_EVENT_NAME
		remoteEvent.Parent = ReplicatedStorage
	else
		remoteEvent = ReplicatedStorage:WaitForChild(ROPOST_EVENT_NAME)
	end
end

local function createEnvelope(channel, topic, data)
	return {
		channel = channel,
		topic = topic,
		timestamp = os.clock(),
		data = data,
	}
end

function RopostMethods.subscribe(kwargs)
	local channel, topic, callback = kwargs.channel, kwargs.topic, kwargs.callback
	assert(type(channel) == "string", "Invalid channel!")
	assert(type(topic) == "string", "Invalid topic!")
	assert(type(callback) == "function", "Invalid callback!")

	local conn
	if RunService:IsServer() then
		conn = remoteEvent.OnServerEvent:connect(function(plr, envelope)
			if envelope.channel == channel and envelope.topic == topic then
				envelope.player = plr
				callback(envelope.data, envelope)
			end
		end)
	else
		conn = remoteEvent.OnClientEvent:connect(function(envelope)
			if envelope.channel == channel and envelope.topic == topic then
				callback(envelope.data, envelope)
			end
		end)
	end

	return function()
		conn:disconnect()
	end
end

function RopostMethods.publish(kwargs)
	local channel, topic, data = kwargs.channel, kwargs.topic, kwargs.data
	assert(type(channel) == "string", "Invalid channel!")
	assert(type(topic) == "string", "Invalid topic!")
	assert(type(data) == "table", "Invalid data!")

	local envelope = createEnvelope(channel, topic, data)
	if RunService:IsServer() then
		local players = kwargs.players
		if players then
			for _, player in pairs(players) do
				remoteEvent:FireClient(player, envelope)
			end
		else
			remoteEvent:FireAllClients(envelope)
		end
	else
		remoteEvent:FireServer(envelope)
	end
end

return RopostMethods
