{"id":13566690,"url":"https://github.com/3mcd/javelin","last_synced_at":"2025-04-04T00:32:01.270Z","repository":{"id":37827968,"uuid":"260356296","full_name":"3mcd/javelin","owner":"3mcd","description":"ECS and multiplayer game development toolkit","archived":false,"fork":false,"pushed_at":"2023-08-03T06:17:46.000Z","size":5451,"stargazers_count":194,"open_issues_count":8,"forks_count":16,"subscribers_count":8,"default_branch":"master","last_synced_at":"2024-08-01T13:36:49.380Z","etag":null,"topics":["ecs","game-development","gamedev","multiplayer","nodejs","typescript","web"],"latest_commit_sha":null,"homepage":"https://javelin.games","language":"TypeScript","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/3mcd.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null},"funding":{"github":["3mcd"]}},"created_at":"2020-05-01T01:36:28.000Z","updated_at":"2024-07-20T09:46:16.000Z","dependencies_parsed_at":"2023-02-16T03:16:48.818Z","dependency_job_id":"3bf4cebc-a44c-47ca-bfe5-1d03a267d15f","html_url":"https://github.com/3mcd/javelin","commit_stats":null,"previous_names":[],"tags_count":60,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/3mcd%2Fjavelin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/3mcd%2Fjavelin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/3mcd%2Fjavelin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/3mcd%2Fjavelin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/3mcd","download_url":"https://codeload.github.com/3mcd/javelin/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223075366,"owners_count":17083506,"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":["ecs","game-development","gamedev","multiplayer","nodejs","typescript","web"],"created_at":"2024-08-01T13:02:14.750Z","updated_at":"2024-11-04T21:30:49.376Z","avatar_url":"https://github.com/3mcd.png","language":"TypeScript","readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"./logo.png\" width=\"180px\"\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://github.com/3mcd/javelin/workflows/CD/badge.svg?branch=release/next\" alt=\"CD\"\u003e\n  \u003ca href=\"https://codecov.io/gh/3mcd/javelin\"\u003e\u003cimg src=\"https://codecov.io/gh/3mcd/javelin/branch/master/graph/badge.svg?token=8UMA33S9UL\" alt=\"codecov\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://discord.gg/AbEWH3taWU\"\u003e\u003cimg src=\"https://img.shields.io/discord/844566064281026600?logo=discord\" alt=\"discord\"\u003e\u003c/a\u003e\n  \u003cimg src=\"https://img.shields.io/lgtm/grade/javascript/github/3mcd/javelin\"\u003e\n\u003c/p\u003e\n\n# Javelin\n\nJoin us on [Discord](https://discord.gg/AbEWH3taWU)!\n\nJavelin is a collection of JavaScript packages that provide the means to create multiplayer games for Node and web browsers. It's comprised of an Entity-Component System (ECS), an efficient networking protocol, and other helpful utilities like a high-precision game loop for Node.\n\nJavelin's lack of opinions makes it a good candidate for building many kinds of multiplayer games, but you'll need to bring your own network transport (WebSockets, WebRTC, etc.), database, auth strategy, controller support, matchmaking, etc.\n\n## API Sample\n\nBelow is an example game server that broadcasts entities with both `Position` and `Velocity` components to connected clients.\n\n```ts\nimport { createWorld, createQuery, component, useMonitor } from \"@javelin/ecs\"\nimport { createMessageProducer, encode, float64 } from \"@javelin/net\"\nimport { createHrtimeLoop } from \"@javelin/hrtime-loop\"\nimport { broadcast } from \"./net\"\n\nconst Position = {\n  x: float64,\n  y: float64,\n}\nconst Velocity = {\n  x: float64,\n  y: float64,\n}\nconst world = createWorld()\nconst points = createQuery(Position, Velocity)\nconst messages = createMessageProducer()\n\n// create an entity\nworld.create(component(Position), component(Velocity, { x: 0, y: -9.81 }))\n// create/delete points on client\nworld.addSystem(() =\u003e useMonitor(points, messages.attach, messages.destroy))\n// update point positions\nworld.addSystem(() =\u003e\n  points((e, [p, v]) =\u003e {\n    p.x += v.x\n    p.y += v.y\n  }),\n)\n// broadcast messages to clients\nworld.addSystem(() =\u003e {\n  if (useInterval((1 / 20) * 1000)) {\n    points(messages.update)\n    broadcast(encode(messages.take()))\n  }\n})\n// start a high-precision game loop\ncreateHrtimeLoop(world.step, (1 / 60) * 1000).start()\n```\n\nThere's a lot more that goes into building a game, but hopefully this example demonstrates the unobtrusive and consise nature of Javelin's APIs.\n\n## Docs\n\nVisit https://javelin.games\n\n## Packages\n\n| Name                                                     | Description                                            |\n| -------------------------------------------------------- | ------------------------------------------------------ |\n| [@javelin/core](./packages/core)                         | Core types, utilities, and data model                  |\n| [@javelin/ecs](./packages/ecs)                           | Build games using the ECS pattern                      |\n| [@javelin/net](./packages/net)                           | Synchronize ECS worlds                                 |\n| [@javelin/pack](./packages/pack)                         | Convert objects to and from binary arrays              |\n| [@javelin/hrtime-loop](./packages/hrtime-loop)           | Create smooth, high-precision game loops in NodeJS     |\n| [@javelin/isomorphic-utils](./packages/isomorphic-utils) | Universal utils requiring separate browser/node builds |\n\n## Examples\n\n| Name                          | Description                                               | NPM Script        |\n| ----------------------------- | --------------------------------------------------------- | ----------------- |\n| [spin](./examples/spin)       | Entity/component synchronization over WebRTC datachannels | `example:spin`    |\n| [interop](./examples/interop) | Interop with Cannon and Three.js objects                  | `example:interop` |\n\n## Development\n\nThis project is a monorepository (monorepo for short), which is a collection of independent NPM packages that are located in the same repository for improved development, publishing, and visibility.\n\nYou can \"bootstrap\" all monorepo and package dependencies using the following command:\n\n```sh\npnpm i\n```\n\nBuild times are quick thanks to TypeScript project references. You can build (or re-build) all packages like so:\n\n```sh\npnpm build --recursive\n```\n\nThe structure of the monorepo looks something like this:\n\n```\npackages/\n├── core/\n│   ├── dist/\n│   │   ├── esm/\n│   │   │   ├── index.js\n│   │   │   ├── index.d.ts\n│   │   │   └── ...\n│   │   └── cjs/index.js\n│   ├── src/\n│   │   ├── index.js\n│   │   └── ...\n│   ├── README.md\n│   ├── package.json\n│   └── tsconfig.json\n├── ecs/\n└── ...\n```\n\nWhere each package has its own README file, TypeScript configuration file, source and dist directories, and scripts which describe how the package is cleaned, build, and prepared for publishing.\n\nEach package has the following specified in its package.json:\n\n```\n\"main\": \"dist/cjs/index.js\",\n\"module\": \"dist/esm/index.js\",\n\"types\": \"dist/esm/index.d.ts\",\n```\n\nWhere `\"main\"` is a CommonJS entrypoint, `\"module\"` is an ESM entrypoint, and `\"types\"` is the root `.d.ts` file generated by the TypeScript compiler.\n\nPackages reference eachother using pnpm workspace aliases and TypeScript project references. For example, the `ecs` package depends on `core`, so in the package.json file of `@javelin/ecs`:\n\n```json\n{\n  \"dependencies\": {\n    \"@javelin/core\": \"workspace:*\"\n  }\n}\n```\n\nAnd in the same package's TypeScript config file, we make sure to include a project reference for faster builds and [other benefits](https://www.typescriptlang.org/docs/handbook/project-references.html):\n\n```json\n{\n  \"references\": [{ \"path\": \"../../core\" }]\n}\n```\n","funding_links":["https://github.com/sponsors/3mcd"],"categories":["TypeScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F3mcd%2Fjavelin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F3mcd%2Fjavelin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F3mcd%2Fjavelin/lists"}