@open-core/ragemp-adapter 0.1.1 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.tsbuildinfo/client.tsbuildinfo +1 -1
- package/dist/.tsbuildinfo/root.tsbuildinfo +1 -1
- package/dist/.tsbuildinfo/server.tsbuildinfo +1 -1
- package/dist/.tsbuildinfo/shared.tsbuildinfo +1 -1
- package/dist/client/create-ragemp-client-adapter.js +10 -3
- package/dist/client/native-chat.d.ts +10 -0
- package/dist/client/native-chat.js +69 -6
- package/dist/client/ragemp-camera-port.d.ts +19 -0
- package/dist/client/ragemp-camera-port.js +72 -0
- package/dist/client/ragemp-local-player-bridge.d.ts +3 -0
- package/dist/client/ragemp-local-player-bridge.js +10 -0
- package/dist/client/ragemp-ped-port.d.ts +23 -0
- package/dist/client/ragemp-ped-port.js +107 -0
- package/dist/client/ragemp-platform-bridge.js +1 -1
- package/dist/client/ragemp-progress-port.d.ts +21 -0
- package/dist/client/ragemp-progress-port.js +169 -0
- package/dist/client/ragemp-runtime-bridge.d.ts +2 -4
- package/dist/client/ragemp-runtime-bridge.js +3 -0
- package/dist/client/ragemp-spawn-bridge.d.ts +4 -4
- package/dist/client/ragemp-spawn-bridge.js +5 -3
- package/dist/client/ragemp-vehicle-port.d.ts +34 -0
- package/dist/client/ragemp-vehicle-port.js +272 -0
- package/dist/client/ragemp-webview-bridge.d.ts +5 -0
- package/dist/client/ragemp-webview-bridge.js +54 -12
- package/dist/server/ragemp-engine-events.d.ts +2 -5
- package/dist/server/ragemp-engine-events.js +3 -15
- package/dist/server/ragemp-entity-server.js +14 -1
- package/dist/server/ragemp-exports.d.ts +51 -0
- package/dist/server/ragemp-exports.js +202 -1
- package/dist/server/ragemp-player-appearance-lifecycle-server.js +4 -3
- package/dist/server/ragemp-resourceinfo.js +3 -0
- package/dist/shared/exports-registry.d.ts +2 -2
- package/dist/shared/transport/helpers.d.ts +3 -3
- package/dist/shared/transport/helpers.js +33 -7
- package/dist/shared/transport/ragemp.events.d.ts +3 -3
- package/dist/shared/transport/ragemp.events.js +4 -2
- package/dist/shared/transport/ragemp.rpc.d.ts +4 -8
- package/dist/shared/transport/ragemp.rpc.js +29 -5
- package/package.json +5 -7
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { IClientSpawnPort, type RespawnRequest, type SpawnExecutionResult, type SpawnRequest, type TeleportRequest } from '@open-core/framework/contracts/client';
|
|
2
2
|
import { IClientPlatformBridge, IClientRuntimeBridge } from '@open-core/framework/contracts/client';
|
|
3
|
-
export declare class RageMPClientSpawnBridge extends
|
|
3
|
+
export declare class RageMPClientSpawnBridge extends IClientSpawnPort {
|
|
4
4
|
private readonly platform;
|
|
5
5
|
private readonly runtime;
|
|
6
6
|
private playerReady;
|
|
7
7
|
constructor(platform: IClientPlatformBridge, runtime: IClientRuntimeBridge);
|
|
8
8
|
waitUntilReady(timeoutMs?: number): Promise<void>;
|
|
9
|
-
spawn(request: SpawnRequest): Promise<
|
|
10
|
-
respawn(request: RespawnRequest): Promise<
|
|
9
|
+
spawn(request: SpawnRequest): Promise<SpawnExecutionResult>;
|
|
10
|
+
respawn(request: RespawnRequest): Promise<SpawnExecutionResult>;
|
|
11
11
|
teleport(request: TeleportRequest): Promise<void>;
|
|
12
12
|
private closeLoadingScreens;
|
|
13
13
|
private setPlayerModel;
|
|
@@ -20,7 +20,7 @@ const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
|
20
20
|
const READY_TIMEOUT_MS = 15000;
|
|
21
21
|
const PED_TIMEOUT_MS = 10000;
|
|
22
22
|
const MODEL_LOAD_TIMEOUT_MS = 10000;
|
|
23
|
-
let RageMPClientSpawnBridge = class RageMPClientSpawnBridge extends client_1.
|
|
23
|
+
let RageMPClientSpawnBridge = class RageMPClientSpawnBridge extends client_1.IClientSpawnPort {
|
|
24
24
|
constructor(platform, runtime) {
|
|
25
25
|
super();
|
|
26
26
|
this.platform = platform;
|
|
@@ -42,14 +42,16 @@ let RageMPClientSpawnBridge = class RageMPClientSpawnBridge extends client_1.ICl
|
|
|
42
42
|
async spawn(request) {
|
|
43
43
|
this.closeLoadingScreens();
|
|
44
44
|
await this.setPlayerModel(request.model);
|
|
45
|
-
await this.ensurePed();
|
|
45
|
+
const ped = await this.ensurePed();
|
|
46
46
|
mp.players.local.position = new mp.Vector3(request.position.x, request.position.y, request.position.z);
|
|
47
47
|
mp.players.local.heading = request.heading ?? 0;
|
|
48
|
+
return { localPlayerHandle: ped };
|
|
48
49
|
}
|
|
49
50
|
async respawn(request) {
|
|
50
|
-
await this.ensurePed();
|
|
51
|
+
const ped = await this.ensurePed();
|
|
51
52
|
mp.players.local.position = new mp.Vector3(request.position.x, request.position.y, request.position.z);
|
|
52
53
|
mp.players.local.heading = request.heading ?? 0;
|
|
54
|
+
return { localPlayerHandle: ped };
|
|
53
55
|
}
|
|
54
56
|
async teleport(request) {
|
|
55
57
|
await this.ensurePed();
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { type ClientVehicleMods, type ClientVehicleSpawnOptions, IClientLocalPlayerBridge, IClientPlatformBridge, IClientVehiclePort } from '@open-core/framework/contracts/client';
|
|
2
|
+
import type { Vector3 } from '@open-core/framework/kernel';
|
|
3
|
+
export declare class RageMPClientVehiclePort extends IClientVehiclePort {
|
|
4
|
+
private readonly platform;
|
|
5
|
+
private readonly localPlayer;
|
|
6
|
+
constructor(platform: IClientPlatformBridge, localPlayer: IClientLocalPlayerBridge);
|
|
7
|
+
spawn(options: ClientVehicleSpawnOptions): Promise<number>;
|
|
8
|
+
delete(vehicle: number): void;
|
|
9
|
+
repair(vehicle: number): void;
|
|
10
|
+
setFuel(vehicle: number, level: number): void;
|
|
11
|
+
getFuel(vehicle: number): number;
|
|
12
|
+
getClosest(radius?: number): number | null;
|
|
13
|
+
isLocalPlayerInVehicle(): boolean;
|
|
14
|
+
getCurrentForLocalPlayer(): number | null;
|
|
15
|
+
getLastForLocalPlayer(): number | null;
|
|
16
|
+
isLocalPlayerDriver(vehicle: number): boolean;
|
|
17
|
+
warpLocalPlayerInto(vehicle: number, seatIndex?: number): void;
|
|
18
|
+
leaveLocalPlayerVehicle(vehicle: number, flags?: number): void;
|
|
19
|
+
applyMods(vehicle: number, mods: ClientVehicleMods): void;
|
|
20
|
+
setDoorsLocked(vehicle: number, locked: boolean): void;
|
|
21
|
+
setEngineRunning(vehicle: number, running: boolean, instant?: boolean): void;
|
|
22
|
+
setInvincible(vehicle: number, invincible: boolean): void;
|
|
23
|
+
getSpeed(vehicle: number): number;
|
|
24
|
+
setHeading(vehicle: number, heading: number): void;
|
|
25
|
+
teleport(vehicle: number, position: Vector3, heading?: number): void;
|
|
26
|
+
exists(vehicle: number): boolean;
|
|
27
|
+
getNetworkId(vehicle: number): number;
|
|
28
|
+
getFromNetworkId(networkId: number): number;
|
|
29
|
+
getState<T = unknown>(vehicle: number, key: string): T | undefined;
|
|
30
|
+
getPosition(vehicle: number): Vector3 | null;
|
|
31
|
+
getHeading(vehicle: number): number;
|
|
32
|
+
getModel(vehicle: number): number;
|
|
33
|
+
getPlate(vehicle: number): string;
|
|
34
|
+
}
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.RageMPClientVehiclePort = void 0;
|
|
16
|
+
const tsyringe_1 = require("tsyringe");
|
|
17
|
+
const client_1 = require("@open-core/framework/contracts/client");
|
|
18
|
+
let RageMPClientVehiclePort = class RageMPClientVehiclePort extends client_1.IClientVehiclePort {
|
|
19
|
+
constructor(platform, localPlayer) {
|
|
20
|
+
super();
|
|
21
|
+
this.platform = platform;
|
|
22
|
+
this.localPlayer = localPlayer;
|
|
23
|
+
}
|
|
24
|
+
async spawn(options) {
|
|
25
|
+
const { model, position, heading = 0, placeOnGround = true, warpIntoVehicle = false, seatIndex = -1, primaryColor, secondaryColor, plate, networked = true, } = options;
|
|
26
|
+
const modelHash = this.platform.getHashKey(model);
|
|
27
|
+
if (!this.platform.isModelInCdimage(modelHash) || !this.platform.isModelAVehicle(modelHash)) {
|
|
28
|
+
throw new Error(`Invalid vehicle model: ${model}`);
|
|
29
|
+
}
|
|
30
|
+
this.platform.requestModel(modelHash);
|
|
31
|
+
while (!this.platform.hasModelLoaded(modelHash)) {
|
|
32
|
+
await new Promise((r) => setTimeout(r, 0));
|
|
33
|
+
}
|
|
34
|
+
const vehicle = this.platform.createVehicle(modelHash, position, heading, networked, false);
|
|
35
|
+
this.platform.setModelAsNoLongerNeeded(modelHash);
|
|
36
|
+
if (!vehicle || vehicle === 0)
|
|
37
|
+
throw new Error('Failed to create vehicle');
|
|
38
|
+
if (placeOnGround)
|
|
39
|
+
this.platform.setVehicleOnGroundProperly(vehicle);
|
|
40
|
+
if (primaryColor !== undefined || secondaryColor !== undefined) {
|
|
41
|
+
const [currentPrimary, currentSecondary] = this.platform.getVehicleColours(vehicle);
|
|
42
|
+
this.platform.setVehicleColours(vehicle, primaryColor ?? currentPrimary, secondaryColor ?? currentSecondary);
|
|
43
|
+
}
|
|
44
|
+
if (plate)
|
|
45
|
+
this.platform.setVehicleNumberPlateText(vehicle, plate);
|
|
46
|
+
if (warpIntoVehicle)
|
|
47
|
+
this.warpLocalPlayerInto(vehicle, seatIndex);
|
|
48
|
+
return vehicle;
|
|
49
|
+
}
|
|
50
|
+
delete(vehicle) {
|
|
51
|
+
if (!this.exists(vehicle))
|
|
52
|
+
return;
|
|
53
|
+
this.platform.setEntityAsMissionEntity(vehicle, true, true);
|
|
54
|
+
this.platform.deleteVehicle(vehicle);
|
|
55
|
+
}
|
|
56
|
+
repair(vehicle) {
|
|
57
|
+
if (!this.exists(vehicle))
|
|
58
|
+
return;
|
|
59
|
+
this.platform.setVehicleFixed(vehicle);
|
|
60
|
+
this.platform.setVehicleDeformationFixed(vehicle);
|
|
61
|
+
this.platform.setVehicleUndriveable(vehicle, false);
|
|
62
|
+
this.platform.setVehicleEngineOn(vehicle, true, true, false);
|
|
63
|
+
this.platform.setVehicleEngineHealth(vehicle, 1000.0);
|
|
64
|
+
this.platform.setVehiclePetrolTankHealth(vehicle, 1000.0);
|
|
65
|
+
}
|
|
66
|
+
setFuel(vehicle, level) {
|
|
67
|
+
if (!this.exists(vehicle))
|
|
68
|
+
return;
|
|
69
|
+
this.platform.setVehicleFuelLevel(vehicle, Math.max(0, Math.min(100, level)));
|
|
70
|
+
}
|
|
71
|
+
getFuel(vehicle) {
|
|
72
|
+
if (!this.exists(vehicle))
|
|
73
|
+
return 0;
|
|
74
|
+
return this.platform.getVehicleFuelLevel(vehicle);
|
|
75
|
+
}
|
|
76
|
+
getClosest(radius = 10) {
|
|
77
|
+
return this.platform.getClosestVehicle(this.localPlayer.getPosition(), radius);
|
|
78
|
+
}
|
|
79
|
+
isLocalPlayerInVehicle() {
|
|
80
|
+
return this.platform.isPedInAnyVehicle(this.localPlayer.getHandle());
|
|
81
|
+
}
|
|
82
|
+
getCurrentForLocalPlayer() {
|
|
83
|
+
const ped = this.localPlayer.getHandle();
|
|
84
|
+
if (!this.platform.isPedInAnyVehicle(ped))
|
|
85
|
+
return null;
|
|
86
|
+
return this.platform.getVehiclePedIsIn(ped, false);
|
|
87
|
+
}
|
|
88
|
+
getLastForLocalPlayer() {
|
|
89
|
+
return this.platform.getVehiclePedIsIn(this.localPlayer.getHandle(), true);
|
|
90
|
+
}
|
|
91
|
+
isLocalPlayerDriver(vehicle) {
|
|
92
|
+
return this.platform.getPedInVehicleSeat(vehicle, -1) === this.localPlayer.getHandle();
|
|
93
|
+
}
|
|
94
|
+
warpLocalPlayerInto(vehicle, seatIndex = -1) {
|
|
95
|
+
if (!this.exists(vehicle))
|
|
96
|
+
return;
|
|
97
|
+
this.platform.taskWarpPedIntoVehicle(this.localPlayer.getHandle(), vehicle, seatIndex);
|
|
98
|
+
}
|
|
99
|
+
leaveLocalPlayerVehicle(vehicle, flags = 16) {
|
|
100
|
+
if (!this.exists(vehicle))
|
|
101
|
+
return;
|
|
102
|
+
this.platform.taskLeaveVehicle(this.localPlayer.getHandle(), vehicle, flags);
|
|
103
|
+
}
|
|
104
|
+
applyMods(vehicle, mods) {
|
|
105
|
+
if (!this.exists(vehicle))
|
|
106
|
+
return;
|
|
107
|
+
this.platform.setVehicleModKit(vehicle, 0);
|
|
108
|
+
if (mods.spoiler !== undefined)
|
|
109
|
+
this.platform.setVehicleMod(vehicle, 0, mods.spoiler, false);
|
|
110
|
+
if (mods.frontBumper !== undefined)
|
|
111
|
+
this.platform.setVehicleMod(vehicle, 1, mods.frontBumper, false);
|
|
112
|
+
if (mods.rearBumper !== undefined)
|
|
113
|
+
this.platform.setVehicleMod(vehicle, 2, mods.rearBumper, false);
|
|
114
|
+
if (mods.sideSkirt !== undefined)
|
|
115
|
+
this.platform.setVehicleMod(vehicle, 3, mods.sideSkirt, false);
|
|
116
|
+
if (mods.exhaust !== undefined)
|
|
117
|
+
this.platform.setVehicleMod(vehicle, 4, mods.exhaust, false);
|
|
118
|
+
if (mods.frame !== undefined)
|
|
119
|
+
this.platform.setVehicleMod(vehicle, 5, mods.frame, false);
|
|
120
|
+
if (mods.grille !== undefined)
|
|
121
|
+
this.platform.setVehicleMod(vehicle, 6, mods.grille, false);
|
|
122
|
+
if (mods.hood !== undefined)
|
|
123
|
+
this.platform.setVehicleMod(vehicle, 7, mods.hood, false);
|
|
124
|
+
if (mods.fender !== undefined)
|
|
125
|
+
this.platform.setVehicleMod(vehicle, 8, mods.fender, false);
|
|
126
|
+
if (mods.rightFender !== undefined)
|
|
127
|
+
this.platform.setVehicleMod(vehicle, 9, mods.rightFender, false);
|
|
128
|
+
if (mods.roof !== undefined)
|
|
129
|
+
this.platform.setVehicleMod(vehicle, 10, mods.roof, false);
|
|
130
|
+
if (mods.engine !== undefined)
|
|
131
|
+
this.platform.setVehicleMod(vehicle, 11, mods.engine, false);
|
|
132
|
+
if (mods.brakes !== undefined)
|
|
133
|
+
this.platform.setVehicleMod(vehicle, 12, mods.brakes, false);
|
|
134
|
+
if (mods.transmission !== undefined)
|
|
135
|
+
this.platform.setVehicleMod(vehicle, 13, mods.transmission, false);
|
|
136
|
+
if (mods.horns !== undefined)
|
|
137
|
+
this.platform.setVehicleMod(vehicle, 14, mods.horns, false);
|
|
138
|
+
if (mods.suspension !== undefined)
|
|
139
|
+
this.platform.setVehicleMod(vehicle, 15, mods.suspension, false);
|
|
140
|
+
if (mods.armor !== undefined)
|
|
141
|
+
this.platform.setVehicleMod(vehicle, 16, mods.armor, false);
|
|
142
|
+
if (mods.turbo !== undefined)
|
|
143
|
+
this.platform.toggleVehicleMod(vehicle, 18, mods.turbo);
|
|
144
|
+
if (mods.xenon !== undefined)
|
|
145
|
+
this.platform.toggleVehicleMod(vehicle, 22, mods.xenon);
|
|
146
|
+
if (mods.wheelType !== undefined)
|
|
147
|
+
this.platform.setVehicleWheelType(vehicle, mods.wheelType);
|
|
148
|
+
if (mods.wheels !== undefined)
|
|
149
|
+
this.platform.setVehicleMod(vehicle, 23, mods.wheels, false);
|
|
150
|
+
if (mods.windowTint !== undefined)
|
|
151
|
+
this.platform.setVehicleWindowTint(vehicle, mods.windowTint);
|
|
152
|
+
if (mods.livery !== undefined)
|
|
153
|
+
this.platform.setVehicleLivery(vehicle, mods.livery);
|
|
154
|
+
if (mods.plateStyle !== undefined)
|
|
155
|
+
this.platform.setVehicleNumberPlateTextIndex(vehicle, mods.plateStyle);
|
|
156
|
+
if (mods.neonEnabled !== undefined) {
|
|
157
|
+
this.platform.setVehicleNeonLightEnabled(vehicle, 0, mods.neonEnabled[0]);
|
|
158
|
+
this.platform.setVehicleNeonLightEnabled(vehicle, 1, mods.neonEnabled[1]);
|
|
159
|
+
this.platform.setVehicleNeonLightEnabled(vehicle, 2, mods.neonEnabled[2]);
|
|
160
|
+
this.platform.setVehicleNeonLightEnabled(vehicle, 3, mods.neonEnabled[3]);
|
|
161
|
+
}
|
|
162
|
+
if (mods.neonColor !== undefined) {
|
|
163
|
+
this.platform.setVehicleNeonLightsColour(vehicle, mods.neonColor[0], mods.neonColor[1], mods.neonColor[2]);
|
|
164
|
+
}
|
|
165
|
+
if (mods.extras) {
|
|
166
|
+
for (const [extraId, enabled] of Object.entries(mods.extras)) {
|
|
167
|
+
this.platform.setVehicleExtra(vehicle, Number(extraId), !enabled);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
if (mods.pearlescentColor !== undefined || mods.wheelColor !== undefined) {
|
|
171
|
+
const [currentPearl, currentWheel] = this.platform.getVehicleExtraColours(vehicle);
|
|
172
|
+
this.platform.setVehicleExtraColours(vehicle, mods.pearlescentColor ?? currentPearl, mods.wheelColor ?? currentWheel);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
setDoorsLocked(vehicle, locked) {
|
|
176
|
+
if (!this.exists(vehicle))
|
|
177
|
+
return;
|
|
178
|
+
this.platform.setVehicleDoorsLocked(vehicle, locked ? 2 : 0);
|
|
179
|
+
}
|
|
180
|
+
setEngineRunning(vehicle, running, instant = false) {
|
|
181
|
+
if (!this.exists(vehicle))
|
|
182
|
+
return;
|
|
183
|
+
this.platform.setVehicleEngineOn(vehicle, running, instant, true);
|
|
184
|
+
}
|
|
185
|
+
setInvincible(vehicle, invincible) {
|
|
186
|
+
if (!this.exists(vehicle))
|
|
187
|
+
return;
|
|
188
|
+
this.platform.setEntityInvincible(vehicle, invincible);
|
|
189
|
+
}
|
|
190
|
+
getSpeed(vehicle) {
|
|
191
|
+
if (!this.exists(vehicle))
|
|
192
|
+
return 0;
|
|
193
|
+
return this.platform.getEntitySpeed(vehicle);
|
|
194
|
+
}
|
|
195
|
+
setHeading(vehicle, heading) {
|
|
196
|
+
if (!this.exists(vehicle))
|
|
197
|
+
return;
|
|
198
|
+
this.platform.setEntityHeading(vehicle, heading);
|
|
199
|
+
}
|
|
200
|
+
teleport(vehicle, position, heading) {
|
|
201
|
+
if (!this.exists(vehicle))
|
|
202
|
+
return;
|
|
203
|
+
this.platform.setEntityCoords(vehicle, position);
|
|
204
|
+
if (heading !== undefined)
|
|
205
|
+
this.platform.setEntityHeading(vehicle, heading);
|
|
206
|
+
this.platform.setVehicleOnGroundProperly(vehicle);
|
|
207
|
+
}
|
|
208
|
+
exists(vehicle) {
|
|
209
|
+
return this.platform.doesEntityExist(vehicle);
|
|
210
|
+
}
|
|
211
|
+
getNetworkId(vehicle) {
|
|
212
|
+
if (!this.exists(vehicle))
|
|
213
|
+
return 0;
|
|
214
|
+
mp.vehicles.atHandle(vehicle);
|
|
215
|
+
try {
|
|
216
|
+
const runtimeVehicle = mp.vehicles.atHandle(vehicle);
|
|
217
|
+
const remoteId = runtimeVehicle?.remoteId ?? runtimeVehicle?.id;
|
|
218
|
+
if (typeof remoteId === 'number')
|
|
219
|
+
return remoteId;
|
|
220
|
+
}
|
|
221
|
+
catch { }
|
|
222
|
+
return this.platform.networkGetNetworkIdFromEntity(vehicle);
|
|
223
|
+
}
|
|
224
|
+
getFromNetworkId(networkId) {
|
|
225
|
+
try {
|
|
226
|
+
const byRemoteId = mp.vehicles.atRemoteId(networkId);
|
|
227
|
+
if (byRemoteId?.handle)
|
|
228
|
+
return byRemoteId.handle;
|
|
229
|
+
const vehicles = mp.vehicles.toArray() ?? [];
|
|
230
|
+
const match = vehicles.find((vehicle) => vehicle?.remoteId === networkId || vehicle?.id === networkId);
|
|
231
|
+
if (match?.handle)
|
|
232
|
+
return match.handle;
|
|
233
|
+
}
|
|
234
|
+
catch { }
|
|
235
|
+
if (!this.platform.networkDoesEntityExistWithNetworkId(networkId))
|
|
236
|
+
return 0;
|
|
237
|
+
return this.platform.networkGetEntityFromNetworkId(networkId);
|
|
238
|
+
}
|
|
239
|
+
getState(vehicle, key) {
|
|
240
|
+
if (!this.exists(vehicle))
|
|
241
|
+
return undefined;
|
|
242
|
+
return this.platform.getEntityState(vehicle, key);
|
|
243
|
+
}
|
|
244
|
+
getPosition(vehicle) {
|
|
245
|
+
if (!this.exists(vehicle))
|
|
246
|
+
return null;
|
|
247
|
+
return this.platform.getEntityCoords(vehicle);
|
|
248
|
+
}
|
|
249
|
+
getHeading(vehicle) {
|
|
250
|
+
if (!this.exists(vehicle))
|
|
251
|
+
return 0;
|
|
252
|
+
return this.platform.getEntityHeading(vehicle);
|
|
253
|
+
}
|
|
254
|
+
getModel(vehicle) {
|
|
255
|
+
if (!this.exists(vehicle))
|
|
256
|
+
return 0;
|
|
257
|
+
return this.platform.getEntityModel(vehicle);
|
|
258
|
+
}
|
|
259
|
+
getPlate(vehicle) {
|
|
260
|
+
if (!this.exists(vehicle))
|
|
261
|
+
return '';
|
|
262
|
+
return this.platform.getVehicleNumberPlateText(vehicle);
|
|
263
|
+
}
|
|
264
|
+
};
|
|
265
|
+
exports.RageMPClientVehiclePort = RageMPClientVehiclePort;
|
|
266
|
+
exports.RageMPClientVehiclePort = RageMPClientVehiclePort = __decorate([
|
|
267
|
+
(0, tsyringe_1.injectable)(),
|
|
268
|
+
__param(0, (0, tsyringe_1.inject)(client_1.IClientPlatformBridge)),
|
|
269
|
+
__param(1, (0, tsyringe_1.inject)(client_1.IClientLocalPlayerBridge)),
|
|
270
|
+
__metadata("design:paramtypes", [client_1.IClientPlatformBridge,
|
|
271
|
+
client_1.IClientLocalPlayerBridge])
|
|
272
|
+
], RageMPClientVehiclePort);
|
|
@@ -2,8 +2,11 @@ import { IClientWebViewBridge } from '@open-core/framework/contracts/client';
|
|
|
2
2
|
import type { WebViewCapabilities, WebViewDefinition, WebViewFocusOptions, WebViewMessage } from '@open-core/framework/contracts/client';
|
|
3
3
|
export declare class RageMPClientWebViewBridge extends IClientWebViewBridge {
|
|
4
4
|
private readonly views;
|
|
5
|
+
private readonly browserViewIds;
|
|
6
|
+
private readonly chatModeViews;
|
|
5
7
|
private readonly handlers;
|
|
6
8
|
private eventRegistered;
|
|
9
|
+
private domReadyRegistered;
|
|
7
10
|
getCapabilities(): WebViewCapabilities;
|
|
8
11
|
create(definition: WebViewDefinition): void;
|
|
9
12
|
destroy(viewId: string): void;
|
|
@@ -19,4 +22,6 @@ export declare class RageMPClientWebViewBridge extends IClientWebViewBridge {
|
|
|
19
22
|
call(viewId: string, eventName: string, ...args: unknown[]): void;
|
|
20
23
|
callProc<T = unknown>(viewId: string, procName: string, ...args: unknown[]): Promise<T | undefined>;
|
|
21
24
|
private ensureEventsRegistered;
|
|
25
|
+
private ensureBrowserReadyRegistered;
|
|
26
|
+
private injectBridge;
|
|
22
27
|
}
|
|
@@ -9,6 +9,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
9
9
|
exports.RageMPClientWebViewBridge = void 0;
|
|
10
10
|
const tsyringe_1 = require("tsyringe");
|
|
11
11
|
const client_1 = require("@open-core/framework/contracts/client");
|
|
12
|
+
const native_chat_1 = require("./native-chat");
|
|
12
13
|
const RAGEMP_WEBVIEW_EVENT = '__opencore:webview:message';
|
|
13
14
|
const RAGEMP_WEBVIEW_CAPABILITIES = {
|
|
14
15
|
supportsFocus: true,
|
|
@@ -17,6 +18,7 @@ const RAGEMP_WEBVIEW_CAPABILITIES = {
|
|
|
17
18
|
supportsBidirectionalMessaging: true,
|
|
18
19
|
supportsExecute: true,
|
|
19
20
|
supportsHeadless: true,
|
|
21
|
+
supportsChatMode: true,
|
|
20
22
|
};
|
|
21
23
|
function js(value) {
|
|
22
24
|
return JSON.stringify(value);
|
|
@@ -25,37 +27,52 @@ let RageMPClientWebViewBridge = class RageMPClientWebViewBridge extends client_1
|
|
|
25
27
|
constructor() {
|
|
26
28
|
super(...arguments);
|
|
27
29
|
this.views = new Map();
|
|
30
|
+
this.browserViewIds = new Map();
|
|
31
|
+
this.chatModeViews = new Set();
|
|
28
32
|
this.handlers = new Set();
|
|
29
33
|
this.eventRegistered = false;
|
|
34
|
+
this.domReadyRegistered = false;
|
|
30
35
|
}
|
|
31
36
|
getCapabilities() { return RAGEMP_WEBVIEW_CAPABILITIES; }
|
|
32
37
|
create(definition) {
|
|
33
38
|
const existing = this.views.get(definition.id);
|
|
34
|
-
if (existing)
|
|
39
|
+
if (existing) {
|
|
40
|
+
this.chatModeViews.delete(definition.id);
|
|
41
|
+
(0, native_chat_1.releaseRageMPNativeChat)(definition.id);
|
|
42
|
+
this.browserViewIds.delete(existing);
|
|
35
43
|
existing.destroy();
|
|
44
|
+
}
|
|
45
|
+
if (definition.chatMode) {
|
|
46
|
+
try {
|
|
47
|
+
mp.gui.chat.activate(false);
|
|
48
|
+
mp.gui.chat.show(false);
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
// Ignore if native chat is not ready yet.
|
|
52
|
+
}
|
|
53
|
+
}
|
|
36
54
|
const browser = mp.browsers.new(definition.url);
|
|
37
55
|
browser.active = definition.visible ?? false;
|
|
38
56
|
browser.inputEnabled = definition.focused ?? false;
|
|
39
57
|
browser.mouseInputEnabled = definition.cursor ?? false;
|
|
40
58
|
this.views.set(definition.id, browser);
|
|
59
|
+
this.browserViewIds.set(browser, definition.id);
|
|
41
60
|
this.ensureEventsRegistered();
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
if (typeof mp !== 'undefined' && typeof mp.trigger === 'function') {
|
|
48
|
-
mp.trigger(${js(RAGEMP_WEBVIEW_EVENT)}, ${js(definition.id)}, event, JSON.stringify(payload ?? null));
|
|
49
|
-
}
|
|
61
|
+
this.ensureBrowserReadyRegistered();
|
|
62
|
+
if (definition.chatMode) {
|
|
63
|
+
this.chatModeViews.add(definition.id);
|
|
64
|
+
(0, native_chat_1.suppressRageMPNativeChat)(definition.id);
|
|
65
|
+
browser.markAsChat();
|
|
50
66
|
}
|
|
51
|
-
};`);
|
|
52
|
-
});
|
|
53
67
|
}
|
|
54
68
|
destroy(viewId) {
|
|
55
69
|
const browser = this.views.get(viewId);
|
|
56
70
|
if (!browser)
|
|
57
71
|
return;
|
|
58
72
|
browser.destroy();
|
|
73
|
+
this.chatModeViews.delete(viewId);
|
|
74
|
+
(0, native_chat_1.releaseRageMPNativeChat)(viewId);
|
|
75
|
+
this.browserViewIds.delete(browser);
|
|
59
76
|
this.views.delete(viewId);
|
|
60
77
|
}
|
|
61
78
|
exists(viewId) { return this.views.has(viewId); }
|
|
@@ -99,7 +116,12 @@ let RageMPClientWebViewBridge = class RageMPClientWebViewBridge extends client_1
|
|
|
99
116
|
return () => this.handlers.delete(handler);
|
|
100
117
|
}
|
|
101
118
|
markAsChat(viewId) {
|
|
102
|
-
this.views.get(viewId)
|
|
119
|
+
const browser = this.views.get(viewId);
|
|
120
|
+
if (!browser)
|
|
121
|
+
return;
|
|
122
|
+
this.chatModeViews.add(viewId);
|
|
123
|
+
(0, native_chat_1.suppressRageMPNativeChat)(viewId);
|
|
124
|
+
browser.markAsChat();
|
|
103
125
|
}
|
|
104
126
|
execute(viewId, code) {
|
|
105
127
|
this.views.get(viewId)?.execute(code);
|
|
@@ -124,6 +146,26 @@ let RageMPClientWebViewBridge = class RageMPClientWebViewBridge extends client_1
|
|
|
124
146
|
}
|
|
125
147
|
});
|
|
126
148
|
}
|
|
149
|
+
ensureBrowserReadyRegistered() {
|
|
150
|
+
if (this.domReadyRegistered)
|
|
151
|
+
return;
|
|
152
|
+
this.domReadyRegistered = true;
|
|
153
|
+
mp.events.add('browserDomReady', (browser) => {
|
|
154
|
+
const viewId = this.browserViewIds.get(browser);
|
|
155
|
+
if (!viewId)
|
|
156
|
+
return;
|
|
157
|
+
this.injectBridge(browser, viewId);
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
injectBridge(browser, viewId) {
|
|
161
|
+
browser.execute(`window.__OpenCoreWebView = {
|
|
162
|
+
emit: function(event, payload) {
|
|
163
|
+
if (typeof mp !== 'undefined' && typeof mp.trigger === 'function') {
|
|
164
|
+
mp.trigger(${js(RAGEMP_WEBVIEW_EVENT)}, ${js(viewId)}, event, JSON.stringify(payload ?? null));
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
};`);
|
|
168
|
+
}
|
|
127
169
|
};
|
|
128
170
|
exports.RageMPClientWebViewBridge = RageMPClientWebViewBridge;
|
|
129
171
|
exports.RageMPClientWebViewBridge = RageMPClientWebViewBridge = __decorate([
|
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
import { IEngineEvents, type RuntimeEventMap, type RuntimeEventName } from '@open-core/framework/contracts/server';
|
|
2
|
-
type EngineHandler = (...args: readonly unknown[]) => void;
|
|
3
2
|
export declare class RageMPEngineEvents extends IEngineEvents {
|
|
4
|
-
constructor();
|
|
5
3
|
getRuntimeEventMap(): RuntimeEventMap;
|
|
6
|
-
onRuntime(eventName: RuntimeEventName, handler?:
|
|
7
|
-
on(eventName: string, handler?:
|
|
4
|
+
onRuntime<TArgs extends readonly unknown[]>(eventName: RuntimeEventName, handler?: (...args: TArgs) => void): void;
|
|
5
|
+
on<TArgs extends readonly unknown[]>(eventName: string, handler?: (...args: TArgs) => void): void;
|
|
8
6
|
emit(eventName: string, ...args: readonly unknown[]): void;
|
|
9
7
|
}
|
|
10
8
|
export declare function resolveSharedEngineEvents(): RageMPEngineEvents;
|
|
11
|
-
export {};
|
|
@@ -11,21 +11,9 @@ const EVENT_MAP = {
|
|
|
11
11
|
function isPlayerMp(value) {
|
|
12
12
|
return typeof value === 'object' && value !== null && 'id' in value;
|
|
13
13
|
}
|
|
14
|
-
// TODO: Refactor runtime event handling to use a single engine listener per event.
|
|
15
14
|
// The listener should forward events to an internal dispatcher/event bus so that
|
|
16
15
|
// multiple framework handlers do not register duplicate mp.events listeners.
|
|
17
16
|
class RageMPEngineEvents extends server_1.IEngineEvents {
|
|
18
|
-
constructor() {
|
|
19
|
-
super();
|
|
20
|
-
this.onRuntime(server_1.RUNTIME_EVENTS.playerCommand, (player, command) => {
|
|
21
|
-
if (!isPlayerMp(player) || typeof command !== 'string')
|
|
22
|
-
return;
|
|
23
|
-
const [commandName, ...args] = command.trim().split(/\s+/);
|
|
24
|
-
if (!commandName)
|
|
25
|
-
return;
|
|
26
|
-
this.emit('core:execute-command', player, commandName, args);
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
17
|
getRuntimeEventMap() {
|
|
30
18
|
return EVENT_MAP;
|
|
31
19
|
}
|
|
@@ -36,14 +24,14 @@ class RageMPEngineEvents extends server_1.IEngineEvents {
|
|
|
36
24
|
mp.events.add(mpEvent, (player, ...args) => {
|
|
37
25
|
const license = player.rgscId;
|
|
38
26
|
if (eventName === server_1.RUNTIME_EVENTS.playerJoining) {
|
|
39
|
-
handler(player.id, { license });
|
|
27
|
+
handler(...[player.id, { license }]);
|
|
40
28
|
return;
|
|
41
29
|
}
|
|
42
30
|
if (eventName === server_1.RUNTIME_EVENTS.playerDropped) {
|
|
43
|
-
handler(player.id);
|
|
31
|
+
handler(...[player.id]);
|
|
44
32
|
return;
|
|
45
33
|
}
|
|
46
|
-
handler(player, ...args);
|
|
34
|
+
handler(...[player, ...args]);
|
|
47
35
|
});
|
|
48
36
|
}
|
|
49
37
|
on(eventName, handler) {
|
|
@@ -51,7 +51,20 @@ let RageMPEntityServer = class RageMPEntityServer extends server_1.IEntityServer
|
|
|
51
51
|
return this.findEntity(handle)?.model ?? 0;
|
|
52
52
|
}
|
|
53
53
|
delete(handle) {
|
|
54
|
-
|
|
54
|
+
const vehicle = mp.vehicles.at(handle);
|
|
55
|
+
if (vehicle && mp.vehicles.exists(vehicle) && typeof vehicle.destroy === 'function') {
|
|
56
|
+
vehicle.destroy();
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const ped = mp.peds.at(handle);
|
|
60
|
+
if (ped && mp.peds.exists(ped) && typeof ped.destroy === 'function') {
|
|
61
|
+
ped.destroy();
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
const entity = this.findEntity(handle);
|
|
65
|
+
if (entity && typeof entity.destroy === 'function') {
|
|
66
|
+
entity.destroy();
|
|
67
|
+
}
|
|
55
68
|
}
|
|
56
69
|
setOrphanMode(_handle, _mode) {
|
|
57
70
|
// Not applicable in RageMP — entities are always managed by the server.
|
|
@@ -1,7 +1,58 @@
|
|
|
1
1
|
import { IExports, IResourceInfo } from '@open-core/framework/contracts/server';
|
|
2
2
|
export declare class RageMPExports extends IExports {
|
|
3
3
|
private readonly resourceInfo;
|
|
4
|
+
private readonly currentResourceName;
|
|
5
|
+
private readonly requestEventName;
|
|
6
|
+
private readonly responseEventName;
|
|
7
|
+
private readonly pendingRequests;
|
|
8
|
+
private readonly localHandlers;
|
|
4
9
|
constructor(resourceInfo: IResourceInfo);
|
|
5
10
|
register(exportName: string, handler: (...args: readonly unknown[]) => unknown): void;
|
|
11
|
+
/**
|
|
12
|
+
* Resolves exports through the local registry shared by the current adapter runtime.
|
|
13
|
+
*/
|
|
6
14
|
getResource<T = unknown>(resourceName: string): T | undefined;
|
|
15
|
+
/**
|
|
16
|
+
* Returns an async proxy that forwards method calls to another server resource.
|
|
17
|
+
*
|
|
18
|
+
* @remarks
|
|
19
|
+
* The proxy intentionally ignores Promise-like properties (`then`, `catch`, `finally`)
|
|
20
|
+
* so `await` does not accidentally treat the proxy itself as a thenable.
|
|
21
|
+
*/
|
|
22
|
+
getRemoteResource<T = unknown>(resourceName: string): T;
|
|
23
|
+
/**
|
|
24
|
+
* Invokes a remote export by sending a server-side RageMP event to the target resource.
|
|
25
|
+
*/
|
|
26
|
+
callRemoteExport<TResult = unknown>(resourceName: string, exportName: string, ...args: unknown[]): Promise<TResult>;
|
|
27
|
+
/**
|
|
28
|
+
* Waits for a remote resource to expose a matching export before returning the async proxy.
|
|
29
|
+
*/
|
|
30
|
+
waitForRemoteResource<T = unknown>(resourceName: string, options?: {
|
|
31
|
+
exportName?: string;
|
|
32
|
+
timeoutMs?: number;
|
|
33
|
+
intervalMs?: number;
|
|
34
|
+
}): Promise<T>;
|
|
35
|
+
/**
|
|
36
|
+
* Installs the request/response listeners used by the optional remote export helper layer.
|
|
37
|
+
*
|
|
38
|
+
* @remarks
|
|
39
|
+
* The listeners reject payloads that look like player-originated server events so clients
|
|
40
|
+
* cannot invoke server resource exports through this transport.
|
|
41
|
+
*/
|
|
42
|
+
private registerTransportListeners;
|
|
43
|
+
/**
|
|
44
|
+
* Executes one remote export request against handlers registered in the current resource.
|
|
45
|
+
*/
|
|
46
|
+
private handleExportRequest;
|
|
47
|
+
/**
|
|
48
|
+
* Resolves or rejects the pending promise associated with a remote export response.
|
|
49
|
+
*/
|
|
50
|
+
private handleExportResponse;
|
|
51
|
+
/**
|
|
52
|
+
* Executes an export from the current resource without going back through the shared registry.
|
|
53
|
+
*/
|
|
54
|
+
private executeLocalExport;
|
|
55
|
+
private createRequestId;
|
|
56
|
+
private serializeError;
|
|
57
|
+
private deserializeError;
|
|
7
58
|
}
|