{"id":15297235,"url":"https://github.com/simbroadcasts/node-insim","last_synced_at":"2025-10-09T21:39:50.255Z","repository":{"id":150164150,"uuid":"279737626","full_name":"simbroadcasts/node-insim","owner":"simbroadcasts","description":"A Node.js library for Live For Speed InSim protocol","archived":false,"fork":false,"pushed_at":"2025-07-14T20:13:40.000Z","size":1727,"stargazers_count":16,"open_issues_count":7,"forks_count":1,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-07-14T23:17:12.471Z","etag":null,"topics":["insim","insim-relay","lfs","node","node-js","nodejs","outgauge","simulator","tcp","udp"],"latest_commit_sha":null,"homepage":"https://simbroadcasts.github.io/node-insim/","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/simbroadcasts.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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":"2020-07-15T02:03:42.000Z","updated_at":"2025-07-14T20:11:23.000Z","dependencies_parsed_at":"2023-12-22T00:49:53.847Z","dependency_job_id":"4ca85667-ef85-4bd8-88ae-c2ec60da8dba","html_url":"https://github.com/simbroadcasts/node-insim","commit_stats":{"total_commits":427,"total_committers":4,"mean_commits":106.75,"dds":"0.030444964871194413","last_synced_commit":"9a753c9bb2829b530dad2e32e95327948120b3a8"},"previous_names":[],"tags_count":32,"template":false,"template_full_name":null,"purl":"pkg:github/simbroadcasts/node-insim","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simbroadcasts%2Fnode-insim","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simbroadcasts%2Fnode-insim/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simbroadcasts%2Fnode-insim/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simbroadcasts%2Fnode-insim/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/simbroadcasts","download_url":"https://codeload.github.com/simbroadcasts/node-insim/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simbroadcasts%2Fnode-insim/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266076037,"owners_count":23872729,"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":["insim","insim-relay","lfs","node","node-js","nodejs","outgauge","simulator","tcp","udp"],"created_at":"2024-09-30T19:15:52.238Z","updated_at":"2025-10-09T21:39:50.249Z","avatar_url":"https://github.com/simbroadcasts.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Node InSim\n\n\u003cimg src=\"https://simbroadcasts.tv/assets/node-insim/node-insim-icon-256.png\" width=\"100px\" align=\"right\" hspace=\"15\"\u003e\n\n[![NPM Version](https://img.shields.io/npm/v/node-insim?style=flat-square)](https://www.npmjs.com/package/node-insim) ![Node.js CI](https://github.com/simbroadcasts/node-insim/actions/workflows/.github/workflows/validate.yml/badge.svg) [![cov](https://simbroadcasts.github.io/node-insim/badges/coverage.svg)](https://github.com/simbroadcasts/node-insim/actions)\n\nAn [InSim](https://en.lfsmanual.net/wiki/InSim.txt) library for Node.js with\nTypeScript support.\n\n## Introduction\n\nNode InSim provides a JavaScript API to communicate with the [Live for Speed](https://www.lfs.net/)\nInSim protocol over a TCP connection. After connecting to an LFS host via a hostname\nand a port, you are able to send InSim packets to the host and receive incoming\npackets from the host.\n\nAll packet structures in Node InSim are identical to the structs defined in the\n[InSim protocol](https://en.lfsmanual.net/wiki/InSim.txt). All packet classes with all their properties are documented\naccording to the specification.\n\n### InSim compatibility\n\nNode InSim is compatible with InSim version 9.\n\n## Installation\n\nInstall the `node-insim` NPM package in your Node.js application:\n\n```shell\nnpm install --save node-insim\n```\n\nor if you use Yarn:\n\n```shell\nyarn add node-insim\n```\n\n## Documentation\n\nFor more detailed documentation of the public API, see https://simbroadcasts.github.io/node-insim/.\n\n## Usage\n\n### Connecting\n\nTo connect to an LFS host, you must enter its hostname, a port and a short name of\nyour InSim application.\n\nThe InSim port must be configured in the LFS host settings. Also, make sure the public\nIP address from which your application is connecting is allowed to connect to the host's\nInSim port.\n\n#### Single host\n\n```ts\nimport { InSim } from 'node-insim';\n\nconst inSim = new InSim();\n\ninSim.connect({\n  Host: '127.0.0.1',\n  Port: 29999,\n  IName: 'Node InSim App',\n});\n```\n\n#### Multiple hosts\n\nTo connect to multiple hosts at once, create a new `InSim` instance for each host.\n\n```ts\nimport { InSim } from 'node-insim';\n\nconst inSim1 = new InSim();\n\ninSim1.connect({\n  Host: '127.0.0.1',\n  Port: 29999,\n  IName: 'Node InSim App',\n});\n\nconst inSim2 = new InSim();\n\ninSim2.connect({\n  Host: '127.0.0.2',\n  Port: 30000,\n  IName: 'Node InSim App',\n});\n```\n\n#### TCP / UDP\n\nBy default, Node InSim opens a TCP connection. If you want to use UDP,\nset the `Protocol` option to `UDP` in the `connect` function.\n\n```ts\nimport { InSim } from 'node-insim';\n\nconst inSim = new InSim();\n\ninSim.connect({\n  Host: '127.0.0.1',\n  Port: 29999,\n  IName: 'Node InSim App',\n  Protocol: 'UDP',\n});\n```\n\n### Sending packets\n\nInSim packets can be sent using the `send()` method on the `InSim` class instance,\nwhich takes a single argument - the packet class instance.\n\nA fast way to set packet properties is to populate them in the class constructor:\n\n```ts\nimport { InSim } from 'node-insim';\nimport { IS_TINY, TinyType } from 'node-insim/packets';\n\nconst inSim = new InSim();\n\ninSim.connect({\n  Host: '127.0.0.1',\n  Port: 29999,\n  IName: 'Node InSim App',\n});\n\ninSim.send(\n  new IS_TINY({\n    ReqI: 1,\n    SubT: TinyType.TINY_PING,\n  }),\n);\n```\n\nAnother way is to assign each property after creating the instance:\n\n```ts\nimport { InSim } from 'node-insim';\nimport { IS_TINY, TinyType } from 'node-insim/packets';\n\nconst inSim = new InSim();\n\ninSim.connect({\n  Host: '127.0.0.1',\n  Port: 29999,\n  IName: 'Node InSim App',\n});\n\nconst pingPacket = new IS_TINY();\npingPacket.ReqI = 1;\npingPacket.SubT = TinyType.TINY_PING;\n\ninSim.send(pingPacket);\n```\n\n### Waiting for packets\n\nThere are cases when you want to send a packet and then wait for a response in another packet. There is a helper method `sendAwait()` which waits for a given packet type and when it's received, it's resolved as a Promise. It also makes sure that the received packet's `ReqI` property matches the one entered in the sent packet.\n\n```ts\nimport { InSim } from 'node-insim';\nimport { IS_TINY, PacketType, TinyType } from 'node-insim/packets';\n\nconst inSim = new InSim();\n\ninSim.connect({\n  Host: '127.0.0.1',\n  Port: 29999,\n  IName: 'Node InSim App',\n});\n\ninSim\n  .sendAwait(\n    new IS_TINY({\n      ReqI: 1,\n      SubT: TinyType.TINY_SST,\n    }),\n    PacketType.ISP_STA,\n  )\n  .then((packet) =\u003e {\n    console.log(packet.NumConns);\n  });\n```\n\nYou can filter the received packet by its data using a callback in the 3rd argument:\n\n```ts\nimport { InSim } from 'node-insim';\nimport { IS_TINY, PacketType, TinyType } from 'node-insim/packets';\n\nconst inSim = new InSim();\n\ninSim.connect({\n  Host: '127.0.0.1',\n  Port: 29999,\n  IName: 'Node InSim App',\n});\n\ninSim\n  .sendAwait(\n    new IS_TINY({\n      ReqI: 1,\n      SubT: TinyType.TINY_GTH,\n    }),\n    PacketType.ISP_SMALL,\n    ({ SubT }) =\u003e SubT === SmallType.SMALL_RTP,\n  )\n  .then((packet) =\u003e {\n    console.log('session time', packet.UVal);\n  });\n```\n\n#### Request-reply packet pairs\n\n| Name         | Request packet                            | Reply packet                                |\n| ------------ | ----------------------------------------- | ------------------------------------------- |\n| Ping         | `IS_TINY`\u003cbr /\u003eSubT: `TinyType.TINY_PING` | `IS_TINY`\u003cbr /\u003eSubT: `TinyType.TINY_REPLY`  |\n| Session time | `IS_TINY`\u003cbr /\u003eSubT: `TinyType.TINY_GTH`  | `IS_SMALL`\u003cbr /\u003eSubT: `SmallType.SMALL_RTP` |\n| State        | `IS_TINY`\u003cbr /\u003eSubT: `TinyType.TINY_SST`  | `IS_STA`                                    |\n| InSim multi  | `TINY_ISM`                                | `IS_ISM`                                    |\n\n### Sending messages\n\nThe `InSim` class has helper methods useful for sending messages to LFS.\n\n#### Send a message which will appear on the local computer only\n\n```ts\ninSim.sendLocalMessage('Local message');\n```\n\n#### Send a command\n\n```ts\ninSim.sendMessage('/end');\n```\n\n#### Send a message\n\n- up to 63 characters - send an `IS_MST` packet\n- 64 characters or more - send an `IS_MSX` packet\n\n```ts\ninSim.sendMessage('This is a message');\n```\n\n#### Send a message to a specific connection by their UCID\n\n```ts\ninSim.sendMessageToConnection(4, 'This is a message targeting UCID 4');\n```\n\n#### Send a message to a specific player by their PLID\n\n```ts\ninSim.sendMessageToPlayer(4, 'This is a message targeting PLID 4');\n```\n\n### Receiving packets\n\nThe `InSim` class exposes an `on()` method, which is used to listen for incoming\npackets by their type.\n\n```ts\nimport { InSim } from 'node-insim';\nimport type { IS_VER } from 'node-insim/packets';\nimport { PacketType } from 'node-insim/packets';\n\nconst inSim = new InSim();\n\ninSim.on(PacketType.ISP_VER, onVersion);\n\nfunction onVersion(packet: IS_VER) {\n  console.log(`Connected to LFS ${packet.product} ${packet.Version}`);\n}\n```\n\nThe event callback contains the received packet, and an optional second argument - the\n`InSim` instance which received that packet. You can use that instance to send\nadditional packets in response.\n\n```ts\nimport { InSim } from 'node-insim';\nimport { PacketType } from 'node-insim/packets';\nimport type { IS_VER } from 'node-insim/packets';\n\nconst inSim = new InSim();\n\ninSim.on(PacketType.ISP_VER, onVersion);\n\nfunction onVersion(packet: IS_VER, inSim: InSim) {\n  inSim.send(\n    new IS_TINY({\n      ReqI: 1,\n      SubT: TinyType.TINY_PING,\n    }),\n  );\n}\n```\n\n#### Multiple hosts\n\nYou can use the `inSim` argument in the event handler callback to identify the source\nhost of the received packets, for instance by the `options.Host` property.\n\nAlternatively, the `InSim` class constructor accepts an optional `id` argument, which\ncan also be used to tell apart the InSim connections.\n\n```ts\nimport { InSim } from 'node-insim';\n\nconst inSim1 = new InSim('Host One');\n\ninSim1.connect({\n  Host: '127.0.0.1',\n  Port: 29999,\n  IName: 'Node InSim App',\n});\n\nconst inSim2 = new InSim('Host Two');\n\ninSim2.connect({\n  Host: '127.0.0.2',\n  Port: 30000,\n  IName: 'Node InSim App',\n});\n\ninSim1.on(PacketType.ISP_VER, onVersion);\ninSim2.on(PacketType.ISP_VER, onVersion);\n\nfunction onVersion(packet: IS_VER, inSim: InSim) {\n  console.log(`Connected to ${inSim.options.Host}:${inSim.options.Port}`);\n\n  if (inSim.id) {\n    console.log(`InSim connection ID: ${inSim.id}`);\n  }\n}\n```\n\n### String encoding\n\nAll strings in received or sent packets are automatically converted from LFS encoding to\nUnicode and vice versa.\n\nIf you need to access the raw LFS-encoded string in a received packet, use the `_raw`\nproperty in the packet instance, which contains all unconverted string properties.\n\n```ts\nimport { InSim } from 'node-insim';\nimport { PacketType } from 'node-insim/packets';\nimport type { IS_ISM } from 'node-insim/packets';\n\nconst inSim = new InSim();\n\ninSim.on(PacketType.ISP_ISM, (packet: IS_ISM) =\u003e {\n  console.log(packet.HName); // UTF-8 string - ^1Drifter Team ^7★ Server\n  console.log(packet._raw.HName); // raw string - ^1Drifter Team ^7^J Server\\u0000\\u0000\\u0000\\u0000\n});\n```\n\nWhen you send a Unicode string value in a packet, each character will get encoded into\nthe correct LFS encoding, so LFS can display the text in a message or a button.\n\n```ts\nimport { InSim } from 'node-insim';\nimport { PacketType } from 'node-insim/packets';\nimport type { IS_MSL } from 'node-insim/packets';\n\nconst inSim = new InSim();\n\ninSim.on(PacketType.ISP_VER, (packet: IS_VER) =\u003e {\n  inSim.send(\n    new IS_MSL({\n      Msg: 'čau světe', // LFS will receive: ^Eèau svìte\n    }),\n  );\n});\n```\n\n#### Special characters\n\nSpecial care needs to be taken when sending strings containing caret (`^`) and slash (`/`) characters:\n\n- A caret needs to be escaped as `^^` because the caret symbol acts as an escape character in LFS. Sending `^^hello` as a message will display `^hello` in LFS. Sending just `^hello` would appear as `#ello`.\n- A slash needs to be escaped as `^s`, otherwise it is treated as an LFS in-game command prefix when used in a message packet. Sending `^sjoin` as a message will display `/join` in LFS, whereas sending `/join` will make the player join the track.\n\n### OutGauge\n\n```ts\nimport { OutGauge, OutGaugePack } from 'node-insim';\n\nconst outGauge = new OutGauge();\n\noutGauge.connect({\n  Host: '127.0.0.1',\n  Port: 29999,\n});\n\noutGauge.on('packet', (data: OutGaugePack) =\u003e {\n  console.clear();\n  console.log(data.RPM);\n});\n```\n\n### OutSim\n\n```ts\nimport { OutSim, OutSimPack } from 'node-insim';\n\nconst outSim = new OutSim();\n\noutSim.connect({\n  Host: '127.0.0.1',\n  Port: 29999,\n});\n\noutSim.on('packet', (data) =\u003e {\n  // Make sure the simple OutSimPack packet is really received, as opposed to OutSimPack2\n  if (!(data instanceof OutSimPack)) {\n    return;\n  }\n\n  console.clear();\n  console.log(data.PosX);\n});\n```\n\n### Debugging\n\nNode InSim uses the [`debug` NPM package](https://github.com/debug-js/debug) for debug\nlogs. By default, Node InSim does not output any logs to the standard output.\n\nTo enable logging, use the `DEBUG` environment variable when running your InSim\napplication. All logs are prefixed with `node-insim`. You can use wildcards to filter\nout the logs that you need.\n\n```sh\nDEBUG=* node insim.js # debug all messages\nDEBUG=node-insim:tcp node insim.js # debug only TCP protocol messages\n```\n\n## Example applications\n\nYou can find example applications using Node InSim in the [examples](./examples) folder.\n\n| Example                           |                                                                |                                                                |\n| --------------------------------- | -------------------------------------------------------------- | -------------------------------------------------------------- |\n| InSim connection                  | [JavaScript + CJS](./examples/javascript/insim-connection)     | [TypeScript + ESM](./examples/typescript/insim-connection)     |\n| InSim connection (multiple hosts) | [JavaScript + CJS](./examples/javascript/insim-multiple-hosts) | [TypeScript + ESM](./examples/typescript/insim-multiple-hosts) |\n| InSim connection (UDP)            | [JavaScript + CJS](./examples/javascript/insim-connection-udp) | [TypeScript + ESM](./examples/typescript/insim-connection-udp) |\n| OutGauge                          | [JavaScript + CJS](./examples/javascript/outgauge)             | [TypeScript + ESM](./examples/typescript/outgauge)             |\n| OutGauge with InSim buttons       | [JavaScript + CJS](./examples/javascript/outgauge-buttons)     | [TypeScript + ESM](./examples/typescript/outgauge-buttons)     |\n| OutSim                            | [JavaScript + CJS](./examples/javascript/outsim-basic)         | [TypeScript + ESM](./examples/typescript/outsim-basic)         |\n| OutSim with Options               | [JavaScript + CJS](./examples/javascript/outsim-advanced)      | [TypeScript + ESM](./examples/typescript/outsim-advanced)      |\n\nBefore you run an example, follow the instructions in each example's `README.md` file.\n\nFor instance, to run the \"InSim connection - TypeScript\" example, run the following\ncommands:\n\n```shell\ncd examples/typescript/insim-connection\nnpm install\nnpm start\n```\n\n## Development\n\n### Requirements\n\n- Node.js 18\n- Yarn\n\n### Start a development server\n\n```shell\nyarn dev\n```\n\n### Code generators\n\nWhen adding new InSim packets to the library, you can use built-in code generators\nusing `yarn generate`. It will create and update all the necessary files for you.\n\n### Run unit tests\n\n```shell\nyarn test\n```\n\n### Run tests against a real LFS application\n\nTo run these tests, LFS must be running with an InSim port open.\n\nBy default, the tests connect to `127.0.0.1:29999`. The InSim host and port can be configured by copying `.env` to `.env.local` in the `lfs-test` directory.\n\n```shell\nyarn test:lfs\n```\n\n### Build all example applications\n\nThis command will go through each application in the `examples/` folder,\ninstall its dependencies, then build the application (typescript only).\n\n```shell\nyarn test:examples\n```\n\n### Lint code\n\n```shell\nyarn lint\n```\n\n### Format code\n\n```shell\nyarn format\n```\n\n### Production build\n\nCompiled files will be created in `dist/`.\n\n```shell\nyarn build\n```\n\n### Run all checks at once\n\nYou can run code format, lint + fix, build and test with the following command:\n\n```shell\nyarn check-all\n```\n\n---\n\n![Node Insim - An open source project by Sim Broadcasts](https://simbroadcasts.tv/assets/node-insim/node-insim-footer.png)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimbroadcasts%2Fnode-insim","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsimbroadcasts%2Fnode-insim","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimbroadcasts%2Fnode-insim/lists"}