An open API service indexing awesome lists of open source software.

https://github.com/simbroadcasts/react-node-insim

React renderer for in-game buttons for Live for Speed
https://github.com/simbroadcasts/react-node-insim

api buttons insim lfs live-for-speed node node-insim node-js nodejs racing react react-reconciler react-renderer renderer simulator

Last synced: 6 months ago
JSON representation

React renderer for in-game buttons for Live for Speed

Awesome Lists containing this project

README

        

# React Node InSim

[![NPM Version](https://img.shields.io/npm/v/react-node-insim?style=flat-square)](https://www.npmjs.com/package/react-node-insim)

A [React renderer](https://legacy.reactjs.org/docs/codebase-overview.html#renderers) for [InSim](https://en.lfsmanual.net/wiki/InSim.txt) buttons, based on [Node InSim](https://github.com/simbroadcasts/node-insim).

## Introduction

> 🚧 This project is still under development. Any API may change as needed.

React Node InSim is a [React renderer](https://legacy.reactjs.org/docs/codebase-overview.html#renderers) for [Live for Speed](https://www.lfs.net/) [InSim](https://en.lfsmanual.net/wiki/InSim.txt) buttons. It also provides [layout components](#horizontal-stack) for easier button positioning, [hooks](#hooks) for handling incoming InSim packets and tracking server connections & players.

It is based on [Node InSim](https://github.com/simbroadcasts/node-insim), a Node.js library, written in TypeScript, for InSim communication.

It allows you to create things like this:

Live list of connections and players

Show source code

```tsx
import type { InSim } from 'node-insim';
import { InSimFlags, IS_BTC, IS_MST, PacketType } from 'node-insim/packets';
import { StrictMode } from 'react';
import {
Button,
ConnectionsProvider,
createRoot,
PlayersProvider,
useConnections,
useOnConnect,
useOnPacket,
usePlayers,
VStack,
} from 'react-node-insim';

function App() {
// Get the list of current players and connections
const players = usePlayers();
const connections = useConnections();

// Do something after the InSim app has been connected to LFS
useOnConnect((packet, inSim) => {
console.log(`Connected to LFS ${packet.Product} ${packet.Version}`);
inSim.send(new IS_MST({ Msg: `React Node InSim connected` }));
});

// Handle incoming packets
useOnPacket(PacketType.ISP_NCN, (packet) => {
console.log(`New connection: ${packet.UName}`);
});

// Clickable buttons
const handlePlayerClick = (plid: number) => (_: IS_BTC, inSim: InSim) => {
inSim.send(new IS_MST({ Msg: `/echo PLID ${plid}` }));
};

const handleConnectionClick = (ucid: number) => (_: IS_BTC, inSim: InSim) => {
inSim.send(new IS_MST({ Msg: `/echo UCID ${ucid}` }));
};

return (
<>

Players


{players.map((player) => (

{player.PName}

))}


Connections


{connections.map((connection) => (

{connection.UName}

))}

>
);
}

const root = createRoot({
name: 'React InSim',
host: '127.0.0.1',
port: 29999,
flags: InSimFlags.ISF_LOCAL,
});

root.render(






,
);
```

## Table of contents

- [Requirements](#requirements)
- [Installation](#installation)
- [Basic usage](#basic-usage)
- [Button](#button)
- [Placement](#placement)
- [Sizes](#sizes)
- [Variants](#variants)
- [Text colors](#text-colors)
- [Background colors](#background-colors)
- [Horizontal stack](#horizontal-stack)
- [Vertical stack](#vertical-stack)
- [Flex](#flex)
- [Grid](#grid)
- [Toggle button](#toggle-button)
- [Variants](#variants-1)
- [Disabled state](#disabled-state)
- [Toggle button group](#toggle-button-group)
- [Text box](#text-box)
- [Hooks](#hooks)
- [`useOnConnect`](#useonconnect)
- [`useOnDisconnect`](#useondisconnect)
- [`useOnPacket`](#useonpacket)
- [`useConnections`](#useconnections)
- [`usePlayers`](#useplayers)
- [`useMessage`](#usemessage)
- [`useRaceControlMessage`](#useracecontrolmessage)
- [`useInSim`](#useinsim)
- [Development](#development)

## Requirements

- [Node.js](https://nodejs.org/) 14 or higher
- [Node InSim](https://github.com/simbroadcasts/node-insim)
- [React](https://github.com/facebook/react) 18

## Installation

[NPM](https://www.npmjs.com/)

```shell
npm install react@18 node-insim react-node-insim
```

[Yarn](https://classic.yarnpkg.com/en/docs)

```shell
yarn add react@18 node-insim react-node-insim
```

[pnpm](https://pnpm.io/)

```shell
pnpm add react@18 node-insim react-node-insim
```

## Basic usage

Displaying an InSim button on a local computer

```tsx
import { InSimFlags } from 'node-insim/packets';
import { Button, createRoot } from 'react-node-insim';

const root = createRoot({
name: 'React InSim',
host: '127.0.0.1',
port: 29999,
flags: InSimFlags.ISF_LOCAL,
});

root.render(

Hello InSim!
,
);
```

You can use [React hooks](https://react.dev/reference/react) as usual to display stateful data via InSim.

Button showing current time

```tsx
import { InSimFlags } from 'node-insim/packets';
import { useEffect, useState } from 'react';
import { Button, createRoot } from 'react-node-insim';

function App() {
const [time, setTime] = useState(new Date());

useEffect(() => {
const interval = setInterval(() => {
setTime(new Date());
}, 1000);

return () => {
clearInterval(interval);
};
});

return (

Current time: {time.toLocaleTimeString()}

);
}

const root = createRoot({
name: 'React InSim',
host: '127.0.0.1',
port: 29999,
flags: InSimFlags.ISF_LOCAL,
});

root.render();
```

## Button

The Button component is used to display a button in LFS.

- Buttons are drawn on a 200 by 200 canvas using absolute positioning
- The maximum number of rendered buttons on a screen is 240

### Import

```ts
import { Button } from 'react-node-insim';
```

### Usage

Button

```tsx

Button

```

#### Placement

Buttons use XY coordinates to position themselves on the screen. The `top` and `left` props control the button's X and Y position on the screen. The allowed range of values is 0 to 200.

Button placement

```tsx
<>

Button


Button


Button


Button

>
```

#### Sizes

Use the `width` and `height` props to change the dimensions of the button. The allowed range of values is 0 to 200.

Button sizes

```tsx
<>

Button


Button


Button

>
```

#### Variants

Use the `variant` prop to change the button's visual style. You can use `light` or `dark`. If you don't specify a variant, the button will have transparent background and a light gray text color.

Button variants

```tsx
<>

Button


Button

>
```

#### Text colors

Use the `color` prop to customize the button's text color. If you don't specify a color, the button text will be `default`.

Button text colors

```tsx
<>

default


title


unselected


selected


ok


cancel


textstring


unavailable

>
```

You can choose from a set of semantic colors or use one of the colors from the LFS color palette.

**Semantic colors**

- default
- title
- unselected
- selected
- ok
- cancel
- textstring
- unavailable

> Note: The semantic color values can be customized in LFS Options -> Display -> Interface.

**LFS color palette**

- black
- red
- green
- yellow
- blue
- magenta
- cyan
- white

#### Background colors

Use the `background` prop to customize the button's background color. If you don't specify a color, the background will be transparent.

Button background colors

```tsx
<>

light


dark


transparent

>
```

## Horizontal stack

`HStack` displays buttons in a column without having to specify each button's position manually. You can also override button colors and sizes.

### Import

```ts
import { HStack } from 'react-node-insim';
```

### Usage

Horizontal stack

```tsx

Stacked button
Custom color
Custom height

```

## Vertical stack

`VStack` displays buttons in a row without having to specify each button's position manually. You can also override button colors and sizes.

### Import

```ts
import { VStack } from 'react-node-insim';
```

### Usage

Vertical stack

```tsx

Stacked button
Custom color
Custom height

```

## Flex

Flex layout displays buttons in a row or column with flexbox options.

### Import

```ts
import { Flex } from 'react-node-insim';
```

### Usage

Flex

```tsx


Left


Center


Right

```

## Grid

Grid layout displays buttons in a grid.

### Import

```ts
import { Grid, GridButton } from 'react-node-insim';
```

### Usage

Grid

```tsx

1

2


3


4


5

```

## Toggle button

A button that can be toggled on and off by clicking it.

### Import

```ts
import { ToggleButton } from 'react-node-insim';
```

### Usage

Toggle button being toggled on and off

```tsx
function App() {
const [isOn, setIsOn] = useState(false);

return (

Toggle

);
}
```

#### Variants

Use the `variant` prop to change the button's background style. You can use `light` or `dark`. If you don't specify a variant, `light` will be used.

Toggle button variants

```tsx
<>

Toggle


Toggle

>
```

#### Disabled state

Use the `isDisabled` prop to prevent toggling the button on/off.

Enabled and disabled toggle buttons

```tsx
<>

Enabled


Disabled


Enabled


Disabled

>
```

## Toggle button group

A group of buttons that can be toggled on and off by clicking them.

### Import

```ts
import { ToggleButtonGroup } from 'react-node-insim';
```

### Usage

Toggle button group

```tsx
const options = [
{ label: 'low', value: 1 },
{ label: 'medium', value: 2 },
{ label: 'high', value: 3 },
];

function App() {
const [selectedOption, setSelectedOption] = useState(options[0]);

return (

);
}
```

## Text box

A text box whose content can span multiple rows. If the content is too long, the text box will show a scrollbar.

### Import

```ts
import { TextBox } from 'react-node-insim';
```

### Usage

Text box

```tsx

Hello world this is a text box lorem ipsum dolor sit amet consectetur
adipisicing elitrea lorem ipsum dolor sit amet consectetur adipisicing elit

```

## Hooks

### `useOnConnect`

Execute code after the InSim app has been connected.

The first parameter is an `IS_VER` packet callback executed when `IS_VER` is received upon successful InSim connection to LFS.

```tsx
import { useOnConnect } from 'react-node-insim';

function App() {
useOnConnect((packet, inSim) => {
console.log(`Connected to LFS ${packet.Product} ${packet.Version}`);
inSim.send(new IS_MST({ Msg: `React Node InSim connected` }));
});

return null;
}
```

### `useOnDisconnect`

Execute code after the InSim app has been disconnected.

The first parameter is the "disconnect" event callback from Node InSim.

```tsx
import { useOnDisconnect } from 'react-node-insim';

function App() {
useOnDisconnect(() => {
console.log('Disconnected from LFS');
});

return null;
}
```

### `useOnPacket`

Execute code when an InSim packet is received

```tsx
import { useOnPacket } from 'react-node-insim';

function App() {
useOnPacket(PacketType.ISP_NCN, (packet) => {
console.log(`New connection: ${packet.UName}`);
});

return null;
}
```

### `useConnections`

Get a live list of all connected guests.

```tsx
import { useConnections } from 'react-node-insim';

function App() {
const connections = useConnections();

return (

{connections.map((connection) => (
{connection.UName}
))}

);
}
```

### `usePlayers`

Get a live list of all players on track.

```tsx
import { usePlayers } from 'react-node-insim';

function App() {
const players = usePlayers();

return (

{players.map((player) => (
{player.PName}
))}

);
}
```

### `useMessage`

Send a message to a connection or a player.

```tsx
import { useMessage } from 'react-node-insim';

function App() {
const { sendMessageToConnection, sendMessageToPlayer } = useMessage();

return (
<>
{
sendMessageToConnection(
packet.UCID,
'Hello from React Node InSim',
MessageSound.SND_SYSMESSAGE,
);
}}
>
Send message to a connection

{
sendMessageToPlayer(
12, // PLID
'Hello from React Node InSim',
MessageSound.SND_SYSMESSAGE,
);
}}
>
Send message to a player

>
);
}
```

### `useRaceControlMessage`

Send a race control message (RCM) to a connection or a player.

```tsx
import { useRaceControlMessage } from 'react-node-insim';

function App() {
const { sendRaceControlMessageToConnection, sendRaceControlMessageToPlayer } =
useRaceControlMessage();

return (
<>
{
sendRaceControlMessageToConnection(
packet.UCID,
'Hello from React Node InSim',
2000,
);
}}
>
Send message to a connection

{
sendRaceControlMessageToPlayer(
12, // PLID
'Hello from React Node InSim',
2000,
);
}}
>
Send message to a player

>
);
}
```

### `useInSim`

Access to Node InSim API of the current InSim client instance.

```tsx
import { useInSim } from 'react-node-insim';

function App() {
const inSim = useInSim();

useEffect(() => {
inSim.send(new IS_MST({ Msg: 'App mounted' }));
}, []);

return null;
}
```

## Development

### Requirements

- [Node.js 18](https://nodejs.org/)
- [Yarn v1](https://classic.yarnpkg.com/)
- [Live for Speed](https://www.lfs.net/)

### Installation

```shell
yarn
```

### Run example app

```shell
yarn start
```

### Lint code

```shell
yarn lint
```

### Format code

```shell
yarn format
```

---

![React Node Insim - An open source project by Sim Broadcasts](https://simbroadcasts.tv/assets/node-insim/react-node-insim-footer.png)