@open-core/framework 1.0.2-beta.1 → 1.0.4-beta.1

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 (77) hide show
  1. package/README.md +2 -2
  2. package/dist/client/client-bootstrap.js +11 -14
  3. package/dist/client/client-core.d.ts +0 -17
  4. package/dist/client/client-core.js +0 -45
  5. package/dist/client/controllers/spawner.controller.d.ts +12 -0
  6. package/dist/client/controllers/spawner.controller.js +51 -0
  7. package/dist/client/index.d.ts +1 -0
  8. package/dist/client/index.js +1 -0
  9. package/dist/client/interfaces/appearance.interface.d.ts +19 -0
  10. package/dist/client/interfaces/appearance.interface.js +2 -0
  11. package/dist/client/services/appearance.service.d.ts +6 -0
  12. package/dist/client/services/appearance.service.js +89 -0
  13. package/dist/client/services/{world/blip.service.d.ts → blip.service.d.ts} +1 -1
  14. package/dist/client/services/index.d.ts +9 -4
  15. package/dist/client/services/index.js +9 -8
  16. package/dist/client/services/{world/marker.service.d.ts → marker.service.d.ts} +1 -1
  17. package/dist/client/services/{world/ped.service.d.ts → ped.service.d.ts} +1 -1
  18. package/dist/client/services/spawn.service.d.ts +73 -0
  19. package/dist/client/services/spawn.service.js +261 -0
  20. package/dist/client/services/{ui/textui.service.d.ts → textui.service.d.ts} +1 -1
  21. package/dist/client/services/{world/vehicle.service.d.ts → vehicle.service.d.ts} +1 -1
  22. package/dist/client/system/processors/export.processor.js +1 -1
  23. package/dist/index.d.ts +0 -2
  24. package/dist/index.js +1 -6
  25. package/dist/server/controllers/session.controller.d.ts +9 -0
  26. package/dist/server/controllers/session.controller.js +70 -0
  27. package/dist/server/database/adapters/oxmysql.adapter.js +1 -1
  28. package/dist/server/decorators/index.d.ts +1 -1
  29. package/dist/server/decorators/index.js +1 -1
  30. package/dist/server/decorators/onFiveMEvent.d.ts +6 -0
  31. package/dist/server/decorators/onFiveMEvent.js +14 -0
  32. package/dist/server/decorators/{coreEvent.d.ts → onFrameworkEvent.d.ts} +2 -2
  33. package/dist/server/decorators/{coreEvent.js → onFrameworkEvent.js} +3 -3
  34. package/dist/server/entities/player.js +1 -1
  35. package/dist/server/helpers/resolve-method.d.ts +5 -0
  36. package/dist/server/helpers/resolve-method.js +18 -0
  37. package/dist/server/index.js +2 -0
  38. package/dist/server/loaders/playerSession.loader.js +13 -4
  39. package/dist/server/system/metadata-server.keys.d.ts +1 -0
  40. package/dist/server/system/metadata-server.keys.js +1 -0
  41. package/dist/server/system/processors/coreEvent.processor.d.ts +1 -1
  42. package/dist/server/system/processors/coreEvent.processor.js +6 -3
  43. package/dist/server/system/processors/export.processor.d.ts +1 -1
  44. package/dist/server/system/processors/export.processor.js +7 -3
  45. package/dist/server/system/processors/fivemEvent.processor.d.ts +7 -0
  46. package/dist/server/system/processors/fivemEvent.processor.js +40 -0
  47. package/dist/server/system/processors/netEvent.processor.d.ts +1 -1
  48. package/dist/server/system/processors/netEvent.processor.js +7 -5
  49. package/dist/server/system/processors.register.js +2 -0
  50. package/dist/server/system/schema-generator.js +12 -6
  51. package/dist/server/templates/admin/admin.controller-template.d.ts +1 -1
  52. package/dist/server/templates/auth/auth-provider.contract.d.ts +2 -2
  53. package/dist/server/types/core-events.d.ts +5 -0
  54. package/package.json +11 -1
  55. package/dist/client/loaders/exports.loader.d.ts +0 -1
  56. package/dist/client/loaders/exports.loader.js +0 -13
  57. package/dist/client/services/core/index.d.ts +0 -1
  58. package/dist/client/services/core/index.js +0 -17
  59. package/dist/client/services/core/spawn.service.d.ts +0 -20
  60. package/dist/client/services/core/spawn.service.js +0 -143
  61. package/dist/client/services/streaming/index.d.ts +0 -1
  62. package/dist/client/services/streaming/index.js +0 -17
  63. package/dist/client/services/ui/index.d.ts +0 -3
  64. package/dist/client/services/ui/index.js +0 -19
  65. package/dist/client/services/world/index.d.ts +0 -4
  66. package/dist/client/services/world/index.js +0 -20
  67. /package/dist/client/services/{world/blip.service.js → blip.service.js} +0 -0
  68. /package/dist/client/services/{world/marker.service.js → marker.service.js} +0 -0
  69. /package/dist/client/services/{ui/notification.service.d.ts → notification.service.d.ts} +0 -0
  70. /package/dist/client/services/{ui/notification.service.js → notification.service.js} +0 -0
  71. /package/dist/client/services/{world/ped.service.js → ped.service.js} +0 -0
  72. /package/dist/client/services/{ui/progress.service.d.ts → progress.service.d.ts} +0 -0
  73. /package/dist/client/services/{ui/progress.service.js → progress.service.js} +0 -0
  74. /package/dist/client/services/{streaming/streaming.service.d.ts → streaming.service.d.ts} +0 -0
  75. /package/dist/client/services/{streaming/streaming.service.js → streaming.service.js} +0 -0
  76. /package/dist/client/services/{ui/textui.service.js → textui.service.js} +0 -0
  77. /package/dist/client/services/{world/vehicle.service.js → vehicle.service.js} +0 -0
