@open-core/ragemp-adapter 0.1.1 → 1.0.0

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.
Files changed (37) hide show
  1. package/dist/.tsbuildinfo/client.tsbuildinfo +1 -1
  2. package/dist/.tsbuildinfo/root.tsbuildinfo +1 -1
  3. package/dist/.tsbuildinfo/server.tsbuildinfo +1 -1
  4. package/dist/.tsbuildinfo/shared.tsbuildinfo +1 -1
  5. package/dist/client/create-ragemp-client-adapter.js +10 -3
  6. package/dist/client/native-chat.d.ts +10 -0
  7. package/dist/client/native-chat.js +69 -6
  8. package/dist/client/ragemp-camera-port.d.ts +19 -0
  9. package/dist/client/ragemp-camera-port.js +72 -0
  10. package/dist/client/ragemp-local-player-bridge.d.ts +3 -0
  11. package/dist/client/ragemp-local-player-bridge.js +10 -0
  12. package/dist/client/ragemp-ped-port.d.ts +23 -0
  13. package/dist/client/ragemp-ped-port.js +107 -0
  14. package/dist/client/ragemp-platform-bridge.js +1 -1
  15. package/dist/client/ragemp-progress-port.d.ts +21 -0
  16. package/dist/client/ragemp-progress-port.js +169 -0
  17. package/dist/client/ragemp-runtime-bridge.d.ts +2 -4
  18. package/dist/client/ragemp-runtime-bridge.js +3 -0
  19. package/dist/client/ragemp-spawn-bridge.d.ts +4 -4
  20. package/dist/client/ragemp-spawn-bridge.js +5 -3
  21. package/dist/client/ragemp-vehicle-port.d.ts +34 -0
  22. package/dist/client/ragemp-vehicle-port.js +272 -0
  23. package/dist/client/ragemp-webview-bridge.d.ts +5 -0
  24. package/dist/client/ragemp-webview-bridge.js +54 -12
  25. package/dist/server/ragemp-engine-events.d.ts +2 -5
  26. package/dist/server/ragemp-engine-events.js +3 -15
  27. package/dist/server/ragemp-entity-server.js +14 -1
  28. package/dist/server/ragemp-player-appearance-lifecycle-server.js +4 -3
  29. package/dist/server/ragemp-resourceinfo.js +3 -0
  30. package/dist/shared/exports-registry.d.ts +2 -2
  31. package/dist/shared/transport/helpers.d.ts +3 -3
  32. package/dist/shared/transport/helpers.js +33 -7
  33. package/dist/shared/transport/ragemp.events.d.ts +3 -3
  34. package/dist/shared/transport/ragemp.events.js +4 -2
  35. package/dist/shared/transport/ragemp.rpc.d.ts +4 -8
  36. package/dist/shared/transport/ragemp.rpc.js +21 -5
  37. package/package.json +5 -7
