@open-core/framework 0.1.0-alpha.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.
- package/LICENSE +373 -0
- package/README.md +360 -0
- package/dist/client/client-bootstrap.d.ts +1 -0
- package/dist/client/client-bootstrap.js +50 -0
- package/dist/client/client-container.d.ts +2 -0
- package/dist/client/client-container.js +6 -0
- package/dist/client/client-core.d.ts +1 -0
- package/dist/client/client-core.js +7 -0
- package/dist/client/controllers/spawner.controller.d.ts +12 -0
- package/dist/client/controllers/spawner.controller.js +51 -0
- package/dist/client/decorators/controller.d.ts +3 -0
- package/dist/client/decorators/controller.js +14 -0
- package/dist/client/decorators/export.d.ts +7 -0
- package/dist/client/decorators/export.js +15 -0
- package/dist/client/decorators/gameEvent.d.ts +47 -0
- package/dist/client/decorators/gameEvent.js +54 -0
- package/dist/client/decorators/index.d.ts +10 -0
- package/dist/client/decorators/index.js +26 -0
- package/dist/client/decorators/interval.d.ts +7 -0
- package/dist/client/decorators/interval.js +15 -0
- package/dist/client/decorators/key.d.ts +2 -0
- package/dist/client/decorators/key.js +10 -0
- package/dist/client/decorators/localEvent.d.ts +7 -0
- package/dist/client/decorators/localEvent.js +15 -0
- package/dist/client/decorators/nui.d.ts +1 -0
- package/dist/client/decorators/nui.js +9 -0
- package/dist/client/decorators/onNet.d.ts +1 -0
- package/dist/client/decorators/onNet.js +9 -0
- package/dist/client/decorators/resourceLifecycle.d.ts +11 -0
- package/dist/client/decorators/resourceLifecycle.js +24 -0
- package/dist/client/decorators/tick.d.ts +1 -0
- package/dist/client/decorators/tick.js +9 -0
- package/dist/client/index.d.ts +7 -0
- package/dist/client/index.js +23 -0
- package/dist/client/interfaces/appearance.interface.d.ts +19 -0
- package/dist/client/interfaces/appearance.interface.js +2 -0
- package/dist/client/player/player.d.ts +262 -0
- package/dist/client/player/player.js +480 -0
- package/dist/client/player/player.loader.d.ts +1 -0
- package/dist/client/player/player.loader.js +22 -0
- package/dist/client/services/appearance.service.d.ts +6 -0
- package/dist/client/services/appearance.service.js +89 -0
- package/dist/client/services/blip.service.d.ts +112 -0
- package/dist/client/services/blip.service.js +215 -0
- package/dist/client/services/index.d.ts +9 -0
- package/dist/client/services/index.js +25 -0
- package/dist/client/services/marker.service.d.ts +94 -0
- package/dist/client/services/marker.service.js +153 -0
- package/dist/client/services/notification.service.d.ts +76 -0
- package/dist/client/services/notification.service.js +111 -0
- package/dist/client/services/ped.service.d.ts +182 -0
- package/dist/client/services/ped.service.js +302 -0
- package/dist/client/services/progress.service.d.ts +82 -0
- package/dist/client/services/progress.service.js +210 -0
- package/dist/client/services/spawn.service.d.ts +73 -0
- package/dist/client/services/spawn.service.js +261 -0
- package/dist/client/services/streaming.service.d.ts +165 -0
- package/dist/client/services/streaming.service.js +341 -0
- package/dist/client/services/textui.service.d.ts +82 -0
- package/dist/client/services/textui.service.js +156 -0
- package/dist/client/services/vehicle.service.d.ts +168 -0
- package/dist/client/services/vehicle.service.js +296 -0
- package/dist/client/system/metadata-client.keys.d.ts +13 -0
- package/dist/client/system/metadata-client.keys.js +16 -0
- package/dist/client/system/processors/export.processor.d.ts +7 -0
- package/dist/client/system/processors/export.processor.js +39 -0
- package/dist/client/system/processors/gameEvent.processor.d.ts +10 -0
- package/dist/client/system/processors/gameEvent.processor.js +58 -0
- package/dist/client/system/processors/interval.processor.d.ts +7 -0
- package/dist/client/system/processors/interval.processor.js +43 -0
- package/dist/client/system/processors/key.processor.d.ts +8 -0
- package/dist/client/system/processors/key.processor.js +27 -0
- package/dist/client/system/processors/localEvent.processor.d.ts +7 -0
- package/dist/client/system/processors/localEvent.processor.js +38 -0
- package/dist/client/system/processors/netEvent.processor.d.ts +7 -0
- package/dist/client/system/processors/netEvent.processor.js +38 -0
- package/dist/client/system/processors/nui.processor.d.ts +7 -0
- package/dist/client/system/processors/nui.processor.js +40 -0
- package/dist/client/system/processors/resourceLifecycle.processor.d.ts +9 -0
- package/dist/client/system/processors/resourceLifecycle.processor.js +69 -0
- package/dist/client/system/processors/tick.processor.d.ts +5 -0
- package/dist/client/system/processors/tick.processor.js +37 -0
- package/dist/client/system/processors.register.d.ts +1 -0
- package/dist/client/system/processors.register.js +27 -0
- package/dist/client/types/game-events.d.ts +126 -0
- package/dist/client/types/game-events.js +83 -0
- package/dist/client/types/index.d.ts +1 -0
- package/dist/client/types/index.js +17 -0
- package/dist/client/ui-bridge.d.ts +116 -0
- package/dist/client/ui-bridge.js +201 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +41 -0
- package/dist/server/bootstrap.d.ts +16 -0
- package/dist/server/bootstrap.js +57 -0
- package/dist/server/bus/core-event-bus.d.ts +6 -0
- package/dist/server/bus/core-event-bus.js +31 -0
- package/dist/server/configs/api.config.d.ts +71 -0
- package/dist/server/configs/api.config.js +81 -0
- package/dist/server/configs/config.base.d.ts +63 -0
- package/dist/server/configs/config.base.js +64 -0
- package/dist/server/configs/index.d.ts +2 -0
- package/dist/server/configs/index.js +18 -0
- package/dist/server/container.d.ts +2 -0
- package/dist/server/container.js +6 -0
- package/dist/server/controllers/chat.controller.d.ts +10 -0
- package/dist/server/controllers/chat.controller.js +50 -0
- package/dist/server/controllers/command.controller.d.ts +7 -0
- package/dist/server/controllers/command.controller.js +47 -0
- package/dist/server/controllers/session.controller.d.ts +9 -0
- package/dist/server/controllers/session.controller.js +70 -0
- package/dist/server/core.d.ts +1 -0
- package/dist/server/core.js +7 -0
- package/dist/server/database/adapters/oxmysql.adapter.d.ts +89 -0
- package/dist/server/database/adapters/oxmysql.adapter.js +149 -0
- package/dist/server/database/database.contract.d.ts +128 -0
- package/dist/server/database/database.contract.js +29 -0
- package/dist/server/database/database.service.d.ts +216 -0
- package/dist/server/database/database.service.js +301 -0
- package/dist/server/database/index.d.ts +53 -0
- package/dist/server/database/index.js +70 -0
- package/dist/server/database/types.d.ts +67 -0
- package/dist/server/database/types.js +7 -0
- package/dist/server/database.d.ts +7 -0
- package/dist/server/database.js +23 -0
- package/dist/server/decorators/bind.d.ts +2 -0
- package/dist/server/decorators/bind.js +15 -0
- package/dist/server/decorators/command.d.ts +49 -0
- package/dist/server/decorators/command.js +23 -0
- package/dist/server/decorators/controller.d.ts +25 -0
- package/dist/server/decorators/controller.js +36 -0
- package/dist/server/decorators/export.d.ts +39 -0
- package/dist/server/decorators/export.js +47 -0
- package/dist/server/decorators/guard.d.ts +56 -0
- package/dist/server/decorators/guard.js +82 -0
- package/dist/server/decorators/index.d.ts +10 -0
- package/dist/server/decorators/index.js +29 -0
- package/dist/server/decorators/onFiveMEvent.d.ts +6 -0
- package/dist/server/decorators/onFiveMEvent.js +14 -0
- package/dist/server/decorators/onFrameworkEvent.d.ts +22 -0
- package/dist/server/decorators/onFrameworkEvent.js +29 -0
- package/dist/server/decorators/onNet.d.ts +58 -0
- package/dist/server/decorators/onNet.js +57 -0
- package/dist/server/decorators/onTick.d.ts +32 -0
- package/dist/server/decorators/onTick.js +40 -0
- package/dist/server/decorators/public.d.ts +27 -0
- package/dist/server/decorators/public.js +36 -0
- package/dist/server/decorators/requiresState.d.ts +56 -0
- package/dist/server/decorators/requiresState.js +63 -0
- package/dist/server/decorators/throttle.d.ts +48 -0
- package/dist/server/decorators/throttle.js +63 -0
- package/dist/server/decorators/utils.d.ts +57 -0
- package/dist/server/decorators/utils.js +63 -0
- package/dist/server/entities/index.d.ts +1 -0
- package/dist/server/entities/index.js +17 -0
- package/dist/server/entities/player.d.ts +157 -0
- package/dist/server/entities/player.js +217 -0
- package/dist/server/error-handler.d.ts +2 -0
- package/dist/server/error-handler.js +43 -0
- package/dist/server/helpers/resolve-method.d.ts +5 -0
- package/dist/server/helpers/resolve-method.js +18 -0
- package/dist/server/index.d.ts +10 -0
- package/dist/server/index.js +31 -0
- package/dist/server/loaders/exports.loader.d.ts +0 -0
- package/dist/server/loaders/exports.loader.js +23 -0
- package/dist/server/loaders/playerSession.loader.d.ts +1 -0
- package/dist/server/loaders/playerSession.loader.js +51 -0
- package/dist/server/services/access-control.service.d.ts +56 -0
- package/dist/server/services/access-control.service.js +99 -0
- package/dist/server/services/chat.service.d.ts +7 -0
- package/dist/server/services/chat.service.js +31 -0
- package/dist/server/services/command.service.d.ts +15 -0
- package/dist/server/services/command.service.js +77 -0
- package/dist/server/services/config.service.d.ts +75 -0
- package/dist/server/services/config.service.js +116 -0
- package/dist/server/services/default/default-security.handler.d.ts +6 -0
- package/dist/server/services/default/default-security.handler.js +26 -0
- package/dist/server/services/http/http.service.d.ts +50 -0
- package/dist/server/services/http/http.service.js +126 -0
- package/dist/server/services/index.d.ts +10 -0
- package/dist/server/services/index.js +26 -0
- package/dist/server/services/parallel/index.d.ts +49 -0
- package/dist/server/services/parallel/index.js +67 -0
- package/dist/server/services/parallel/parallel-compute.service.d.ts +132 -0
- package/dist/server/services/parallel/parallel-compute.service.js +449 -0
- package/dist/server/services/parallel/types.d.ts +188 -0
- package/dist/server/services/parallel/types.js +7 -0
- package/dist/server/services/parallel/worker-pool.d.ts +83 -0
- package/dist/server/services/parallel/worker-pool.js +350 -0
- package/dist/server/services/parallel/worker.d.ts +19 -0
- package/dist/server/services/parallel/worker.js +49 -0
- package/dist/server/services/persistence.service.d.ts +59 -0
- package/dist/server/services/persistence.service.js +166 -0
- package/dist/server/services/player.service.d.ts +96 -0
- package/dist/server/services/player.service.js +132 -0
- package/dist/server/services/rate-limiter.service.d.ts +5 -0
- package/dist/server/services/rate-limiter.service.js +39 -0
- package/dist/server/services/registers.d.ts +1 -0
- package/dist/server/services/registers.js +18 -0
- package/dist/server/setup.d.ts +9 -0
- package/dist/server/setup.js +28 -0
- package/dist/server/system/metadata-server.keys.d.ts +10 -0
- package/dist/server/system/metadata-server.keys.js +13 -0
- package/dist/server/system/processors/command.processor.d.ts +9 -0
- package/dist/server/system/processors/command.processor.js +30 -0
- package/dist/server/system/processors/coreEvent.processor.d.ts +7 -0
- package/dist/server/system/processors/coreEvent.processor.js +41 -0
- package/dist/server/system/processors/export.processor.d.ts +7 -0
- package/dist/server/system/processors/export.processor.js +30 -0
- package/dist/server/system/processors/fivemEvent.processor.d.ts +7 -0
- package/dist/server/system/processors/fivemEvent.processor.js +40 -0
- package/dist/server/system/processors/netEvent.processor.d.ts +11 -0
- package/dist/server/system/processors/netEvent.processor.js +103 -0
- package/dist/server/system/processors/tick.processor.d.ts +5 -0
- package/dist/server/system/processors/tick.processor.js +36 -0
- package/dist/server/system/processors.register.d.ts +1 -0
- package/dist/server/system/processors.register.js +23 -0
- package/dist/server/system/schema-generator.d.ts +2 -0
- package/dist/server/system/schema-generator.js +34 -0
- package/dist/server/templates/admin/admin.controller-template.d.ts +12 -0
- package/dist/server/templates/admin/admin.controller-template.js +2 -0
- package/dist/server/templates/auth/auth-provider.contract.d.ts +58 -0
- package/dist/server/templates/auth/auth-provider.contract.js +23 -0
- package/dist/server/templates/index.d.ts +8 -0
- package/dist/server/templates/index.js +21 -0
- package/dist/server/templates/persistence/index.d.ts +30 -0
- package/dist/server/templates/persistence/index.js +34 -0
- package/dist/server/templates/persistence/player-persistence.contract.d.ts +86 -0
- package/dist/server/templates/persistence/player-persistence.contract.js +52 -0
- package/dist/server/templates/repository/index.d.ts +57 -0
- package/dist/server/templates/repository/index.js +61 -0
- package/dist/server/templates/repository/repository.contract.d.ts +224 -0
- package/dist/server/templates/repository/repository.contract.js +342 -0
- package/dist/server/templates/repository/repository.types.d.ts +51 -0
- package/dist/server/templates/repository/repository.types.js +7 -0
- package/dist/server/templates/security/permission.types.d.ts +32 -0
- package/dist/server/templates/security/permission.types.js +2 -0
- package/dist/server/templates/security/principal-provider.contract.d.ts +43 -0
- package/dist/server/templates/security/principal-provider.contract.js +19 -0
- package/dist/server/templates/security/security-handler.contract.d.ts +5 -0
- package/dist/server/templates/security/security-handler.contract.js +6 -0
- package/dist/server/types/core-events.d.ts +22 -0
- package/dist/server/types/core-events.js +2 -0
- package/dist/server/types/security.types.d.ts +7 -0
- package/dist/server/types/security.types.js +2 -0
- package/dist/shared/index.d.ts +1 -0
- package/dist/shared/index.js +17 -0
- package/dist/shared/logger/core-logger.d.ts +35 -0
- package/dist/shared/logger/core-logger.js +52 -0
- package/dist/shared/logger/index.d.ts +11 -0
- package/dist/shared/logger/index.js +26 -0
- package/dist/shared/logger/logger.config.d.ts +47 -0
- package/dist/shared/logger/logger.config.js +33 -0
- package/dist/shared/logger/logger.service.d.ts +161 -0
- package/dist/shared/logger/logger.service.js +279 -0
- package/dist/shared/logger/logger.types.d.ts +85 -0
- package/dist/shared/logger/logger.types.js +74 -0
- package/dist/shared/logger/transports/buffered.transport.d.ts +88 -0
- package/dist/shared/logger/transports/buffered.transport.js +174 -0
- package/dist/shared/logger/transports/console.transport.d.ts +37 -0
- package/dist/shared/logger/transports/console.transport.js +134 -0
- package/dist/shared/logger/transports/index.d.ts +3 -0
- package/dist/shared/logger/transports/index.js +19 -0
- package/dist/shared/logger/transports/transport.interface.d.ts +40 -0
- package/dist/shared/logger/transports/transport.interface.js +2 -0
- package/dist/system/class-constructor.d.ts +1 -0
- package/dist/system/class-constructor.js +2 -0
- package/dist/system/decorator-processor.d.ts +4 -0
- package/dist/system/decorator-processor.js +2 -0
- package/dist/system/metadata.scanner.d.ts +7 -0
- package/dist/system/metadata.scanner.js +45 -0
- package/dist/utils/errors.d.ts +14 -0
- package/dist/utils/errors.js +25 -0
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.js +20 -0
- package/dist/utils/result.d.ts +12 -0
- package/dist/utils/result.js +10 -0
- package/dist/utils/rgb.d.ts +5 -0
- package/dist/utils/rgb.js +2 -0
- package/dist/utils/vector3.d.ts +13 -0
- package/dist/utils/vector3.js +27 -0
- package/package.json +98 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RequiresState = RequiresState;
|
|
4
|
+
const utils_1 = require("../../utils");
|
|
5
|
+
/**
|
|
6
|
+
* Enforces gameplay state requirements before executing a method.
|
|
7
|
+
*
|
|
8
|
+
* The decorator intercepts the method call and verifies whether
|
|
9
|
+
* the player satisfies required state flags (e.g. "dead", "cuffed",
|
|
10
|
+
* "on_duty_police").
|
|
11
|
+
*
|
|
12
|
+
* ## Whitelist (`has`)
|
|
13
|
+
* The player MUST have *all* required states. Missing any state blocks execution.
|
|
14
|
+
*
|
|
15
|
+
* ## Blacklist (`missing`)
|
|
16
|
+
* The player MUST NOT have any of the forbidden states.
|
|
17
|
+
*
|
|
18
|
+
* ## Error Handling
|
|
19
|
+
* - Throws a normal Error if the method is called without a valid Player.
|
|
20
|
+
* - Throws an `AppError(GAME_STATE_ERROR)` if validation fails.
|
|
21
|
+
*
|
|
22
|
+
* ## Example
|
|
23
|
+
* ```ts
|
|
24
|
+
* @RequiresState({ missing: ["dead", "cuffed"] })
|
|
25
|
+
* openInventory(player: Server.Player) { ... }
|
|
26
|
+
*
|
|
27
|
+
* @RequiresState({
|
|
28
|
+
* has: ["police_duty"],
|
|
29
|
+
* missing: ["dead"],
|
|
30
|
+
* errorMessage: "You must be on duty to access the armory."
|
|
31
|
+
* })
|
|
32
|
+
* openArmory(player: Server.Player) { ... }
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* @param req - State validation configuration.
|
|
36
|
+
*/
|
|
37
|
+
function RequiresState(req) {
|
|
38
|
+
return function (target, propertyKey, descriptor) {
|
|
39
|
+
const originalMethod = descriptor.value;
|
|
40
|
+
descriptor.value = async function (...args) {
|
|
41
|
+
const player = args[0];
|
|
42
|
+
if (!player) {
|
|
43
|
+
throw new Error(`@RequiresState used on ${propertyKey} without Player context`);
|
|
44
|
+
}
|
|
45
|
+
if (req.has) {
|
|
46
|
+
for (const state of req.has) {
|
|
47
|
+
if (!player.hasState(state)) {
|
|
48
|
+
throw new utils_1.AppError('GAME_STATE_ERROR', req.errorMessage || `You must be [${state}] to do this.`, 'client');
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
if (req.missing) {
|
|
53
|
+
for (const state of req.missing) {
|
|
54
|
+
if (player.hasState(state)) {
|
|
55
|
+
throw new utils_1.AppError('GAME_STATE_ERROR', req.errorMessage || `You can't do this while you're [${state}].`, 'client');
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return originalMethod.apply(this, args);
|
|
60
|
+
};
|
|
61
|
+
return descriptor;
|
|
62
|
+
};
|
|
63
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { SecurityAction } from '../types/security.types';
|
|
2
|
+
interface ThrottleOptions {
|
|
3
|
+
/**
|
|
4
|
+
* limit of calls per windowMs
|
|
5
|
+
*/
|
|
6
|
+
limit: number;
|
|
7
|
+
/**
|
|
8
|
+
* time window for numeric overload
|
|
9
|
+
*/
|
|
10
|
+
windowMs: number;
|
|
11
|
+
/**
|
|
12
|
+
* action to perform on exceed limit
|
|
13
|
+
*/
|
|
14
|
+
onExceed?: SecurityAction;
|
|
15
|
+
/**
|
|
16
|
+
* custom message to display on exceed limit (ERROR MESSAGE)
|
|
17
|
+
*/
|
|
18
|
+
message?: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Rate-limits how frequently a method can be called by a specific player.
|
|
22
|
+
*
|
|
23
|
+
* Uses `RateLimiterService` and a unique key composed of:
|
|
24
|
+
* `playerID:ClassName:MethodName`.
|
|
25
|
+
*
|
|
26
|
+
* ## Overload
|
|
27
|
+
* - `@Throttle(5, 1000)` → limit = 5 calls per 1000 ms
|
|
28
|
+
* - `@Throttle({ limit, windowMs, onExceed, message })`
|
|
29
|
+
*
|
|
30
|
+
* ## Behavior
|
|
31
|
+
* If the rate limit is exceeded:
|
|
32
|
+
* - A `SecurityError` is thrown.
|
|
33
|
+
* - Optional custom behavior (`onExceed`) may be executed.
|
|
34
|
+
*
|
|
35
|
+
* ## Example
|
|
36
|
+
* ```ts
|
|
37
|
+
* @Throttle(5, 2000)
|
|
38
|
+
* async search(player: Server.Player, query: string) { ... }
|
|
39
|
+
*
|
|
40
|
+
* @Throttle({ limit: 1, windowMs: 5000, message: "Too fast!" })
|
|
41
|
+
* async placeOrder(player: Server.Player) { ... }
|
|
42
|
+
* ```
|
|
43
|
+
*
|
|
44
|
+
* @param optionsOrLimit - Number (simple mode) or full config object.
|
|
45
|
+
* @param windowMs - Time window for numeric overload.
|
|
46
|
+
*/
|
|
47
|
+
export declare function Throttle(optionsOrLimit: number | ThrottleOptions, windowMs?: number): (target: any, propertyKey: string, descriptor?: PropertyDescriptor) => PropertyDescriptor | undefined;
|
|
48
|
+
export {};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Throttle = Throttle;
|
|
4
|
+
const tsyringe_1 = require("tsyringe");
|
|
5
|
+
const rate_limiter_service_1 = require("../services/rate-limiter.service");
|
|
6
|
+
const utils_1 = require("../../utils");
|
|
7
|
+
/**
|
|
8
|
+
* Rate-limits how frequently a method can be called by a specific player.
|
|
9
|
+
*
|
|
10
|
+
* Uses `RateLimiterService` and a unique key composed of:
|
|
11
|
+
* `playerID:ClassName:MethodName`.
|
|
12
|
+
*
|
|
13
|
+
* ## Overload
|
|
14
|
+
* - `@Throttle(5, 1000)` → limit = 5 calls per 1000 ms
|
|
15
|
+
* - `@Throttle({ limit, windowMs, onExceed, message })`
|
|
16
|
+
*
|
|
17
|
+
* ## Behavior
|
|
18
|
+
* If the rate limit is exceeded:
|
|
19
|
+
* - A `SecurityError` is thrown.
|
|
20
|
+
* - Optional custom behavior (`onExceed`) may be executed.
|
|
21
|
+
*
|
|
22
|
+
* ## Example
|
|
23
|
+
* ```ts
|
|
24
|
+
* @Throttle(5, 2000)
|
|
25
|
+
* async search(player: Server.Player, query: string) { ... }
|
|
26
|
+
*
|
|
27
|
+
* @Throttle({ limit: 1, windowMs: 5000, message: "Too fast!" })
|
|
28
|
+
* async placeOrder(player: Server.Player) { ... }
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* @param optionsOrLimit - Number (simple mode) or full config object.
|
|
32
|
+
* @param windowMs - Time window for numeric overload.
|
|
33
|
+
*/
|
|
34
|
+
function Throttle(optionsOrLimit, windowMs) {
|
|
35
|
+
return function (target, propertyKey, descriptor) {
|
|
36
|
+
if (!descriptor) {
|
|
37
|
+
// In benchmarks or edge cases, skip method wrapping
|
|
38
|
+
// This should NOT happen in production code with proper TypeScript compilation
|
|
39
|
+
// Note: Throttle cannot work without descriptor, so we just skip it
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const originalMethod = descriptor.value;
|
|
43
|
+
let opts;
|
|
44
|
+
if (typeof optionsOrLimit === 'number') {
|
|
45
|
+
opts = { limit: optionsOrLimit, windowMs: windowMs || 1000, onExceed: 'LOG' };
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
opts = Object.assign({ onExceed: 'LOG' }, optionsOrLimit);
|
|
49
|
+
}
|
|
50
|
+
descriptor.value = async function (...args) {
|
|
51
|
+
const player = args[0];
|
|
52
|
+
if (player === null || player === void 0 ? void 0 : player.clientID) {
|
|
53
|
+
const service = tsyringe_1.container.resolve(rate_limiter_service_1.RateLimiterService);
|
|
54
|
+
const key = `${player.clientID}:${target.constructor.name}:${propertyKey}`;
|
|
55
|
+
if (!service.checkLimit(key, opts.limit, opts.windowMs)) {
|
|
56
|
+
throw new utils_1.SecurityError(opts.onExceed, opts.message || `Rate limit exceeded on ${propertyKey}`, { limit: opts.limit, key });
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return originalMethod.apply(this, args);
|
|
60
|
+
};
|
|
61
|
+
return descriptor;
|
|
62
|
+
};
|
|
63
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { BindingScope } from './bind';
|
|
2
|
+
/**
|
|
3
|
+
* Marks a class as a framework-managed Service.
|
|
4
|
+
*
|
|
5
|
+
* The decorator binds the class into the dependency injection
|
|
6
|
+
* container using the provided scope (default: `singleton`).
|
|
7
|
+
*
|
|
8
|
+
* Services represent reusable, stateless or stateful logic such as:
|
|
9
|
+
* - Business rules
|
|
10
|
+
* - Utility layers
|
|
11
|
+
* - Gameplay systems
|
|
12
|
+
* - Internal modules
|
|
13
|
+
*
|
|
14
|
+
* This decorator is a convenience wrapper over `@Bind()`, allowing
|
|
15
|
+
* future extension of service-specific behavior without changing
|
|
16
|
+
* end-user code.
|
|
17
|
+
*
|
|
18
|
+
* ## Example
|
|
19
|
+
* ```ts
|
|
20
|
+
* @Service()
|
|
21
|
+
* export class InventoryService {
|
|
22
|
+
* addItem() { ... }
|
|
23
|
+
* }
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* @param options.scope - Optional binding scope (`singleton` | `transient`)
|
|
27
|
+
*/
|
|
28
|
+
export declare function Service(options?: {
|
|
29
|
+
scope?: BindingScope;
|
|
30
|
+
}): (target: any) => void;
|
|
31
|
+
/**
|
|
32
|
+
* Marks a class as a Repository within the framework.
|
|
33
|
+
*
|
|
34
|
+
* A Repository abstracts persistence operations (e.g., database,
|
|
35
|
+
* API, in-memory, or hybrid storage). It is registered in the
|
|
36
|
+
* dependency injection container using the provided scope
|
|
37
|
+
* (default: `singleton`).
|
|
38
|
+
*
|
|
39
|
+
* `@Repo()` is intentionally separate from `@Service()` to clearly
|
|
40
|
+
* distinguish persistence-oriented classes from business logic.
|
|
41
|
+
* In the future, repository-specific behavior (caching layers,
|
|
42
|
+
* transactional wrappers, profiling, etc.) can be attached here
|
|
43
|
+
* without modifying user code.
|
|
44
|
+
*
|
|
45
|
+
* ## Example
|
|
46
|
+
* ```ts
|
|
47
|
+
* @Repo()
|
|
48
|
+
* export class AccountRepository {
|
|
49
|
+
* async findById(id: string) { ... }
|
|
50
|
+
* }
|
|
51
|
+
* ```
|
|
52
|
+
*
|
|
53
|
+
* @param options.scope - Optional binding scope (`singleton` | `transient`)
|
|
54
|
+
*/
|
|
55
|
+
export declare function Repo(options?: {
|
|
56
|
+
scope?: BindingScope;
|
|
57
|
+
}): (target: any) => void;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Service = Service;
|
|
4
|
+
exports.Repo = Repo;
|
|
5
|
+
const bind_1 = require("./bind");
|
|
6
|
+
/**
|
|
7
|
+
* Marks a class as a framework-managed Service.
|
|
8
|
+
*
|
|
9
|
+
* The decorator binds the class into the dependency injection
|
|
10
|
+
* container using the provided scope (default: `singleton`).
|
|
11
|
+
*
|
|
12
|
+
* Services represent reusable, stateless or stateful logic such as:
|
|
13
|
+
* - Business rules
|
|
14
|
+
* - Utility layers
|
|
15
|
+
* - Gameplay systems
|
|
16
|
+
* - Internal modules
|
|
17
|
+
*
|
|
18
|
+
* This decorator is a convenience wrapper over `@Bind()`, allowing
|
|
19
|
+
* future extension of service-specific behavior without changing
|
|
20
|
+
* end-user code.
|
|
21
|
+
*
|
|
22
|
+
* ## Example
|
|
23
|
+
* ```ts
|
|
24
|
+
* @Service()
|
|
25
|
+
* export class InventoryService {
|
|
26
|
+
* addItem() { ... }
|
|
27
|
+
* }
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* @param options.scope - Optional binding scope (`singleton` | `transient`)
|
|
31
|
+
*/
|
|
32
|
+
function Service(options) {
|
|
33
|
+
var _a;
|
|
34
|
+
return (0, bind_1.Bind)((_a = options === null || options === void 0 ? void 0 : options.scope) !== null && _a !== void 0 ? _a : 'singleton');
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Marks a class as a Repository within the framework.
|
|
38
|
+
*
|
|
39
|
+
* A Repository abstracts persistence operations (e.g., database,
|
|
40
|
+
* API, in-memory, or hybrid storage). It is registered in the
|
|
41
|
+
* dependency injection container using the provided scope
|
|
42
|
+
* (default: `singleton`).
|
|
43
|
+
*
|
|
44
|
+
* `@Repo()` is intentionally separate from `@Service()` to clearly
|
|
45
|
+
* distinguish persistence-oriented classes from business logic.
|
|
46
|
+
* In the future, repository-specific behavior (caching layers,
|
|
47
|
+
* transactional wrappers, profiling, etc.) can be attached here
|
|
48
|
+
* without modifying user code.
|
|
49
|
+
*
|
|
50
|
+
* ## Example
|
|
51
|
+
* ```ts
|
|
52
|
+
* @Repo()
|
|
53
|
+
* export class AccountRepository {
|
|
54
|
+
* async findById(id: string) { ... }
|
|
55
|
+
* }
|
|
56
|
+
* ```
|
|
57
|
+
*
|
|
58
|
+
* @param options.scope - Optional binding scope (`singleton` | `transient`)
|
|
59
|
+
*/
|
|
60
|
+
function Repo(options) {
|
|
61
|
+
var _a;
|
|
62
|
+
return (0, bind_1.Bind)((_a = options === null || options === void 0 ? void 0 : options.scope) !== null && _a !== void 0 ? _a : 'singleton');
|
|
63
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './player';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./player"), exports);
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import type { Vector3 } from '../../utils';
|
|
2
|
+
import type { LinkedID, PlayerSession } from '../services/player.service';
|
|
3
|
+
/**
|
|
4
|
+
* Core-level representation of a connected player on the server.
|
|
5
|
+
*
|
|
6
|
+
* This class wraps FiveM natives and session information.
|
|
7
|
+
* It serves as an abstraction layer to interact with the connected client
|
|
8
|
+
* (kicking, teleporting, emitting events) without dealing with raw IDs everywhere.
|
|
9
|
+
*
|
|
10
|
+
* ⚠️ **Design Note:** This class does NOT contain gameplay logic (money, jobs, inventory).
|
|
11
|
+
* Domain logic should live in your modules' services/models (e.g., `EconomyService`, `JobModel`).
|
|
12
|
+
*/
|
|
13
|
+
export declare class Player {
|
|
14
|
+
private readonly session;
|
|
15
|
+
private states;
|
|
16
|
+
/**
|
|
17
|
+
* Creates a new Player entity instance.
|
|
18
|
+
* This is typically instantiated by the `PlayerService` upon connection.
|
|
19
|
+
*
|
|
20
|
+
* @param session - The internal session data structure holding ID and metadata.
|
|
21
|
+
*/
|
|
22
|
+
constructor(session: PlayerSession);
|
|
23
|
+
/**
|
|
24
|
+
* The numeric FiveM Server ID (Source) of the player.
|
|
25
|
+
* Useful for internal logic and array indexing.
|
|
26
|
+
*/
|
|
27
|
+
get clientID(): number;
|
|
28
|
+
/**
|
|
29
|
+
* The FiveM Server ID as a string.
|
|
30
|
+
* Required by most FiveM native functions (e.g., `GetPlayerName`, `DropPlayer`).
|
|
31
|
+
*/
|
|
32
|
+
get clientIDStr(): string;
|
|
33
|
+
/**
|
|
34
|
+
* The persistent Account ID linked to this session, if the player is authenticated.
|
|
35
|
+
* Returns `undefined` if the player has not logged in yet.
|
|
36
|
+
*/
|
|
37
|
+
get accountID(): string | undefined;
|
|
38
|
+
/**
|
|
39
|
+
* The display name of the player (Steam name or FiveM username).
|
|
40
|
+
*/
|
|
41
|
+
get name(): string;
|
|
42
|
+
/**
|
|
43
|
+
* Retrieves all platform identifiers associated with the player (steam, license, discord, ip, etc.).
|
|
44
|
+
*
|
|
45
|
+
* @returns An array of identifier strings (e.g., `['steam:11000...', 'license:2332...']`).
|
|
46
|
+
*/
|
|
47
|
+
getIdentifiers(): string[];
|
|
48
|
+
/**
|
|
49
|
+
* Sends a network event exclusively to this specific player (Client-side).
|
|
50
|
+
* Wrapper for `emitNet` ensuring the correct target Source ID is used.
|
|
51
|
+
*
|
|
52
|
+
* @param eventName - The name of the event to trigger on the client.
|
|
53
|
+
* @param args - Data to send to the client.
|
|
54
|
+
*/
|
|
55
|
+
emit(eventName: string, ...args: any[]): void;
|
|
56
|
+
/**
|
|
57
|
+
* Teleports the player to a given position using Server-Side natives.
|
|
58
|
+
*
|
|
59
|
+
* **Note:** This forces the entity position on the server. For smoother gameplay transitions
|
|
60
|
+
* (e.g., inside interiors or across the map), consider using `teleportClient`.
|
|
61
|
+
*
|
|
62
|
+
* @param vector - The target coordinates (x, y, z).
|
|
63
|
+
*/
|
|
64
|
+
teleport(vector: Vector3): void;
|
|
65
|
+
/**
|
|
66
|
+
* Requests the Client to teleport itself via the Core Spawner system.
|
|
67
|
+
*
|
|
68
|
+
* This method is preferred for gameplay logic as it allows the client to handle
|
|
69
|
+
* loading screens, fading, and collision loading gracefully.
|
|
70
|
+
*
|
|
71
|
+
* @param vector - The target coordinates (x, y, z).
|
|
72
|
+
*/
|
|
73
|
+
teleportClient(vector: Vector3): void;
|
|
74
|
+
/**
|
|
75
|
+
* Disconnects the player from the server.
|
|
76
|
+
*
|
|
77
|
+
* @param reason - The message displayed to the player upon disconnection.
|
|
78
|
+
*/
|
|
79
|
+
kick(reason?: string): void;
|
|
80
|
+
/**
|
|
81
|
+
* Sets the routing bucket (virtual world / dimension) for the player.
|
|
82
|
+
* Players in different buckets cannot see or interact with each other.
|
|
83
|
+
*
|
|
84
|
+
* @param bucket - The bucket ID (0 is the default shared world).
|
|
85
|
+
*/
|
|
86
|
+
setRoutingBucket(bucket: number): void;
|
|
87
|
+
/**
|
|
88
|
+
* Stores arbitrary transient metadata for this player's session.
|
|
89
|
+
* Useful for flags like `isDead`, `isInRaid`, `lastLocation`, etc.
|
|
90
|
+
*
|
|
91
|
+
* @param key - The unique key for the metadata.
|
|
92
|
+
* @param value - The value to store.
|
|
93
|
+
*/
|
|
94
|
+
setMeta(key: string, value: unknown): void;
|
|
95
|
+
/**
|
|
96
|
+
* Retrieves metadata previously stored in the session.
|
|
97
|
+
*
|
|
98
|
+
* @template T - The expected type of the value.
|
|
99
|
+
* @param key - The metadata key.
|
|
100
|
+
* @returns The value cast to T, or `undefined` if not set.
|
|
101
|
+
*/
|
|
102
|
+
getMeta<T = unknown>(key: string): T | undefined;
|
|
103
|
+
/**
|
|
104
|
+
* Links a persistent Account ID to the current session.
|
|
105
|
+
* Should be called after successful authentication.
|
|
106
|
+
*
|
|
107
|
+
* @param accountID - The unique ID from the database.
|
|
108
|
+
*/
|
|
109
|
+
linkAccount(accountID: LinkedID): void;
|
|
110
|
+
/**
|
|
111
|
+
* Checks if the player currently possesses a specific state flag.
|
|
112
|
+
*
|
|
113
|
+
* @param state - The unique string identifier of the state (e.g., 'dead', 'cuffed').
|
|
114
|
+
* @returns `true` if the state is active, `false` otherwise.
|
|
115
|
+
*/
|
|
116
|
+
hasState(state: string): boolean;
|
|
117
|
+
/**
|
|
118
|
+
* Applies a state flag to the player.
|
|
119
|
+
*
|
|
120
|
+
* @remarks
|
|
121
|
+
* Since states are stored in a `Set`, adding an existing state has no effect (idempotent).
|
|
122
|
+
* Ideally, this should trigger a sync event to the client if needed.
|
|
123
|
+
*
|
|
124
|
+
* @param state - The state key to add.
|
|
125
|
+
*/
|
|
126
|
+
addState(state: string): void;
|
|
127
|
+
/**
|
|
128
|
+
* Removes a specific state flag from the player.
|
|
129
|
+
*
|
|
130
|
+
* @param state - The state key to remove.
|
|
131
|
+
*/
|
|
132
|
+
removeState(state: string): void;
|
|
133
|
+
/**
|
|
134
|
+
* Toggles the presence of a state flag.
|
|
135
|
+
*
|
|
136
|
+
* @param state - The state key to toggle.
|
|
137
|
+
* @param force - If provided, forces the state to be added (`true`) or removed (`false`) regardless of its current status.
|
|
138
|
+
*
|
|
139
|
+
* @returns The final status of the state (`true` if active, `false` if inactive).
|
|
140
|
+
*
|
|
141
|
+
* @example
|
|
142
|
+
* ```ts
|
|
143
|
+
* // Standard toggle
|
|
144
|
+
* player.toggleState('duty'); // turns on if off, off if on
|
|
145
|
+
*
|
|
146
|
+
* // Force enable (equivalent to addState but returns boolean)
|
|
147
|
+
* player.toggleState('duty', true); // always results in true
|
|
148
|
+
* ```
|
|
149
|
+
*/
|
|
150
|
+
toggleState(state: string, force?: boolean): boolean;
|
|
151
|
+
/**
|
|
152
|
+
* Retrieves a snapshot of all currently active state flags for this player.
|
|
153
|
+
*
|
|
154
|
+
* @returns An array containing all active state keys.
|
|
155
|
+
*/
|
|
156
|
+
getStates(): string[];
|
|
157
|
+
}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Player = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Core-level representation of a connected player on the server.
|
|
6
|
+
*
|
|
7
|
+
* This class wraps FiveM natives and session information.
|
|
8
|
+
* It serves as an abstraction layer to interact with the connected client
|
|
9
|
+
* (kicking, teleporting, emitting events) without dealing with raw IDs everywhere.
|
|
10
|
+
*
|
|
11
|
+
* ⚠️ **Design Note:** This class does NOT contain gameplay logic (money, jobs, inventory).
|
|
12
|
+
* Domain logic should live in your modules' services/models (e.g., `EconomyService`, `JobModel`).
|
|
13
|
+
*/
|
|
14
|
+
class Player {
|
|
15
|
+
/**
|
|
16
|
+
* Creates a new Player entity instance.
|
|
17
|
+
* This is typically instantiated by the `PlayerService` upon connection.
|
|
18
|
+
*
|
|
19
|
+
* @param session - The internal session data structure holding ID and metadata.
|
|
20
|
+
*/
|
|
21
|
+
constructor(session) {
|
|
22
|
+
this.session = session;
|
|
23
|
+
this.states = new Set();
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* The numeric FiveM Server ID (Source) of the player.
|
|
27
|
+
* Useful for internal logic and array indexing.
|
|
28
|
+
*/
|
|
29
|
+
get clientID() {
|
|
30
|
+
return this.session.clientID;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* The FiveM Server ID as a string.
|
|
34
|
+
* Required by most FiveM native functions (e.g., `GetPlayerName`, `DropPlayer`).
|
|
35
|
+
*/
|
|
36
|
+
get clientIDStr() {
|
|
37
|
+
return this.session.clientID.toString();
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* The persistent Account ID linked to this session, if the player is authenticated.
|
|
41
|
+
* Returns `undefined` if the player has not logged in yet.
|
|
42
|
+
*/
|
|
43
|
+
get accountID() {
|
|
44
|
+
var _a;
|
|
45
|
+
return (_a = this.session.accountID) === null || _a === void 0 ? void 0 : _a.toString();
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* The display name of the player (Steam name or FiveM username).
|
|
49
|
+
*/
|
|
50
|
+
get name() {
|
|
51
|
+
return GetPlayerName(this.clientIDStr);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Retrieves all platform identifiers associated with the player (steam, license, discord, ip, etc.).
|
|
55
|
+
*
|
|
56
|
+
* @returns An array of identifier strings (e.g., `['steam:11000...', 'license:2332...']`).
|
|
57
|
+
*/
|
|
58
|
+
getIdentifiers() {
|
|
59
|
+
const ids = [];
|
|
60
|
+
for (let i = 0;; i++) {
|
|
61
|
+
const id = GetPlayerIdentifier(this.clientIDStr, i);
|
|
62
|
+
if (!id)
|
|
63
|
+
break;
|
|
64
|
+
ids.push(id);
|
|
65
|
+
}
|
|
66
|
+
return ids;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Sends a network event exclusively to this specific player (Client-side).
|
|
70
|
+
* Wrapper for `emitNet` ensuring the correct target Source ID is used.
|
|
71
|
+
*
|
|
72
|
+
* @param eventName - The name of the event to trigger on the client.
|
|
73
|
+
* @param args - Data to send to the client.
|
|
74
|
+
*/
|
|
75
|
+
emit(eventName, ...args) {
|
|
76
|
+
emitNet(eventName, this.clientID, ...args);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Teleports the player to a given position using Server-Side natives.
|
|
80
|
+
*
|
|
81
|
+
* **Note:** This forces the entity position on the server. For smoother gameplay transitions
|
|
82
|
+
* (e.g., inside interiors or across the map), consider using `teleportClient`.
|
|
83
|
+
*
|
|
84
|
+
* @param vector - The target coordinates (x, y, z).
|
|
85
|
+
*/
|
|
86
|
+
teleport(vector) {
|
|
87
|
+
SetEntityCoords(GetPlayerPed(this.clientIDStr), vector.x, vector.y, vector.z, false, false, false, true);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Requests the Client to teleport itself via the Core Spawner system.
|
|
91
|
+
*
|
|
92
|
+
* This method is preferred for gameplay logic as it allows the client to handle
|
|
93
|
+
* loading screens, fading, and collision loading gracefully.
|
|
94
|
+
*
|
|
95
|
+
* @param vector - The target coordinates (x, y, z).
|
|
96
|
+
*/
|
|
97
|
+
teleportClient(vector) {
|
|
98
|
+
this.emit('opencore:spawner:teleport', vector);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Disconnects the player from the server.
|
|
102
|
+
*
|
|
103
|
+
* @param reason - The message displayed to the player upon disconnection.
|
|
104
|
+
*/
|
|
105
|
+
kick(reason = 'Kicked from server') {
|
|
106
|
+
DropPlayer(this.clientID.toString(), reason);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Sets the routing bucket (virtual world / dimension) for the player.
|
|
110
|
+
* Players in different buckets cannot see or interact with each other.
|
|
111
|
+
*
|
|
112
|
+
* @param bucket - The bucket ID (0 is the default shared world).
|
|
113
|
+
*/
|
|
114
|
+
setRoutingBucket(bucket) {
|
|
115
|
+
SetPlayerRoutingBucket(this.clientID.toString(), bucket);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Stores arbitrary transient metadata for this player's session.
|
|
119
|
+
* Useful for flags like `isDead`, `isInRaid`, `lastLocation`, etc.
|
|
120
|
+
*
|
|
121
|
+
* @param key - The unique key for the metadata.
|
|
122
|
+
* @param value - The value to store.
|
|
123
|
+
*/
|
|
124
|
+
setMeta(key, value) {
|
|
125
|
+
this.session.meta[key] = value;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Retrieves metadata previously stored in the session.
|
|
129
|
+
*
|
|
130
|
+
* @template T - The expected type of the value.
|
|
131
|
+
* @param key - The metadata key.
|
|
132
|
+
* @returns The value cast to T, or `undefined` if not set.
|
|
133
|
+
*/
|
|
134
|
+
getMeta(key) {
|
|
135
|
+
return this.session.meta[key];
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Links a persistent Account ID to the current session.
|
|
139
|
+
* Should be called after successful authentication.
|
|
140
|
+
*
|
|
141
|
+
* @param accountID - The unique ID from the database.
|
|
142
|
+
*/
|
|
143
|
+
linkAccount(accountID) {
|
|
144
|
+
this.session.accountID = accountID;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Checks if the player currently possesses a specific state flag.
|
|
148
|
+
*
|
|
149
|
+
* @param state - The unique string identifier of the state (e.g., 'dead', 'cuffed').
|
|
150
|
+
* @returns `true` if the state is active, `false` otherwise.
|
|
151
|
+
*/
|
|
152
|
+
hasState(state) {
|
|
153
|
+
return this.states.has(state);
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Applies a state flag to the player.
|
|
157
|
+
*
|
|
158
|
+
* @remarks
|
|
159
|
+
* Since states are stored in a `Set`, adding an existing state has no effect (idempotent).
|
|
160
|
+
* Ideally, this should trigger a sync event to the client if needed.
|
|
161
|
+
*
|
|
162
|
+
* @param state - The state key to add.
|
|
163
|
+
*/
|
|
164
|
+
addState(state) {
|
|
165
|
+
this.states.add(state);
|
|
166
|
+
// this.emit('core:state:add', state) // ? optional !!
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Removes a specific state flag from the player.
|
|
170
|
+
*
|
|
171
|
+
* @param state - The state key to remove.
|
|
172
|
+
*/
|
|
173
|
+
removeState(state) {
|
|
174
|
+
this.states.delete(state);
|
|
175
|
+
// this.emit('core:state:remove', state) // ? optional !!
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Toggles the presence of a state flag.
|
|
179
|
+
*
|
|
180
|
+
* @param state - The state key to toggle.
|
|
181
|
+
* @param force - If provided, forces the state to be added (`true`) or removed (`false`) regardless of its current status.
|
|
182
|
+
*
|
|
183
|
+
* @returns The final status of the state (`true` if active, `false` if inactive).
|
|
184
|
+
*
|
|
185
|
+
* @example
|
|
186
|
+
* ```ts
|
|
187
|
+
* // Standard toggle
|
|
188
|
+
* player.toggleState('duty'); // turns on if off, off if on
|
|
189
|
+
*
|
|
190
|
+
* // Force enable (equivalent to addState but returns boolean)
|
|
191
|
+
* player.toggleState('duty', true); // always results in true
|
|
192
|
+
* ```
|
|
193
|
+
*/
|
|
194
|
+
toggleState(state, force) {
|
|
195
|
+
if (force !== undefined) {
|
|
196
|
+
force ? this.addState(state) : this.removeState(state);
|
|
197
|
+
return force;
|
|
198
|
+
}
|
|
199
|
+
if (this.hasState(state)) {
|
|
200
|
+
this.removeState(state);
|
|
201
|
+
return false;
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
this.addState(state);
|
|
205
|
+
return true;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Retrieves a snapshot of all currently active state flags for this player.
|
|
210
|
+
*
|
|
211
|
+
* @returns An array containing all active state keys.
|
|
212
|
+
*/
|
|
213
|
+
getStates() {
|
|
214
|
+
return Array.from(this.states);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
exports.Player = Player;
|