Skip to content

Commit

Permalink
feat: synced binder for webview, client, etc. (#90)
Browse files Browse the repository at this point in the history
  • Loading branch information
Stuyk authored Jun 27, 2024
1 parent 345a278 commit d438ed3
Show file tree
Hide file tree
Showing 15 changed files with 347 additions and 25 deletions.
17 changes: 17 additions & 0 deletions docs/api/client/system/useStreamSyncedGetter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# useStreamSyncedGetter

When using the [Stream Synced Binder](../../server/systems/useStreamSyncedBinder.md), this allows you to get type safe responses on client-side.

```ts
import * as alt from 'alt-client';
import { useRebarClient } from '../../../main/client/index.js';

const RebarClient = useRebarClient();

const streamGetter = RebarClient.systems.useStreamSyncedGetter();

const money = streamGetter.player(alt.Player.local).get('money');
const name = streamGetter.player(alt.Player.local).get('name');

const fuel = streamGetter.vehicle(someVehicle).get('fuel');
```
21 changes: 21 additions & 0 deletions docs/api/server/systems/useStreamSyncedBinder.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# useStreamSyncedBinder

What this allows you to do is target a specific document field from a `Character` or `Vehicle` document and automatically synchronize the document data to client-side through `streamSyncedMeta`.

Whenever the value changes, it automatically updates for a player or vehicle.

For instance, if specify the propery `money` and `money` is updated for the player, it will be available on client-side, and in the webview.

```ts
import { useRebar } from '../../../main/server/index.js';

const Rebar = useRebar();
const SyncedBinder = Rebar.systems.useStreamSyncedBinder();

// Bind character document data
SyncedBinder.syncCharacterKey('money');
SyncedBinder.syncCharacterKey('name');

// Bind vehicle document data
SyncedBinder.syncVehicleKey('fuel');
```
14 changes: 14 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
# Changelog

## Version 41

### Code Changes

- Added `useStreamSyncedBinder` to automatically synchronize document data from server to client for vehicles and characters
- Added `useSyncedMeta` composable to the webview, to get data synced from `useStreamSyncedBinder`
- Added `useStreamSyncedGetter` to client-side to get type safe responses for stream synced meta data

### Docs Changes

- Documented `useStreamSyncedBinder`, `useSyncedMeta`, and `useStreamSyncedGetter`

---

## Version 40

### Code Changes
Expand Down
23 changes: 23 additions & 0 deletions docs/webview/composables/use-synced-meta.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# useSyncedMeta

When using the [Stream Synced Binder](../../api/server/systems/useStreamSyncedBinder.md), this webview component allows you to get that data as vue refs.

```jsx
<script lang="ts" setup>
import { useSyncedMeta } from '../../../../webview/composables/useSyncedMeta';

const syncedMeta = useSyncedMeta();

const character = syncedMeta.getCharacter();
const vehicle = syncedMeta.getVehicle();
</script>

<template>
<div class="fixed left-0 top-0 bg-black text-white">
<div class="text-2xl">Character</div>
{{ character }}
<div class="text-2xl">Vehicle</div>
{{ vehicle }}
</div>
</template>
```
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"author": "stuyk",
"type": "module",
"version": "40",
"version": "41",
"scripts": {
"dev": "nodemon -x pnpm start",
"dev:linux": "nodemon -x pnpm start:linux",
Expand Down Expand Up @@ -40,7 +40,7 @@
"mongodb": "^6.7.0",
"sjcl": "^1.0.8",
"typescript": "^5.5.2",
"vite": "^5.3.1",
"vite": "^5.3.2",
"vue": "^3.4.30",
"vue-tsc": "^2.0.22"
},
Expand Down
26 changes: 13 additions & 13 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion src/main/client/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { useRaycast } from './system/raycasts.js';
import { isWorldMenuOpen, useWorldMenu } from './menus/world/index.js';
import { drawText2D, drawText3D } from './screen/textlabel.js';
import { draw, drawSimple } from './screen/marker.js';
import { useStreamSyncedGetter } from './system/streamSyncedGetter.js';

export function useRebarClient() {
return {
Expand Down Expand Up @@ -62,7 +63,10 @@ export function useRebarClient() {
drawSimple,
},
},
useProxyFetch,
systems: {
useStreamSyncedGetter,
useProxyFetch,
},
utility: {
math,
text,
Expand Down
52 changes: 52 additions & 0 deletions src/main/client/system/streamSyncedGetter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import * as alt from 'alt-client';
import { Vehicle } from '../../shared/types/vehicle.js';
import { Character } from '@Shared/types/character.js';

export function useStreamSyncedGetter() {
/**
* Get synced data from `streamedSyncedBinder` if it is available for a given vehicle
*
* @param {alt.Vehicle} vehicle
* @return
*/
function vehicle(vehicle: alt.Vehicle) {
function has<K extends keyof Vehicle>(key: K): boolean {
return vehicle.hasStreamSyncedMeta(key);
}

function get<K extends keyof Vehicle>(key: K): Vehicle[K] {
return vehicle.getStreamSyncedMeta(key) as Vehicle[K];
}

return {
has,
get,
};
}

/**
* Get synced data from `streamedSyncedBinder` if it is available for a given player
*
* @param {alt.Player} player
* @return
*/
function player(player: alt.Player) {
function has<K extends keyof Character>(key: K): boolean {
return player.hasStreamSyncedMeta(key);
}

function get<K extends keyof Character>(key: K): Character[K] {
return player.getStreamSyncedMeta(key) as Character[K];
}

return {
has,
get,
};
}

return {
player,
vehicle,
};
}
39 changes: 39 additions & 0 deletions src/main/client/webview/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,42 @@ export function useWebview(path = 'http://assets/webview/index.html') {
onCloseEvents[pageName].push(callback);
}

function onSyncedMetaChange(object: alt.Object, key: string, newValue: any) {
if (native.isEntityAPed(object.scriptID)) {
webview.emit(Events.view.syncPartialCharacter, key, newValue);
return;
}

if (!alt.Player.local.vehicle) {
return;
}

if (!native.isEntityAVehicle(object.scriptID)) {
return;
}

if (alt.Player.local.vehicle.scriptID !== object.scriptID) {
return;
}

webview.emit(Events.view.syncPartialVehicle, key, newValue);
}

function onVehicleEnter(vehicle: alt.Vehicle) {
const keys = vehicle.getStreamSyncedMetaKeys();
const data = {};

for (let key of keys) {
data[key] = vehicle.getStreamSyncedMeta(key);
}

webview.emit(Events.view.syncVehicle, data);
}

function onVehicleLeave() {
webview.emit(Events.view.syncVehicle, {});
}

if (!isInitialized) {
alt.onServer(Events.view.focus, focus);
alt.onServer(Events.view.unfocus, unfocus);
Expand All @@ -337,6 +373,9 @@ export function useWebview(path = 'http://assets/webview/index.html') {
webview.on(Events.view.emitServer, handleServerEvent);
webview.on(Events.view.emitServerRpc, handleServerRpcEvent);
webview.on(Events.view.emitClientRpc, handleClientRpcEvent);
alt.on('streamSyncedMetaChange', onSyncedMetaChange);
alt.on('enteredVehicle', onVehicleEnter);
alt.on('leftVehicle', onVehicleLeave);
}

return {
Expand Down
12 changes: 12 additions & 0 deletions src/main/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ import * as ClothingUtility from '@Shared/data/clothing.js';
import { useScreenshot } from './systems/screenshot.js';
import { useKeypress } from './systems/serverKeypress.js';
import { useD2DTextLabel, useD2DTextLabelLocal } from './controllers/d2dTextLabel.js';
import { useStreamSyncedBinder } from './systems/streamSyncedBinder.js';

export function useRebar() {
return {
Expand Down Expand Up @@ -165,6 +166,15 @@ export function useRebar() {
useServerConfig,
useServerTime,
useServerWeather,
systems: {
useStreamSyncedBinder,
useKeybinder,
useKeypress,
useProxyFetch,
useServerConfig,
useServerTime,
useServerWeather,
},
utility: {
clothing: { ...ClothingUtility },
sha256,
Expand All @@ -183,6 +193,8 @@ export function useRebar() {
};
}

useRebar().useKeybinder;

declare module 'alt-server' {
// extending interface by interface merging
export interface ICustomGlobalMeta {
Expand Down
Loading

0 comments on commit d438ed3

Please sign in to comment.