Lifecycle
e2en provides hooks for player and character lifecycle events with automatic cleanup through Troves.
Server Lifecycle
Player Added
Called when a player joins. Also fires retroactively for players already in the game.
e2en.OnPlayerAdded(function(player: Player, trove: Trove)
print(player.Name, "joined")
-- Load their data
local data = loadData(player)
-- Add things to the trove for auto-cleanup
trove:Add(createPlayerState(player))
trove:Connect(player.Chatted, function(message)
print(player.Name, "said:", message)
end)
end)
The trove automatically cleans up when the player leaves, so no manual disconnection is needed.
Player Removing
Called when a player is about to leave. Use this for saving data.
e2en.OnPlayerRemoving(function(player: Player)
print(player.Name, "leaving")
saveData(player)
end)
Character Added
Called when a character spawns. Also fires retroactively for existing characters.
e2en.OnCharacterAdded(function(player: Player, character: Model, trove: Trove)
print(player.Name, "spawned")
local humanoid = character:WaitForChild("Humanoid") :: Humanoid
-- Auto-cleanup when character dies/respawns
trove:Connect(humanoid.Died, function()
print(player.Name, "died")
end)
trove:Connect(humanoid.Running, function(speed)
if speed > 0 then
print(player.Name, "is running")
end
end)
end)
Character Removing
Called when a character is about to be removed.
e2en.OnCharacterRemoving(function(player: Player, character: Model)
print(player.Name, "character removing")
end)
Getting Troves Manually
local playerTrove = e2en.GetPlayerTrove(player)
local characterTrove = e2en.GetCharacterTrove(player)
if playerTrove then
playerTrove:Add(someCleanupTarget)
end
Client Lifecycle
Character Added
e2en.OnCharacterAdded(function(character: Model, trove: Trove)
print("Spawned")
local humanoid = character:WaitForChild("Humanoid") :: Humanoid
trove:Connect(humanoid.Died, function()
print("Died")
end)
trove:Connect(humanoid.HealthChanged, function(health)
updateHealthBar(health)
end)
end)
Character Removing
e2en.OnCharacterRemoving(function(character: Model)
print("Character removing")
end)
Getting Current Character
-- Returns nil if no character exists
local character = e2en.GetCharacter()
-- Get the character's trove (nil if no character)
local trove = e2en.GetCharacterTrove()
Player Reference
local player = e2en.Player
print("I am", player.Name)
The Trove Pattern
Troves manage cleanup automatically. When a trove is cleaned (player leaves, character dies), everything added to it is destroyed/disconnected.
Adding Objects
e2en.OnPlayerAdded(function(player, trove)
-- Instances are destroyed
local folder = Instance.new("Folder")
folder.Name = player.Name
trove:Add(folder)
folder.Parent = workspace
-- Connections are disconnected
trove:Connect(player.Chatted, function(msg)
print(msg)
end)
-- Tables with Destroy method
local state = { Destroy = function() print("cleaned up") end }
trove:Add(state)
-- Custom cleanup method
local resource = createResource()
trove:Add(resource, "Release") -- calls resource:Release()
end)
Nested Troves
Create sub-troves for grouped cleanup:
e2en.OnCharacterAdded(function(player, character, trove)
-- Combat-related stuff
local combatTrove = Trove.new()
trove:Add(combatTrove)
combatTrove:Connect(...)
combatTrove:Add(...)
-- Clear combat stuff without clearing everything
combatTrove:Clean()
end)
Common Patterns
Per-Player State
local playerStates = {}
e2en.OnPlayerAdded(function(player, trove)
playerStates[player] = {
score = 0,
inventory = {},
}
end)
e2en.OnPlayerRemoving(function(player)
playerStates[player] = nil
end)
Character Components
e2en.OnCharacterAdded(function(player, character, trove)
-- Add a highlight that auto-removes on death
local highlight = Instance.new("Highlight")
highlight.FillColor = Color3.new(1, 0, 0)
trove:Add(highlight)
highlight.Parent = character
-- Track running state
local humanoid = character:WaitForChild("Humanoid") :: Humanoid
local isRunning = false
trove:Connect(humanoid.Running, function(speed)
isRunning = speed > 0
end)
end)
Waiting for Character
function MyService:DoSomethingWithCharacter(player: Player)
local character = player.Character
if not character then
character = player.CharacterAdded:Wait()
end
-- Now we have a character
end
Client: Waiting for Server
function MyController:Start()
-- Wait for framework to be fully ready
e2en.OnStart()
-- Now safe to access services
local GameService = e2en.GetService("GameService")
end