{"id":31050512,"url":"https://github.com/jakobhellermann/utas","last_synced_at":"2025-09-14T22:59:33.777Z","repository":{"id":305833656,"uuid":"666049811","full_name":"jakobhellermann/uTas","owner":"jakobhellermann","description":null,"archived":false,"fork":false,"pushed_at":"2024-01-30T23:09:59.000Z","size":1524,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-09-06T03:56:30.524Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C#","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/jakobhellermann.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,"zenodo":null}},"created_at":"2023-07-13T15:34:02.000Z","updated_at":"2023-07-13T15:34:46.000Z","dependencies_parsed_at":"2025-07-22T09:08:53.741Z","dependency_job_id":null,"html_url":"https://github.com/jakobhellermann/uTas","commit_stats":null,"previous_names":["jakobhellermann/utas"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/jakobhellermann/uTas","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jakobhellermann%2FuTas","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jakobhellermann%2FuTas/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jakobhellermann%2FuTas/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jakobhellermann%2FuTas/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jakobhellermann","download_url":"https://codeload.github.com/jakobhellermann/uTas/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jakobhellermann%2FuTas/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":275180204,"owners_count":25419065,"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","status":"online","status_checked_at":"2025-09-14T02:00:10.474Z","response_time":75,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":"2025-09-14T22:59:29.644Z","updated_at":"2025-09-14T22:59:33.761Z","avatar_url":"https://github.com/jakobhellermann.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# uTas\n\n\u003cimg src=\"./docs/logo/logo_wind.png\" align=\"left\" height=\"128px\" alt=\"logo image, the letter U inside a purple gradient circle\"\u003e\n\n\u003ca href=\"https://www.nuget.org/packages/uTas.TasFormat/\" alt=\"Contributors\"\u003e\u003cimg src=\"https://img.shields.io/nuget/v/uTas.TasFormat?label=uTas.TasFormat\u0026color=green\"/\u003e\u003c/a\u003e\n\u003ca href=\"https://www.nuget.org/packages/uTas.Communication/\" alt=\"Contributors\"\u003e\u003cimg src=\"https://img.shields.io/nuget/v/uTas.Communication?label=uTas.Communication\u0026color=green\"/\u003e\u003c/a\u003e\n\n[Celeste](https://github.com/EverestAPI/CelesteTAS-EverestInterop)-inspired universal (game-independent) TAS tooling.\n\n\u003cbr clear=\"left\" /\u003e\n\u003cbr /\u003e\n\nExamples of games with support for uTas:\n\n- [Moonscars](https://store.steampowered.com/app/1374970/Moonscars/)\n  (WIP): https://github.com/jakobhellermann/MoonscarsTasTools\n\n![picture of the uTas editor](./docs/editor.png)\n\n## Architecture\n\nThe repository contains the [uTas Editor](./TasEditor), [shared communication code](./Communication) and a parser for\nthe [uTAS File Format](./TasEditor).\n\nThe editor starts listening for TCP connections on a specific port (currently 34729), which in-game TAS mods can connect\nto.\nThey will then exchange messages via simple messages of `\u003copcode\u003e \u003cdata\u003e`, where opcode can\nbe `SetInfoString`, `KeybindTriggered`, etc.\nSee [Messages.cs](./Communication/Messages.cs) for what is implemented right now.\n\nA typical exchange of messages looks like this:\n\n```\nClient: EstablishConnection\nClient: SendKeybinds \u003ckeybinding configuration\u003e (not yet implemented)\nServer: SendPath /path/to/opened/file.tas\n\nClient: SetInfoString\nClient: SetInfoString\nClient: SetInfoString\nClient: SetInfoString\n...\n\nServer: KeybindTriggered StartStop\n...\nServer: KeybindTriggered FrameAdvance\n\n\nClient: CloseConnection\n```\n\nSince the Editor is game-agnostic, the client is responsible for\n\n- actually parsing the TAS file, and playing it back\n- mapping from inputs `R`, `A` to game-specific actions like hold right, attack\n- configurable keybindings that are sent to the editor\n\n## TAS Format\n\n```jl\n#lvl_1 hashtags begin comments\n   5,R       # hold right for 5 frames\n   15,D,R,X  # hold down-right and dash\n   10        # do nothing for 10 frames\n\n# \"Calls\", arbitrary `Name, Param0, Param1, ...` interpreted by the client\nSet, Player.Speed.X, 100\n\n# \"Commands\", arbitrary `name Param0, Param1 ...` interpreted by the client\nconsole load 1 2 3\n\n\n*** # breakpoints: when starting the TAS, execution will fast-forward to the latest breakpoint and stop\n\n 100 # this will run at half spee\n***0.5\n   5,R\n   14,R,J # this will get executed at double speed\n***2 \n```\n\n## Development\n\nOpen in your favorite IDE (Rider, VS, ...) and run `TasEditor.Desktop`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjakobhellermann%2Futas","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjakobhellermann%2Futas","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjakobhellermann%2Futas/lists"}