{"id":15888212,"url":"https://github.com/corecii/roblox-networkclock","last_synced_at":"2025-04-02T16:44:16.241Z","repository":{"id":105909352,"uuid":"282605535","full_name":"Corecii/Roblox-NetworkClock","owner":"Corecii","description":"Synced time module for Roblox","archived":false,"fork":false,"pushed_at":"2020-09-07T22:40:59.000Z","size":19,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-08T07:25:11.007Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Lua","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Corecii.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-07-26T08:11:21.000Z","updated_at":"2021-04-16T17:54:24.000Z","dependencies_parsed_at":"2024-06-15T07:03:14.578Z","dependency_job_id":null,"html_url":"https://github.com/Corecii/Roblox-NetworkClock","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Corecii%2FRoblox-NetworkClock","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Corecii%2FRoblox-NetworkClock/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Corecii%2FRoblox-NetworkClock/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Corecii%2FRoblox-NetworkClock/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Corecii","download_url":"https://codeload.github.com/Corecii/Roblox-NetworkClock/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246853357,"owners_count":20844566,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-06T06:06:41.503Z","updated_at":"2025-04-02T16:44:16.218Z","avatar_url":"https://github.com/Corecii.png","language":"Lua","funding_links":[],"categories":[],"sub_categories":[],"readme":"# NetworkClock\n\nThis module provides synchronized network time for the server and client.\n\n**This module has not undergone rigorous or complete testing, and has not reached a stable version. Use at your own risk!**\n\n# How To (With The Default Clock)\n\n1. Add this module to your project\n2. Add the Promise library (any version 3.x.x) to your project\n2. Initialize the default network clock as part of starting your game. The clock *must* be initialized before you use it or it will error.\n```lua\nlocal NetworkClock = require(game.ReplicatedStorage.NetworkClock)\n\nNetworkClock.Default():WaitUntilInitialized()\n```\n3. Use your clock in your project\n```lua\nlocal Clock = require(game.ReplicatedStorage.NetworkClock).Default()\n\nprint(\"The current timestamp is:\", Clock:GetTime())\nprint(\"The timestamp's accuracy relative to the source is:\", Clock:GetAccuracy())\n\nprint(\"The current time is:\", Clock()) -- This works too\n```\n\nThat's it!\n\n# Stable API\n\n```lua\nNetworkClock.new(NetworkClockOptions) --\u003e NetworkClock\n-- Creates a new network clock with the given options\n\nNetworkClock:GetInitializedPromise() --\u003e Promise\u003cself\u003e\n-- Returns a promise that resolve once the clock is synchronized and useable\n\nNetworkClock:WaitUntilInitialized() --\u003e self\n-- Waits for the clock to be initialized\n-- Sugar for NetworkClock:GetInitializedPromise():expect()\n\nNetworkClock:GetTime() --\u003e number\n-- Returns the current decimal-precision timestamp from this clock\n-- This will error if the clock is not initialized.\n\nNetworkClock() -- \u003e number\n-- Sugar for NetworkClock:GetTime()\n\nNetworkClock:GetAccuracy() --\u003e number\n-- Returns how far off at maximum the time could be from the source\n-- For http time on the server, \"the source\" is unix time\n-- For remote time on the client, \"the source\" is the server's time\n\nNetworkClock.CREATE_REMOTE_FUNCTION\n-- A constant representing that NetworkClock should handle creating/waiting for remote functions\n\nNetworkClock.Default()\n-- Returns a default network clock that can safely be used between different projects and modules\n\nNetworkClock.DefaultNoHttp()\n-- Returns a default, server os.clock-based network clock that can safely be used between different projects and modules\n```\n\n```lua\nNetworkClockOptions\n\tname: string\n\t-- The name of this network clock -- typically your project's owner:name\n\n\tremoteFunction?: CREATE_REMOTE_FUNCTION | RemoteFunction | Promise\u003cRemoteFunction\u003e | false\n\t-- Default: CREATE_REMOTE_FUNCTION\n\t-- The remote function to use or handle\n\t-- If set to CREATE_REMOTE_FUNCTION, NetworkClock will create a remote function in ReplicatedStorage on the server, and wait for one on the client\n\n\tsyncMode: \"Http\" | \"OsClock\" | \"RemoteFunction\"\n\t-- How to sync the time\n\t-- OsTime is meant to be used for testing in studio. OsTime can vary multiple minutes between servers!\n\t-- OsClock is meant for when you only need synchronized time between server and client and not between server\n\t-- Default: \"Http\" on server, \"RemoteFunction\" on client\n\n\tresyncOnSuccessInterval: number\n\t-- Default: 120 on server, 30 on client\n\t-- How often to resync time. Set to 0 to sync only once at the start of the game.\n\n\tresyncOnFailureInterval: number\n\t-- Default: 10\n\t-- How often to re-attempt sync when sync fails.\n\n\tresyncLerpOffset: boolean\n\t-- Default: true\n\t-- Whether to lerp the time offset to prevent discontinuous time jumps after resyncs\n\n\thttpTimeout: number\n\t-- Default: 10\n\t-- Max time an http request can take\n\thttpMinResults: number\n\t-- Default: 3\n\t-- Minimum number of results for this clock to be \"confident\" in its http-retrieved network time\n\thttpUrls: Array\u003cstring\u003e\n\t-- Urls to retrieve time from\n\t-- Urls are requested as url/?nocache={GUID}\n\t-- All given urls are requested at once on every sync\n\t-- This is done to detect and avoid misconfigured and out-of-sync servers\n\t-- Default: {\n\t--  \"https://www.wikipedia.org\",\n\t--  \"https://www.microsoft.com\",\n\t--  \"https://stackoverflow.com\",\n\t--  \"https://www.amazon.com\",\n\t--  \"https://aws.amazon.com\",\n\t-- }\n```\n\n# How To (With Your Own Clock)\n\n1. Add this module to your project\n2. Add the Promise library (any version 3.x.x) to your project\n2. Create modules to initialize your project's network clock. You should wait for your clock to initialize before using it.\n```lua\n-- MyNetworkClock.lua\nlocal NetworkClock = require(game.ReplicatedStorage.NetworkClock)\n\nlocal myClock = NetworkClock.new({name = \"Me:MyGame\"})\nmyClock:WaitUntilInitialized()\n\nreturn myClock\n```\n3. Use your clock in your project\n```lua\nlocal Clock = require(game.ReplicatedStorage.MyNetworkClock)\n\nprint(\"The current timestamp is:\", Clock:GetTime())\nprint(\"The timestamp's accuracy relative to the source is:\", Clock:GetAccuracy())\n\nprint(\"The current time is:\", Clock()) -- This works too\n```\n\nThat's it!\n\n# Design and Implementation\n\n### Instanced Clocks\n\nEveryone might not want the same clock behavior: some developers might not want http time, some might want to fetch time from different urls, some others might want to change the resync intervals.\n\nWith instanced clocks, you can safely depend on other modules that use NetworkClock. In one codebase, two modules can use two different clock settings without conflict.\n\n### Avoiding Misconfigured Http Time Results\n\nNetworkClock pulls its http time from the `Date` headers of popular websites. In a rare case, a web server could be misconfigured and report a bad Date. By pulling the Date headers from multiple websites, we can remove outliers.\n\n### Accuracy\n\nPulling time from remote sources is inherently inaccurate: data has to travel a variable amount of time, and there's no way of knowing the exact one-way-trip-time. Even worse, time from http servers only has 1-second precision.\n\nBy storing the \"accuracy\" with the current time offset we can:\n* know when we've found a more accurate time\n* know when our accurate time is more out of date than its accuracy\n\nOn the server with http the accuracy is `1.5 + round_trip_time`. On the client with remotes the accuracy is `round_trip_time`.\n\nWhen retrieving the time, estimated one-way-trip-time is accounted for.\n\n###  Offset Lerp\n\nWe resync time because we can end up with a \"better\" network time for a variety of reasons:\n* the new network time is more accurate (smaller round trip time)\n* the old network time was wrong (misconfigured servers)\n* the local time-keeping mechanism is bad (that is, when 1 second elapsed irl is not 1 second elapsed in the computer)\n\nWhen we end up with a better network time we should ideally switch to it. Switching to it instantly can cause a jump or discontinuity in the local time, however small. This means time could jump forward unreasonably fast or it could *move backwards*.\n\nTo keep time moving smoothly and prevent backwards jumps we lerp between the old and new time offsets when a better network time is found.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcorecii%2Froblox-networkclock","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcorecii%2Froblox-networkclock","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcorecii%2Froblox-networkclock/lists"}