@armoury/fivem-framework-server 1.0.15 → 1.0.16

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.
@@ -0,0 +1,101 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var Database_1;
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.Database = void 0;
14
+ const injection_js_1 = require("injection-js");
15
+ const mysql2_1 = require("drizzle-orm/mysql2");
16
+ const promise_1 = require("mysql2/promise");
17
+ let Database = Database_1 = class Database {
18
+ constructor() {
19
+ this._tables = new Map();
20
+ console.log(`[DB:] Database service initialized! (this resource: ${Cfx.Server.GetCurrentResourceName()})`);
21
+ }
22
+ registerTable(identifier, table) {
23
+ if (this._tables.has(identifier)) {
24
+ throw new Error(`Table '${identifier}' is already registered.`);
25
+ }
26
+ this._tables.set(identifier, table);
27
+ return table;
28
+ }
29
+ getTable(identifier) {
30
+ const table = this._tables.get(identifier);
31
+ if (!table) {
32
+ throw new Error(`Table '${identifier}' is not registered.`);
33
+ }
34
+ return table;
35
+ }
36
+ getClient() {
37
+ if (!this._db) {
38
+ throw new Error('Database is not yet initialized');
39
+ }
40
+ return this._db;
41
+ }
42
+ setClient(db, rootResource) {
43
+ if (this._db) {
44
+ throw new Error('Database client is already set.');
45
+ }
46
+ this._db = db;
47
+ this._rootResource = rootResource;
48
+ }
49
+ isRoot() {
50
+ return Cfx.Server.GetCurrentResourceName() === this._rootResource;
51
+ }
52
+ static forRoot() {
53
+ return ({
54
+ provide: Database_1,
55
+ useFactory: () => {
56
+ const rootResource = Cfx.Server.GetCurrentResourceName();
57
+ const settings = Cfx.Server.GetConvar('mysql_connection_string', '')
58
+ .split(';')
59
+ .filter(Boolean)
60
+ .reduce((settings, entry) => {
61
+ const index = entry.indexOf('=');
62
+ if (index !== -1) {
63
+ settings[entry.slice(0, index)] = entry.slice(index + 1);
64
+ }
65
+ return settings;
66
+ }, {});
67
+ const pool = (0, promise_1.createPool)({
68
+ host: settings.host || 'localhost',
69
+ port: !isNaN(Number(settings.port)) ? Number(settings.port) : 3306,
70
+ user: settings.user || 'root',
71
+ password: settings.password,
72
+ database: settings.database || 'test',
73
+ });
74
+ console.log(`[DB:] Creating Drizzle instance... (rootResource: ${rootResource})`);
75
+ const drizzl = (0, mysql2_1.drizzle)({ client: pool });
76
+ console.log(`[DB:] Drizzle instance created! (rootResource: ${rootResource})`);
77
+ const db = new Database_1();
78
+ db.setClient(drizzl, Cfx.Server.GetCurrentResourceName());
79
+ return db;
80
+ },
81
+ deps: [],
82
+ });
83
+ }
84
+ static forChild() {
85
+ return ({
86
+ provide: Database_1,
87
+ useFactory: () => {
88
+ const db = new Database_1();
89
+ // TODO: Set client based on main resource here
90
+ // db.setClient(drizzl, Cfx.Server.GetCurrentResourceName());
91
+ return db;
92
+ },
93
+ deps: [],
94
+ });
95
+ }
96
+ };
97
+ exports.Database = Database;
98
+ exports.Database = Database = Database_1 = __decorate([
99
+ (0, injection_js_1.Injectable)(),
100
+ __metadata("design:paramtypes", [])
101
+ ], Database);
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AccountsTable = void 0;
4
+ const mysql_core_1 = require("drizzle-orm/mysql-core");
5
+ exports.AccountsTable = (0, mysql_core_1.mysqlTable)('accounts', {
6
+ id: (0, mysql_core_1.int)('id').primaryKey().autoincrement(),
7
+ platformId: (0, mysql_core_1.varchar)('platformId', { length: 64 }).notNull(),
8
+ lastKnownName: (0, mysql_core_1.varchar)('lastKnownName', { length: 255 }).notNull(),
9
+ });
@@ -15,50 +15,17 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
16
16
  };
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
- exports.SERVER_PROVIDERS = void 0;
18
+ exports.SERVER_EAGER_PROVIDERS = exports.SERVER_LAZY_PROVIDERS = void 0;
19
19
  exports.bootstrap = bootstrap;
20
20
  require("reflect-metadata");
21
- const default_entities_1 = require("./services/session/default-entities");
22
21
  const fivem_framework_common_1 = require("@armoury/fivem-framework-common");
