Appearance
Usage Examples
💰 Currency Management with Validation
Example
lua
-- Award coins (validation handled internally)
local function awardCoins(player, amount, source)
local currentCoins = PlayerState.Get(player, "Coins") or 0
local success = PlayerState.Set(player, "Coins", currentCoins + amount)
if success then
print(`Awarded {amount} coins to {player.Name} from {source}`)
return true
else
warn(`Failed to award coins to {player.Name}`)
return false
end
end
-- Spend coins with validation
local function spendCoins(player, amount, item)
local currentCoins = PlayerState.Get(player, "Coins") or 0
if currentCoins < amount then
return false, "Insufficient coins"
end
local success = PlayerState.Set(player, "Coins", currentCoins - amount)
if success then
print(`{player.Name} spent {amount} coins on {item}`)
return true, "Purchase successful"
else
return false, "Transaction failed"
end
end📈 Level System with Batch Operations
Example
lua
-- Level up player with batch operations
local function levelUp(player)
local currentLevel = PlayerState.Get(player, "Level") or 1
local currentCoins = PlayerState.Get(player, "Coins") or 0
local bonusCoins = currentLevel * 100
local success = PlayerState.BatchSetValues(player, {
{path = "Level", value = currentLevel + 1},
{path = "Experience", value = 0},
{path = "Coins", value = currentCoins + bonusCoins}
})
if success then
print(`{player.Name} leveled up to {currentLevel + 1}!`)
return true
end
return false
end
-- Add experience with level up check
local function addExperience(player, amount)
local currentExp = PlayerState.Get(player, "Experience") or 0
local currentLevel = PlayerState.Get(player, "Level") or 1
local expNeeded = currentLevel * 100
local newExp = currentExp + amount
if newExp >= expNeeded then
-- Level up
levelUp(player)
else
-- Just add experience
PlayerState.Set(player, "Experience", newExp)
end
end🎒 Enhanced Inventory Management
Example
lua
local MAX_INVENTORY_SIZE = 50
-- Add item with validation and limits
local function addItem(player, item)
local inventory = PlayerState.GetPath(player, "Inventory") or {}
if #inventory >= MAX_INVENTORY_SIZE then
return false, "Inventory full"
end
-- Add timestamp to item
item.AcquiredTime = os.time()
local success = PlayerState.AddToArray(player, "Inventory", item)
if success then
print(`Added {item.Name} to {player.Name}'s inventory`)
return true, "Item added"
end
return false, "Failed to add item"
end
-- Remove item by ID
local function removeItemById(player, itemId)
local inventory = PlayerState.GetPath(player, "Inventory") or {}
for index, item in ipairs(inventory) do
if item.Id == itemId then
local success = PlayerState.RemoveFromArray(player, "Inventory", index)
if success then
print(`Removed {item.Name} from {player.Name}'s inventory`)
return true
end
break
end
end
return false
end
-- Upgrade item in inventory
local function upgradeItem(player, itemIndex, newStats)
local inventory = PlayerState.GetPath(player, "Inventory") or {}
local item = inventory[itemIndex]
if not item then
return false, "Item not found"
end
-- Merge new stats
for key, value in pairs(newStats) do
item[key] = value
end
-- Update upgraded time
item.UpgradedTime = os.time()
local success = PlayerState.UpdateArrayItem(player, "Inventory", itemIndex, item)
if success then
print(`Upgraded {item.Name} for {player.Name}`)
return true
end
return false, "Upgrade failed"
end🏆 Leaderboard Management
Example
lua
-- Server: Comprehensive leaderboard system with validation
local function setupLeaderboardSystem()
-- Configuration reminder
-- Make sure PlayerStateConfig.Server.Leaderboard is properly configured!
-- ✅ Get top 10 players for coins (works if configured)
local topCoins = PlayerState.GetLeaderboard("Coins", 10)
if #topCoins > 0 then
for rank, entry in ipairs(topCoins) do
print(`#{rank}: User {entry.userId} - {entry.score} coins`)
end
else
print("No coin leaderboard data available (check configuration)")
end
-- ✅ Get player's current rank (returns nil if not ranked)
local playerRank = PlayerState.GetPlayerRank(player, "Coins")
if playerRank then
print(`You're currently ranked #{playerRank} for coins!`)
else
print("You're not yet ranked for coins")
end
-- ✅ Manual leaderboard update (for special cases)
local success = PlayerState.UpdateLeaderboard(player, "HighScore", 2500)
if success then
print("High score leaderboard updated!")
else
print("Failed to update leaderboard (check configuration)")
end
end
-- Safe leaderboard usage with error handling
local function safeLeaderboardUsage()
-- Always check if leaderboard is available before heavy usage
local testBoard = PlayerState.GetLeaderboard("Coins", 1)
if #testBoard == 0 then
warn("Leaderboard not configured properly - check PlayerStateConfig")
return false
end
-- Proceed with leaderboard operations
local playerRank = PlayerState.GetPlayerRank(player, "Coins")
return PlayerState.UpdateLeaderboard(player, "Coins", 100)
end
-- Get multiple leaderboard stats at once
local function getPlayerStatsSummary(player)
local stats = {
coinRank = PlayerState.GetPlayerRank(player, "Coins"),
levelRank = PlayerState.GetPlayerRank(player, "Level"),
scoreRank = PlayerState.GetPlayerRank(player, "HighScore"),
}
-- Display player's rankings
for statName, rank in pairs(stats) do
if rank then
print(`{statName}: Rank #{rank}`)
else
print(`{statName}: Not ranked yet`)
end
end
return stats
end
-- Leaderboard UI data
local function getLeaderboardUIData(statName, maxEntries)
local leaderboard = PlayerState.GetLeaderboard(statName, maxEntries or 50)
local uiData = {}
for i, entry in ipairs(leaderboard) do
table.insert(uiData, {
rank = entry.rank,
userId = entry.userId,
score = entry.score,
displayName = "Loading...", -- You'll need to get this from Player service
})
end
return uiData
end
-- Periodic leaderboard announcements
local function announceTopPlayers()
local topPlayers = PlayerState.GetLeaderboard("Coins", 3)
if #topPlayers >= 3 then
print("🏆 TOP 3 RICHEST PLAYERS 🏆")
for i, entry in ipairs(topPlayers) do
local medal = i == 1 and "🥇" or i == 2 and "🥈" or "🥉"
print(`{medal} #{i}: User {entry.userId} - {entry.score} coins`)
end
end
end🏠 Plot Building System
Example
lua
-- Build structure on plot (efficient nested updates)
local function buildStructure(player, buildingType, position)
local buildingData = {
Type = buildingType,
Level = 1,
Position = position,
BuiltTime = os.time(),
Health = 100
}
local buildingId = `{buildingType}_{os.time()}`
local success = PlayerState.SetInDict(player, "Plot.Buildings", buildingId, buildingData)
if success then
print(`{player.Name} built {buildingType} at {position}`)
return true, buildingId
end
return false, "Build failed"
end
-- Upgrade building (efficient single-key update)
local function upgradeBuilding(player, buildingId)
local building = PlayerState.GetPath(player, `Plot.Buildings.{buildingId}`)
if not building then
return false, "Building not found"
end
building.Level = building.Level + 1
building.UpgradedTime = os.time()
local success = PlayerState.SetInDict(player, "Plot.Buildings", buildingId, building)
if success then
print(`{player.Name} upgraded {building.Type} to level {building.Level}`)
return true
end
return false, "Upgrade failed"
end
-- Remove building (efficient key removal)
local function removeBuilding(player, buildingId)
local success = PlayerState.RemoveFromDict(player, "Plot.Buildings", buildingId)
if success then
print(`{player.Name} removed building {buildingId}`)
return true
end
return false, "Removal failed"
end🔄 Event-Driven Data Management
Example
lua
-- Setup event handlers for comprehensive data management
local function setupPlayerStateEvents()
-- When player data loads
PlayerState.ProfileLoaded:Connect(function(player, data)
-- Welcome back message
local loginCount = (data.Stats.Logins or 0) + 1
PlayerState.SetPath(player, "Stats.Logins", loginCount)
PlayerState.Set(player, "LastJoinTime", os.time())
-- Check for daily rewards
local lastReward = data.Stats.LastDailyReward or 0
local currentDay = math.floor(os.time() / 86400) -- Days since epoch
if currentDay > lastReward then
PlayerState.SetPath(player, "Stats.LastDailyReward", currentDay)
PlayerState.Increment(player, "Coins", 100)
print(`{player.Name} received daily reward!`)
end
-- Initialize player systems
setupPlayerUI(player)
setupPlayerEffects(player)
end)
-- Before data saves
PlayerState.BeforeSave:Connect(function(player, data)
-- Final cleanup and validation
data.LastSaveTime = os.time()
-- Calculate session playtime
local joinTime = data.LastJoinTime or os.time()
local sessionTime = os.time() - joinTime
local totalPlayTime = (data.Stats.TotalPlayTime or 0) + sessionTime
PlayerState.SetPath(player, "Stats.TotalPlayTime", totalPlayTime)
PlayerState.SetPath(player, "Stats.LastSessionTime", sessionTime)
-- Validate data integrity
if data.Coins and data.Coins < 0 then
warn(`{player.Name} had negative coins, resetting to 0`)
PlayerState.Set(player, "Coins", 0)
end
print(`Saving {player.Name}'s data - Session: {sessionTime}s, Total: {totalPlayTime}s`)
end)
-- When profile unloads
PlayerState.ProfileUnloaded:Connect(function(player, data)
-- Analytics and external system updates
local finalStats = {
userId = player.UserId,
coins = data.Coins or 0,
level = data.Level or 1,
totalPlayTime = data.Stats.TotalPlayTime or 0,
logins = data.Stats.Logins or 0
}
-- Send to analytics (direct data access only)
sendToAnalytics(finalStats)
-- Cleanup player-specific systems
cleanupPlayerUI(player)
cleanupPlayerEffects(player)
print(`{player.Name} profile unloaded - Final coins: {finalStats.coins}`)
end)
end
-- Call this during server startup
setupPlayerStateEvents()