{"id":"german-rod/roundkit","name":"roundkit","scope":"german-rod","platform":"roblox","description":"A modular, round-flow framework for Roblox.","version":"1.0.0","latest":"1.0.0","versions":["1.0.0"],"license":"MIT","licenseRating":"safe","licenseCaveats":[],"licenseVerified":true,"dependencies":{},"integrity":"795e858375308869bcacaac04d97074023e4e8d9543e9d82bf3024cf4761f60a","likes":0,"downloads":0,"install":"forest install german-rod/roundkit","url":"https://forest.dev/p/roblox/german-rod/roundkit","files":"https://api.forest.dev/ai/package/roblox/german-rod/roundkit/files","readme":"# RoundKit\r\n\r\nRoundKit is a framework for building round-based games on Roblox. It models a round as a collection of **phases**, so you can define how a match progresses: lobby, countdown, active play and results without tangling that flow into your gameplay code.\r\n\r\n## Why this exists\r\n\r\nI built RoundKit while working on my own round-based games, after rewriting the same phase/state-machine logic from scratch too many times. It started as an internal tool and portfolio piece. I'm publishing it because the architecture may be useful to other Roblox developers.\r\n\r\nIf your game has rounds: lobby → countdown → play → results, or similar. RoundKit gives you:\r\n\r\n- **Phases** as data.\r\n- **Win conditions** decoupled from phase logic, including composable `AnyOf` / `AllOf` combinators.\r\n- **Reconnection handling** as a pluggable policy.\r\n- **Per-player and global round state** (`PlayerStateRegistry`, `GlobalMetricRegistry`) that gets cleaned up automatically instead of leaking across rounds.\r\n- **An event bus** (`Context:Connect`) so phases, win conditions, and your own game code can react to round events without direct references to each other.\r\n\r\nIf your game only has one or two simple states, or you're already happy with a hand-rolled state machine, RoundKit is probably more structure than you need.\r\n\r\n## Example\r\n\r\n```lua\r\nlocal RoundKit = require(game.ReplicatedStorage.RoundKit)\r\n\r\nlocal Phases = {\r\n    Lobby = {\r\n        Name = \"Lobby\",\r\n        AllowedTransitions = { \"Countdown\" },\r\n        CanTransitionTo = function(context)\r\n            return context:GetReadyPlayerCount() >= context.Config.MinPlayers\r\n        end,\r\n    },\r\n\r\n    Countdown = {\r\n        Name = \"Countdown\",\r\n        AllowedTransitions = { \"Active\" },\r\n        Duration = 5,\r\n    },\r\n\r\n    Active = {\r\n        Name = \"Active\",\r\n        AllowedTransitions = { \"Lobby\" },\r\n        EvaluateWinCondition = true,\r\n\r\n        OnEnter = function(context)\r\n            context:Connect(\"OnWinConditionMet\", function(outcome)\r\n                context:TransitionTo(\"Lobby\")\r\n            end)\r\n        end,\r\n    },\r\n}\r\n\r\nlocal manager = RoundKit.new({\r\n    Phases = Phases,\r\n    InitialPhase = \"Lobby\",\r\n    WinCondition = \"LastAlive\",\r\n    AutoWirePlayers = true,\r\n    MinPlayers = 4,\r\n})\r\n\r\nmanager:Start()\r\n```\r\n\r\nSee the [documentation](https://german-rod.github.io/RoundKit/) for the full guide and API reference, including custom win conditions, reconnection policies, and the event bus.\r\n\r\n## Documentation\r\n\r\nFull documentation, guides, and API reference: **https://german-rod.github.io/RoundKit/**\r\n\r\n## Project Status\r\n\r\nRoundKit is provided **as-is**, with no guaranteed maintenance, feature requests, or support timeline. It was built for my own projects and shared publicly in case it's useful to others.\r\n\r\n- **Docs:** the link above is the extent of available guidance.\r\n- **Issues:** bug reports with a minimal reproduction are welcome.\r\n- **Pull requests:** open to them.\r\n- **Support:** I don't provide implementation help or game-scripting support.\r\n\r\n## License\r\n\r\nRoundKit is licensed under the [MIT License](LICENSE).","readmeTruncated":false}