Obby Timer with Global Ranking and Best Times
Generate a professional race system for obbies with individual timers, fully server-side validation, start and finish detection, persistent personal best times, and a ranking of the fastest players worldwide. The result is adapted to your game’s real structure, using the names and Explorer paths you provide.
The prompt requires a secure, production-ready implementation, with DataStore protected by pcall, anti-spam limits, invalid-result prevention, and handling for players who leave during a run. It also includes optional integration with RemoteEvents and a strategy for displaying the time and ranking in the existing interface.
It is intended for developers of obbies, parkour games, and competitive experiences that need a solid foundation for records, speedruns, and leaderboards without trusting client-submitted data.
Act as a senior Roblox developer specialized in Luau, competitive multiplayer systems, DataStoreService, and server-authoritative architecture. Create a complete obby completion timer system with persistent best times and a global ranking, strictly adapted to the context of my game provided below. Before writing the code, read and consider this context. If any field is empty, use reasonable default names, clearly state your assumptions, and keep the settings centralized at the top of the script to make adjustments easier: --- MY GAME CONTEXT --- - Path/name of the part that starts the race (Start): [PASTE HERE] - Path/name of the part that finishes the race (Finish): [PASTE HERE] - Are there checkpoints? Provide folder, tags, or names and how they should affect validation: [PASTE HERE] - Is there a default leaderboard (leaderstats)? Which values already exist?: [PASTE HERE] - Existing RemoteEvents/RemoteFunctions, with path and purpose: [PASTE HERE] - Existing GUI for time/ranking, including TextLabel paths: [PASTE HERE] - Desired OrderedDataStore name, if any: [PASTE HERE] - Minimum acceptable time to complete the map and additional anti-exploit rules: [PASTE HERE] - Do I want a global ranking in SurfaceGui/GUI, leaderstats, or both?: [PASTE HERE] - Other obby rules (teleport, reset, multiple maps, rounds, etc.): [PASTE HERE] --- END OF CONTEXT --- The main result must be ONE complete server Script, not a LocalScript and not a ModuleScript. Explicitly instruct that it must be created as a Script and placed in ServerScriptService, for example with the name ObbyTimerServer. The script should work autonomously as much as possible and use configurable references to objects in Workspace, ReplicatedStorage, and other services. If the context requires dynamic UI or updates via RemoteEvent, the server Script must expose/integrate the necessary events securely; if it is unavoidable to create a complementary LocalScript for an existing GUI, present it only in an additional, separate section, explaining its exact location. Prioritize keeping every critical rule on the server. Implement these technical requirements: 1. Detect the character touching the start area and begin a run only if the player is not already running. Record the time on the server using an appropriate time source and keep state by UserId, never by player name. 2. Detect the finish only for players with an active run. Compute the time on the server, reject times below the configured minimum, duplicate executions, inconsistent states, and any completion without a required checkpoint, when applicable. 3. Create or integrate leaderstats with at least BestTime (NumberValue, using 0 or a defined value for no record) and Wins/Completions, without destructively overwriting existing values. Choose names compatible with the context and document the decision in comments. 4. Save and load each player’s best time with DataStoreService. Use pcall in every DataStore operation, controlled retries when appropriate, failure handling without deleting valid data, and saving in PlayerRemoving and BindToClose. Do not save every frame and do not rely on client data. 5. Use OrderedDataStore to register only the best valid time and allow a global ranking of the lowest times. Since OrderedDataStore sorts numbers in ascending order, explain the chosen strategy in a comment. Implement a safe function to fetch the Top 10/Top N, converting UserIds into names with failure protection and respecting request limits. 6. If there is a RemoteEvent to display time to the player or feed the interface, the server must send only data calculated by it. Any received RemoteEvent must validate type, limits, player, race state, and permissions. Never trust the client for damage, coins, inventory, wins, time, or records. Never accept a time sent by the client under any circumstances. 7. Handle CharacterAdded, death/reset, PlayerRemoving, multiple rapid touches, parts with CanTouch, NPC characters, and players who leave the race. Do not use heavy infinite loops or duplicate connections. 8. Add useful comments in Portuguese, clear warning messages, and a configuration table at the top with paths, DataStore names, minimum time, ranking size, and relevant options. First provide a short explanation of the architecture and the assumptions adopted. Then provide the full Luau code, syntactically valid, inside a single markdown block exactly in the form ```lua. Do not deliver pseudocode, incomplete snippets, "...", hidden dependencies, or client code disguised as server code. After the block, list the objects/RemoteEvents I need to create manually, only if they cannot be created or found safely by the Script. Finish with an objective step-by-step guide to test it in Roblox Studio, including enabling API Services for DataStore in a published game/proper test environment, testing with two players via Start Server/Start Player, and verifying invalid completion attempts.