rock-mod 0.21.0 → 0.22.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.
- package/dist/client/entities/ccmp/blip/CCMPBlip.d.ts +38 -0
- package/dist/client/entities/ccmp/blip/CCMPBlip.js +118 -0
- package/dist/client/entities/ccmp/blip/CCMPBlipsManager.d.ts +27 -0
- package/dist/client/entities/ccmp/blip/CCMPBlipsManager.js +191 -0
- package/dist/client/entities/ccmp/camera/CCMPCamera.d.ts +1 -1
- package/dist/client/entities/ccmp/camera/CCMPCamera.js +1 -1
- package/dist/client/entities/ccmp/camera/CCMPCameraManager.js +2 -1
- package/dist/client/entities/ccmp/colshape/CCMPColshape.d.ts +26 -0
- package/dist/client/entities/ccmp/colshape/CCMPColshape.js +83 -0
- package/dist/client/entities/ccmp/colshape/CCMPColshapesManager.d.ts +31 -0
- package/dist/client/entities/ccmp/colshape/CCMPColshapesManager.js +193 -0
- package/dist/client/entities/ccmp/marker/CCMPMarker.d.ts +34 -0
- package/dist/client/entities/ccmp/marker/CCMPMarker.js +109 -0
- package/dist/client/entities/ccmp/marker/CCMPMarkersManager.d.ts +27 -0
- package/dist/client/entities/ccmp/marker/CCMPMarkersManager.js +180 -0
- package/dist/client/entities/ccmp/object/CCMPObject.d.ts +53 -0
- package/dist/client/entities/ccmp/object/CCMPObject.js +218 -0
- package/dist/client/entities/ccmp/object/CCMPObjectsManager.d.ts +27 -0
- package/dist/client/entities/ccmp/object/CCMPObjectsManager.js +177 -0
- package/dist/client/entities/ccmp/ped/CCMPPed.d.ts +1 -1
- package/dist/client/entities/ccmp/ped/CCMPPed.js +21 -7
- package/dist/client/entities/ccmp/ped/CCMPPedsManager.d.ts +7 -0
- package/dist/client/entities/ccmp/ped/CCMPPedsManager.js +82 -10
- package/dist/client/entities/ccmp/player/CCMPPlayer.d.ts +1 -1
- package/dist/client/entities/ccmp/player/CCMPPlayer.js +10 -4
- package/dist/client/entities/ccmp/player/CCMPPlayersManager.d.ts +4 -3
- package/dist/client/entities/ccmp/player/CCMPPlayersManager.js +20 -7
- package/dist/client/entities/ccmp/vehicle/CCMPVehicle.d.ts +119 -0
- package/dist/client/entities/ccmp/vehicle/CCMPVehicle.js +392 -0
- package/dist/client/entities/ccmp/vehicle/CCMPVehiclesManager.d.ts +11 -48
- package/dist/client/entities/ccmp/vehicle/CCMPVehiclesManager.js +152 -74
- package/dist/client/entities/common/baseObject/IBaseObject.d.ts +2 -1
- package/dist/client/entities/ragemp/entity/RageEntity.d.ts +4 -0
- package/dist/client/entities/ragemp/entity/RageEntity.js +34 -2
- package/dist/client/factories/ccmp/CCMPManagersFactory.d.ts +9 -7
- package/dist/client/factories/ccmp/CCMPManagersFactory.js +62 -22
- package/dist/client/game/ccmp/storage/CCMPStorageManager.d.ts +0 -18
- package/dist/client/game/ccmp/storage/CCMPStorageManager.js +4 -36
- package/dist/client/net/ccmp/CCMPNetManager.js +1 -1
- package/dist/client/net/ccmp/dataHandler/CCMPDataHandler.d.ts +2 -2
- package/dist/client/net/ccmp/dataHandler/CCMPDataHandler.js +2 -2
- package/dist/client/net/ccmp/events/CCMPSyncedMetaBridge.d.ts +21 -16
- package/dist/client/net/ccmp/events/CCMPSyncedMetaBridge.js +32 -22
- package/dist/client/net/common/dataHandler/IDataHandler.d.ts +2 -2
- package/dist/client/net/common/events/types.d.ts +4 -4
- package/dist/client/net/ragemp/dataHandler/RageDataHandler.d.ts +2 -2
- package/dist/server/entities/ccmp/baseObject/CCMPBaseObjectsManager.js +4 -4
- package/dist/server/entities/ccmp/blip/CCMPBlip.d.ts +2 -0
- package/dist/server/entities/ccmp/blip/CCMPBlip.js +6 -0
- package/dist/server/entities/ccmp/colshape/CCMPColshape.d.ts +2 -0
- package/dist/server/entities/ccmp/colshape/CCMPColshape.js +6 -0
- package/dist/server/entities/ccmp/marker/CCMPMarker.d.ts +2 -0
- package/dist/server/entities/ccmp/marker/CCMPMarker.js +6 -0
- package/dist/server/entities/ccmp/object/CCMPObject.d.ts +1 -1
- package/dist/server/entities/ccmp/object/CCMPObject.js +3 -5
- package/dist/server/entities/ccmp/object/CCMPObjectsManager.js +1 -2
- package/dist/server/entities/ccmp/vehicle/CCMPVehicle.d.ts +2 -2
- package/dist/server/entities/ccmp/vehicle/CCMPVehicle.js +5 -5
- package/dist/server/entities/ragemp/entity/RageEntity.d.ts +5 -1
- package/dist/server/entities/ragemp/entity/RageEntity.js +17 -1
- package/dist/server/entities/ragemp/object/RageObjectsManager.js +1 -1
- package/dist/server/entities/ragemp/ped/RagePedsManager.js +1 -1
- package/dist/server/entities/ragemp/vehicle/RageVehiclesManager.js +1 -1
- package/package.json +2 -2
|
@@ -1,105 +1,183 @@
|
|
|
1
1
|
/// <reference types="@classic-mp/types/client" />
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
*
|
|
6
|
-
* ### Почему пусто
|
|
7
|
-
*
|
|
8
|
-
* RageMP даёт `mp.vehicles.toArray()`/`mp.vehicles.at(id)` — JS-side pool из
|
|
9
|
-
* stream'нутых-в-радиус транспортных средств, заполняемый рантаймом. CCMP
|
|
10
|
-
* такого пула на client-side не экспонирует:
|
|
11
|
-
* - `ccmp.natives.vehicle.createVehicle` создаёт локальный handle без id /
|
|
12
|
-
* replication / managed lifecycle.
|
|
13
|
-
* - `ccmp.vehicles.*` (server-side) спавнит реплицируемые vehicle-сущности,
|
|
14
|
-
* но клиент видит их данные через game state, а не как managed-IVehicle-
|
|
15
|
-
* инстансы в JS-pool'е.
|
|
16
|
-
*
|
|
17
|
-
* Поэтому iterator всегда пустой, `find*` возвращает null, `get*` и `deleteById` кидают.
|
|
18
|
-
*
|
|
19
|
-
* ### Hot path: `iterator.all()` на каждый render-tick
|
|
20
|
-
*
|
|
21
|
-
* Геймод-консьюмер `VehiclePartsInteractionController.syncVehicleProximity` →
|
|
22
|
-
* `VehiclePartsInteractionService.syncState` → `VehicleService.getNearbyVehicles`
|
|
23
|
-
* → `VehicleRepository.getNearby` → `VehicleRepository.getAll` → `iterator.all()`.
|
|
24
|
-
* До этой реализации `VehiclesManager` был `createNotImplementedProxy`, и каждый
|
|
25
|
-
* frame падал `CCMPVehiclesManager.iterator.all: not implemented yet`. Теперь
|
|
26
|
-
* iterator возвращает пустой итератор — interaction-сервис тихо деградирует
|
|
27
|
-
* (нет vehicles в радиусе → нет UI-хинтов / интеракций).
|
|
28
|
-
*
|
|
29
|
-
* ### `create(...)` под CCMP
|
|
30
|
-
*
|
|
31
|
-
* Не реализован осознанно: `VehicleRepository.create(...)` в геймоде ожидает
|
|
32
|
-
* `IRockModVehicle` с id/remoteId/position/etc, а CCMP-натив `createVehicle`
|
|
33
|
-
* возвращает только handle без id-mapping'а. Для корректной поддержки нужен
|
|
34
|
-
* полноценный `CCMPVehicle`-класс и интеграция с server-side `ccmp.vehicles.*`
|
|
35
|
-
* — отдельная задача. Сейчас бросаем понятную ошибку.
|
|
36
|
-
*
|
|
37
|
-
* ### `getDisplayNameFromVehicleModel`
|
|
38
|
-
*
|
|
39
|
-
* Этот метод **реализован** — натив `getDisplayNameFromVehicleModel`
|
|
40
|
-
* (`0xB215AAC32D25D019`) экспонирован в `ccmp.natives.vehicle.*` и работает
|
|
41
|
-
* без vehicle-pool'а (принимает только modelHash, возвращает GXT-ключ или
|
|
42
|
-
* "CARNOTFOUND" для unknown-моделей).
|
|
43
|
-
*
|
|
44
|
-
* TODO: когда понадобится spawning vehicles из клиента (миссии, тестовые
|
|
45
|
-
* объекты) — реализовать через `ccmp.natives.vehicle.createVehicle` + локальный
|
|
46
|
-
* id-counter + `CCMPVehicle`-обёртку. Для синхронизированных vehicles нужна
|
|
47
|
-
* server-side фабрика с `ccmp.vehicles.create` и net-events для распространения
|
|
48
|
-
* id-mapping'а.
|
|
49
|
-
*/
|
|
2
|
+
import { RockMod } from "../../../RockMod";
|
|
3
|
+
import { ClientInternalEventName } from "../../../net/common/events/types";
|
|
4
|
+
import { CCMPVehicle } from "./CCMPVehicle";
|
|
50
5
|
export class CCMPVehiclesManager {
|
|
51
6
|
constructor() {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
// `VehiclePartsInteractionController.syncVehicleProximity` → `VehicleRepository.getNearby`
|
|
55
|
-
// теперь тихо деградирует вместо падения на каждом render-tick'е.
|
|
7
|
+
this._vehicles = new Map();
|
|
8
|
+
this._vehiclesByRemoteId = new Map();
|
|
56
9
|
this._iterator = {
|
|
57
|
-
all: () =>
|
|
58
|
-
dimension: () =>
|
|
59
|
-
range2D: () =>
|
|
60
|
-
|
|
10
|
+
all: () => this._filter(() => true),
|
|
11
|
+
dimension: (value) => this._filter((vehicle) => vehicle.dimension === value),
|
|
12
|
+
range2D: (center, range) => this._filter((vehicle) => {
|
|
13
|
+
const position = vehicle.position;
|
|
14
|
+
const squaredDistance = (position.x - center.x) ** 2 + (position.y - center.y) ** 2;
|
|
15
|
+
return squaredDistance <= range * range;
|
|
16
|
+
}),
|
|
17
|
+
range3D: (center, range) => this._filter((vehicle) => vehicle.position.isInRange(center, range)),
|
|
61
18
|
};
|
|
19
|
+
this._registerLifecycleEvents();
|
|
20
|
+
this.syncWithMpPool();
|
|
62
21
|
}
|
|
63
22
|
create(options) {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
23
|
+
var _a;
|
|
24
|
+
const ccmpVehicle = (_a = this._getNativeVehiclesApi()) === null || _a === void 0 ? void 0 : _a.create(options.model, options.position, options.rotation, {
|
|
25
|
+
dimension: options.dimension,
|
|
26
|
+
engine: options.engine,
|
|
27
|
+
locked: options.locked,
|
|
28
|
+
});
|
|
29
|
+
if (!ccmpVehicle) {
|
|
30
|
+
throw new Error(`CCMPVehiclesManager.create: ccmp.vehicles.create failed for model "${options.model}"`);
|
|
31
|
+
}
|
|
32
|
+
return this._register(ccmpVehicle);
|
|
68
33
|
}
|
|
69
34
|
getDisplayNameFromVehicleModel(modelHash) {
|
|
70
35
|
return ccmp.natives.vehicle.getDisplayNameFromVehicleModel(modelHash);
|
|
71
36
|
}
|
|
72
|
-
// -- IEntitiesManager -----------------------------------------------------
|
|
73
37
|
syncWithMpPool() {
|
|
74
|
-
|
|
38
|
+
this._pruneDestroyed();
|
|
39
|
+
const ccmpVehicles = this._getNativeVehiclesApi();
|
|
40
|
+
if (!ccmpVehicles)
|
|
41
|
+
return;
|
|
42
|
+
for (const ccmpVehicle of ccmpVehicles.all) {
|
|
43
|
+
this._register(ccmpVehicle);
|
|
44
|
+
}
|
|
75
45
|
}
|
|
76
46
|
registerById(id) {
|
|
77
|
-
|
|
78
|
-
|
|
47
|
+
var _a, _b;
|
|
48
|
+
const existingVehicle = this.findByID(id);
|
|
49
|
+
if (existingVehicle)
|
|
50
|
+
return existingVehicle;
|
|
51
|
+
const ccmpVehicle = (_b = (_a = this._getNativeVehiclesApi()) === null || _a === void 0 ? void 0 : _a.getById(id)) !== null && _b !== void 0 ? _b : null;
|
|
52
|
+
if (!ccmpVehicle) {
|
|
53
|
+
throw new Error(`CCMPVehiclesManager.registerById(${id}): vehicle not found.`);
|
|
54
|
+
}
|
|
55
|
+
return this._register(ccmpVehicle);
|
|
79
56
|
}
|
|
80
57
|
unregisterById(id) {
|
|
81
|
-
|
|
82
|
-
"разрегистрировать vehicle по id невозможно.");
|
|
58
|
+
return this.deleteById(id);
|
|
83
59
|
}
|
|
84
|
-
// -- IBaseObjectsManager / IWorldObjectsManager ---------------------------
|
|
85
60
|
findByID(id) {
|
|
86
|
-
|
|
87
|
-
|
|
61
|
+
var _a, _b, _c;
|
|
62
|
+
const vehicle = (_a = this._vehicles.get(id)) !== null && _a !== void 0 ? _a : null;
|
|
63
|
+
if (vehicle && vehicle.isExists)
|
|
64
|
+
return vehicle;
|
|
65
|
+
if (vehicle)
|
|
66
|
+
this._unregister(vehicle);
|
|
67
|
+
const ccmpVehicle = (_c = (_b = this._getNativeVehiclesApi()) === null || _b === void 0 ? void 0 : _b.getById(id)) !== null && _c !== void 0 ? _c : null;
|
|
68
|
+
if (!ccmpVehicle)
|
|
69
|
+
return null;
|
|
70
|
+
return this._register(ccmpVehicle);
|
|
88
71
|
}
|
|
89
72
|
getByID(id) {
|
|
90
|
-
|
|
73
|
+
const vehicle = this.findByID(id);
|
|
74
|
+
if (!vehicle) {
|
|
75
|
+
throw new Error(`CCMPVehiclesManager.getByID(${id}): vehicle not found.`);
|
|
76
|
+
}
|
|
77
|
+
return vehicle;
|
|
91
78
|
}
|
|
92
79
|
findByRemoteID(remoteId) {
|
|
93
|
-
|
|
94
|
-
|
|
80
|
+
var _a, _b, _c;
|
|
81
|
+
const vehicle = (_a = this._vehiclesByRemoteId.get(remoteId)) !== null && _a !== void 0 ? _a : null;
|
|
82
|
+
if (vehicle && vehicle.isExists)
|
|
83
|
+
return vehicle;
|
|
84
|
+
if (vehicle)
|
|
85
|
+
this._unregister(vehicle);
|
|
86
|
+
const ccmpVehicle = (_c = (_b = this._getNativeVehiclesApi()) === null || _b === void 0 ? void 0 : _b.getByRemoteId(remoteId)) !== null && _c !== void 0 ? _c : null;
|
|
87
|
+
if (!ccmpVehicle)
|
|
88
|
+
return null;
|
|
89
|
+
return this._register(ccmpVehicle);
|
|
95
90
|
}
|
|
96
91
|
getByRemoteID(remoteId) {
|
|
97
|
-
|
|
92
|
+
const vehicle = this.findByRemoteID(remoteId);
|
|
93
|
+
if (!vehicle) {
|
|
94
|
+
throw new Error(`CCMPVehiclesManager.getByRemoteID(${remoteId}): vehicle not found.`);
|
|
95
|
+
}
|
|
96
|
+
return vehicle;
|
|
98
97
|
}
|
|
99
98
|
deleteById(id) {
|
|
100
|
-
|
|
99
|
+
const vehicle = this.getByID(id);
|
|
100
|
+
vehicle.destroy();
|
|
101
|
+
return vehicle;
|
|
101
102
|
}
|
|
102
103
|
get iterator() {
|
|
103
104
|
return this._iterator;
|
|
104
105
|
}
|
|
106
|
+
_register(ccmpVehicle) {
|
|
107
|
+
const existingVehicle = this._findRegistered(ccmpVehicle);
|
|
108
|
+
if (existingVehicle && existingVehicle.isExists)
|
|
109
|
+
return existingVehicle;
|
|
110
|
+
if (existingVehicle)
|
|
111
|
+
this._unregister(existingVehicle);
|
|
112
|
+
const vehicle = new CCMPVehicle(ccmpVehicle, (destroyedVehicle) => {
|
|
113
|
+
this._unregister(destroyedVehicle);
|
|
114
|
+
});
|
|
115
|
+
this._vehicles.set(vehicle.id, vehicle);
|
|
116
|
+
if (vehicle.remoteId !== null) {
|
|
117
|
+
this._vehiclesByRemoteId.set(vehicle.remoteId, vehicle);
|
|
118
|
+
}
|
|
119
|
+
return vehicle;
|
|
120
|
+
}
|
|
121
|
+
_unregister(vehicle) {
|
|
122
|
+
this._vehicles.delete(vehicle.id);
|
|
123
|
+
if (vehicle.remoteId !== null) {
|
|
124
|
+
this._vehiclesByRemoteId.delete(vehicle.remoteId);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
_findRegistered(ccmpVehicle) {
|
|
128
|
+
var _a, _b, _c;
|
|
129
|
+
return ((_c = (_b = (ccmpVehicle.remoteId === null ? null : ((_a = this._vehiclesByRemoteId.get(ccmpVehicle.remoteId)) !== null && _a !== void 0 ? _a : null))) !== null && _b !== void 0 ? _b : this._vehicles.get(ccmpVehicle.id)) !== null && _c !== void 0 ? _c : null);
|
|
130
|
+
}
|
|
131
|
+
_registerLifecycleEvents() {
|
|
132
|
+
const eventsApi = ccmp;
|
|
133
|
+
eventsApi.on("vehicleCreated", (ccmpVehicle) => {
|
|
134
|
+
if (!ccmpVehicle)
|
|
135
|
+
return;
|
|
136
|
+
const vehicle = this._register(ccmpVehicle);
|
|
137
|
+
RockMod.instance.net.events.emitInternal(ClientInternalEventName.EntityCreated, vehicle);
|
|
138
|
+
});
|
|
139
|
+
eventsApi.on("vehicleDestroyed", (ccmpVehicle) => {
|
|
140
|
+
var _a;
|
|
141
|
+
if (!ccmpVehicle)
|
|
142
|
+
return;
|
|
143
|
+
const vehicle = (_a = this._findRegistered(ccmpVehicle)) !== null && _a !== void 0 ? _a : this._register(ccmpVehicle);
|
|
144
|
+
RockMod.instance.net.events.emitInternal(ClientInternalEventName.EntityDestroyed, vehicle);
|
|
145
|
+
this._unregister(vehicle);
|
|
146
|
+
});
|
|
147
|
+
eventsApi.on("vehicleStreamIn", (ccmpVehicle) => {
|
|
148
|
+
if (!ccmpVehicle)
|
|
149
|
+
return;
|
|
150
|
+
const vehicle = this._register(ccmpVehicle);
|
|
151
|
+
RockMod.instance.net.events.emitInternal(ClientInternalEventName.EntityStreamIn, vehicle);
|
|
152
|
+
});
|
|
153
|
+
eventsApi.on("vehicleStreamOut", (ccmpVehicle) => {
|
|
154
|
+
var _a;
|
|
155
|
+
if (!ccmpVehicle)
|
|
156
|
+
return;
|
|
157
|
+
const vehicle = (_a = this._findRegistered(ccmpVehicle)) !== null && _a !== void 0 ? _a : this._register(ccmpVehicle);
|
|
158
|
+
RockMod.instance.net.events.emitInternal(ClientInternalEventName.EntityStreamOut, vehicle);
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
*_filter(predicate) {
|
|
162
|
+
for (const vehicle of this._vehicles.values()) {
|
|
163
|
+
if (!vehicle.isExists) {
|
|
164
|
+
this._unregister(vehicle);
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
if (predicate(vehicle)) {
|
|
168
|
+
yield vehicle;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
_pruneDestroyed() {
|
|
173
|
+
for (const vehicle of this._vehicles.values()) {
|
|
174
|
+
if (!vehicle.isExists) {
|
|
175
|
+
this._unregister(vehicle);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
_getNativeVehiclesApi() {
|
|
180
|
+
var _a;
|
|
181
|
+
return (_a = ccmp.vehicles) !== null && _a !== void 0 ? _a : null;
|
|
182
|
+
}
|
|
105
183
|
}
|
|
@@ -5,7 +5,8 @@ export interface IBaseObjectOptions {
|
|
|
5
5
|
}
|
|
6
6
|
export interface IBaseObject {
|
|
7
7
|
get id(): number;
|
|
8
|
-
|
|
8
|
+
/** Server/network id for remote objects; null for client-only objects. */
|
|
9
|
+
get remoteId(): number | null;
|
|
9
10
|
get type(): BaseObjectType;
|
|
10
11
|
get isExists(): boolean;
|
|
11
12
|
get handle(): number;
|
|
@@ -31,4 +31,8 @@ export declare abstract class RageEntity<T extends EntityMp> extends RageWorldOb
|
|
|
31
31
|
detach(useDetachVelocity: boolean, collision: boolean): void;
|
|
32
32
|
getSpeed(): number;
|
|
33
33
|
isPlayingAnim(dictionary: string, name: string, taskFlag: number): boolean;
|
|
34
|
+
private _getNativeRotation;
|
|
35
|
+
private _getEntityRotationProperty;
|
|
36
|
+
private _hasValidHandle;
|
|
37
|
+
private _isVectorLike;
|
|
34
38
|
}
|
|
@@ -5,8 +5,8 @@ export class RageEntity extends RageWorldObject {
|
|
|
5
5
|
return this.mpEntity.model;
|
|
6
6
|
}
|
|
7
7
|
get rotation() {
|
|
8
|
-
|
|
9
|
-
return new Vector3D(
|
|
8
|
+
var _a, _b;
|
|
9
|
+
return (_b = (_a = this._getNativeRotation()) !== null && _a !== void 0 ? _a : this._getEntityRotationProperty()) !== null && _b !== void 0 ? _b : new Vector3D(0, 0, this.heading);
|
|
10
10
|
}
|
|
11
11
|
constructor(options) {
|
|
12
12
|
super(options);
|
|
@@ -22,6 +22,9 @@ export class RageEntity extends RageWorldObject {
|
|
|
22
22
|
}
|
|
23
23
|
setRotation(value) {
|
|
24
24
|
this.mpEntity.rotation = new mp.Vector3(value);
|
|
25
|
+
if (this._hasValidHandle()) {
|
|
26
|
+
mp.game.entity.setRotation(this.handle, value.x, value.y, value.z, 2, true);
|
|
27
|
+
}
|
|
25
28
|
}
|
|
26
29
|
get forwardVector() {
|
|
27
30
|
const vector = this.mpEntity.getForwardVector();
|
|
@@ -88,4 +91,33 @@ export class RageEntity extends RageWorldObject {
|
|
|
88
91
|
isPlayingAnim(dictionary, name, taskFlag) {
|
|
89
92
|
return mp.game.entity.isPlayingAnim(this.handle, dictionary, name, taskFlag);
|
|
90
93
|
}
|
|
94
|
+
_getNativeRotation() {
|
|
95
|
+
if (!this._hasValidHandle())
|
|
96
|
+
return null;
|
|
97
|
+
try {
|
|
98
|
+
const rotation = mp.game.entity.getRotation(this.handle, 2);
|
|
99
|
+
if (!this._isVectorLike(rotation))
|
|
100
|
+
return null;
|
|
101
|
+
return new Vector3D(rotation.x, rotation.y, rotation.z);
|
|
102
|
+
}
|
|
103
|
+
catch (_a) {
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
_getEntityRotationProperty() {
|
|
108
|
+
const rotation = this.mpEntity.rotation;
|
|
109
|
+
if (!this._isVectorLike(rotation))
|
|
110
|
+
return null;
|
|
111
|
+
return new Vector3D(rotation.x, rotation.y, rotation.z);
|
|
112
|
+
}
|
|
113
|
+
_hasValidHandle() {
|
|
114
|
+
return typeof this.handle === "number" && this.handle > 0;
|
|
115
|
+
}
|
|
116
|
+
_isVectorLike(value) {
|
|
117
|
+
return (typeof value === "object" &&
|
|
118
|
+
value !== null &&
|
|
119
|
+
typeof value.x === "number" &&
|
|
120
|
+
typeof value.y === "number" &&
|
|
121
|
+
typeof value.z === "number");
|
|
122
|
+
}
|
|
91
123
|
}
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import { type IManagersFactory } from "../common/IManagersFactory";
|
|
2
2
|
type ManagerReturn<K extends keyof IManagersFactory> = IManagersFactory[K] extends (...args: never[]) => infer R ? R : never;
|
|
3
3
|
export declare class CCMPManagersFactory implements IManagersFactory {
|
|
4
|
-
/**
|
|
5
|
-
* Сохраняем созданный `CCMPNetManager` потому что другим менеджерам
|
|
6
|
-
* (например, `CCMPPlayersManager`) нужен доступ к его событиям. Порядок
|
|
7
|
-
* создания в `RockMod` гарантирует, что `createNetManager` вызывается
|
|
8
|
-
* первым — мы можем безопасно полагаться на наличие `_netManager` в
|
|
9
|
-
* последующих фабричных методах.
|
|
10
|
-
*/
|
|
11
4
|
private _netManager;
|
|
5
|
+
private _blipsManager;
|
|
6
|
+
private _colshapesManager;
|
|
7
|
+
private _markersManager;
|
|
8
|
+
private _objectsManager;
|
|
9
|
+
private _pedsManager;
|
|
10
|
+
private _playersManager;
|
|
11
|
+
private _vehiclesManager;
|
|
12
|
+
private _syncedMetaBridgeRegistered;
|
|
12
13
|
createNetManager(): ManagerReturn<"createNetManager">;
|
|
13
14
|
private _requireNetManager;
|
|
15
|
+
private _registerSyncedMetaBridgeIfReady;
|
|
14
16
|
createBlipsManager(): ManagerReturn<"createBlipsManager">;
|
|
15
17
|
createColshapesManager(): ManagerReturn<"createColshapesManager">;
|
|
16
18
|
createMarkersManager(): ManagerReturn<"createMarkersManager">;
|
|
@@ -8,6 +8,10 @@ import { CCMPControlsManager } from "../../game/ccmp/controls/CCMPControlsManage
|
|
|
8
8
|
import { CCMPPlayersManager } from "../../entities/ccmp/player/CCMPPlayersManager";
|
|
9
9
|
import { CCMPPedsManager } from "../../entities/ccmp/ped/CCMPPedsManager";
|
|
10
10
|
import { CCMPVehiclesManager } from "../../entities/ccmp/vehicle/CCMPVehiclesManager";
|
|
11
|
+
import { CCMPObjectsManager } from "../../entities/ccmp/object/CCMPObjectsManager";
|
|
12
|
+
import { CCMPMarkersManager } from "../../entities/ccmp/marker/CCMPMarkersManager";
|
|
13
|
+
import { CCMPBlipsManager } from "../../entities/ccmp/blip/CCMPBlipsManager";
|
|
14
|
+
import { CCMPColshapesManager } from "../../entities/ccmp/colshape/CCMPColshapesManager";
|
|
11
15
|
import { CCMPUtilsManager } from "../../utils/ccmp/CCMPUtilsManager";
|
|
12
16
|
import { CCMPGraphicsManager } from "../../game/ccmp/graphics/CCMPGraphicsManager";
|
|
13
17
|
import { CCMPUiManager } from "../../game/ccmp/ui/CCMPUiManager";
|
|
@@ -25,14 +29,15 @@ import { CCMPGameplayManager } from "../../game/ccmp/gameplay/CCMPGameplayManage
|
|
|
25
29
|
import { createNotImplementedProxy } from "./createNotImplementedProxy";
|
|
26
30
|
export class CCMPManagersFactory {
|
|
27
31
|
constructor() {
|
|
28
|
-
/**
|
|
29
|
-
* Сохраняем созданный `CCMPNetManager` потому что другим менеджерам
|
|
30
|
-
* (например, `CCMPPlayersManager`) нужен доступ к его событиям. Порядок
|
|
31
|
-
* создания в `RockMod` гарантирует, что `createNetManager` вызывается
|
|
32
|
-
* первым — мы можем безопасно полагаться на наличие `_netManager` в
|
|
33
|
-
* последующих фабричных методах.
|
|
34
|
-
*/
|
|
35
32
|
this._netManager = null;
|
|
33
|
+
this._blipsManager = null;
|
|
34
|
+
this._colshapesManager = null;
|
|
35
|
+
this._markersManager = null;
|
|
36
|
+
this._objectsManager = null;
|
|
37
|
+
this._pedsManager = null;
|
|
38
|
+
this._playersManager = null;
|
|
39
|
+
this._vehiclesManager = null;
|
|
40
|
+
this._syncedMetaBridgeRegistered = false;
|
|
36
41
|
}
|
|
37
42
|
createNetManager() {
|
|
38
43
|
this._netManager = new CCMPNetManager();
|
|
@@ -41,41 +46,76 @@ export class CCMPManagersFactory {
|
|
|
41
46
|
_requireNetManager(forMethod) {
|
|
42
47
|
if (!this._netManager) {
|
|
43
48
|
throw new Error(`CCMPManagersFactory.${forMethod}: ` +
|
|
44
|
-
"createNetManager()
|
|
45
|
-
"фабричных методов в RockMod-конструкторе.");
|
|
49
|
+
"createNetManager() was not called yet. This violates RockMod manager factory order.");
|
|
46
50
|
}
|
|
47
51
|
return this._netManager;
|
|
48
52
|
}
|
|
53
|
+
_registerSyncedMetaBridgeIfReady() {
|
|
54
|
+
if (this._syncedMetaBridgeRegistered ||
|
|
55
|
+
!this._netManager ||
|
|
56
|
+
!this._blipsManager ||
|
|
57
|
+
!this._colshapesManager ||
|
|
58
|
+
!this._markersManager ||
|
|
59
|
+
!this._objectsManager ||
|
|
60
|
+
!this._pedsManager ||
|
|
61
|
+
!this._playersManager ||
|
|
62
|
+
!this._vehiclesManager) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
new CCMPSyncedMetaBridge(this._netManager.events, {
|
|
66
|
+
blips: this._blipsManager,
|
|
67
|
+
colshapes: this._colshapesManager,
|
|
68
|
+
markers: this._markersManager,
|
|
69
|
+
objects: this._objectsManager,
|
|
70
|
+
peds: this._pedsManager,
|
|
71
|
+
players: this._playersManager,
|
|
72
|
+
vehicles: this._vehiclesManager,
|
|
73
|
+
}).register();
|
|
74
|
+
this._syncedMetaBridgeRegistered = true;
|
|
75
|
+
}
|
|
49
76
|
createBlipsManager() {
|
|
50
|
-
|
|
77
|
+
const netManager = this._requireNetManager("createBlipsManager");
|
|
78
|
+
this._blipsManager = new CCMPBlipsManager(netManager.events);
|
|
79
|
+
this._registerSyncedMetaBridgeIfReady();
|
|
80
|
+
return this._blipsManager;
|
|
51
81
|
}
|
|
52
82
|
createColshapesManager() {
|
|
53
|
-
|
|
83
|
+
const netManager = this._requireNetManager("createColshapesManager");
|
|
84
|
+
this._colshapesManager = new CCMPColshapesManager(netManager.events);
|
|
85
|
+
this._registerSyncedMetaBridgeIfReady();
|
|
86
|
+
return this._colshapesManager;
|
|
54
87
|
}
|
|
55
88
|
createMarkersManager() {
|
|
56
|
-
|
|
89
|
+
const netManager = this._requireNetManager("createMarkersManager");
|
|
90
|
+
this._markersManager = new CCMPMarkersManager(netManager.events);
|
|
91
|
+
this._registerSyncedMetaBridgeIfReady();
|
|
92
|
+
return this._markersManager;
|
|
57
93
|
}
|
|
58
94
|
createObjectsManager() {
|
|
59
|
-
|
|
95
|
+
const netManager = this._requireNetManager("createObjectsManager");
|
|
96
|
+
this._objectsManager = new CCMPObjectsManager(netManager.events);
|
|
97
|
+
this._registerSyncedMetaBridgeIfReady();
|
|
98
|
+
return this._objectsManager;
|
|
60
99
|
}
|
|
61
100
|
createPedsManager() {
|
|
62
|
-
|
|
101
|
+
const netManager = this._requireNetManager("createPedsManager");
|
|
102
|
+
this._pedsManager = new CCMPPedsManager(netManager.events);
|
|
103
|
+
this._registerSyncedMetaBridgeIfReady();
|
|
104
|
+
return this._pedsManager;
|
|
63
105
|
}
|
|
64
106
|
createPlayersManager() {
|
|
65
107
|
const netManager = this._requireNetManager("createPlayersManager");
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
// — для эмиссии `rm::syncedMetaChange` (на который уже подписан
|
|
70
|
-
// `CCMPDataHandler`, инстанцированный в `CCMPNetManager`).
|
|
71
|
-
new CCMPSyncedMetaBridge(netManager.events, playersManager).register();
|
|
72
|
-
return playersManager;
|
|
108
|
+
this._playersManager = new CCMPPlayersManager(netManager.events);
|
|
109
|
+
this._registerSyncedMetaBridgeIfReady();
|
|
110
|
+
return this._playersManager;
|
|
73
111
|
}
|
|
74
112
|
createUtilsManager() {
|
|
75
113
|
return new CCMPUtilsManager();
|
|
76
114
|
}
|
|
77
115
|
createVehiclesManager() {
|
|
78
|
-
|
|
116
|
+
this._vehiclesManager = new CCMPVehiclesManager();
|
|
117
|
+
this._registerSyncedMetaBridgeIfReady();
|
|
118
|
+
return this._vehiclesManager;
|
|
79
119
|
}
|
|
80
120
|
createBrowserManager() {
|
|
81
121
|
return new CCMPBrowserManager();
|
|
@@ -1,23 +1,5 @@
|
|
|
1
1
|
import { type IStorageManager } from "../../common/storage/IStorageManager";
|
|
2
|
-
/**
|
|
3
|
-
* In-memory реализация `IStorageManager` под CCMP.
|
|
4
|
-
*
|
|
5
|
-
* RageMP даёт `mp.storage.data` — персистентное JSON-K/V на диске между
|
|
6
|
-
* сессиями. У CCMP нативного аналога client-side storage пока нет. Этот
|
|
7
|
-
* MVP — обычный `Map` в памяти процесса:
|
|
8
|
-
* - Данные доступны в рамках одной сессии.
|
|
9
|
-
* - Не переживают переподключение/перезапуск игры.
|
|
10
|
-
*
|
|
11
|
-
* Этого достаточно для `CacheController` геймода: пустой кэш заставит
|
|
12
|
-
* перезапросить данные с сервера, чуть менее эффективно но функционально.
|
|
13
|
-
*
|
|
14
|
-
* Долгосрочно: добавить persistent storage в CCMP-клиент (Rust) — файл в
|
|
15
|
-
* `%APPDATA%/ccmp/storage/<server>.json` через `Deno.core.ops`, тогда
|
|
16
|
-
* заменить этот класс на адаптер к ops.
|
|
17
|
-
*/
|
|
18
2
|
export declare class CCMPStorageManager implements IStorageManager {
|
|
19
|
-
private readonly _data;
|
|
20
|
-
constructor();
|
|
21
3
|
getData<T>(key: string): T | null;
|
|
22
4
|
setData<T>(key: string, value: T): void;
|
|
23
5
|
removeData(key: string): void;
|
|
@@ -1,46 +1,14 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* In-memory реализация `IStorageManager` под CCMP.
|
|
3
|
-
*
|
|
4
|
-
* RageMP даёт `mp.storage.data` — персистентное JSON-K/V на диске между
|
|
5
|
-
* сессиями. У CCMP нативного аналога client-side storage пока нет. Этот
|
|
6
|
-
* MVP — обычный `Map` в памяти процесса:
|
|
7
|
-
* - Данные доступны в рамках одной сессии.
|
|
8
|
-
* - Не переживают переподключение/перезапуск игры.
|
|
9
|
-
*
|
|
10
|
-
* Этого достаточно для `CacheController` геймода: пустой кэш заставит
|
|
11
|
-
* перезапросить данные с сервера, чуть менее эффективно но функционально.
|
|
12
|
-
*
|
|
13
|
-
* Долгосрочно: добавить persistent storage в CCMP-клиент (Rust) — файл в
|
|
14
|
-
* `%APPDATA%/ccmp/storage/<server>.json` через `Deno.core.ops`, тогда
|
|
15
|
-
* заменить этот класс на адаптер к ops.
|
|
16
|
-
*/
|
|
17
1
|
export class CCMPStorageManager {
|
|
18
|
-
constructor() {
|
|
19
|
-
this._data = new Map();
|
|
20
|
-
console.warn("[rock-mod] CCMPStorageManager uses in-memory storage; data will not persist between sessions");
|
|
21
|
-
}
|
|
22
2
|
getData(key) {
|
|
23
|
-
|
|
24
|
-
if (!this._data.has(key)) {
|
|
25
|
-
return null;
|
|
26
|
-
}
|
|
27
|
-
return (_a = this._data.get(key)) !== null && _a !== void 0 ? _a : null;
|
|
3
|
+
return ccmp.storage.getItem(key);
|
|
28
4
|
}
|
|
29
5
|
setData(key, value) {
|
|
30
|
-
|
|
6
|
+
ccmp.storage.setItem(key, value);
|
|
31
7
|
}
|
|
32
8
|
removeData(key) {
|
|
33
|
-
|
|
9
|
+
ccmp.storage.removeItem(key);
|
|
34
10
|
}
|
|
35
11
|
clearData(prefix) {
|
|
36
|
-
|
|
37
|
-
this._data.clear();
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
for (const key of [...this._data.keys()]) {
|
|
41
|
-
if (key.startsWith(prefix)) {
|
|
42
|
-
this._data.delete(key);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
12
|
+
ccmp.storage.clear(prefix);
|
|
45
13
|
}
|
|
46
14
|
}
|
|
@@ -44,7 +44,7 @@ export class CCMPNetManager {
|
|
|
44
44
|
this._rpcManager = new CCMPRPCManager();
|
|
45
45
|
// DataHandler сначала, чтобы он успел подписаться на internal-bus до
|
|
46
46
|
// первых эмиссий `rm::syncedMetaChange` от `CCMPSyncedMetaBridge`
|
|
47
|
-
// (
|
|
47
|
+
// (registers later, when all stream-synced base-object managers are ready).
|
|
48
48
|
this._dataHandler = new CCMPDataHandler(this._eventsManager);
|
|
49
49
|
this._bridge = new CCMPEventsBridge(this._eventsManager);
|
|
50
50
|
this._renderTicker = new CCMPRenderTicker();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type IBaseObject } from "../../../entities";
|
|
2
2
|
import { type IDataHandler } from "../../common/dataHandler/IDataHandler";
|
|
3
3
|
import { type CCMPEventsManager } from "../events/CCMPEventsManager";
|
|
4
|
-
type DataHandlerCallback = (
|
|
4
|
+
type DataHandlerCallback = (object: IBaseObject, value: unknown, oldValue?: unknown) => void;
|
|
5
5
|
/**
|
|
6
6
|
* Реализация `IDataHandler` под CCMP поверх `rm::syncedMetaChange`.
|
|
7
7
|
*
|
|
@@ -16,14 +16,14 @@ export class CCMPDataHandler {
|
|
|
16
16
|
constructor(events) {
|
|
17
17
|
this._handlers = new Map();
|
|
18
18
|
events.onInternal({
|
|
19
|
-
[ClientInternalEventName.SyncedMetaChange]: (
|
|
19
|
+
[ClientInternalEventName.SyncedMetaChange]: (object, key, value, oldValue) => {
|
|
20
20
|
const callbacks = this._handlers.get(key);
|
|
21
21
|
if (!callbacks || callbacks.length === 0) {
|
|
22
22
|
return;
|
|
23
23
|
}
|
|
24
24
|
for (const callback of [...callbacks]) {
|
|
25
25
|
try {
|
|
26
|
-
callback(
|
|
26
|
+
callback(object, value, oldValue);
|
|
27
27
|
}
|
|
28
28
|
catch (error) {
|
|
29
29
|
console.error(`[CCMPDataHandler] callback for key "${key}" failed:`, error);
|
|
@@ -1,24 +1,29 @@
|
|
|
1
|
+
import { type CCMPBlipsManager } from "../../../entities/ccmp/blip/CCMPBlipsManager";
|
|
2
|
+
import { type CCMPColshapesManager } from "../../../entities/ccmp/colshape/CCMPColshapesManager";
|
|
3
|
+
import { type CCMPMarkersManager } from "../../../entities/ccmp/marker/CCMPMarkersManager";
|
|
4
|
+
import { type CCMPObjectsManager } from "../../../entities/ccmp/object/CCMPObjectsManager";
|
|
5
|
+
import { type CCMPPedsManager } from "../../../entities/ccmp/ped/CCMPPedsManager";
|
|
1
6
|
import { type CCMPPlayersManager } from "../../../entities/ccmp/player/CCMPPlayersManager";
|
|
7
|
+
import { type CCMPVehiclesManager } from "../../../entities/ccmp/vehicle/CCMPVehiclesManager";
|
|
2
8
|
import { type CCMPEventsManager } from "./CCMPEventsManager";
|
|
9
|
+
export interface ICCMPSyncedMetaBridgeManagers {
|
|
10
|
+
blips: CCMPBlipsManager;
|
|
11
|
+
colshapes: CCMPColshapesManager;
|
|
12
|
+
markers: CCMPMarkersManager;
|
|
13
|
+
objects: CCMPObjectsManager;
|
|
14
|
+
peds: CCMPPedsManager;
|
|
15
|
+
players: CCMPPlayersManager;
|
|
16
|
+
vehicles: CCMPVehiclesManager;
|
|
17
|
+
}
|
|
3
18
|
/**
|
|
4
|
-
*
|
|
5
|
-
* `rm::syncedMetaChange
|
|
6
|
-
*
|
|
7
|
-
* Вынесено в отдельный класс от `CCMPEventsBridge` из-за порядка
|
|
8
|
-
* инстанцирования: bridge'у нужна ссылка на `CCMPPlayersManager` чтобы
|
|
9
|
-
* резолвить `payload.entityId → CCMPPlayer`, а players manager создаётся
|
|
10
|
-
* в `CCMPManagersFactory` **после** `CCMPNetManager` (внутри которого
|
|
11
|
-
* живёт `CCMPEventsBridge`). Поэтому этот bridge создаётся вторым
|
|
12
|
-
* шагом из `createPlayersManager`, когда обе зависимости уже доступны.
|
|
13
|
-
*
|
|
14
|
-
* Сейчас обслуживается только `entityType === Player` (=0) — на клиенте
|
|
15
|
-
* rock-mod-CCMP других сущностей пока нет. Остальные типы тихо
|
|
16
|
-
* игнорируем (snapshot прилетает на каждом stream-in, для несуществующих
|
|
17
|
-
* на клиенте сущностей это нормально).
|
|
19
|
+
* Translates CCMP `streamSyncedMetaChange` into Rock-Mod's internal
|
|
20
|
+
* `rm::syncedMetaChange` for stream-synced base objects.
|
|
18
21
|
*/
|
|
19
22
|
export declare class CCMPSyncedMetaBridge {
|
|
20
23
|
private readonly _events;
|
|
21
|
-
private readonly
|
|
22
|
-
|
|
24
|
+
private readonly _managers;
|
|
25
|
+
private _registered;
|
|
26
|
+
constructor(events: CCMPEventsManager, managers: ICCMPSyncedMetaBridgeManagers);
|
|
23
27
|
register(): void;
|
|
28
|
+
private _resolveObject;
|
|
24
29
|
}
|