@@ -0,0 +1,261 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.SpawnService = void 0;
13
+ const tsyringe_1 = require("tsyringe");
14
+ const shared_1 = require("../../shared");
15
+ const appearance_service_1 = require("./appearance.service");
16
+ const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
17
+ const NETWORK_TIMEOUT_MS = 15000;
18
+ const PED_TIMEOUT_MS = 10000;
19
+ const COLLISION_TIMEOUT_MS = 7000;
20
+ /**
21
+ * Handles all player spawning logic on the client.
22
+ *
23
+ * This service manages the complete lifecycle of a player spawn:
24
+ * - Waiting for the network session
25
+ * - Loading and applying the player model
26
+ * - Ensuring collision and world data is ready
27
+ * - Resurrecting the player cleanly
28
+ * - Applying default ped components for freemode models
29
+ * - Fading the screen in/out during transitions
30
+ *
31
+ * The service is designed to be robust, predictable, and safe for any gamemode.
32
+ */
33
+ let SpawnService = class SpawnService {
34
+ constructor(appearanceService) {
35
+ this.appearanceService = appearanceService;
36
+ this.spawned = false;
37
+ this.spawning = false;
38
+ }
39
+ async init() {
40
+ shared_1.loggers.spawn.debug('SpawnService initialized');
41
+ }
42
+ /**
43
+ * Performs the first spawn of the player.
44
+ *
45
+ * This method handles:
46
+ * - Fade out
47
+ * - Closing loading screens
48
+ * - Setting the player model
49
+ * - Ensuring the ped exists
50
+ * - Ensuring collision is loaded
51
+ * - Resurrecting the player
52
+ * - Preparing the ped for gameplay
53
+ * - Placing the player at the desired position
54
+ * - Fade in
55
+ *
56
+ * It should only be called once when the player joins.
57
+ */
58
+ async spawn(position, model, heading = 0.0, options) {
59
+ if (this.spawning) {
60
+ shared_1.loggers.spawn.warn('Spawn requested while a spawn is already in progress');
61
+ return;
62
+ }
63
+ this.spawning = true;
64
+ try {
65
+ await this.ensureNetworkReady();
66
+ if (!IsScreenFadedOut() && !IsScreenFadingOut()) {
67
+ DoScreenFadeOut(500);
68
+ while (!IsScreenFadedOut()) {
69
+ await delay(0);
70
+ }
71
+ }
72
+ this.closeLoadingScreens();
73
+ await this.setPlayerModel(model);
74
+ const ped = await this.ensurePed();
75
+ await this.applyAppearanceIfNeeded(ped, options === null || options === void 0 ? void 0 : options.appearance);
76
+ await this.ensureCollisionAt(position, ped);
77
+ NetworkResurrectLocalPlayer(position.x, position.y, position.z, heading, 0, false);
78
+ const finalPed = await this.ensurePed();
79
+ await this.setupPedForGameplay(finalPed);
80
+ await this.placePed(finalPed, position, heading);
81
+ this.spawned = true;
82
+ if (!IsScreenFadedIn() && !IsScreenFadingIn()) {
83
+ DoScreenFadeIn(500);
84
+ }
85
+ shared_1.loggers.spawn.info('Player spawned successfully (first spawn)', {
86
+ position: { x: position.x, y: position.y, z: position.z },
87
+ model,
88
+ });
89
+ }
90
+ catch (err) {
91
+ shared_1.loggers.spawn.error('Failed to spawn player', {
92
+ error: err instanceof Error ? err.message : String(err),
93
+ });
94
+ throw err;
95
+ }
96
+ finally {
97
+ this.spawning = false;
98
+ }
99
+ }
100
+ /**
101
+ * Teleports the player instantly to a new position.
102
+ * Does not change the model or resurrect the player.
103
+ * Safe for gameplay use.
104
+ */
105
+ async teleportTo(position, heading) {
106
+ const ped = await this.ensurePed();
107
+ await this.ensureCollisionAt(position, ped);
108
+ FreezeEntityPosition(ped, true);
109
+ SetEntityCoordsNoOffset(ped, position.x, position.y, position.z, false, false, false);
110
+ if (heading !== undefined) {
111
+ SetEntityHeading(ped, heading);
112
+ }
113
+ FreezeEntityPosition(ped, false);
114
+ shared_1.loggers.spawn.debug('Teleported', {
115
+ position: { x: position.x, y: position.y, z: position.z },
116
+ heading,
117
+ });
118
+ }
119
+ /**
120
+ * Respawns the player after death or a gameplay event.
121
+ * Restores health, resurrects the player, loads collision,
122
+ * prepares the ped and teleports them to the desired location.
123
+ */
124
+ async respawn(position, heading = 0.0) {
125
+ const ped = await this.ensurePed();
126
+ await this.ensureCollisionAt(position, ped);
127
+ ClearPedTasksImmediately(ped);
128
+ SetEntityHealth(ped, GetEntityMaxHealth(ped));
129
+ NetworkResurrectLocalPlayer(position.x, position.y, position.z, heading, 0, false);
130
+ const finalPed = await this.ensurePed();
131
+ await this.setupPedForGameplay(finalPed);
132
+ await this.teleportTo(position, heading);
133
+ shared_1.loggers.spawn.info('Player respawned', {
134
+ position: { x: position.x, y: position.y, z: position.z },
135
+ heading,
136
+ });
137
+ }
138
+ /**
139
+ * Returns whether the player has completed their first spawn.
140
+ */
141
+ isSpawned() {
142
+ return this.spawned;
143
+ }
144
+ /**
145
+ * Allows other systems to wait until the player is fully spawned.
146
+ */
147
+ async waitUntilSpawned() {
148
+ while (!this.spawned) {
149
+ await delay(0);
150
+ }
151
+ }
152
+ async ensureNetworkReady() {
153
+ const start = GetGameTimer();
154
+ while (!NetworkIsSessionStarted()) {
155
+ if (GetGameTimer() - start > NETWORK_TIMEOUT_MS) {
156
+ shared_1.loggers.spawn.error('Network session did not start in time');
157
+ throw new Error('NETWORK_TIMEOUT');
158
+ }
159
+ await delay(0);
160
+ }
161
+ }
162
+ closeLoadingScreens() {
163
+ try {
164
+ ShutdownLoadingScreen();
165
+ }
166
+ catch (_a) { }
167
+ try {
168
+ ShutdownLoadingScreenNui();
169
+ }
170
+ catch (_b) { }
171
+ }
172
+ async setPlayerModel(model) {
173
+ const modelHash = GetHashKey(model);
174
+ if (!IsModelInCdimage(modelHash) || !IsModelValid(modelHash)) {
175
+ shared_1.loggers.spawn.error('Invalid model requested', { model });
176
+ throw new Error('MODEL_INVALID');
177
+ }
178
+ RequestModel(modelHash);
179
+ while (!HasModelLoaded(modelHash)) {
180
+ await delay(0);
181
+ }
182
+ SetPlayerModel(PlayerId(), modelHash);
183
+ SetModelAsNoLongerNeeded(modelHash);
184
+ const ped = PlayerPedId();
185
+ if (ped !== 0) {
186
+ SetPedDefaultComponentVariation(ped);
187
+ }
188
+ shared_1.loggers.spawn.debug('Player model set', { model, modelHash });
189
+ }
190
+ async ensurePed() {
191
+ const start = GetGameTimer();
192
+ let ped = PlayerPedId();
193
+ while (ped === 0) {
194
+ if (GetGameTimer() - start > PED_TIMEOUT_MS) {
195
+ shared_1.loggers.spawn.error('PlayerPedId() did not become valid in time');
196
+ throw new Error('PED_TIMEOUT');
197
+ }
198
+ await delay(0);
199
+ ped = PlayerPedId();
200
+ }
201
+ return ped;
202
+ }
203
+ async ensureCollisionAt(position, ped) {
204
+ RequestCollisionAtCoord(position.x, position.y, position.z);
205
+ const start = GetGameTimer();
206
+ while (!HasCollisionLoadedAroundEntity(ped)) {
207
+ if (GetGameTimer() - start > COLLISION_TIMEOUT_MS) {
208
+ shared_1.loggers.spawn.warn('Collision did not fully load around entity in time', {
209
+ x: position.x,
210
+ y: position.y,
211
+ z: position.z,
212
+ });
213
+ break;
214
+ }
215
+ await delay(0);
216
+ }
217
+ }
218
+ async setupPedForGameplay(ped) {
219
+ SetEntityAsMissionEntity(ped, true, true);
220
+ ClearPedTasksImmediately(ped);
221
+ RemoveAllPedWeapons(ped, true);
222
+ ResetEntityAlpha(ped);
223
+ await delay(0);
224
+ SetEntityAlpha(ped, 255, false);
225
+ SetEntityVisible(ped, true, false);
226
+ SetEntityCollision(ped, true, true);
227
+ SetEntityInvincible(ped, false);
228
+ shared_1.loggers.spawn.debug('Ped prepared for gameplay', { ped });
229
+ }
230
+ async placePed(ped, position, heading) {
231
+ FreezeEntityPosition(ped, true);
232
+ SetEntityCoordsNoOffset(ped, position.x, position.y, position.z, false, false, false);
233
+ SetEntityHeading(ped, heading);
234
+ await delay(0);
235
+ FreezeEntityPosition(ped, false);
236
+ }
237
+ async applyAppearanceIfNeeded(ped, appearance) {
238
+ if (!appearance) {
239
+ SetPedDefaultComponentVariation(ped);
240
+ return;
241
+ }
242
+ if (!this.appearanceService.validateAppearance(appearance)) {
243
+ SetPedDefaultComponentVariation(ped);
244
+ return;
245
+ }
246
+ try {
247
+ await this.appearanceService.applyAppearance(ped, appearance);
248
+ }
249
+ catch (error) {
250
+ shared_1.loggers.spawn.error('Failed to apply appearance, using default variation', {
251
+ error: error instanceof Error ? error.message : String(error),
252
+ });
253
+ SetPedDefaultComponentVariation(ped);
254
+ }
255
+ }
256
+ };
257
+ exports.SpawnService = SpawnService;
258
+ exports.SpawnService = SpawnService = __decorate([
259
+ (0, tsyringe_1.injectable)(),
260
+ __metadata("design:paramtypes", [appearance_service_1.AppearanceService])
261
+ ], SpawnService);
@@ -1,4 +1,4 @@
1
- import type { Vector3 } from '../../../utils';
1
+ import type { Vector3 } from '../../utils';
2
2
  export interface TextUIOptions {
3
3
  /** Font (0-8) */
4
4
  font?: number;
@@ -1,4 +1,4 @@
1
- import type { Vector3 } from '../../../utils';
1
+ import type { Vector3 } from '../../utils';
2
2
  export interface VehicleSpawnOptions {
3
3
  /** Model name or hash */
4
4
  model: string;
@@ -18,7 +18,7 @@ let ClientExportProcessor = class ClientExportProcessor {
18
18
  process(target, methodName, metadata) {
19
19
  const handler = target[methodName].bind(target);
20
20
  const handlerName = `${target.constructor.name}.${methodName}`;
21
- exports(metadata.exportName, async (...args) => {
21
+ globalThis.exports(metadata.exportName, async (...args) => {
22
22
  try {
23
23
  return await handler(...args);
24
24
  }
package/dist/index.d.ts CHANGED
@@ -3,5 +3,3 @@ export * as Utils from './utils';
3
3
  export * as Shared from './shared';
4
4
  export * as Server from './server';
5
5
  export * as Client from './client';
6
- export { LoggerService, LogLevel, LogDomain } from './shared/logger';
7
- export type { LogTransport, LogContext, LogEntry, LoggerConfig } from './shared/logger';
package/dist/index.js CHANGED
@@ -33,14 +33,9 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.LogDomain = exports.LogLevel = exports.LoggerService = exports.Client = exports.Server = exports.Shared = exports.Utils = void 0;
36
+ exports.Client = exports.Server = exports.Shared = exports.Utils = void 0;
37
37
  require("reflect-metadata");
38
38
  exports.Utils = __importStar(require("./utils"));
39
39
  exports.Shared = __importStar(require("./shared"));
40
40
  exports.Server = __importStar(require("./server"));
41
41
  exports.Client = __importStar(require("./client"));
42
- // Re-export logger at root level for convenience
43
- var logger_1 = require("./shared/logger");
44
- Object.defineProperty(exports, "LoggerService", { enumerable: true, get: function () { return logger_1.LoggerService; } });
45
- Object.defineProperty(exports, "LogLevel", { enumerable: true, get: function () { return logger_1.LogLevel; } });
46
- Object.defineProperty(exports, "LogDomain", { enumerable: true, get: function () { return logger_1.LogDomain; } });
@@ -0,0 +1,9 @@
1
+ import { PlayerService } from '../services';
2
+ import { PlayerPersistenceService } from '../services/persistence.service';
3
+ export declare class SessionController {
4
+ private readonly playerManager;
5
+ private readonly persistance;
6
+ constructor(playerManager: PlayerService, persistance: PlayerPersistenceService);
7
+ onPlayerJoining(): Promise<void>;
8
+ onPlayerDropped(): Promise<void>;
9
+ }
@@ -0,0 +1,70 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.SessionController = void 0;
13
+ const shared_1 = require("../../shared");
14
+ const core_event_bus_1 = require("../bus/core-event-bus");
15
+ const decorators_1 = require("../decorators");
16
+ const onFiveMEvent_1 = require("../decorators/onFiveMEvent");
17
+ const services_1 = require("../services");
18
+ const persistence_service_1 = require("../services/persistence.service");
19
+ let SessionController = class SessionController {
20
+ constructor(playerManager, persistance) {
21
+ this.playerManager = playerManager;
22
+ this.persistance = persistance;
23
+ }
24
+ async onPlayerJoining() {
25
+ var _a;
26
+ const clientId = source;
27
+ const license = (_a = GetPlayerIdentifier(clientId.toString(), 0)) !== null && _a !== void 0 ? _a : undefined;
28
+ const player = this.playerManager.bind(clientId, { license });
29
+ shared_1.loggers.session.info(`Player session created`, {
30
+ clientId,
31
+ license: license !== null && license !== void 0 ? license : 'none',
32
+ });
33
+ await this.persistance.handleSessionLoad(player);
34
+ (0, core_event_bus_1.emitCoreEvent)('core:playerSessionCreated', { clientId, license });
35
+ setImmediate(() => {
36
+ const currentPlayer = this.playerManager.getByClient(clientId);
37
+ if (!currentPlayer)
38
+ return;
39
+ (0, core_event_bus_1.emitCoreEvent)('core:playerFullyConnected', { clientId, license });
40
+ });
41
+ }
42
+ async onPlayerDropped() {
43
+ const clientId = Number(source);
44
+ const player = this.playerManager.getByClient(clientId);
45
+ if (player) {
46
+ await this.persistance.handleSessionSave(player);
47
+ }
48
+ this.playerManager.unbindByClient(clientId);
49
+ (0, core_event_bus_1.emitCoreEvent)('core:playerSessionDestroyed', { clientId });
50
+ shared_1.loggers.session.info(`Player session destroyed`, { clientId });
51
+ }
52
+ };
53
+ exports.SessionController = SessionController;
54
+ __decorate([
55
+ (0, onFiveMEvent_1.OnFiveMEvent)('playerJoining'),
56
+ __metadata("design:type", Function),
57
+ __metadata("design:paramtypes", []),
58
+ __metadata("design:returntype", Promise)
59
+ ], SessionController.prototype, "onPlayerJoining", null);
60
+ __decorate([
61
+ (0, onFiveMEvent_1.OnFiveMEvent)('playerDropped'),
62
+ __metadata("design:type", Function),
63
+ __metadata("design:paramtypes", []),
64
+ __metadata("design:returntype", Promise)
65
+ ], SessionController.prototype, "onPlayerDropped", null);
66
+ exports.SessionController = SessionController = __decorate([
67
+ (0, decorators_1.Controller)(),
68
+ __metadata("design:paramtypes", [services_1.PlayerService,
69
+ persistence_service_1.PlayerPersistenceService])
70
+ ], SessionController);
@@ -15,7 +15,7 @@ const database_contract_1 = require("../database.contract");
15
15
  * Get the oxmysql export from FiveM
16
16
  */
17
17
  function getOxMySQL() {
18
- const ox = global.exports['oxmysql'];
18
+ const ox = exports['oxmysql'];
19
19
  if (!ox) {
20
20
  throw new Error('[OpenCore] oxmysql is not available. Make sure oxmysql resource is started before your resource.');
21
21
  }
@@ -1,7 +1,7 @@
1
1
  export * from './bind';
2
2
  export * from './utils';
3
3
  export { Command, CommandConfig } from './command';
4
- export * from './coreEvent';
4
+ export * from './onFrameworkEvent';
5
5
  export * from './onNet';
6
6
  export * from './onTick';
7
7
  export { Controller } from './controller';
@@ -19,7 +19,7 @@ __exportStar(require("./bind"), exports);
19
19
  __exportStar(require("./utils"), exports);
20
20
  var command_1 = require("./command");
21
21
  Object.defineProperty(exports, "Command", { enumerable: true, get: function () { return command_1.Command; } });
22
- __exportStar(require("./coreEvent"), exports);
22
+ __exportStar(require("./onFrameworkEvent"), exports);
23
23
  __exportStar(require("./onNet"), exports);
24
24
  __exportStar(require("./onTick"), exports);
25
25
  var controller_1 = require("./controller");
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Listen to FiveM events server-side, check the list below
3
+ *
4
+ * https://docs.fivem.net/docs/scripting-reference/events/server-events/
5
+ */
6
+ export declare function OnFiveMEvent(event: string): (target: any, propertyKey: string) => void;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OnFiveMEvent = OnFiveMEvent;
4
+ const metadata_server_keys_1 = require("../system/metadata-server.keys");
5
+ /**
6
+ * Listen to FiveM events server-side, check the list below
7
+ *
8
+ * https://docs.fivem.net/docs/scripting-reference/events/server-events/
9
+ */
10
+ function OnFiveMEvent(event) {
11
+ return (target, propertyKey) => {
12
+ Reflect.defineMetadata(metadata_server_keys_1.METADATA_KEYS.FIVEM_EVENT, { event }, target, propertyKey);
13
+ };
14
+ }
@@ -12,11 +12,11 @@ import type { CoreEventMap } from '../types/core-events';
12
12
  * @Server.Controller()
13
13
  * export class SystemController {
14
14
  *
15
- * @OnCoreEvent('server:ready')
15
+ * @OnFrameworkEvent('server:ready')
16
16
  * public onServerStart() {
17
17
  * console.log('OpenCore Framework is ready!')
18
18
  * }
19
19
  * }
20
20
  * ```
21
21
  */
22
- export declare function OnCoreEvent<K extends keyof CoreEventMap>(event: K): (target: any, propertyKey: string) => void;
22
+ export declare function OnFrameworkEvent<K extends keyof CoreEventMap>(event: K): (target: any, propertyKey: string) => void;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.OnCoreEvent = OnCoreEvent;
3
+ exports.OnFrameworkEvent = OnFrameworkEvent;
4
4
  const metadata_server_keys_1 = require("../system/metadata-server.keys");
5
5
  /**
6
6
  * Method decorator used to register a method as a listener for an internal OpenCore framework event.
@@ -15,14 +15,14 @@ const metadata_server_keys_1 = require("../system/metadata-server.keys");
15
15
  * @Server.Controller()
16
16
  * export class SystemController {
17
17
  *
18
- * @OnCoreEvent('server:ready')
18
+ * @OnFrameworkEvent('server:ready')
19
19
  * public onServerStart() {
20
20
  * console.log('OpenCore Framework is ready!')
21
21
  * }
22
22
  * }
23
23
  * ```
24
24
  */
25
- function OnCoreEvent(event) {
25
+ function OnFrameworkEvent(event) {
26
26
  return (target, propertyKey) => {
27
27
  Reflect.defineMetadata(metadata_server_keys_1.METADATA_KEYS.CORE_EVENT, { event }, target, propertyKey);
28
28
  };
@@ -95,7 +95,7 @@ class Player {
95
95
  * @param vector - The target coordinates (x, y, z).
96
96
  */
97
97
  teleportClient(vector) {
98
- this.emit('core:spawner:teleport', vector);
98
+ this.emit('opencore:spawner:teleport', vector);
99
99
  }
100
100
  /**
101
101
  * Disconnects the player from the server.
@@ -0,0 +1,5 @@
1
+ export declare function resolveMethod(instance: Record<string, any>, methodName: string, errorMessage: string): {
2
+ handler: Function;
3
+ handlerName: string;
4
+ proto: any;
5
+ } | undefined;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveMethod = resolveMethod;
4
+ const logger_1 = require("../../shared/logger");
5
+ function resolveMethod(instance, methodName, errorMessage) {
6
+ const proto = Object.getPrototypeOf(instance);
7
+ const method = instance[methodName];
8
+ if (typeof method !== 'function') {
9
+ logger_1.loggers.scanner.error(errorMessage, {
10
+ className: instance.constructor.name,
11
+ methodName,
12
+ });
13
+ return;
14
+ }
15
+ const handler = method.bind(instance);
16
+ const handlerName = `${instance.constructor.name}.${methodName}`;
17
+ return { handler, handlerName, proto };
18
+ }
@@ -27,3 +27,5 @@ __exportStar(require("./setup"), exports);
27
27
  // Controllers
28
28
  require("./controllers/command.controller");
29
29
  require("./controllers/chat.controller");
30
+ const container_1 = require("./container");
31
+ globalThis.oc_container = container_1.di;
@@ -11,9 +11,9 @@ const playerSessionLoader = () => {
11
11
  const persistenceService = tsyringe_1.container.resolve(persistence_service_1.PlayerPersistenceService);
12
12
  // Initialize persistence service (resolves provider if configured)
13
13
  persistenceService.initialize();
14
- on('playerJoining', async (source) => {
14
+ on('playerJoining', async () => {
15
15
  var _a;
16
- const clientId = Number(source);
16
+ const clientId = source;
17
17
  const license = (_a = GetPlayerIdentifier(clientId.toString(), 0)) !== null && _a !== void 0 ? _a : undefined;
18
18
  const player = playerManager.bind(clientId, { license });
19
19
  logger_1.loggers.session.info(`Player session created`, {
@@ -26,9 +26,18 @@ const playerSessionLoader = () => {
26
26
  clientId,
27
27
  license,
28
28
  });
29
+ setImmediate(() => {
30
+ const currentPlayer = playerManager.getByClient(clientId);
31
+ if (!currentPlayer)
32
+ return;
33
+ (0, core_event_bus_1.emitCoreEvent)('core:playerFullyConnected', {
34
+ clientId,
35
+ license,
36
+ });
37
+ });
29
38
  });
30
- on('playerDropped', async () => {
31
- const clientId = Number(global.source);
39
+ on('playerDropped', async (source) => {
40
+ const clientId = Number(source);
32
41
  const player = playerManager.getByClient(clientId);
33
42
  // Save player data before destroying session
34
43
  if (player) {
@@ -4,6 +4,7 @@ export declare const METADATA_KEYS: {
4
4
  NET_EVENT: string;
5
5
  TICK: string;
6
6
  CORE_EVENT: string;
7
+ FIVEM_EVENT: string;
7
8
  EXPORT: string;
8
9
  PUBLIC: string;
9
10
  };
@@ -7,6 +7,7 @@ exports.METADATA_KEYS = {
7
7
  NET_EVENT: 'core:meta:net_event',
8
8
  TICK: 'core:meta:tick',
9
9
  CORE_EVENT: 'core:meta:core_event',
10
+ FIVEM_EVENT: 'core:meta:fivem_event',
10
11
  EXPORT: 'core:meta:export',
11
12
  PUBLIC: 'core:meta:public',
12
13
  };
@@ -1,7 +1,7 @@
1
1
  import { DecoratorProcessor } from '../../../system/decorator-processor';
2
2
  export declare class CoreEventProcessor implements DecoratorProcessor {
3
3
  readonly metadataKey: string;
4
- process(target: any, methodName: string, metadata: {
4
+ process(instance: any, methodName: string, metadata: {
5
5
  event: string;
6
6
  }): void;
7
7
  }
@@ -11,13 +11,16 @@ const tsyringe_1 = require("tsyringe");
11
11
  const core_event_bus_1 = require("../../bus/core-event-bus");
12
12
  const metadata_server_keys_1 = require("../metadata-server.keys");
13
13
  const logger_1 = require("../../../shared/logger");
14
+ const resolve_method_1 = require("../../helpers/resolve-method");
14
15
  let CoreEventProcessor = class CoreEventProcessor {
15
16
  constructor() {
16
17
  this.metadataKey = metadata_server_keys_1.METADATA_KEYS.CORE_EVENT;
17
18
  }
18
- process(target, methodName, metadata) {
19
- const handler = target[methodName].bind(target);
20
- const handlerName = `${target.constructor.name}.${methodName}`;
19
+ process(instance, methodName, metadata) {
20
+ const result = (0, resolve_method_1.resolveMethod)(instance, methodName, `[CoreEventProcessor] Method "${methodName}" not found`);
21
+ if (!result)
22
+ return;
23
+ const { handler, handlerName } = result;
21
24
  (0, core_event_bus_1.onCoreEvent)(metadata.event, (payload) => {
22
25
  try {
23
26
  handler(payload);
@@ -1,7 +1,7 @@
1
1
  import { DecoratorProcessor } from '../../../system/decorator-processor';
2
2
  export declare class ExportProcessor implements DecoratorProcessor {
3
3
  readonly metadataKey: string;
4
- process(target: any, methodName: string, metadata: {
4
+ process(instance: any, methodName: string, metadata: {
5
5
  exportName: string;
6
6
  }): void;
7
7
  }
@@ -10,13 +10,17 @@ exports.ExportProcessor = void 0;
10
10
  const tsyringe_1 = require("tsyringe");
11
11
  const metadata_server_keys_1 = require("../metadata-server.keys");
12
12
  const logger_1 = require("../../../shared/logger");
13
+ const resolve_method_1 = require("../../helpers/resolve-method");
13
14
  let ExportProcessor = class ExportProcessor {
14
15
  constructor() {
15
16
  this.metadataKey = metadata_server_keys_1.METADATA_KEYS.EXPORT;
16
17
  }
17
- process(target, methodName, metadata) {
18
- const handler = target[methodName].bind(target);
19
- exports(metadata.exportName, handler);
18
+ process(instance, methodName, metadata) {
19
+ const result = (0, resolve_method_1.resolveMethod)(instance, methodName, `[ExportEventProcessor] Method "${methodName}" not found`);
20
+ if (!result)
21
+ return;
22
+ const { handler } = result;
23
+ globalThis.exports(metadata.exportName, handler);
20
24
  logger_1.loggers.exports.debug(`Registered: ${metadata.exportName}`);
21
25
  }
22
26
  };
@@ -0,0 +1,7 @@
1
+ import { DecoratorProcessor } from '../../../system/decorator-processor';
2
+ export declare class FiveMEventProcessor implements DecoratorProcessor {
3
+ readonly metadataKey: string;
4
+ process(instance: any, methodName: string, metadata: {
5
+ event: string;
6
+ }): void;
7
+ }