@@ -1,13 +1,13 @@
1
- import { IClientSpawnBridge, type RespawnRequest, type SpawnRequest, type TeleportRequest } from '@open-core/framework/contracts/client';
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 IClientSpawnBridge {
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<void>;
10
- respawn(request: RespawnRequest): Promise<void>;
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.IClientSpawnBridge {
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
- mp.events.add('browserDomReady', (readyBrowser) => {
43
- if (readyBrowser !== browser)
44
- return;
45
- browser.execute(`window.__OpenCoreWebView = {
46
- emit: function(event, payload) {
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)?.markAsChat();
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?: EngineHandler): void;
7
- on(eventName: string, handler?: EngineHandler): void;
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
- this.findEntity(handle)?.destroy();
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.
@@ -15,6 +15,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.RageMPPlayerAppearanceLifecycleServer = void 0;
16
16
  const tsyringe_1 = require("tsyringe");
17
17
  const contracts_1 = require("@open-core/framework/contracts");
18
+ const framework_1 = require("@open-core/framework");
18
19
  const server_1 = require("@open-core/framework/server");
19
20
  const server_2 = require("@open-core/framework/contracts/server");
20
21
  const server_3 = require("@open-core/framework/contracts/server");
@@ -33,21 +34,21 @@ let RageMPPlayerAppearanceLifecycleServer = class RageMPPlayerAppearanceLifecycl
33
34
  if (appearance.model) {
34
35
  this.playerServer.setModel(playerSrc, appearance.model);
35
36
  }
36
- this.events.emit('opencore:appearance:apply', target, appearance);
37
+ this.events.emit(framework_1.SYSTEM_EVENTS.appearance.apply, target, appearance);
37
38
  return { success: true, appearance };
38
39
  }
39
40
  applyClothing(playerSrc, appearance) {
40
41
  const target = this.resolveTarget(playerSrc);
41
42
  if (!target)
42
43
  return false;
43
- this.events.emit('opencore:appearance:apply', target, appearance);
44
+ this.events.emit(framework_1.SYSTEM_EVENTS.appearance.apply, target, appearance);
44
45
  return true;
45
46
  }
46
47
  reset(playerSrc) {
47
48
  const target = this.resolveTarget(playerSrc);
48
49
  if (!target)
49
50
  return false;
50
- this.events.emit('opencore:appearance:reset', target);
51
+ this.events.emit(framework_1.SYSTEM_EVENTS.appearance.reset, target);
51
52
  return true;
52
53
  }
53
54
  resolveTarget(playerSrc) {
@@ -4,6 +4,9 @@ exports.RageMPResourceInfo = void 0;
4
4
  const server_1 = require("@open-core/framework/contracts/server");
5
5
  class RageMPResourceInfo extends server_1.IResourceInfo {
6
6
  getCurrentResourceName() {
7
+ if (typeof __OPENCORE_RESOURCE_NAME__ === 'string' && __OPENCORE_RESOURCE_NAME__.trim()) {
8
+ return __OPENCORE_RESOURCE_NAME__;
9
+ }
7
10
  if (typeof __dirname !== 'string')
8
11
  return 'default';
9
12
  const normalized = __dirname.replace(/\\/g, '/');
@@ -11,7 +11,7 @@ export type ExportsProxy = {
11
11
  export declare class ExportsRegistry {
12
12
  private readonly registry;
13
13
  private readonly namespaceProxyCache;
14
- register(resource: string, name: string, handler: ExportHandler): void;
14
+ register<TArgs extends readonly unknown[], TResult = unknown>(resource: string, name: string, handler: (...args: TArgs) => TResult): void;
15
15
  call(resource: string, name: string, ...args: ExportArgs): unknown;
16
16
  private createNamespaceProxy;
17
17
  private getOrCreateNamespaceProxy;
@@ -24,6 +24,6 @@ export declare class ExportsRegistry {
24
24
  list(resource: string): string[];
25
25
  }
26
26
  export declare const exportsRegistry: ExportsRegistry;
27
- export declare function registerExport(resource: string, name: string, handler: ExportHandler): void;
27
+ export declare function registerExport<TArgs extends readonly unknown[], TResult = unknown>(resource: string, name: string, handler: (...args: TArgs) => TResult): void;
28
28
  export declare function callExport(resource: string, name: string, ...args: ExportArgs): unknown;
29
29
  export {};
@@ -5,10 +5,10 @@ import type { RuntimeContext } from '@open-core/framework/contracts';
5
5
  *
6
6
  * Analogous to FiveM's `onNet`:
7
7
  * - Server: RageMP prepends the PlayerMp as the first native argument.
8
- * We expose it as-is so callers can read player.id before any await.
8
+ * We expose it as-is so callers can read player.id before awaiting.
9
9
  * - Client: no source argument; we pass undefined to keep the signature uniform.
10
10
  */
11
- export declare function onNet(context: RuntimeContext, event: string, handler: (source: PlayerMp | undefined, ...args: any[]) => void): void;
11
+ export declare function onNet<TArgs extends readonly unknown[]>(context: RuntimeContext, event: string, handler: (source: PlayerMp | undefined, ...args: TArgs) => void): void;
12
12
  /**
13
13
  * Normalizes RageMP's server/client event emission into a single interface.
14
14
  *
@@ -21,4 +21,4 @@ export declare function onNet(context: RuntimeContext, event: string, handler: (
21
21
  * NOTE: Only player targets are supported — vehicles/peds are not valid
22
22
  * network targets, matching FiveM's TriggerClientEvent semantics.
23
23
  */
24
- export declare function emitNet(context: RuntimeContext, event: string, target: number | number[] | -1, ...payload: any[]): void;
24
+ export declare function emitNet(context: RuntimeContext, event: string, target: number | number[] | -1, ...payload: unknown[]): void;