{"id":"risebit/playerstate","name":"playerstate","scope":"risebit","platform":"roblox","description":"A modern player data management system for Roblox games featuring ProfileService integration, replica-based state replication, automatic leaderboards, and batched updates.","version":"1.1111.0","latest":"1.1111.0","versions":["1.1.0","1.1.2","1.1.201","1.1111.0"],"license":"MIT","licenseRating":"safe","licenseCaveats":["The package archive does not include its license text; the license is declared in its manifest metadata."],"licenseVerified":false,"dependencies":{},"integrity":"7f192041782fc0154986856d927333c0a517e620a61320de57ce0c62c718613f","likes":0,"downloads":0,"install":"forest install risebit/playerstate","url":"https://forest.dev/p/roblox/risebit/playerstate","files":"https://api.forest.dev/ai/package/roblox/risebit/playerstate/files","readme":"# PlayerState\n\nA modern player data management system for Roblox games featuring ProfileService integration, replica-based state replication, automatic leaderboards, and batched updates.\n\n## Features\n\n- ✅ **ProfileService Integration** - Secure data persistence with session locking\n- ✅ **Real-time Replication** - Automatic client data sync with change tracking\n- ✅ **Built-in Leaderboards** - Automatic stat tracking and rankings\n- ✅ **Batched Updates** - Efficient DataStore writes\n- ✅ **Path-Based Access** - Access nested data with dot notation\n- ✅ **Type-Safe API** - Full Luau type coverage\n- ✅ **Performance Optimized** - Intelligent caching and rate limiting\n\n## Installation\n\n### Option 1: Manual Installation\n\n1. Clone or download this repository\n```bash\ngit clone https://github.com/YOURUSERNAME/PlayerState.git\n```\n\n2. Open your Roblox game in Studio\n3. In ReplicatedStorage, make sure the folder is named `PlayerState`\n4. The require path will be: `game.ReplicatedStorage.PlayerState.PlayerStateServer`\n\n### Option 2: GitHub Cloning Plugin\n\nUse the [GitHub Cloning Plugin](https://devforum.roblox.com/t/github-cloning-plugin/31267) to clone directly into Roblox Studio.\n\n## Quick Start\n\n### 1. Configure Your Data Structure\n\nEdit `DefaultData.luau` to define your player data:\n\n```lua\nreturn {\n    Coins = 0,\n    Level = 1,\n    \n    Inventory = {\n        Weapons = {},\n        Items = {}\n    },\n    \n    leaderstats = {\n        [\"💰 Coins\"] = \"Coins\",\n        [\"⭐ Level\"] = \"Level\"\n    }\n}\n```\n\n### 2. Configure Settings\n\nEdit `PlayerStateConfig.luau` for your game settings:\n\n```lua\nlocal Config = {\n    Server = {\n        DataStore = {\n            Name = \"PlayerData_v1\",\n            Scope = \"Production\"\n        },\n        \n        Leaderboard = {\n            Enabled = true,\n            TrackedStats = {\"Coins\", \"Level\"}\n        }\n    }\n}\n\nreturn Config\n```\n\n### 3. Initialize on Server\n\n```lua\nlocal Players = game:GetService(\"Players\")\nlocal PlayerState = require(ReplicatedStorage.PlayerState.PlayerStateServer)\n\nPlayers.PlayerAdded:Connect(function(player)\n    local success = PlayerState.Init(player)\n    \n    if success then\n        print(`[PlayerState] Loaded data for {player.Name}`)\n    end\nend)\n\nPlayers.PlayerRemoving:Connect(function(player)\n    PlayerState.SaveData(player)\nend)\n```\n\n### 4. Use on Client\n\n```lua\nlocal PlayerState = require(ReplicatedStorage.PlayerState.PlayerStateClient)\n\n-- Wait for data to load\nPlayerState.IsReady() -- Check if ready\n\n-- Listen for changes\nPlayerState.OnChanged(\"Coins\", function(newValue, oldValue)\n    print(`Coins: {oldValue} → {newValue}`)\nend)\n```\n\n## API Reference\n\n### Server API\n\n#### Basic Operations\n\n```lua\n-- Set a value\nPlayerState.Set(player, \"Coins\", 100)\n\n-- Get a value\nlocal coins = PlayerState.Get(player, \"Coins\")\n\n-- Access nested data with dot notation\nPlayerState.SetPath(player, \"Inventory.Weapons[1].Durability\", 95)\nlocal durability = PlayerState.GetPath(player, \"Inventory.Weapons[1].Durability\")\n```\n\n#### Increment/Decrement\n\n```lua\n-- Increment by 1\nPlayerState.Increment(player, \"Coins\")\n\n-- Increment by custom amount\nPlayerState.Increment(player, \"Level\", 5)\n\n-- Decrement\nPlayerState.Decrement(player, \"Coins\", 10)\n```\n\n#### Arrays\n\n```lua\n-- Add item to array\nPlayerState.AddToArray(player, \"Inventory.Weapons\", {\n    Id = \"sword_001\",\n    Name = \"Iron Sword\",\n    Damage = 10\n})\n\n-- Update array item\nPlayerState.UpdateArrayItem(player, \"Inventory.Weapons\", 1, {\n    Id = \"sword_001\",\n    Name = \"Iron Sword\",\n    Damage = 15\n})\n\n-- Remove from array\nPlayerState.RemoveFromArray(player, \"Inventory.Weapons\", 1)\n```\n\n#### Dictionaries\n\n```lua\n-- Set dictionary value\nPlayerState.SetInDict(player, \"Inventory.Items\", \"health_potion\", 5)\n\n-- Get dictionary value\nlocal quantity = PlayerState.GetFromDict(player, \"Inventory.Items\", \"health_potion\")\n\n-- Remove from dictionary\nPlayerState.RemoveFromDict(player, \"Inventory.Items\", \"health_potion\")\n```\n\n#### Batch Operations\n\n```lua\n-- Update multiple values at once\nPlayerState.BatchSetValues(player, {\n    {path = \"Coins\", value = 200},\n    {path = \"Level\", value = 5},\n    {path = \"Experience\", value = 1000}\n})\n\n-- Manually flush batch (normally auto-flushes)\nPlayerState.FlushBatch(player)\n```\n\n#### Leaderboards\n\n```lua\n-- Get top players\nlocal topPlayers = PlayerState.GetLeaderboard(\"Coins\", 10)\n-- Returns: {{userId = 123, score = 5000, rank = 1}, ...}\n\n-- Get player's rank\nlocal rank = PlayerState.GetPlayerRank(player, \"Coins\")\n```\n\n#### Events\n\n```lua\n-- Before data is saved\nPlayerState.BeforeSave:Connect(function(player, data)\n    -- Validate or modify data before saving\nend)\n\n-- When player data loads\nPlayerState.ProfileLoaded:Connect(function(player, data)\n    print(\"Data loaded for\", player.Name)\nend)\n\n-- When player leaves\nPlayerState.ProfileUnloaded:Connect(function(player, data)\n    print(\"Data saved for\", player.Name)\nend)\n```\n\n#### Utilities\n\n```lua\n-- Get all player data\nlocal allData = PlayerState.GetAll(player)\n\n-- Check if data is ready\nif PlayerState.IsPlayerDataReady(player) then\n    -- Safe to use data\nend\n\n-- Save data manually\nPlayerState.SaveData(player)\n\n-- Admin: Wipe player data\nPlayerState.WipePlayerData(player)\n```\n\n### Client API\n\n#### Reading Data\n\n```lua\n-- Get value\nlocal coins = PlayerState.Get(\"Coins\")\n\n-- Get nested value\nlocal durability = PlayerState.GetPath(\"Inventory.Weapons[1].Durability\")\n\n-- Get dictionary value\nlocal quantity = PlayerState.GetFromDict(\"Inventory.Items\", \"health_potion\")\n\n-- Get all data\nlocal allData = PlayerState.GetAll()\n```\n\n#### Listening for Changes\n\n```lua\n-- Listen to any path\nPlayerState.OnChanged(\"Coins\", function(newValue, oldValue)\n    print(`Coins changed: {oldValue} → {newValue}`)\nend)\n\nPlayerState.OnChanged(\"Inventory.Weapons\", function(newValue, oldValue)\n    print(\"Weapons updated!\")\nend)\n```\n\n#### Utilities\n\n```lua\n-- Check if data is ready\nif PlayerState.IsReady() then\n    -- Data loaded\nend\n\n-- Clear cache (advanced)\nPlayerState.ClearCache()\n\n-- Get underlying Replica (advanced)\nlocal replica = PlayerState.GetReplica()\n```\n\n## Attribution\n\nThis library uses the following third-party dependencies (included):\n\n- **ProfileStore** by [MAD STUDIO (loleris)](https://madstudioroblox.com/) - DataStore session management\n- **Replica** by [MAD STUDIO (loleris)](https://madstudioroblox.com/) - State replication system  \n- **Maid, Signal, Remote, RateLimit** by MAD STUDIO - Supporting utilities\n\nSee individual file headers for full attribution details.\n\n## Documentation\n\nFull documentation available at: **[playerstate.netlify.app](https://playerstate.netlify.app)**\n\n## License\n\nMIT License - See LICENSE file for details\n\n## Support\n\n- 💬 [DevForum Post](https://devforum.roblox.com/t/your-post-link)\n- 🐛 [Report Issues](https://github.com/YOURUSERNAME/PlayerState/issues)\n","readmeBorrowedFrom":{"version":"1.1.201","source":"wally"},"readmeTruncated":false}