23
- exports.SERVER_PROVIDERS = [
24
- {
25
- provide: 'sessionItems',
26
- useValue: new default_entities_1.SessionId(),
27
- multi: true,
28
- },
29
- {
30
- provide: 'sessionItems',
31
- useValue: new default_entities_1.SessionAccountId(),
32
- multi: true,
33
- },
34
- {
35
- provide: 'sessionItems',
36
- useValue: new default_entities_1.SessionName(),
37
- multi: true,
38
- },
39
- {
40
- provide: 'sessionItems',
41
- useValue: new default_entities_1.SessionCash(),
42
- multi: true,
43
- },
44
- {
45
- provide: 'sessionItems',
46
- useValue: new default_entities_1.SessionHoursPlayed(),
47
- multi: true,
48
- },
49
- {
50
- provide: 'sessionItems',
51
- useValue: new default_entities_1.SessionLastLocation(),
52
- multi: true,
53
- },
54
- {
55
- provide: 'sessionItems',
56
- useValue: new default_entities_1.SessionLanguage(),
57
- multi: true,
58
- },
22
+ const database_1 = require("./database/database");
23
+ exports.SERVER_LAZY_PROVIDERS = [];
24
+ exports.SERVER_EAGER_PROVIDERS = [
25
+ database_1.Database.forChild(),
59
26
  ];
60
27
  async function bootstrap(_class, options = {}) {
61
- return (0, fivem_framework_common_1.bootstrapWithProviders)(_class, exports.SERVER_PROVIDERS, options, undefined, (key, index) => Cfx.Server.GetResourceMetadata(Cfx.Server.GetCurrentResourceName(), key, index), (resourceName) => Cfx.exports[resourceName]);
28
+ return (0, fivem_framework_common_1.bootstrapWithProviders)(_class, exports.SERVER_LAZY_PROVIDERS, options, undefined, (key, index) => Cfx.Server.GetResourceMetadata(Cfx.Server.GetCurrentResourceName(), key, index), (resourceName) => Cfx.exports[resourceName], exports.SERVER_EAGER_PROVIDERS);
62
29
  }
63
30
  __exportStar(require("./services"), exports);
64
31
  __exportStar(require("./models"), exports);
@@ -18,4 +18,3 @@ __exportStar(require("./server-resource-database.service"), exports);
18
18
  __exportStar(require("./server-enterable-database.service"), exports);
19
19
  __exportStar(require("./server-virtual-worlds.service"), exports);
20
20
  __exportStar(require("./server-translate.service"), exports);
21
- __exportStar(require("./session"), exports);
@@ -15,7 +15,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.ServerVirtualWorldsService = void 0;
16
16
  const injection_js_1 = require("injection-js");
17
17
  const fivem_framework_common_1 = require("@armoury/fivem-framework-common");
18
- const session_1 = require("./session");
18
+ const server_session_service_1 = require("./session/server-session.service");
19
19
  let ServerVirtualWorldsService = class ServerVirtualWorldsService {
20
20
  constructor(_session) {
21
21
  this._session = _session;
@@ -30,19 +30,30 @@ let ServerVirtualWorldsService = class ServerVirtualWorldsService {
30
30
  Cfx.Server.TriggerClientEvent(`${Cfx.Server.GetCurrentResourceName()}:refresh-virtual-world`, data.for);
31
31
  }
32
32
  setPlayerVirtualWorld(playerId, virtualWorld) {
33
- const currentPlayerVirtualWorld = this.getPlayerVirtualWorld(playerId);
33
+ /*const currentPlayerVirtualWorld: number = this.getPlayerVirtualWorld(playerId);
34
+
34
35
  if (!isNaN(currentPlayerVirtualWorld)) {
35
- this._virtualWorldsWithPlayers.set(currentPlayerVirtualWorld, (this._virtualWorldsWithPlayers.has(currentPlayerVirtualWorld) ? this._virtualWorldsWithPlayers.get(currentPlayerVirtualWorld) : []).filter((_playerId) => _playerId !== playerId));
36
+ this._virtualWorldsWithPlayers.set(
37
+ currentPlayerVirtualWorld,
38
+ (this._virtualWorldsWithPlayers.has(currentPlayerVirtualWorld) ? this._virtualWorldsWithPlayers.get(currentPlayerVirtualWorld) : [])!.filter((_playerId: number) => _playerId !== playerId)
39
+ );
36
40
  }
37
- const newPlayersInVirtualWorld = [
38
- ...(this._virtualWorldsWithPlayers.has(virtualWorld) ? this._virtualWorldsWithPlayers.get(virtualWorld) : []),
41
+
42
+ const newPlayersInVirtualWorld: number[] = [
43
+ ...(this._virtualWorldsWithPlayers.has(virtualWorld) ? this._virtualWorldsWithPlayers.get(virtualWorld) : [])!,
39
44
  playerId
40
45
  ];
41
- this._virtualWorldsWithPlayers.set(virtualWorld, newPlayersInVirtualWorld);
42
- this._session.setPlayerInfo(playerId, 'virtualWorld', virtualWorld);
46
+
47
+ this._virtualWorldsWithPlayers.set(
48
+ virtualWorld,
49
+ newPlayersInVirtualWorld
50
+ );
51
+
52
+ this._session.setPlayerInfo(playerId, 'virtualWorld', virtualWorld);*/
43
53
  }
44
54
  getPlayerVirtualWorld(playerId) {
45
- return Math.max(0, this._session.getPlayerInfo(playerId, 'virtualWorld'));
55
+ return 0;
56
+ // return Math.max(0, this._session.getPlayerInfo(playerId, 'virtualWorld'));
46
57
  }
47
58
  removeClientsideVehicles() {
48
59
  Cfx.Server.TriggerClientEvent(`${Cfx.Server.GetCurrentResourceName()}:ARM_remove-vehicles`, -1);
@@ -57,6 +68,6 @@ __decorate([
57
68
  ], ServerVirtualWorldsService.prototype, "onPlayerEnteredScope", null);
58
69
  exports.ServerVirtualWorldsService = ServerVirtualWorldsService = __decorate([
59
70
  (0, injection_js_1.Injectable)(),
60
- __param(0, (0, injection_js_1.Inject)(session_1.ServerSessionService)),
61
- __metadata("design:paramtypes", [session_1.ServerSessionService])
71
+ __param(0, (0, injection_js_1.Inject)(server_session_service_1.ServerSessionService)),
72
+ __metadata("design:paramtypes", [server_session_service_1.ServerSessionService])
62
73
  ], ServerVirtualWorldsService);
@@ -8,264 +8,25 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
8
8
  var __metadata = (this && this.__metadata) || function (k, v) {
9
9
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
10
  };
11
- var __param = (this && this.__param) || function (paramIndex, decorator) {
12
- return function (target, key) { decorator(target, key, paramIndex); }
13
- };
14
- var ServerSessionService_1;
15
11
  Object.defineProperty(exports, "__esModule", { value: true });
16
12
  exports.ServerSessionService = void 0;
17
13
  const injection_js_1 = require("injection-js");
18
- const utils_1 = require("../../../utils/utils");
19
- const decorators_1 = require("../../../decorators");
20
- let ServerSessionService = ServerSessionService_1 = class ServerSessionService {
21
- get players() {
22
- return Array.from(this._sessions.keys());
23
- }
24
- get authenticatedPlayers() {
25
- return Array.from(this._sessions.entries())
26
- .filter(([, session]) => session.id)
27
- .map(([playerId,]) => playerId);
28
- }
29
- constructor(_sessionItems) {
30
- var _a;
31
- this._sessionItems = _sessionItems;
32
- this._sessions = new Map();
33
- this._untrackedSessionItems = [];
34
- this._sessionItems = (_a = _sessionItems === null || _sessionItems === void 0 ? void 0 : _sessionItems.filter((item) => !!item)) !== null && _a !== void 0 ? _a : [];
35
- if (!Cfx.exports['oxmysql']) {
36
- console.error(`[Armoury (${Cfx.Server.GetCurrentResourceName()}):] Could not find the 'oxmysql' resource. Armoury's session service can't work without it. Did you forget to load it?`);
37
- return;
14
+ const database_1 = require("../../database/database");
15
+ const accounts_table_1 = require("../../database/schemas/accounts.table");
16
+ let ServerSessionService = class ServerSessionService {
17
+ constructor(_database) {
18
+ this._database = _database;
19
+ if (_database.isRoot()) {
20
+ this._database.registerTable('accounts', accounts_table_1.AccountsTable);
21
+ console.log('[ServerSessionService] Registered accounts table in the database.');
38
22
  }
39
- }
40
- /**
41
- * Registers an account.
42
- * @param playerId The playerId (NOT from the database) of this player
43
- * @param accountName The account name of this player
44
- * @param hashedPassword The hashed password of this account
45
- * @param email The email of this account
46
- * @returns The SQL ID of the newly-created account
47
- */
48
- async register(playerId, accountName, hashedPassword, email) {
49
- const accountId = await Cfx.exports['oxmysql'].insert_async('INSERT INTO `accounts`(`name`, `password`, `email`) VALUES (?, ?, ?)', [accountName, hashedPassword, email]);
50
- this._sessions.set(playerId, { accountId });
51
- return accountId;
52
- }
53
- /**
54
- * Logs into an account
55
- * @param playerId The playerId (NOT from the database) of this player
56
- * @param email The email of the account
57
- * @param hashedPassword The hashed password fo this account
58
- * @returns Account data for this account
59
- */
60
- async login(playerId, email, hashedPassword) {
61
- const result = await Cfx.exports['oxmysql'].single_async('SELECT * FROM `accounts` WHERE email=? AND password=?', [email, hashedPassword]);
62
- this._sessions.set(playerId, { accountId: result.id });
63
- return result;
64
- }
65
- /**
66
- * Fetches all the characters related to the provided account
67
- * @param playerId The playerId (NOT from the database) of this player
68
- * @param accountId The accountId of the
69
- * @returns Data for all characters on the given account
70
- */
71
- async fetch(playerId, accountId) {
72
- var _a;
73
- accountId = accountId !== null && accountId !== void 0 ? accountId : (_a = this._sessions.get(playerId)) === null || _a === void 0 ? void 0 : _a.accountId;
74
- return await global.exports['oxmysql'].query_async(`SELECT * FROM players WHERE accountId = ?`, [accountId]);
75
- }
76
- /**
77
- * Loads the entire character given a character ID
78
- * @param playerId The playerId (NOT from the database) of this player
79
- * @param characterId The character's SQL ID
80
- * @returns Data for the given characterId
81
- */
82
- async load(playerId, characterId) {
83
- var _a;
84
- if (!this._sessions.has(playerId)) {
85
- throw new Error('No session has been found for that user.');
23
+ else {
24
+ console.log('[ServerSessionService] Not the root resource, skipping table registration.');
86
25
  }
87
- const session = await global.exports['oxmysql'].single_async('SELECT * FROM `players` WHERE id=? AND accountId=?', [characterId, (_a = this._sessions.get(playerId)) === null || _a === void 0 ? void 0 : _a.accountId]);
88
- Array.from(Object.entries(session))
89
- .map(([key,]) => { var _a; return (_a = this._sessionItems) === null || _a === void 0 ? void 0 : _a.find((sessionItem) => sessionItem.name === key); })
90
- .filter((sessionItem) => !!sessionItem)
91
- .forEach(async (sessionItem) => {
92
- var _a, _b, _c, _d;
93
- console.log('for sessionItem', sessionItem.name, 'the value is', (_b = await (sessionItem === null || sessionItem === void 0 ? void 0 : sessionItem.load((_a = this._sessions.get(playerId)) === null || _a === void 0 ? void 0 : _a.accountId, characterId, session[sessionItem === null || sessionItem === void 0 ? void 0 : sessionItem.name]))) !== null && _b !== void 0 ? _b : session[sessionItem === null || sessionItem === void 0 ? void 0 : sessionItem.name].value);
94
- this.setPlayerInfo(playerId, sessionItem.name, (_d = await (sessionItem === null || sessionItem === void 0 ? void 0 : sessionItem.load((_c = this._sessions.get(playerId)) === null || _c === void 0 ? void 0 : _c.accountId, characterId, session[sessionItem === null || sessionItem === void 0 ? void 0 : sessionItem.name]))) !== null && _d !== void 0 ? _d : session[sessionItem === null || sessionItem === void 0 ? void 0 : sessionItem.name].value);
95
- });
96
- this._sessions.set(playerId, Object.assign(Object.assign({}, this._sessions.get(playerId)), { id: characterId }));
97
- return session;
98
- }
99
- /**
100
- * Creates a character
101
- * @param playerId
102
- * @param accountName
103
- * @param hashedPassword
104
- * @param email
105
- * @returns
106
- */
107
- async create(playerId, accountId) {
108
- var _a;
109
- accountId = accountId !== null && accountId !== void 0 ? accountId : (_a = this._sessions.get(playerId)) === null || _a === void 0 ? void 0 : _a.accountId;
110
- const characterId = await Cfx.exports['oxmysql'].insert_async('INSERT INTO `players`(`accountId`) VALUES (?)', [accountId]);
111
- this._sessions.set(playerId, { accountId });
112
- return characterId;
113
- }
114
- setPlayerInfo(playerId, stat, value, ...args) {
115
- const updater = new SessionUpdater(playerId).from(stat, value, ...args);
116
- updater.execute(this.getPlayerInfo(playerId, 'accountId'), this.getPlayerInfo(playerId, 'id'), this._sessionItems);
117
- const untrackedItems = updater.items
118
- .filter((item) => {
119
- var _a;
120
- return !this._untrackedSessionItems.includes(item.stat)
121
- && !((_a = this._sessionItems) === null || _a === void 0 ? void 0 : _a.some((sessionItem) => sessionItem.name === item.stat));
122
- });
123
- if (untrackedItems.length) {
124
- this._untrackedSessionItems.push(...untrackedItems.map((item) => item.stat));
125
- }
126
- }
127
- setPlayerCash(playerId, value, options) {
128
- return this.setPlayerInfo(playerId, 'cash', value, options);
129
- }
130
- givePlayerCash(playerId, value, options) {
131
- return this.setPlayerCash(playerId, this.getPlayerCash(playerId) + value, options);
132
- }
133
- getPlayerCash(playerId) {
134
- return this.getPlayerInfo(playerId, 'cash');
135
- }
136
- saveCritical(playerId) {
137
- var _a, _b;
138
- const criticalStats = (_b = (_a = this._sessionItems) === null || _a === void 0 ? void 0 : _a.filter((sessionItem) => sessionItem.critical)) === null || _b === void 0 ? void 0 : _b.map((sessionItem) => sessionItem.name);
139
- console.log(`${Cfx.Server.GetCurrentResourceName()}: Critical keys are`, criticalStats, 'playerId is', playerId);
140
- this.setPlayerInfo(playerId, criticalStats[0], this.getPlayerInfo(playerId, criticalStats[0]), ...criticalStats.slice(1).reduce((prev, curr) => [
141
- ...prev,
142
- curr,
143
- this.getPlayerInfo(playerId, curr)
144
- ], []), {
145
- executeSqlCommand: true
146
- });
147
- }
148
- getPlayerInfo(playerId, stat) {
149
- let value = Cfx.Server.GetConvar(`${playerId}_PI_${stat}`, '-1');
150
- if ((0, utils_1.isJSON)(value.toString())) {
151
- value = JSON.parse(value, function (_k, v) {
152
- return typeof v === 'object' || isNaN(v) ? v : Number(v);
153
- });
154
- }
155
- return value;
156
- }
157
- clearPlayerInfo(playerId) {
158
- var _a;
159
- [...(_a = this._sessionItems) === null || _a === void 0 ? void 0 : _a.map((sessionItem) => sessionItem.name), ...this._untrackedSessionItems]
160
- .forEach((prop) => {
161
- Cfx.Server.SetConvarReplicated(`${playerId}_PI_${prop}`, '-1');
162
- Cfx.Server.SetConvarReplicated(`${playerId}_PI_${prop}_lastUpdate`, '-1');
163
- });
164
- }
165
- onResourceStart(resource) {
166
- var _a, _b;
167
- if (resource !== Cfx.Server.GetCurrentResourceName()) {
168
- if (Cfx.exports[resource].exchangeSessionItems) {
169
- console.log(`[Armoury:] Resource (${resource}) has started. Attempting to exchange session items with it..`);
170
- this.exchangeSessionItems((_b = Cfx.exports[resource].exchangeSessionItems((_a = this._sessionItems) !== null && _a !== void 0 ? _a : [])) !== null && _b !== void 0 ? _b : []);
171
- }
172
- }
173
- }
174
- exchangeSessionItems(items) {
175
- var _a, _b;
176
- items.forEach((item) => {
177
- var _a, _b;
178
- if (!((_a = this._sessionItems) === null || _a === void 0 ? void 0 : _a.some((sessionItem) => sessionItem.name === item.name))) {
179
- (_b = this._sessionItems) === null || _b === void 0 ? void 0 : _b.push(item);
180
- }
181
- });
182
- console.log(`[${Cfx.Server.GetCurrentResourceName()}:] My updated session items are now`, (_a = this._sessionItems) !== null && _a !== void 0 ? _a : []);
183
- return (_b = this._sessionItems) !== null && _b !== void 0 ? _b : [];
184
- }
185
- static withDefaults() {
186
- return ({
187
- provide: ServerSessionService_1,
188
- useFactory: (sessionItems) => new ServerSessionService_1(sessionItems || []),
189
- deps: ['sessionItems'],
190
- });
191
- }
192
- static withItems(...items) {
193
- return [
194
- ...items.map((sessionItem) => ({
195
- provide: 'sessionItems',
196
- useValue: new sessionItem(),
197
- multi: true,
198
- })),
199
- ServerSessionService_1.withDefaults()
200
- ];
201
26
  }
202
27
  };
203
28
  exports.ServerSessionService = ServerSessionService;
204
- __decorate([
205
- (0, decorators_1.EventListener)({ eventName: 'onResourceStart', direction: decorators_1.EVENT_DIRECTIONS.CLIENT_TO_CLIENT }),
206
- __metadata("design:type", Function),
207
- __metadata("design:paramtypes", [String]),
208
- __metadata("design:returntype", void 0)
209
- ], ServerSessionService.prototype, "onResourceStart", null);
210
- __decorate([
211
- (0, decorators_1.Export)(),
212
- __metadata("design:type", Function),
213
- __metadata("design:paramtypes", [Array]),
214
- __metadata("design:returntype", Array)
215
- ], ServerSessionService.prototype, "exchangeSessionItems", null);
216
- exports.ServerSessionService = ServerSessionService = ServerSessionService_1 = __decorate([
29
+ exports.ServerSessionService = ServerSessionService = __decorate([
217
30
  (0, injection_js_1.Injectable)(),
218
- __param(0, (0, injection_js_1.Optional)()),
219
- __param(0, (0, injection_js_1.Inject)('sessionItems')),
220
- __metadata("design:paramtypes", [Array])
31
+ __metadata("design:paramtypes", [database_1.Database])
221
32
  ], ServerSessionService);
222
- class SessionUpdater {
223
- constructor(playerId) {
224
- this.playerId = playerId;
225
- this.items = [];
226
- this.options = null;
227
- }
228
- from(...statsAndValues) {
229
- if (statsAndValues.length % 2 !== 0 && typeof statsAndValues.slice(-1)[0] === 'object') {
230
- this.options = statsAndValues.slice(-1)[0];
231
- }
232
- for (let i = 0; i < statsAndValues.length; i += 2) {
233
- if (typeof statsAndValues[i] === 'string' && !!statsAndValues[i + 1]) {
234
- this.add(statsAndValues[i], statsAndValues[i + 1]);
235
- }
236
- }
237
- return this;
238
- }
239
- add(stat, value) {
240
- this.items.push({ stat, value });
241
- return this;
242
- }
243
- execute(accountId, characterId, sessionItems) {
244
- var _a;
245
- this.items.forEach((item) => {
246
- let value = item.value;
247
- const correspondingSessionItem = sessionItems.find((sessionItem) => sessionItem.name === item.stat);
248
- if (correspondingSessionItem) {
249
- value = correspondingSessionItem.compute(this.playerId, item.value);
250
- }
251
- Cfx.Server.SetConvarReplicated(`${this.playerId}_PI_${item.stat}`, Array.isArray(value) || typeof value === 'object'
252
- ? JSON.stringify(value)
253
- : value.toString());
254
- Cfx.Server.SetConvarReplicated(`${this.playerId}_PI_${item.stat}_lastUpdate`, new Date().getTime().toString());
255
- });
256
- if ((_a = this.options) === null || _a === void 0 ? void 0 : _a.executeSqlCommand) {
257
- const syncableItems = this.items.filter((item) => {
258
- var _a, _b;
259
- return sessionItems.some((sessionItem) => sessionItem.name === item.stat) && !((_b = (_a = this.options) === null || _a === void 0 ? void 0 : _a.ignoreSqlCommandFor) === null || _b === void 0 ? void 0 : _b.includes(item.stat));
260
- });
261
- if (syncableItems.length) {
262
- const predicate = (item) => { var _a; return (_a = sessionItems.find((sessionItem) => sessionItem.name === item.stat)) === null || _a === void 0 ? void 0 : _a.save; };
263
- const simpleSyncableItems = syncableItems.filter((item) => !predicate(item)).filter((item) => !!item && item.value != null);
264
- console.log('simpleSyncableItems are', simpleSyncableItems);
265
- Cfx.exports['oxmysql'].update_async(`UPDATE \`players\` SET ${simpleSyncableItems.map((item) => `${item.stat} = ?`).join(', ')} WHERE id = ?`, [...simpleSyncableItems.map((item) => JSON.stringify(item.value)), characterId]);
266
- const nonSimpleSyncableItems = syncableItems.filter((item) => predicate(item));
267
- nonSimpleSyncableItems.forEach((item) => sessionItems.find((sessionItem) => sessionItem.name === item.stat).save(accountId, characterId, item.value));
268
- }
269
- }
270
- }
271
- }
@@ -0,0 +1,98 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ 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;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ var Database_1;
11
+ import { Injectable } from 'injection-js';
12
+ import { drizzle } from 'drizzle-orm/mysql2';
13
+ import { createPool } from 'mysql2/promise';
14
+ let Database = Database_1 = class Database {
15
+ constructor() {
16
+ this._tables = new Map();
17
+ console.log(`[DB:] Database service initialized! (this resource: ${Cfx.Server.GetCurrentResourceName()})`);
18
+ }
19
+ registerTable(identifier, table) {
20
+ if (this._tables.has(identifier)) {
21
+ throw new Error(`Table '${identifier}' is already registered.`);
22
+ }
23
+ this._tables.set(identifier, table);
24
+ return table;
25
+ }
26
+ getTable(identifier) {
27
+ const table = this._tables.get(identifier);
28
+ if (!table) {
29
+ throw new Error(`Table '${identifier}' is not registered.`);
30
+ }
31
+ return table;
32
+ }
33
+ getClient() {
34
+ if (!this._db) {
35
+ throw new Error('Database is not yet initialized');
36
+ }
37
+ return this._db;
38
+ }
39
+ setClient(db, rootResource) {
40
+ if (this._db) {
41
+ throw new Error('Database client is already set.');
42
+ }
43
+ this._db = db;
44
+ this._rootResource = rootResource;
45
+ }
46
+ isRoot() {
47
+ return Cfx.Server.GetCurrentResourceName() === this._rootResource;
48
+ }
49
+ static forRoot() {
50
+ return ({
51
+ provide: Database_1,
52
+ useFactory: () => {
53
+ const rootResource = Cfx.Server.GetCurrentResourceName();
54
+ const settings = Cfx.Server.GetConvar('mysql_connection_string', '')
55
+ .split(';')
56
+ .filter(Boolean)
57
+ .reduce((settings, entry) => {
58
+ const index = entry.indexOf('=');
59
+ if (index !== -1) {
60
+ settings[entry.slice(0, index)] = entry.slice(index + 1);
61
+ }
62
+ return settings;
63
+ }, {});
64
+ const pool = createPool({
65
+ host: settings.host || 'localhost',
66
+ port: !isNaN(Number(settings.port)) ? Number(settings.port) : 3306,
67
+ user: settings.user || 'root',
68
+ password: settings.password,
69
+ database: settings.database || 'test',
70
+ });
71
+ console.log(`[DB:] Creating Drizzle instance... (rootResource: ${rootResource})`);
72
+ const drizzl = drizzle({ client: pool });
73
+ console.log(`[DB:] Drizzle instance created! (rootResource: ${rootResource})`);
74
+ const db = new Database_1();
75
+ db.setClient(drizzl, Cfx.Server.GetCurrentResourceName());
76
+ return db;
77
+ },
78
+ deps: [],
79
+ });
80
+ }
81
+ static forChild() {
82
+ return ({
83
+ provide: Database_1,
84
+ useFactory: () => {
85
+ const db = new Database_1();
86
+ // TODO: Set client based on main resource here
87
+ // db.setClient(drizzl, Cfx.Server.GetCurrentResourceName());
88
+ return db;
89
+ },
90
+ deps: [],
91
+ });
92
+ }
93
+ };
94
+ Database = Database_1 = __decorate([
95
+ Injectable(),
96
+ __metadata("design:paramtypes", [])
97
+ ], Database);
98
+ export { Database };
@@ -0,0 +1,6 @@
1
+ import { mysqlTable, int, varchar } from 'drizzle-orm/mysql-core';
2
+ export const AccountsTable = mysqlTable('accounts', {
3
+ id: int('id').primaryKey().autoincrement(),
4
+ platformId: varchar('platformId', { length: 64 }).notNull(),
5
+ lastKnownName: varchar('lastKnownName', { length: 255 }).notNull(),
6
+ });
@@ -1,46 +1,13 @@
1
1
  /// <reference path = "../ambient.declarations.d.ts" />
2
2
  import 'reflect-metadata';
3
- import { SessionAccountId, SessionCash, SessionHoursPlayed, SessionId, SessionLanguage, SessionLastLocation, SessionName } from './services/session/default-entities';
4
3
  import { bootstrapWithProviders } from '@armoury/fivem-framework-common';
5
- export const SERVER_PROVIDERS = [
6
- {
7
- provide: 'sessionItems',
8
- useValue: new SessionId(),
9
- multi: true,
10
- },
11
- {
12
- provide: 'sessionItems',
13
- useValue: new SessionAccountId(),
14
- multi: true,
15
- },
16
- {
17
- provide: 'sessionItems',
18
- useValue: new SessionName(),
19
- multi: true,
20
- },
21
- {
22
- provide: 'sessionItems',
23
- useValue: new SessionCash(),
24
- multi: true,
25
- },
26
- {
27
- provide: 'sessionItems',
28
- useValue: new SessionHoursPlayed(),
29
- multi: true,
30
- },
31
- {
32
- provide: 'sessionItems',
33
- useValue: new SessionLastLocation(),
34
- multi: true,
35
- },
36
- {
37
- provide: 'sessionItems',
38
- useValue: new SessionLanguage(),
39
- multi: true,
40
- },
4
+ import { Database } from './database/database';
5
+ export const SERVER_LAZY_PROVIDERS = [];
6
+ export const SERVER_EAGER_PROVIDERS = [
7
+ Database.forChild(),
41
8
  ];
42
9
  export async function bootstrap(_class, options = {}) {
43
- return bootstrapWithProviders(_class, SERVER_PROVIDERS, options, undefined, (key, index) => Cfx.Server.GetResourceMetadata(Cfx.Server.GetCurrentResourceName(), key, index), (resourceName) => Cfx.exports[resourceName]);
10
+ return bootstrapWithProviders(_class, SERVER_LAZY_PROVIDERS, options, undefined, (key, index) => Cfx.Server.GetResourceMetadata(Cfx.Server.GetCurrentResourceName(), key, index), (resourceName) => Cfx.exports[resourceName], SERVER_EAGER_PROVIDERS);
44
11
  }
45
12
  export * from './services';
46
13
  export * from './models';
@@ -2,4 +2,3 @@ export * from './server-resource-database.service';
2
2
  export * from './server-enterable-database.service';
3
3
  export * from './server-virtual-worlds.service';
4
4
  export * from './server-translate.service';
5
- export * from './session';
@@ -10,9 +10,9 @@ var __metadata = (this && this.__metadata) || function (k, v) {
10
10
  var __param = (this && this.__param) || function (paramIndex, decorator) {
11
11
  return function (target, key) { decorator(target, key, paramIndex); }
12
12
  };
13
- import { Inject, Injectable } from "injection-js";
13
+ import { Inject, Injectable } from 'injection-js';
14
14
  import { EventListener } from '@armoury/fivem-framework-common';
15
- import { ServerSessionService } from "./session";
15
+ import { ServerSessionService } from './session/server-session.service';
16
16
  let ServerVirtualWorldsService = class ServerVirtualWorldsService {
17
17
  constructor(_session) {
18
18
  this._session = _session;
@@ -27,19 +27,30 @@ let ServerVirtualWorldsService = class ServerVirtualWorldsService {
27
27
  Cfx.Server.TriggerClientEvent(`${Cfx.Server.GetCurrentResourceName()}:refresh-virtual-world`, data.for);
28
28
  }
29
29
  setPlayerVirtualWorld(playerId, virtualWorld) {
30
- const currentPlayerVirtualWorld = this.getPlayerVirtualWorld(playerId);
30
+ /*const currentPlayerVirtualWorld: number = this.getPlayerVirtualWorld(playerId);
31
+
31
32
  if (!isNaN(currentPlayerVirtualWorld)) {
32
- this._virtualWorldsWithPlayers.set(currentPlayerVirtualWorld, (this._virtualWorldsWithPlayers.has(currentPlayerVirtualWorld) ? this._virtualWorldsWithPlayers.get(currentPlayerVirtualWorld) : []).filter((_playerId) => _playerId !== playerId));
33
+ this._virtualWorldsWithPlayers.set(
34
+ currentPlayerVirtualWorld,
35
+ (this._virtualWorldsWithPlayers.has(currentPlayerVirtualWorld) ? this._virtualWorldsWithPlayers.get(currentPlayerVirtualWorld) : [])!.filter((_playerId: number) => _playerId !== playerId)
36
+ );
33
37
  }
34
- const newPlayersInVirtualWorld = [
35
- ...(this._virtualWorldsWithPlayers.has(virtualWorld) ? this._virtualWorldsWithPlayers.get(virtualWorld) : []),
38
+
39
+ const newPlayersInVirtualWorld: number[] = [
40
+ ...(this._virtualWorldsWithPlayers.has(virtualWorld) ? this._virtualWorldsWithPlayers.get(virtualWorld) : [])!,
36
41
  playerId
37
42
  ];
38
- this._virtualWorldsWithPlayers.set(virtualWorld, newPlayersInVirtualWorld);
39
- this._session.setPlayerInfo(playerId, 'virtualWorld', virtualWorld);
43
+
44
+ this._virtualWorldsWithPlayers.set(
45
+ virtualWorld,
46
+ newPlayersInVirtualWorld
47
+ );
48
+
49
+ this._session.setPlayerInfo(playerId, 'virtualWorld', virtualWorld);*/
40
50
  }
41
51
  getPlayerVirtualWorld(playerId) {
42
- return Math.max(0, this._session.getPlayerInfo(playerId, 'virtualWorld'));
52
+ return 0;
53
+ // return Math.max(0, this._session.getPlayerInfo(playerId, 'virtualWorld'));
43
54
  }
44
55
  removeClientsideVehicles() {
45
56
  Cfx.Server.TriggerClientEvent(`${Cfx.Server.GetCurrentResourceName()}:ARM_remove-vehicles`, -1);
@@ -7,262 +7,23 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
7
7
  var __metadata = (this && this.__metadata) || function (k, v) {
8
8
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
9
  };
10
- var __param = (this && this.__param) || function (paramIndex, decorator) {
11
- return function (target, key) { decorator(target, key, paramIndex); }
12
- };
13
- var ServerSessionService_1;
14
- import { Inject, Injectable, Optional } from "injection-js";
15
- import { isJSON } from "../../../utils/utils";
16
- import { EVENT_DIRECTIONS, EventListener, Export } from "../../../decorators";
17
- let ServerSessionService = ServerSessionService_1 = class ServerSessionService {
18
- get players() {
19
- return Array.from(this._sessions.keys());
20
- }
21
- get authenticatedPlayers() {
22
- return Array.from(this._sessions.entries())
23
- .filter(([, session]) => session.id)
24
- .map(([playerId,]) => playerId);
25
- }
26
- constructor(_sessionItems) {
27
- var _a;
28
- this._sessionItems = _sessionItems;
29
- this._sessions = new Map();
30
- this._untrackedSessionItems = [];
31
- this._sessionItems = (_a = _sessionItems === null || _sessionItems === void 0 ? void 0 : _sessionItems.filter((item) => !!item)) !== null && _a !== void 0 ? _a : [];
32
- if (!Cfx.exports['oxmysql']) {
33
- console.error(`[Armoury (${Cfx.Server.GetCurrentResourceName()}):] Could not find the 'oxmysql' resource. Armoury's session service can't work without it. Did you forget to load it?`);
34
- return;
10
+ import { Injectable } from 'injection-js';
11
+ import { Database } from '../../database/database';
12
+ import { AccountsTable } from '../../database/schemas/accounts.table';
13
+ let ServerSessionService = class ServerSessionService {
14
+ constructor(_database) {
15
+ this._database = _database;
16
+ if (_database.isRoot()) {
17
+ this._database.registerTable('accounts', AccountsTable);
18
+ console.log('[ServerSessionService] Registered accounts table in the database.');
35
19
  }
36
- }
37
- /**
38
- * Registers an account.
39
- * @param playerId The playerId (NOT from the database) of this player
40
- * @param accountName The account name of this player
41
- * @param hashedPassword The hashed password of this account
42
- * @param email The email of this account
43
- * @returns The SQL ID of the newly-created account
44
- */
45
- async register(playerId, accountName, hashedPassword, email) {
46
- const accountId = await Cfx.exports['oxmysql'].insert_async('INSERT INTO `accounts`(`name`, `password`, `email`) VALUES (?, ?, ?)', [accountName, hashedPassword, email]);
47
- this._sessions.set(playerId, { accountId });
48
- return accountId;
49
- }
50
- /**
51
- * Logs into an account
52
- * @param playerId The playerId (NOT from the database) of this player
53
- * @param email The email of the account
54
- * @param hashedPassword The hashed password fo this account
55
- * @returns Account data for this account
56
- */
57
- async login(playerId, email, hashedPassword) {
58
- const result = await Cfx.exports['oxmysql'].single_async('SELECT * FROM `accounts` WHERE email=? AND password=?', [email, hashedPassword]);
59
- this._sessions.set(playerId, { accountId: result.id });
60
- return result;
61
- }
62
- /**
63
- * Fetches all the characters related to the provided account
64
- * @param playerId The playerId (NOT from the database) of this player
65
- * @param accountId The accountId of the
66
- * @returns Data for all characters on the given account
67
- */
68
- async fetch(playerId, accountId) {
69
- var _a;
70
- accountId = accountId !== null && accountId !== void 0 ? accountId : (_a = this._sessions.get(playerId)) === null || _a === void 0 ? void 0 : _a.accountId;
71
- return await global.exports['oxmysql'].query_async(`SELECT * FROM players WHERE accountId = ?`, [accountId]);
72
- }
73
- /**
74
- * Loads the entire character given a character ID
75
- * @param playerId The playerId (NOT from the database) of this player
76
- * @param characterId The character's SQL ID
77
- * @returns Data for the given characterId
78
- */
79
- async load(playerId, characterId) {
80
- var _a;
81
- if (!this._sessions.has(playerId)) {
82
- throw new Error('No session has been found for that user.');
20
+ else {
21
+ console.log('[ServerSessionService] Not the root resource, skipping table registration.');
83
22
  }
84
- const session = await global.exports['oxmysql'].single_async('SELECT * FROM `players` WHERE id=? AND accountId=?', [characterId, (_a = this._sessions.get(playerId)) === null || _a === void 0 ? void 0 : _a.accountId]);
85
- Array.from(Object.entries(session))
86
- .map(([key,]) => { var _a; return (_a = this._sessionItems) === null || _a === void 0 ? void 0 : _a.find((sessionItem) => sessionItem.name === key); })
87
- .filter((sessionItem) => !!sessionItem)
88
- .forEach(async (sessionItem) => {
89
- var _a, _b, _c, _d;
90
- console.log('for sessionItem', sessionItem.name, 'the value is', (_b = await (sessionItem === null || sessionItem === void 0 ? void 0 : sessionItem.load((_a = this._sessions.get(playerId)) === null || _a === void 0 ? void 0 : _a.accountId, characterId, session[sessionItem === null || sessionItem === void 0 ? void 0 : sessionItem.name]))) !== null && _b !== void 0 ? _b : session[sessionItem === null || sessionItem === void 0 ? void 0 : sessionItem.name].value);
91
- this.setPlayerInfo(playerId, sessionItem.name, (_d = await (sessionItem === null || sessionItem === void 0 ? void 0 : sessionItem.load((_c = this._sessions.get(playerId)) === null || _c === void 0 ? void 0 : _c.accountId, characterId, session[sessionItem === null || sessionItem === void 0 ? void 0 : sessionItem.name]))) !== null && _d !== void 0 ? _d : session[sessionItem === null || sessionItem === void 0 ? void 0 : sessionItem.name].value);
92
- });
93
- this._sessions.set(playerId, Object.assign(Object.assign({}, this._sessions.get(playerId)), { id: characterId }));
94
- return session;
95
- }
96
- /**
97
- * Creates a character
98
- * @param playerId
99
- * @param accountName
100
- * @param hashedPassword
101
- * @param email
102
- * @returns
103
- */
104
- async create(playerId, accountId) {
105
- var _a;
106
- accountId = accountId !== null && accountId !== void 0 ? accountId : (_a = this._sessions.get(playerId)) === null || _a === void 0 ? void 0 : _a.accountId;
107
- const characterId = await Cfx.exports['oxmysql'].insert_async('INSERT INTO `players`(`accountId`) VALUES (?)', [accountId]);
108
- this._sessions.set(playerId, { accountId });
109
- return characterId;
110
- }
111
- setPlayerInfo(playerId, stat, value, ...args) {
112
- const updater = new SessionUpdater(playerId).from(stat, value, ...args);
113
- updater.execute(this.getPlayerInfo(playerId, 'accountId'), this.getPlayerInfo(playerId, 'id'), this._sessionItems);
114
- const untrackedItems = updater.items
115
- .filter((item) => {
116
- var _a;
117
- return !this._untrackedSessionItems.includes(item.stat)
118
- && !((_a = this._sessionItems) === null || _a === void 0 ? void 0 : _a.some((sessionItem) => sessionItem.name === item.stat));
119
- });
120
- if (untrackedItems.length) {
121
- this._untrackedSessionItems.push(...untrackedItems.map((item) => item.stat));
122
- }
123
- }
124
- setPlayerCash(playerId, value, options) {
125
- return this.setPlayerInfo(playerId, 'cash', value, options);
126
- }
127
- givePlayerCash(playerId, value, options) {
128
- return this.setPlayerCash(playerId, this.getPlayerCash(playerId) + value, options);
129
- }
130
- getPlayerCash(playerId) {
131
- return this.getPlayerInfo(playerId, 'cash');
132
- }
133
- saveCritical(playerId) {
134
- var _a, _b;
135
- const criticalStats = (_b = (_a = this._sessionItems) === null || _a === void 0 ? void 0 : _a.filter((sessionItem) => sessionItem.critical)) === null || _b === void 0 ? void 0 : _b.map((sessionItem) => sessionItem.name);
136
- console.log(`${Cfx.Server.GetCurrentResourceName()}: Critical keys are`, criticalStats, 'playerId is', playerId);
137
- this.setPlayerInfo(playerId, criticalStats[0], this.getPlayerInfo(playerId, criticalStats[0]), ...criticalStats.slice(1).reduce((prev, curr) => [
138
- ...prev,
139
- curr,
140
- this.getPlayerInfo(playerId, curr)
141
- ], []), {
142
- executeSqlCommand: true
143
- });
144
- }
145
- getPlayerInfo(playerId, stat) {
146
- let value = Cfx.Server.GetConvar(`${playerId}_PI_${stat}`, '-1');
147
- if (isJSON(value.toString())) {
148
- value = JSON.parse(value, function (_k, v) {
149
- return typeof v === 'object' || isNaN(v) ? v : Number(v);
150
- });
151
- }
152
- return value;
153
- }
154
- clearPlayerInfo(playerId) {
155
- var _a;
156
- [...(_a = this._sessionItems) === null || _a === void 0 ? void 0 : _a.map((sessionItem) => sessionItem.name), ...this._untrackedSessionItems]
157
- .forEach((prop) => {
158
- Cfx.Server.SetConvarReplicated(`${playerId}_PI_${prop}`, '-1');
159
- Cfx.Server.SetConvarReplicated(`${playerId}_PI_${prop}_lastUpdate`, '-1');
160
- });
161
- }
162
- onResourceStart(resource) {
163
- var _a, _b;
164
- if (resource !== Cfx.Server.GetCurrentResourceName()) {
165
- if (Cfx.exports[resource].exchangeSessionItems) {
166
- console.log(`[Armoury:] Resource (${resource}) has started. Attempting to exchange session items with it..`);
167
- this.exchangeSessionItems((_b = Cfx.exports[resource].exchangeSessionItems((_a = this._sessionItems) !== null && _a !== void 0 ? _a : [])) !== null && _b !== void 0 ? _b : []);
168
- }
169
- }
170
- }
171
- exchangeSessionItems(items) {
172
- var _a, _b;
173
- items.forEach((item) => {
174
- var _a, _b;
175
- if (!((_a = this._sessionItems) === null || _a === void 0 ? void 0 : _a.some((sessionItem) => sessionItem.name === item.name))) {
176
- (_b = this._sessionItems) === null || _b === void 0 ? void 0 : _b.push(item);
177
- }
178
- });
179
- console.log(`[${Cfx.Server.GetCurrentResourceName()}:] My updated session items are now`, (_a = this._sessionItems) !== null && _a !== void 0 ? _a : []);
180
- return (_b = this._sessionItems) !== null && _b !== void 0 ? _b : [];
181
- }
182
- static withDefaults() {
183
- return ({
184
- provide: ServerSessionService_1,
185
- useFactory: (sessionItems) => new ServerSessionService_1(sessionItems || []),
186
- deps: ['sessionItems'],
187
- });
188
- }
189
- static withItems(...items) {
190
- return [
191
- ...items.map((sessionItem) => ({
192
- provide: 'sessionItems',
193
- useValue: new sessionItem(),
194
- multi: true,
195
- })),
196
- ServerSessionService_1.withDefaults()
197
- ];
198
23
  }
199
24
  };
200
- __decorate([
201
- EventListener({ eventName: 'onResourceStart', direction: EVENT_DIRECTIONS.CLIENT_TO_CLIENT }),
202
- __metadata("design:type", Function),
203
- __metadata("design:paramtypes", [String]),
204
- __metadata("design:returntype", void 0)
205
- ], ServerSessionService.prototype, "onResourceStart", null);
206
- __decorate([
207
- Export(),
208
- __metadata("design:type", Function),
209
- __metadata("design:paramtypes", [Array]),
210
- __metadata("design:returntype", Array)
211
- ], ServerSessionService.prototype, "exchangeSessionItems", null);
212
- ServerSessionService = ServerSessionService_1 = __decorate([
25
+ ServerSessionService = __decorate([
213
26
  Injectable(),
214
- __param(0, Optional()),
215
- __param(0, Inject('sessionItems')),
216
- __metadata("design:paramtypes", [Array])
27
+ __metadata("design:paramtypes", [Database])
217
28
  ], ServerSessionService);
218
29
  export { ServerSessionService };
219
- class SessionUpdater {
220
- constructor(playerId) {
221
- this.playerId = playerId;
222
- this.items = [];
223
- this.options = null;
224
- }
225
- from(...statsAndValues) {
226
- if (statsAndValues.length % 2 !== 0 && typeof statsAndValues.slice(-1)[0] === 'object') {
227
- this.options = statsAndValues.slice(-1)[0];
228
- }
229
- for (let i = 0; i < statsAndValues.length; i += 2) {
230
- if (typeof statsAndValues[i] === 'string' && !!statsAndValues[i + 1]) {
231
- this.add(statsAndValues[i], statsAndValues[i + 1]);
232
- }
233
- }
234
- return this;
235
- }
236
- add(stat, value) {
237
- this.items.push({ stat, value });
238
- return this;
239
- }
240
- execute(accountId, characterId, sessionItems) {
241
- var _a;
242
- this.items.forEach((item) => {
243
- let value = item.value;
244
- const correspondingSessionItem = sessionItems.find((sessionItem) => sessionItem.name === item.stat);
245
- if (correspondingSessionItem) {
246
- value = correspondingSessionItem.compute(this.playerId, item.value);
247
- }
248
- Cfx.Server.SetConvarReplicated(`${this.playerId}_PI_${item.stat}`, Array.isArray(value) || typeof value === 'object'
249
- ? JSON.stringify(value)
250
- : value.toString());
251
- Cfx.Server.SetConvarReplicated(`${this.playerId}_PI_${item.stat}_lastUpdate`, new Date().getTime().toString());
252
- });
253
- if ((_a = this.options) === null || _a === void 0 ? void 0 : _a.executeSqlCommand) {
254
- const syncableItems = this.items.filter((item) => {
255
- var _a, _b;
256
- return sessionItems.some((sessionItem) => sessionItem.name === item.stat) && !((_b = (_a = this.options) === null || _a === void 0 ? void 0 : _a.ignoreSqlCommandFor) === null || _b === void 0 ? void 0 : _b.includes(item.stat));
257
- });
258
- if (syncableItems.length) {
259
- const predicate = (item) => { var _a; return (_a = sessionItems.find((sessionItem) => sessionItem.name === item.stat)) === null || _a === void 0 ? void 0 : _a.save; };
260
- const simpleSyncableItems = syncableItems.filter((item) => !predicate(item)).filter((item) => !!item && item.value != null);
261
- console.log('simpleSyncableItems are', simpleSyncableItems);
262
- Cfx.exports['oxmysql'].update_async(`UPDATE \`players\` SET ${simpleSyncableItems.map((item) => `${item.stat} = ?`).join(', ')} WHERE id = ?`, [...simpleSyncableItems.map((item) => JSON.stringify(item.value)), characterId]);
263
- const nonSimpleSyncableItems = syncableItems.filter((item) => predicate(item));
264
- nonSimpleSyncableItems.forEach((item) => sessionItems.find((sessionItem) => sessionItem.name === item.stat).save(accountId, characterId, item.value));
265
- }
266
- }
267
- }
268
- }
@@ -0,0 +1,16 @@
1
+ import { Provider } from 'injection-js';
2
+ import { MySqlTable } from 'drizzle-orm/mysql-core';
3
+ import { MySql2Database } from 'drizzle-orm/mysql2';
4
+ export declare class Database {
5
+ private _rootResource?;
6
+ private _db?;
7
+ private readonly _tables;
8
+ constructor();
9
+ registerTable<T extends MySqlTable>(identifier: string, table: T): T;
10
+ getTable<T extends MySqlTable>(identifier: string): T;
11
+ getClient(): MySql2Database;
12
+ setClient(db: MySql2Database, rootResource: string): void;
13
+ isRoot(): boolean;
14
+ static forRoot(): Provider;
15
+ static forChild(): Provider;
16
+ }
@@ -0,0 +1,58 @@
1
+ export declare const AccountsTable: import("drizzle-orm/mysql-core").MySqlTableWithColumns<{
2
+ name: "accounts";
3
+ schema: undefined;
4
+ columns: {
5
+ id: import("drizzle-orm/mysql-core").MySqlColumn<{
6
+ name: "id";
7
+ tableName: "accounts";
8
+ dataType: "number";
9
+ columnType: "MySqlInt";
10
+ data: number;
11
+ driverParam: string | number;
12
+ notNull: true;
13
+ hasDefault: true;
14
+ isPrimaryKey: true;
15
+ isAutoincrement: true;
16
+ hasRuntimeDefault: false;
17
+ enumValues: undefined;
18
+ baseColumn: never;
19
+ identity: undefined;
20
+ generated: undefined;
21
+ }, {}, {}>;
22
+ platformId: import("drizzle-orm/mysql-core").MySqlColumn<{
23
+ name: "platformId";
24
+ tableName: "accounts";
25
+ dataType: "string";
26
+ columnType: "MySqlVarChar";
27
+ data: string;
28
+ driverParam: string | number;
29
+ notNull: true;
30
+ hasDefault: false;
31
+ isPrimaryKey: false;
32
+ isAutoincrement: false;
33
+ hasRuntimeDefault: false;
34
+ enumValues: [string, ...string[]];
35
+ baseColumn: never;
36
+ identity: undefined;
37
+ generated: undefined;
38
+ }, {}, {}>;
39
+ lastKnownName: import("drizzle-orm/mysql-core").MySqlColumn<{
40
+ name: "lastKnownName";
41
+ tableName: "accounts";
42
+ dataType: "string";
43
+ columnType: "MySqlVarChar";
44
+ data: string;
45
+ driverParam: string | number;
46
+ notNull: true;
47
+ hasDefault: false;
48
+ isPrimaryKey: false;
49
+ isAutoincrement: false;
50
+ hasRuntimeDefault: false;
51
+ enumValues: [string, ...string[]];
52
+ baseColumn: never;
53
+ identity: undefined;
54
+ generated: undefined;
55
+ }, {}, {}>;
56
+ };
57
+ dialect: "mysql";
58
+ }>;
@@ -1,21 +1,9 @@
1
1
  /// <reference path="../ambient.declarations.d.ts" />
2
2
  import 'reflect-metadata';
3
- import { Provider } from 'injection-js';
4
- import { SessionId, SessionLastLocation, SessionName } from './services/session/default-entities';
5
3
  import { BootstrapOptions } from '@armoury/fivem-framework-common';
6
- export declare const SERVER_PROVIDERS: ({
7
- provide: string;
8
- useValue: SessionId;
9
- multi: boolean;
10
- } | {
11
- provide: string;
12
- useValue: SessionName;
13
- multi: boolean;
14
- } | {
15
- provide: string;
16
- useValue: SessionLastLocation;
17
- multi: boolean;
18
- })[];
4
+ import { Provider } from 'injection-js';
5
+ export declare const SERVER_LAZY_PROVIDERS: Provider[];
6
+ export declare const SERVER_EAGER_PROVIDERS: Provider[];
19
7
  export declare function bootstrap<T extends {
20
8
  new (...args: any[]): any;
21
9
  } & Provider>(_class: T, options?: BootstrapOptions): Promise<InstanceType<T>>;
@@ -2,4 +2,3 @@ export * from './server-resource-database.service';
2
2
  export * from './server-enterable-database.service';
3
3
  export * from './server-virtual-worlds.service';
4
4
  export * from './server-translate.service';
5
- export * from './session';
@@ -1,4 +1,4 @@
1
- import { ServerSessionService } from "./session";
1
+ import { ServerSessionService } from './session/server-session.service';
2
2
  export declare class ServerVirtualWorldsService {
3
3
  private readonly _session;
4
4
  constructor(_session: ServerSessionService);
@@ -1,70 +1,5 @@
1
- import { Provider } from "injection-js";
2
- import { IAccount } from "../../../shared";
3
- import { ISessionItemBase } from "../../models";
4
- import { ISession } from "../../models/session/session.model";
1
+ import { Database } from '../../database/database';
5
2
  export declare class ServerSessionService {
6
- private readonly _sessionItems?;
7
- private _sessions;
8
- private _untrackedSessionItems;
9
- get players(): number[];
10
- get authenticatedPlayers(): number[];
11
- constructor(_sessionItems?: ISessionItemBase[] | undefined);
12
- /**
13
- * Registers an account.
14
- * @param playerId The playerId (NOT from the database) of this player
15
- * @param accountName The account name of this player
16
- * @param hashedPassword The hashed password of this account
17
- * @param email The email of this account
18
- * @returns The SQL ID of the newly-created account
19
- */
20
- register(playerId: number, accountName: string, hashedPassword: string, email: string): Promise<number>;
21
- /**
22
- * Logs into an account
23
- * @param playerId The playerId (NOT from the database) of this player
24
- * @param email The email of the account
25
- * @param hashedPassword The hashed password fo this account
26
- * @returns Account data for this account
27
- */
28
- login(playerId: number, email: string, hashedPassword: string): Promise<IAccount>;
29
- /**
30
- * Fetches all the characters related to the provided account
31
- * @param playerId The playerId (NOT from the database) of this player
32
- * @param accountId The accountId of the
33
- * @returns Data for all characters on the given account
34
- */
35
- fetch(playerId: number, accountId?: number): Promise<ISession[]>;
36
- /**
37
- * Loads the entire character given a character ID
38
- * @param playerId The playerId (NOT from the database) of this player
39
- * @param characterId The character's SQL ID
40
- * @returns Data for the given characterId
41
- */
42
- load(playerId: number, characterId: number): Promise<ISession>;
43
- /**
44
- * Creates a character
45
- * @param playerId
46
- * @param accountName
47
- * @param hashedPassword
48
- * @param email
49
- * @returns
50
- */
51
- create(playerId: number, accountId?: number): Promise<number>;
52
- setPlayerInfo<T>(playerId: number, stat: string, value: T, ...args: any[]): void;
53
- setPlayerCash(playerId: number, value: number, options?: SessionUpdaterOptions): void;
54
- givePlayerCash(playerId: number, value: number, options?: SessionUpdaterOptions): void;
55
- getPlayerCash(playerId: number): number;
56
- saveCritical(playerId: number): void;
57
- getPlayerInfo<T>(playerId: number, stat: string): T;
58
- clearPlayerInfo(playerId: number): void;
59
- onResourceStart(resource: string): void;
60
- exchangeSessionItems(items: ISessionItemBase[]): ISessionItemBase[];
61
- static withDefaults(): Provider;
62
- static withItems<T extends {
63
- new (...args: any[]): any;
64
- }>(...items: T[]): Provider[];
3
+ private readonly _database;
4
+ constructor(_database: Database);
65
5
  }
66
- interface SessionUpdaterOptions {
67
- executeSqlCommand?: boolean;
68
- ignoreSqlCommandFor?: string[];
69
- }
70
- export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@armoury/fivem-framework-server",
3
- "version": "1.0.15",
3
+ "version": "1.0.16",
4
4
  "description": "Server APIs for the Armoury FiveM framework",
5
5
  "main": "dist/cjs/server/index.js",
6
6
  "module": "dist/esm/server/index.js",
@@ -27,7 +27,7 @@
27
27
  "rxjs": "^7.8.1"
28
28
  },
29
29
  "peerDependencies": {
30
- "@armoury/fivem-framework-common": "1.0.15",
30
+ "@armoury/fivem-framework-common": "1.0.16",
31
31
  "drizzle-orm": "^0.45.4",
32
32
  "mysql2": "^3.24.5"
33
33
  },