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
- Host: GitHub
- URL: https://github.com/simbroadcasts/react-node-insim
- Owner: simbroadcasts
- Created: 2023-04-12T14:28:12.000Z (about 2 years ago)
- Default Branch: main
- Last Pushed: 2024-06-26T09:24:50.000Z (10 months ago)
- Last Synced: 2024-11-14T06:36:08.324Z (6 months ago)
- Topics: api, buttons, insim, lfs, live-for-speed, node, node-insim, node-js, nodejs, racing, react, react-reconciler, react-renderer, renderer, simulator
- Language: TypeScript
- Homepage:
- Size: 4.71 MB
- Stars: 4
- Watchers: 5
- Forks: 0
- Open Issues: 5
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# React Node InSim
[](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:
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.
```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
```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.
```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.
```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.
```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`.
```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.
```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
```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
```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
```tsx
Left
Center
Right
```
## Grid
Grid layout displays buttons in a grid.
### Import
```ts
import { Grid, GridButton } from 'react-node-insim';
```### Usage
```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
```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.
```tsx
<>
Toggle
Toggle
>
```#### Disabled state
Use the `isDisabled` prop to prevent toggling the button on/off.
```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
```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
```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
```---
