@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
|
@@ -5,15 +5,18 @@ exports.RageMPClientAdapter = RageMPClientAdapter;
|
|
|
5
5
|
const client_1 = require("@open-core/framework/client");
|
|
6
6
|
const client_2 = require("@open-core/framework/contracts/client");
|
|
7
7
|
const adapter_1 = require("../shared/transport/adapter");
|
|
8
|
-
const native_chat_1 = require("./native-chat");
|
|
9
8
|
const ragemp_hasher_1 = require("./ragemp-hasher");
|
|
10
9
|
const ragemp_log_console_1 = require("./ragemp-log-console");
|
|
11
10
|
const ragemp_local_player_bridge_1 = require("./ragemp-local-player-bridge");
|
|
12
11
|
const ragemp_blip_bridge_1 = require("./ragemp-blip-bridge");
|
|
12
|
+
const ragemp_camera_port_1 = require("./ragemp-camera-port");
|
|
13
13
|
const ragemp_marker_bridge_1 = require("./ragemp-marker-bridge");
|
|
14
14
|
const ragemp_notification_bridge_1 = require("./ragemp-notification-bridge");
|
|
15
|
+
const ragemp_ped_port_1 = require("./ragemp-ped-port");
|
|
16
|
+
const ragemp_progress_port_1 = require("./ragemp-progress-port");
|
|
15
17
|
const ragemp_platform_bridge_1 = require("./ragemp-platform-bridge");
|
|
16
18
|
const ragemp_spawn_bridge_1 = require("./ragemp-spawn-bridge");
|
|
19
|
+
const ragemp_vehicle_port_1 = require("./ragemp-vehicle-port");
|
|
17
20
|
const ragemp_runtime_bridge_1 = require("./ragemp-runtime-bridge");
|
|
18
21
|
const ragemp_webview_bridge_1 = require("./ragemp-webview-bridge");
|
|
19
22
|
const contracts_1 = require("@open-core/framework/contracts");
|
|
@@ -26,13 +29,17 @@ function RageMPClientAdapter() {
|
|
|
26
29
|
register(ctx) {
|
|
27
30
|
const transport = new adapter_1.RageMPMessagingTransport();
|
|
28
31
|
ctx.bindMessagingTransport(transport);
|
|
29
|
-
(0, native_chat_1.enableRageMPNativeChat)(transport.events);
|
|
30
32
|
ctx.bindSingleton(contracts_1.IHasher, ragemp_hasher_1.RageMPClientHasher);
|
|
31
33
|
ctx.bindSingleton(client_2.IClientLogConsole, ragemp_log_console_1.RageMPClientLogConsole);
|
|
32
34
|
ctx.bindSingleton(client_1.IClientRuntimeBridge, ragemp_runtime_bridge_1.RageMPRuntimeBridge);
|
|
33
35
|
ctx.bindSingleton(client_1.IClientLocalPlayerBridge, ragemp_local_player_bridge_1.RageMPLocalPlayerBridge);
|
|
34
36
|
ctx.bindSingleton(client_1.IClientPlatformBridge, ragemp_platform_bridge_1.RageMPPlatformBridge);
|
|
35
|
-
ctx.bindSingleton(client_2.
|
|
37
|
+
ctx.bindSingleton(client_2.IClientCameraPort, ragemp_camera_port_1.RageMPClientCameraPort);
|
|
38
|
+
ctx.bindSingleton(client_2.IClientPedPort, ragemp_ped_port_1.RageMPClientPedPort);
|
|
39
|
+
ctx.bindSingleton(client_2.IClientProgressPort, ragemp_progress_port_1.RageMPClientProgressPort);
|
|
40
|
+
ctx.bindSingleton(client_2.IClientSpawnPort, ragemp_spawn_bridge_1.RageMPClientSpawnBridge);
|
|
41
|
+
ctx.bindSingleton(client_2.IClientVehiclePort, ragemp_vehicle_port_1.RageMPClientVehiclePort);
|
|
42
|
+
ctx.bindFactory(client_2.IClientSpawnBridge, () => ctx.container.resolve(client_2.IClientSpawnPort));
|
|
36
43
|
ctx.bindSingleton(client_2.IClientBlipBridge, ragemp_blip_bridge_1.RageMPClientBlipBridge);
|
|
37
44
|
ctx.bindSingleton(client_2.IClientMarkerBridge, ragemp_marker_bridge_1.RageMPClientMarkerBridge);
|
|
38
45
|
ctx.bindSingleton(client_2.IClientNotificationBridge, ragemp_notification_bridge_1.RageMPClientNotificationBridge);
|
|
@@ -1,2 +1,12 @@
|
|
|
1
1
|
import type { EventsAPI } from '@open-core/framework/contracts';
|
|
2
|
+
/**
|
|
3
|
+
* Optional native RageMP chat bridge.
|
|
4
|
+
*
|
|
5
|
+
* This is intentionally opt-in. Resources using a WebView chat should not
|
|
6
|
+
* enable it, otherwise the native chat UI can interfere with the custom one.
|
|
7
|
+
*/
|
|
2
8
|
export declare function enableRageMPNativeChat(events: EventsAPI<'client'>): void;
|
|
9
|
+
export declare function disableRageMPNativeChatUi(): void;
|
|
10
|
+
export declare function enableRageMPNativeChatUi(): void;
|
|
11
|
+
export declare function suppressRageMPNativeChat(source: string): void;
|
|
12
|
+
export declare function releaseRageMPNativeChat(source: string): void;
|
|
@@ -1,7 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.enableRageMPNativeChat = enableRageMPNativeChat;
|
|
4
|
+
exports.disableRageMPNativeChatUi = disableRageMPNativeChatUi;
|
|
5
|
+
exports.enableRageMPNativeChatUi = enableRageMPNativeChatUi;
|
|
6
|
+
exports.suppressRageMPNativeChat = suppressRageMPNativeChat;
|
|
7
|
+
exports.releaseRageMPNativeChat = releaseRageMPNativeChat;
|
|
8
|
+
const framework_1 = require("@open-core/framework");
|
|
4
9
|
const nativeChatGlobal = globalThis;
|
|
10
|
+
function getSuppressors() {
|
|
11
|
+
if (!nativeChatGlobal.__OPENCORE_RAGEMP_NATIVE_CHAT_SUPPRESSORS__) {
|
|
12
|
+
nativeChatGlobal.__OPENCORE_RAGEMP_NATIVE_CHAT_SUPPRESSORS__ = new Set();
|
|
13
|
+
}
|
|
14
|
+
return nativeChatGlobal.__OPENCORE_RAGEMP_NATIVE_CHAT_SUPPRESSORS__;
|
|
15
|
+
}
|
|
5
16
|
const CHAT_TYPE_COLORS = {
|
|
6
17
|
chat: { r: 255, g: 255, b: 255 },
|
|
7
18
|
error: { r: 224, g: 62, b: 62 },
|
|
@@ -13,15 +24,29 @@ function toHex(color) {
|
|
|
13
24
|
return `${part(color.r)}${part(color.g)}${part(color.b)}`;
|
|
14
25
|
}
|
|
15
26
|
function pushNativeChatLine(text, color) {
|
|
27
|
+
if (nativeChatGlobal.__OPENCORE_RAGEMP_NATIVE_CHAT_VISIBLE__ === false) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
16
30
|
try {
|
|
17
|
-
mp.gui.chat.activate(true);
|
|
18
|
-
mp.gui.chat.show(true);
|
|
19
31
|
mp.gui.chat.push(`!{${toHex(color)}}${text}`);
|
|
20
32
|
}
|
|
21
33
|
catch {
|
|
22
34
|
// Ignore chat output when RageMP chat runtime is not ready yet.
|
|
23
35
|
}
|
|
24
36
|
}
|
|
37
|
+
function setNativeChatVisible(visible) {
|
|
38
|
+
nativeChatGlobal.__OPENCORE_RAGEMP_NATIVE_CHAT_VISIBLE__ = visible;
|
|
39
|
+
try {
|
|
40
|
+
mp.gui.chat.activate(false);
|
|
41
|
+
mp.gui.chat.show(visible);
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
// Ignore when the chat runtime is not ready yet.
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function syncNativeChatVisibility() {
|
|
48
|
+
setNativeChatVisible(getSuppressors().size === 0);
|
|
49
|
+
}
|
|
25
50
|
function formatPayload(payload) {
|
|
26
51
|
const [author, message] = payload.args ?? ['SYSTEM', ''];
|
|
27
52
|
return {
|
|
@@ -29,22 +54,60 @@ function formatPayload(payload) {
|
|
|
29
54
|
color: payload.color ?? CHAT_TYPE_COLORS.chat,
|
|
30
55
|
};
|
|
31
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* Optional native RageMP chat bridge.
|
|
59
|
+
*
|
|
60
|
+
* This is intentionally opt-in. Resources using a WebView chat should not
|
|
61
|
+
* enable it, otherwise the native chat UI can interfere with the custom one.
|
|
62
|
+
*/
|
|
32
63
|
function enableRageMPNativeChat(events) {
|
|
33
64
|
if (nativeChatGlobal.__OPENCORE_RAGEMP_NATIVE_CHAT_ENABLED__)
|
|
34
65
|
return;
|
|
35
66
|
nativeChatGlobal.__OPENCORE_RAGEMP_NATIVE_CHAT_ENABLED__ = true;
|
|
36
|
-
|
|
67
|
+
if (nativeChatGlobal.__OPENCORE_RAGEMP_NATIVE_CHAT_VISIBLE__ === undefined) {
|
|
68
|
+
nativeChatGlobal.__OPENCORE_RAGEMP_NATIVE_CHAT_VISIBLE__ = true;
|
|
69
|
+
}
|
|
70
|
+
events.on(framework_1.SYSTEM_EVENTS.chat.addMessage, (_ctx, payload) => {
|
|
37
71
|
const { text, color } = formatPayload(payload);
|
|
38
72
|
pushNativeChatLine(text, color);
|
|
39
73
|
});
|
|
40
|
-
events.on(
|
|
74
|
+
events.on(framework_1.SYSTEM_EVENTS.chat.message, (_ctx, payload) => {
|
|
41
75
|
const { text, color } = formatPayload(payload);
|
|
42
76
|
pushNativeChatLine(text, color);
|
|
43
77
|
});
|
|
44
|
-
events.on(
|
|
78
|
+
events.on(framework_1.SYSTEM_EVENTS.chat.send, (_ctx, message, type = 'chat') => {
|
|
45
79
|
pushNativeChatLine(message, CHAT_TYPE_COLORS[type] ?? CHAT_TYPE_COLORS.chat);
|
|
46
80
|
});
|
|
47
|
-
events.on(
|
|
81
|
+
events.on(framework_1.SYSTEM_EVENTS.chat.clear, () => {
|
|
48
82
|
// RageMP native chat has no public clear API.
|
|
49
83
|
});
|
|
50
84
|
}
|
|
85
|
+
function disableRageMPNativeChatUi() {
|
|
86
|
+
getSuppressors().add('__manual__');
|
|
87
|
+
syncNativeChatVisibility();
|
|
88
|
+
}
|
|
89
|
+
function enableRageMPNativeChatUi() {
|
|
90
|
+
getSuppressors().delete('__manual__');
|
|
91
|
+
syncNativeChatVisibility();
|
|
92
|
+
}
|
|
93
|
+
function suppressRageMPNativeChat(source) {
|
|
94
|
+
getSuppressors().add(source);
|
|
95
|
+
syncNativeChatVisibility();
|
|
96
|
+
}
|
|
97
|
+
function releaseRageMPNativeChat(source) {
|
|
98
|
+
getSuppressors().delete(source);
|
|
99
|
+
syncNativeChatVisibility();
|
|
100
|
+
}
|
|
101
|
+
if (typeof mp !== 'undefined') {
|
|
102
|
+
mp.events.add('render', () => {
|
|
103
|
+
if (nativeChatGlobal.__OPENCORE_RAGEMP_NATIVE_CHAT_VISIBLE__ === false) {
|
|
104
|
+
try {
|
|
105
|
+
mp.gui.chat.activate(false);
|
|
106
|
+
mp.gui.chat.show(false);
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
// Ignore while chat runtime is unavailable.
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type ClientCameraCreateOptions, type ClientCameraRenderOptions, type ClientCameraRotation, type ClientCameraShakeOptions, type ClientCameraTransform, IClientCameraPort } from '@open-core/framework/contracts/client';
|
|
2
|
+
import type { Vector3 } from '@open-core/framework/kernel';
|
|
3
|
+
export declare class RageMPClientCameraPort extends IClientCameraPort {
|
|
4
|
+
create(options?: ClientCameraCreateOptions): number;
|
|
5
|
+
setActive(camera: number, active: boolean): void;
|
|
6
|
+
render(enable: boolean, options?: ClientCameraRenderOptions): void;
|
|
7
|
+
destroy(camera: number, destroyActiveCamera?: boolean): void;
|
|
8
|
+
destroyAll(destroyActiveCamera?: boolean): void;
|
|
9
|
+
setTransform(camera: number, transform: ClientCameraTransform): void;
|
|
10
|
+
setPosition(camera: number, position: Vector3): void;
|
|
11
|
+
setRotation(camera: number, rotation: ClientCameraRotation, rotationOrder?: number): void;
|
|
12
|
+
setFov(camera: number, fov: number): void;
|
|
13
|
+
pointAtCoords(camera: number, position: Vector3): void;
|
|
14
|
+
pointAtEntity(camera: number, entity: number, offset?: Vector3): void;
|
|
15
|
+
stopPointing(camera: number): void;
|
|
16
|
+
interpolate(fromCamera: number, toCamera: number, durationMs: number, easeLocation?: boolean, easeRotation?: boolean): void;
|
|
17
|
+
shake(camera: number, options: ClientCameraShakeOptions): void;
|
|
18
|
+
stopShaking(camera: number, stopImmediately?: boolean): void;
|
|
19
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.RageMPClientCameraPort = void 0;
|
|
10
|
+
const tsyringe_1 = require("tsyringe");
|
|
11
|
+
const client_1 = require("@open-core/framework/contracts/client");
|
|
12
|
+
function getCameraApi() {
|
|
13
|
+
return mp.game.cam;
|
|
14
|
+
}
|
|
15
|
+
let RageMPClientCameraPort = class RageMPClientCameraPort extends client_1.IClientCameraPort {
|
|
16
|
+
create(options = {}) {
|
|
17
|
+
const camera = getCameraApi().createCam(options.camName ?? 'DEFAULT_SCRIPTED_CAMERA', options.active ?? false);
|
|
18
|
+
if (options.transform)
|
|
19
|
+
this.setTransform(camera, options.transform);
|
|
20
|
+
return camera;
|
|
21
|
+
}
|
|
22
|
+
setActive(camera, active) {
|
|
23
|
+
getCameraApi().setActive(camera, active);
|
|
24
|
+
}
|
|
25
|
+
render(enable, options = {}) {
|
|
26
|
+
getCameraApi().renderScriptCams(enable, options.ease ?? false, options.easeTimeMs ?? 0, true, true, 0);
|
|
27
|
+
}
|
|
28
|
+
destroy(camera, destroyActiveCamera = false) {
|
|
29
|
+
getCameraApi().destroy(camera, destroyActiveCamera);
|
|
30
|
+
}
|
|
31
|
+
destroyAll(destroyActiveCamera = false) {
|
|
32
|
+
getCameraApi().destroyAllCams(destroyActiveCamera);
|
|
33
|
+
}
|
|
34
|
+
setTransform(camera, transform) {
|
|
35
|
+
this.setPosition(camera, transform.position);
|
|
36
|
+
if (transform.rotation)
|
|
37
|
+
this.setRotation(camera, transform.rotation);
|
|
38
|
+
if (typeof transform.fov === 'number')
|
|
39
|
+
this.setFov(camera, transform.fov);
|
|
40
|
+
}
|
|
41
|
+
setPosition(camera, position) {
|
|
42
|
+
getCameraApi().setCoord(camera, position.x, position.y, position.z);
|
|
43
|
+
}
|
|
44
|
+
setRotation(camera, rotation, rotationOrder = 2) {
|
|
45
|
+
getCameraApi().setRot(camera, rotation.x, rotation.y, rotation.z, rotationOrder);
|
|
46
|
+
}
|
|
47
|
+
setFov(camera, fov) {
|
|
48
|
+
getCameraApi().setFov(camera, fov);
|
|
49
|
+
}
|
|
50
|
+
pointAtCoords(camera, position) {
|
|
51
|
+
getCameraApi().pointAtCoord(camera, position.x, position.y, position.z);
|
|
52
|
+
}
|
|
53
|
+
pointAtEntity(camera, entity, offset = { x: 0, y: 0, z: 0 }) {
|
|
54
|
+
getCameraApi().pointAtEntity(camera, entity, offset.x, offset.y, offset.z, true);
|
|
55
|
+
}
|
|
56
|
+
stopPointing(camera) {
|
|
57
|
+
getCameraApi().stopPointing(camera);
|
|
58
|
+
}
|
|
59
|
+
interpolate(fromCamera, toCamera, durationMs, easeLocation = true, easeRotation = true) {
|
|
60
|
+
getCameraApi().setActiveWithInterp(toCamera, fromCamera, durationMs, easeLocation ? 1 : 0, easeRotation ? 1 : 0);
|
|
61
|
+
}
|
|
62
|
+
shake(camera, options) {
|
|
63
|
+
getCameraApi().shake(camera, options.type, options.amplitude);
|
|
64
|
+
}
|
|
65
|
+
stopShaking(camera, stopImmediately = true) {
|
|
66
|
+
getCameraApi().stopShaking(camera, stopImmediately);
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
exports.RageMPClientCameraPort = RageMPClientCameraPort;
|
|
70
|
+
exports.RageMPClientCameraPort = RageMPClientCameraPort = __decorate([
|
|
71
|
+
(0, tsyringe_1.injectable)()
|
|
72
|
+
], RageMPClientCameraPort);
|
|
@@ -4,5 +4,8 @@ import type { Vector3 } from '@open-core/framework/kernel';
|
|
|
4
4
|
* RAGE Multiplayer implementation of local player movement helpers.
|
|
5
5
|
*/
|
|
6
6
|
export declare class RageMPLocalPlayerBridge extends IClientLocalPlayerBridge {
|
|
7
|
+
getHandle(): number;
|
|
8
|
+
getPosition(): Vector3;
|
|
9
|
+
getHeading(): number;
|
|
7
10
|
setPosition(position: Vector3, heading?: number): void;
|
|
8
11
|
}
|
|
@@ -13,6 +13,16 @@ const client_1 = require("@open-core/framework/contracts/client");
|
|
|
13
13
|
* RAGE Multiplayer implementation of local player movement helpers.
|
|
14
14
|
*/
|
|
15
15
|
let RageMPLocalPlayerBridge = class RageMPLocalPlayerBridge extends client_1.IClientLocalPlayerBridge {
|
|
16
|
+
getHandle() {
|
|
17
|
+
return mp.players.local.handle;
|
|
18
|
+
}
|
|
19
|
+
getPosition() {
|
|
20
|
+
const { x, y, z } = mp.players.local.position;
|
|
21
|
+
return { x, y, z };
|
|
22
|
+
}
|
|
23
|
+
getHeading() {
|
|
24
|
+
return mp.players.local.heading;
|
|
25
|
+
}
|
|
16
26
|
setPosition(position, heading) {
|
|
17
27
|
mp.players.local.position = new mp.Vector3(position.x, position.y, position.z);
|
|
18
28
|
if (typeof heading === 'number') {
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type ClientPedAnimationOptions, type ClientPedSpawnOptions, IClientLocalPlayerBridge, IClientPedPort, IClientPlatformBridge } from '@open-core/framework/contracts/client';
|
|
2
|
+
import type { Vector3 } from '@open-core/framework/kernel';
|
|
3
|
+
export declare class RageMPClientPedPort extends IClientPedPort {
|
|
4
|
+
private readonly platform;
|
|
5
|
+
private readonly localPlayer;
|
|
6
|
+
constructor(platform: IClientPlatformBridge, localPlayer: IClientLocalPlayerBridge);
|
|
7
|
+
spawn(options: ClientPedSpawnOptions): Promise<number>;
|
|
8
|
+
delete(handle: number): void;
|
|
9
|
+
exists(handle: number): boolean;
|
|
10
|
+
playAnimation(handle: number, options: ClientPedAnimationOptions): Promise<void>;
|
|
11
|
+
stopAnimation(handle: number): void;
|
|
12
|
+
stopAnimationImmediately(handle: number): void;
|
|
13
|
+
freeze(handle: number, freeze: boolean): void;
|
|
14
|
+
setInvincible(handle: number, invincible: boolean): void;
|
|
15
|
+
giveWeapon(handle: number, weapon: string, ammo?: number, hidden?: boolean, forceInHand?: boolean): void;
|
|
16
|
+
removeAllWeapons(handle: number): void;
|
|
17
|
+
getClosest(radius?: number, excludeLocalPlayer?: boolean): number | null;
|
|
18
|
+
getNearby(position: Vector3, radius: number, excludeEntity?: number): number[];
|
|
19
|
+
lookAtEntity(handle: number, entity: number, duration?: number): void;
|
|
20
|
+
lookAtCoords(handle: number, position: Vector3, duration?: number): void;
|
|
21
|
+
walkTo(handle: number, position: Vector3, speed?: number): void;
|
|
22
|
+
setCombatAttributes(handle: number, canFight: boolean, canUseCover?: boolean): void;
|
|
23
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
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.RageMPClientPedPort = void 0;
|
|
16
|
+
const tsyringe_1 = require("tsyringe");
|
|
17
|
+
const client_1 = require("@open-core/framework/contracts/client");
|
|
18
|
+
let RageMPClientPedPort = class RageMPClientPedPort extends client_1.IClientPedPort {
|
|
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, networked = false, missionEntity = true, blockEvents = true, relationshipGroup = 'CIVMALE', } = options;
|
|
26
|
+
const modelHash = this.platform.getHashKey(model);
|
|
27
|
+
if (!this.platform.isModelInCdimage(modelHash) || !this.platform.isModelValid(modelHash)) {
|
|
28
|
+
throw new Error(`Invalid ped 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 ped = this.platform.createPed(4, modelHash, position, heading, networked, true);
|
|
35
|
+
this.platform.setModelAsNoLongerNeeded(modelHash);
|
|
36
|
+
if (!ped || ped === 0)
|
|
37
|
+
throw new Error('Failed to create ped');
|
|
38
|
+
if (missionEntity)
|
|
39
|
+
this.platform.setEntityAsMissionEntity(ped, true, true);
|
|
40
|
+
if (blockEvents)
|
|
41
|
+
this.platform.setBlockingOfNonTemporaryEvents(ped, true);
|
|
42
|
+
this.platform.setPedRelationshipGroupHash(ped, this.platform.getHashKey(relationshipGroup));
|
|
43
|
+
return ped;
|
|
44
|
+
}
|
|
45
|
+
delete(handle) {
|
|
46
|
+
if (!this.exists(handle))
|
|
47
|
+
return;
|
|
48
|
+
this.platform.setEntityAsMissionEntity(handle, true, true);
|
|
49
|
+
this.platform.deletePed(handle);
|
|
50
|
+
}
|
|
51
|
+
exists(handle) { return this.platform.doesEntityExist(handle); }
|
|
52
|
+
async playAnimation(handle, options) {
|
|
53
|
+
if (!this.exists(handle))
|
|
54
|
+
return;
|
|
55
|
+
this.platform.requestAnimDict(options.dict);
|
|
56
|
+
while (!this.platform.hasAnimDictLoaded(options.dict)) {
|
|
57
|
+
await new Promise((r) => setTimeout(r, 0));
|
|
58
|
+
}
|
|
59
|
+
this.platform.taskPlayAnim(handle, options.dict, options.anim, options.blendInSpeed ?? 8, options.blendOutSpeed ?? -8, options.duration ?? -1, options.flags ?? 1, options.playbackRate ?? 0);
|
|
60
|
+
}
|
|
61
|
+
stopAnimation(handle) { if (this.exists(handle))
|
|
62
|
+
this.platform.clearPedTasks(handle); }
|
|
63
|
+
stopAnimationImmediately(handle) { if (this.exists(handle))
|
|
64
|
+
this.platform.clearPedTasksImmediately(handle); }
|
|
65
|
+
freeze(handle, freeze) { if (this.exists(handle))
|
|
66
|
+
this.platform.freezeEntityPosition(handle, freeze); }
|
|
67
|
+
setInvincible(handle, invincible) { if (this.exists(handle))
|
|
68
|
+
this.platform.setEntityInvincible(handle, invincible); }
|
|
69
|
+
giveWeapon(handle, weapon, ammo = 100, hidden = false, forceInHand = true) {
|
|
70
|
+
if (!this.exists(handle))
|
|
71
|
+
return;
|
|
72
|
+
this.platform.giveWeaponToPed(handle, this.platform.getHashKey(weapon), ammo, hidden, forceInHand);
|
|
73
|
+
}
|
|
74
|
+
removeAllWeapons(handle) { if (this.exists(handle))
|
|
75
|
+
this.platform.removeAllPedWeapons(handle, true); }
|
|
76
|
+
getClosest(radius = 10, excludeLocalPlayer = true) {
|
|
77
|
+
const handle = this.platform.getClosestPed(this.localPlayer.getPosition(), radius);
|
|
78
|
+
if (!handle)
|
|
79
|
+
return null;
|
|
80
|
+
if (excludeLocalPlayer && handle === this.localPlayer.getHandle())
|
|
81
|
+
return null;
|
|
82
|
+
return handle;
|
|
83
|
+
}
|
|
84
|
+
getNearby(position, radius, excludeEntity) {
|
|
85
|
+
return this.platform.getNearbyPeds(position, radius, excludeEntity);
|
|
86
|
+
}
|
|
87
|
+
lookAtEntity(handle, entity, duration = -1) { if (this.exists(handle))
|
|
88
|
+
this.platform.taskLookAtEntity(handle, entity, duration); }
|
|
89
|
+
lookAtCoords(handle, position, duration = -1) { if (this.exists(handle))
|
|
90
|
+
this.platform.taskLookAtCoord(handle, position, duration); }
|
|
91
|
+
walkTo(handle, position, speed = 1) { if (this.exists(handle))
|
|
92
|
+
this.platform.taskGoStraightToCoord(handle, position, speed); }
|
|
93
|
+
setCombatAttributes(handle, canFight, canUseCover = true) {
|
|
94
|
+
if (!this.exists(handle))
|
|
95
|
+
return;
|
|
96
|
+
this.platform.setPedCombatAttributes(handle, 46, canFight);
|
|
97
|
+
this.platform.setPedCombatAttributes(handle, 0, canUseCover);
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
exports.RageMPClientPedPort = RageMPClientPedPort;
|
|
101
|
+
exports.RageMPClientPedPort = RageMPClientPedPort = __decorate([
|
|
102
|
+
(0, tsyringe_1.injectable)(),
|
|
103
|
+
__param(0, (0, tsyringe_1.inject)(client_1.IClientPlatformBridge)),
|
|
104
|
+
__param(1, (0, tsyringe_1.inject)(client_1.IClientLocalPlayerBridge)),
|
|
105
|
+
__metadata("design:paramtypes", [client_1.IClientPlatformBridge,
|
|
106
|
+
client_1.IClientLocalPlayerBridge])
|
|
107
|
+
], RageMPClientPedPort);
|
|
@@ -280,7 +280,7 @@ let RageMPPlatformBridge = class RageMPPlatformBridge extends client_1.IClientPl
|
|
|
280
280
|
tryGetEntity(vehicle)?.destroy();
|
|
281
281
|
}
|
|
282
282
|
setVehicleOnGroundProperly(vehicle) {
|
|
283
|
-
|
|
283
|
+
getGame().vehicle.setOnGroundProperly(vehicle, 0);
|
|
284
284
|
}
|
|
285
285
|
getVehicleColours(vehicle) {
|
|
286
286
|
const colors = getGame().vehicle.getColours(vehicle);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { IClientLocalPlayerBridge, IClientPlatformBridge, IClientProgressPort, IClientRuntimeBridge, type ClientProgressOptions, type ClientProgressState } from '@open-core/framework/contracts/client';
|
|
2
|
+
export declare class RageMPClientProgressPort extends IClientProgressPort {
|
|
3
|
+
private readonly platform;
|
|
4
|
+
private readonly runtime;
|
|
5
|
+
private readonly localPlayer;
|
|
6
|
+
private state;
|
|
7
|
+
private tickHandle;
|
|
8
|
+
private callback;
|
|
9
|
+
private propHandle;
|
|
10
|
+
constructor(platform: IClientPlatformBridge, runtime: IClientRuntimeBridge, localPlayer: IClientLocalPlayerBridge);
|
|
11
|
+
start(options: ClientProgressOptions): Promise<boolean>;
|
|
12
|
+
cancel(): void;
|
|
13
|
+
isActive(): boolean;
|
|
14
|
+
getProgress(): number;
|
|
15
|
+
getState(): ClientProgressState | null;
|
|
16
|
+
private startProgress;
|
|
17
|
+
private drawProgressBar;
|
|
18
|
+
private cleanup;
|
|
19
|
+
private loadAnimDict;
|
|
20
|
+
private loadModel;
|
|
21
|
+
}
|
|
@@ -0,0 +1,169 @@
|
|
|
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.RageMPClientProgressPort = void 0;
|
|
16
|
+
const tsyringe_1 = require("tsyringe");
|
|
17
|
+
const client_1 = require("@open-core/framework/contracts/client");
|
|
18
|
+
let RageMPClientProgressPort = class RageMPClientProgressPort extends client_1.IClientProgressPort {
|
|
19
|
+
constructor(platform, runtime, localPlayer) {
|
|
20
|
+
super();
|
|
21
|
+
this.platform = platform;
|
|
22
|
+
this.runtime = runtime;
|
|
23
|
+
this.localPlayer = localPlayer;
|
|
24
|
+
this.state = null;
|
|
25
|
+
this.tickHandle = null;
|
|
26
|
+
this.callback = null;
|
|
27
|
+
this.propHandle = null;
|
|
28
|
+
}
|
|
29
|
+
async start(options) {
|
|
30
|
+
if (this.state?.active)
|
|
31
|
+
return false;
|
|
32
|
+
return new Promise((resolve) => {
|
|
33
|
+
this.state = {
|
|
34
|
+
active: true,
|
|
35
|
+
progress: 0,
|
|
36
|
+
label: options.label,
|
|
37
|
+
startTime: this.runtime.getGameTimer(),
|
|
38
|
+
duration: options.duration,
|
|
39
|
+
options,
|
|
40
|
+
};
|
|
41
|
+
this.callback = resolve;
|
|
42
|
+
void this.startProgress();
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
cancel() {
|
|
46
|
+
if (!this.state?.active)
|
|
47
|
+
return;
|
|
48
|
+
this.cleanup(false);
|
|
49
|
+
}
|
|
50
|
+
isActive() { return this.state?.active ?? false; }
|
|
51
|
+
getProgress() { return this.state?.progress ?? 0; }
|
|
52
|
+
getState() { return this.state; }
|
|
53
|
+
async startProgress() {
|
|
54
|
+
if (!this.state)
|
|
55
|
+
return;
|
|
56
|
+
const { options } = this.state;
|
|
57
|
+
const ped = this.localPlayer.getHandle();
|
|
58
|
+
if (options.animation) {
|
|
59
|
+
await this.loadAnimDict(options.animation.dict);
|
|
60
|
+
this.platform.taskPlayAnim(ped, options.animation.dict, options.animation.anim, 8.0, -8.0, options.duration, options.animation.flags ?? 1, 0.0);
|
|
61
|
+
}
|
|
62
|
+
if (options.prop) {
|
|
63
|
+
await this.loadModel(options.prop.model);
|
|
64
|
+
const propHash = this.platform.getHashKey(options.prop.model);
|
|
65
|
+
const coords = this.localPlayer.getPosition();
|
|
66
|
+
this.propHandle = this.platform.createObject(propHash, coords, true, true, true);
|
|
67
|
+
this.platform.attachEntityToEntity(this.propHandle, ped, this.platform.getPedBoneIndex(ped, options.prop.bone), options.prop.offset, options.prop.rotation);
|
|
68
|
+
}
|
|
69
|
+
this.tickHandle = this.runtime.setTick(() => {
|
|
70
|
+
if (!this.state)
|
|
71
|
+
return;
|
|
72
|
+
const elapsed = this.runtime.getGameTimer() - this.state.startTime;
|
|
73
|
+
this.state.progress = Math.min((elapsed / this.state.duration) * 100, 100);
|
|
74
|
+
if (options.disableControls) {
|
|
75
|
+
this.platform.disableAllControlActions(0);
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
if (options.disableMovement) {
|
|
79
|
+
this.platform.disableControlAction(0, 30, true);
|
|
80
|
+
this.platform.disableControlAction(0, 31, true);
|
|
81
|
+
this.platform.disableControlAction(0, 21, true);
|
|
82
|
+
this.platform.disableControlAction(0, 22, true);
|
|
83
|
+
}
|
|
84
|
+
if (options.disableCombat) {
|
|
85
|
+
this.platform.disableControlAction(0, 24, true);
|
|
86
|
+
this.platform.disableControlAction(0, 25, true);
|
|
87
|
+
this.platform.disableControlAction(0, 47, true);
|
|
88
|
+
this.platform.disableControlAction(0, 58, true);
|
|
89
|
+
this.platform.disableControlAction(0, 263, true);
|
|
90
|
+
this.platform.disableControlAction(0, 264, true);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
if (options.canCancel && this.platform.isControlJustPressed(0, 200)) {
|
|
94
|
+
this.cancel();
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
this.drawProgressBar();
|
|
98
|
+
if (elapsed >= this.state.duration)
|
|
99
|
+
this.cleanup(true);
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
drawProgressBar() {
|
|
103
|
+
if (!this.state)
|
|
104
|
+
return;
|
|
105
|
+
const { label, progress, options } = this.state;
|
|
106
|
+
if (options.useCircular) {
|
|
107
|
+
this.platform.beginTextCommandBusyspinnerOn('STRING');
|
|
108
|
+
this.platform.addTextComponentString(label);
|
|
109
|
+
this.platform.endTextCommandBusyspinnerOn(4);
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
const barWidth = 0.15;
|
|
113
|
+
const barHeight = 0.015;
|
|
114
|
+
const x = 0.5 - barWidth / 2;
|
|
115
|
+
const y = 0.88;
|
|
116
|
+
this.platform.drawRect(0.5, y + barHeight / 2, barWidth, barHeight, 0, 0, 0, 180);
|
|
117
|
+
const fillWidth = (barWidth * progress) / 100;
|
|
118
|
+
this.platform.drawRect(x + fillWidth / 2, y + barHeight / 2, fillWidth, barHeight, 255, 255, 255, 255);
|
|
119
|
+
this.platform.setTextFont(4);
|
|
120
|
+
this.platform.setTextScale(0.35);
|
|
121
|
+
this.platform.setTextColour({ r: 255, g: 255, b: 255, a: 255 });
|
|
122
|
+
this.platform.setTextCentre(true);
|
|
123
|
+
this.platform.beginTextCommandDisplayText('STRING');
|
|
124
|
+
this.platform.addTextComponentString(`${label} (${Math.floor(progress)}%)`);
|
|
125
|
+
this.platform.endTextCommandDisplayText(0.5, y - 0.03);
|
|
126
|
+
}
|
|
127
|
+
cleanup(completed) {
|
|
128
|
+
const ped = this.localPlayer.getHandle();
|
|
129
|
+
if (this.state?.options.animation) {
|
|
130
|
+
this.platform.stopAnimTask(ped, this.state.options.animation.dict, this.state.options.animation.anim, 1.0);
|
|
131
|
+
}
|
|
132
|
+
if (this.propHandle) {
|
|
133
|
+
this.platform.deleteEntity(this.propHandle);
|
|
134
|
+
this.propHandle = null;
|
|
135
|
+
}
|
|
136
|
+
if (this.tickHandle !== null) {
|
|
137
|
+
this.runtime.clearTick(this.tickHandle);
|
|
138
|
+
this.tickHandle = null;
|
|
139
|
+
}
|
|
140
|
+
if (this.state?.options.useCircular)
|
|
141
|
+
this.platform.busyspinnerOff();
|
|
142
|
+
this.state = null;
|
|
143
|
+
this.callback?.(completed);
|
|
144
|
+
this.callback = null;
|
|
145
|
+
}
|
|
146
|
+
async loadAnimDict(dict) {
|
|
147
|
+
this.platform.requestAnimDict(dict);
|
|
148
|
+
while (!this.platform.hasAnimDictLoaded(dict)) {
|
|
149
|
+
await new Promise((r) => setTimeout(r, 0));
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
async loadModel(model) {
|
|
153
|
+
const hash = this.platform.getHashKey(model);
|
|
154
|
+
this.platform.requestModel(hash);
|
|
155
|
+
while (!this.platform.hasModelLoaded(hash)) {
|
|
156
|
+
await new Promise((r) => setTimeout(r, 0));
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
exports.RageMPClientProgressPort = RageMPClientProgressPort;
|
|
161
|
+
exports.RageMPClientProgressPort = RageMPClientProgressPort = __decorate([
|
|
162
|
+
(0, tsyringe_1.injectable)(),
|
|
163
|
+
__param(0, (0, tsyringe_1.inject)(client_1.IClientPlatformBridge)),
|
|
164
|
+
__param(1, (0, tsyringe_1.inject)(client_1.IClientRuntimeBridge)),
|
|
165
|
+
__param(2, (0, tsyringe_1.inject)(client_1.IClientLocalPlayerBridge)),
|
|
166
|
+
__metadata("design:paramtypes", [client_1.IClientPlatformBridge,
|
|
167
|
+
client_1.IClientRuntimeBridge,
|
|
168
|
+
client_1.IClientLocalPlayerBridge])
|
|
169
|
+
], RageMPClientProgressPort);
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { IClientRuntimeBridge } from '@open-core/framework/contracts/client';
|
|
2
2
|
type CommandHandler = (...args: readonly unknown[]) => void;
|
|
3
|
-
type RuntimeHandler = (...args: readonly unknown[]) => void | Promise<void>;
|
|
4
|
-
type RuntimeExport = (...args: readonly unknown[]) => unknown;
|
|
5
3
|
/**
|
|
6
4
|
* RAGE Multiplayer implementation of the client runtime bridge.
|
|
7
5
|
*
|
|
@@ -15,7 +13,7 @@ export declare class RageMPRuntimeBridge extends IClientRuntimeBridge {
|
|
|
15
13
|
private tickSeq;
|
|
16
14
|
private executeRegisteredCommand;
|
|
17
15
|
getCurrentResourceName(): string;
|
|
18
|
-
on(eventName: string, handler:
|
|
16
|
+
on<TArgs extends readonly unknown[]>(eventName: string, handler: (...args: TArgs) => void | Promise<void>): void;
|
|
19
17
|
registerCommand(commandName: string, handler: CommandHandler, _restricted: boolean): void;
|
|
20
18
|
registerKeyMapping(commandName: string, _description: string, inputMapper: string, key: string): void;
|
|
21
19
|
setTick(handler: () => void | Promise<void>): unknown;
|
|
@@ -25,6 +23,6 @@ export declare class RageMPRuntimeBridge extends IClientRuntimeBridge {
|
|
|
25
23
|
sendNuiMessage(_message: string): void;
|
|
26
24
|
setNuiFocus(_hasFocus: boolean, _hasCursor: boolean): void;
|
|
27
25
|
setNuiFocusKeepInput(_keepInput: boolean): void;
|
|
28
|
-
registerExport(exportName: string, handler:
|
|
26
|
+
registerExport<TArgs extends readonly unknown[], TResult = unknown>(exportName: string, handler: (...args: TArgs) => TResult): void;
|
|
29
27
|
}
|
|
30
28
|
export {};
|
|
@@ -32,6 +32,9 @@ let RageMPRuntimeBridge = class RageMPRuntimeBridge extends client_1.IClientRunt
|
|
|
32
32
|
handler(...args);
|
|
33
33
|
}
|
|
34
34
|
getCurrentResourceName() {
|
|
35
|
+
if (typeof __OPENCORE_RESOURCE_NAME__ === 'string' && __OPENCORE_RESOURCE_NAME__.trim()) {
|
|
36
|
+
return __OPENCORE_RESOURCE_NAME__;
|
|
37
|
+
}
|
|
35
38
|
// RageMP does not provide an equivalent to FiveM's GetCurrentResourceName().
|
|
36
39
|
// Client scripts are executed from the compiled bundle inside the resource
|
|
37
40
|
// folder (usually under `client_packages/<resourceName>/...`).
|