Last active
January 21, 2024 02:29
-
-
Save gaymeowing/b9cd1af5518743cdfd389afac9679edc to your computer and use it in GitHub Desktop.
PlayerLoaded event handler for Zap https://zap.redblox.dev/
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type void = boolean? | |
event PlayerLoaded = { | |
from: Client, | |
type: Reliable, | |
call: SingleAsync, | |
data: void | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--!strict | |
local ReplicatedStorage = game:GetService("ReplicatedStorage") | |
local Workspace = game:GetService("Workspace") | |
local Events = require(Path.To.ZapClient) | |
if not game:IsLoaded() then | |
game.Loaded:Wait() | |
Workspace.PersistentLoaded:Wait() | |
end | |
Events.PlayerLoaded.Fire() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--!strict | |
-- PlayerLoaded | |
-- Small serverside module for knowing when a player has loaded | |
-- @Kalrnlo | |
-- 20/01/2024 | |
local ReplicatedStorage = game:GetService("ReplicatedStorage") | |
local Players = game:GetService("Players") | |
local Events = require(Path.To.ZapServer) | |
local Spawn = require(Path.To.Spawn) | |
-- [userid] = {threads yielding for player to load} | |
local SpecificWaitingThreads = {} :: {[number]: {thread}} | |
local CallbackList = {} :: {{(Player: Player) -> ()}} | |
local NonSpecificWaitingThreads = {} :: {thread} | |
local PlayersLoaded = {} :: {Player} | |
local HasInitiated = false | |
local function SpawnCallbacks(Callbacks: {{(Player: Player) -> ()}}, Player: Player) | |
for _, CallbackData in Callbacks do | |
Spawn(CallbackData[1], Player) | |
end | |
end | |
local function ResumeThreadsWithPlayer(Threads: {thread}, Player: Player) | |
for _, Thread in Threads do | |
if Player then | |
coroutine.resume(Thread, Player) | |
else | |
-- just closing the thread as the player left | |
coroutine.close(Thread) | |
end | |
end | |
end | |
local function WaitForLoad(Player: Player): Player | |
if not table.find(PlayersLoaded, Player) then | |
local SpecificThreads = SpecificWaitingThreads[Player.UserId] | |
local Thread = coroutine.running() | |
if SpecificThreads then | |
table.insert(SpecificThreads, Thread) | |
else | |
SpecificWaitingThreads[Player.UserId] = table.create(1, Thread) | |
end | |
return coroutine.yield() | |
else | |
return Player | |
end | |
end | |
local function SafeOn(Callback: (Player: Player) -> ()) | |
local CallbackData = table.create(1, Callback) | |
table.insert(CallbackList, CallbackData) | |
if #PlayersLoaded ~= 0 then | |
for _, Player in PlayersLoaded do | |
if not Player then continue end | |
Spawn(Callback, Player) | |
end | |
end | |
return function() | |
local Index = table.find(CallbackList, CallbackData) | |
table.remove(CallbackList, Index) | |
end | |
end | |
local function On(Callback: (Player: Player) -> ()) | |
local CallbackData = table.create(1, Callback) | |
table.insert(CallbackList, CallbackData) | |
return function() | |
local Index = table.find(CallbackList, CallbackData) | |
table.remove(CallbackList, Index) | |
end | |
end | |
local function Wait(): Player | |
table.insert(NonSpecificWaitingThreads, coroutine.running()) | |
return coroutine.yield() | |
end | |
local function Init() | |
if not HasInitiated then | |
HasInitiated = true | |
else | |
error("[PlayerLoaded] cannot initalize twice") | |
end | |
Events.PlayerLoaded.SetCallback(function(Player) | |
if not table.find(PlayersLoaded, Player) then | |
local SpecificThreads = SpecificWaitingThreads[Player.UserId] | |
if #NonSpecificWaitingThreads ~= 0 then | |
Spawn(ResumeThreadsWithPlayer, NonSpecificWaitingThreads, Player) | |
NonSpecificWaitingThreads = {} | |
end | |
if SpecificThreads then | |
Spawn(ResumeThreadsWithPlayer, SpecificThreads, Player) | |
SpecificWaitingThreads[Player.UserId] = nil | |
end | |
if #CallbackList ~= 0 then | |
Spawn(SpawnCallbacks, CallbackList, Player) | |
end | |
end | |
end) | |
Players.PlayerRemoving:Connect(function(Player) | |
local Index = table.find(PlayersLoaded, Player) | |
SpecificWaitingThreads[Player.UserId] = nil | |
if Index then | |
table.remove(PlayersLoaded, Index) | |
end | |
end) | |
end | |
return { | |
WaitForLoad = WaitForLoad, | |
SafeOn = SafeOn, | |
Wait = Wait, | |
Init = Init, | |
On = On, | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment