@takaro/gameserver 0.0.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/README.md +36 -0
- package/dist/TakaroEmitter.d.ts +26 -0
- package/dist/TakaroEmitter.js +97 -0
- package/dist/TakaroEmitter.js.map +1 -0
- package/dist/gameservers/7d2d/apiResponses.d.ts +193 -0
- package/dist/gameservers/7d2d/apiResponses.js +2 -0
- package/dist/gameservers/7d2d/apiResponses.js.map +1 -0
- package/dist/gameservers/7d2d/connectionInfo.d.ts +32 -0
- package/dist/gameservers/7d2d/connectionInfo.js +58 -0
- package/dist/gameservers/7d2d/connectionInfo.js.map +1 -0
- package/dist/gameservers/7d2d/emitter.d.ts +30 -0
- package/dist/gameservers/7d2d/emitter.js +261 -0
- package/dist/gameservers/7d2d/emitter.js.map +1 -0
- package/dist/gameservers/7d2d/index.d.ts +28 -0
- package/dist/gameservers/7d2d/index.js +267 -0
- package/dist/gameservers/7d2d/index.js.map +1 -0
- package/dist/gameservers/7d2d/itemWorker.d.ts +1 -0
- package/dist/gameservers/7d2d/itemWorker.js +31 -0
- package/dist/gameservers/7d2d/itemWorker.js.map +1 -0
- package/dist/gameservers/7d2d/items-7d2d.json +17705 -0
- package/dist/gameservers/7d2d/sdtdAPIClient.d.ts +14 -0
- package/dist/gameservers/7d2d/sdtdAPIClient.js +60 -0
- package/dist/gameservers/7d2d/sdtdAPIClient.js.map +1 -0
- package/dist/gameservers/mock/connectionInfo.d.ts +20 -0
- package/dist/gameservers/mock/connectionInfo.js +37 -0
- package/dist/gameservers/mock/connectionInfo.js.map +1 -0
- package/dist/gameservers/mock/emitter.d.ts +12 -0
- package/dist/gameservers/mock/emitter.js +33 -0
- package/dist/gameservers/mock/emitter.js.map +1 -0
- package/dist/gameservers/mock/index.d.ts +31 -0
- package/dist/gameservers/mock/index.js +135 -0
- package/dist/gameservers/mock/index.js.map +1 -0
- package/dist/gameservers/rust/connectionInfo.d.ts +28 -0
- package/dist/gameservers/rust/connectionInfo.js +51 -0
- package/dist/gameservers/rust/connectionInfo.js.map +1 -0
- package/dist/gameservers/rust/emitter.d.ts +30 -0
- package/dist/gameservers/rust/emitter.js +160 -0
- package/dist/gameservers/rust/emitter.js.map +1 -0
- package/dist/gameservers/rust/index.d.ts +29 -0
- package/dist/gameservers/rust/index.js +189 -0
- package/dist/gameservers/rust/index.js.map +1 -0
- package/dist/gameservers/rust/items-rust.json +20771 -0
- package/dist/getGame.d.ts +8 -0
- package/dist/getGame.js +26 -0
- package/dist/getGame.js.map +1 -0
- package/dist/interfaces/GameServer.d.ts +57 -0
- package/dist/interfaces/GameServer.js +95 -0
- package/dist/interfaces/GameServer.js.map +1 -0
- package/dist/main.d.ts +9 -0
- package/dist/main.js +10 -0
- package/dist/main.js.map +1 -0
- package/package.json +26 -0
- package/src/TakaroEmitter.ts +138 -0
- package/src/TakaroEmitter.unit.test.ts +125 -0
- package/src/__tests__/gameEventEmitter.test.ts +36 -0
- package/src/gameservers/7d2d/__tests__/7d2dActions.unit.test.ts +91 -0
- package/src/gameservers/7d2d/__tests__/7d2dEventDetection.unit.test.ts +324 -0
- package/src/gameservers/7d2d/apiResponses.ts +214 -0
- package/src/gameservers/7d2d/connectionInfo.ts +40 -0
- package/src/gameservers/7d2d/emitter.ts +325 -0
- package/src/gameservers/7d2d/index.ts +318 -0
- package/src/gameservers/7d2d/itemWorker.ts +34 -0
- package/src/gameservers/7d2d/items-7d2d.json +17705 -0
- package/src/gameservers/7d2d/sdtdAPIClient.ts +82 -0
- package/src/gameservers/mock/connectionInfo.ts +25 -0
- package/src/gameservers/mock/emitter.ts +37 -0
- package/src/gameservers/mock/index.ts +156 -0
- package/src/gameservers/rust/__tests__/rustActions.unit.test.ts +140 -0
- package/src/gameservers/rust/connectionInfo.ts +35 -0
- package/src/gameservers/rust/emitter.ts +198 -0
- package/src/gameservers/rust/index.ts +230 -0
- package/src/gameservers/rust/items-rust.json +20771 -0
- package/src/getGame.ts +32 -0
- package/src/interfaces/GameServer.ts +95 -0
- package/src/main.ts +14 -0
- package/tsconfig.build.json +9 -0
- package/tsconfig.json +9 -0
- package/typedoc.json +3 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { AxiosResponse } from 'axios';
|
|
2
|
+
import { SdtdConnectionInfo } from './connectionInfo.js';
|
|
3
|
+
import { CommandResponse, InventoryResponse, OnlinePlayerResponse, PlayerLocation, StatsResponse } from './apiResponses.js';
|
|
4
|
+
export declare class SdtdApiClient {
|
|
5
|
+
private config;
|
|
6
|
+
private client;
|
|
7
|
+
constructor(config: SdtdConnectionInfo);
|
|
8
|
+
private get url();
|
|
9
|
+
getStats(): Promise<AxiosResponse<StatsResponse>>;
|
|
10
|
+
executeConsoleCommand(command: string): Promise<AxiosResponse<CommandResponse>>;
|
|
11
|
+
getPlayersLocation(): Promise<AxiosResponse<Array<PlayerLocation>>>;
|
|
12
|
+
getOnlinePlayers(): Promise<AxiosResponse<Array<OnlinePlayerResponse>>>;
|
|
13
|
+
getPlayerInventory(id: string): Promise<AxiosResponse<InventoryResponse>>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
2
|
+
import { addCounterToAxios, errors } from '@takaro/util';
|
|
3
|
+
export class SdtdApiClient {
|
|
4
|
+
constructor(config) {
|
|
5
|
+
this.config = config;
|
|
6
|
+
this.client = axios.create({
|
|
7
|
+
baseURL: this.url,
|
|
8
|
+
});
|
|
9
|
+
addCounterToAxios(this.client, {
|
|
10
|
+
name: 'sdtd_api_requests_total',
|
|
11
|
+
help: 'Total number of requests to the 7D2D API',
|
|
12
|
+
});
|
|
13
|
+
this.client.interceptors.request.use((req) => {
|
|
14
|
+
req.headers['X-SDTD-API-TOKENNAME'] = config.adminUser;
|
|
15
|
+
req.headers['X-SDTD-API-SECRET'] = config.adminToken;
|
|
16
|
+
return req;
|
|
17
|
+
});
|
|
18
|
+
this.client.interceptors.response.use(function (response) {
|
|
19
|
+
return response;
|
|
20
|
+
}, function (error) {
|
|
21
|
+
// Any status codes that falls outside the range of 2xx cause this function to trigger
|
|
22
|
+
if (error.response) {
|
|
23
|
+
const simplifiedError = new errors.BadRequestError('Axios error', {
|
|
24
|
+
extra: 'A request to the 7D2D server failed',
|
|
25
|
+
status: error.response.status,
|
|
26
|
+
statusText: error.response.statusText,
|
|
27
|
+
url: error.config.url,
|
|
28
|
+
});
|
|
29
|
+
return Promise.reject(simplifiedError);
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
const simplifiedError = new errors.BadRequestError('Axios error', {
|
|
33
|
+
extra: 'A request to the 7D2D server failed',
|
|
34
|
+
message: error.message,
|
|
35
|
+
url: error.config.url,
|
|
36
|
+
});
|
|
37
|
+
return Promise.reject(simplifiedError);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
get url() {
|
|
42
|
+
return `${this.config.useTls ? 'https' : 'http'}://${this.config.host}`;
|
|
43
|
+
}
|
|
44
|
+
async getStats() {
|
|
45
|
+
return this.client.get('/api/getstats');
|
|
46
|
+
}
|
|
47
|
+
async executeConsoleCommand(command) {
|
|
48
|
+
return this.client.get(`/api/executeconsolecommand?command=${command}`);
|
|
49
|
+
}
|
|
50
|
+
async getPlayersLocation() {
|
|
51
|
+
return this.client.get('/api/getplayerslocation');
|
|
52
|
+
}
|
|
53
|
+
async getOnlinePlayers() {
|
|
54
|
+
return this.client.get('/api/getplayersonline');
|
|
55
|
+
}
|
|
56
|
+
async getPlayerInventory(id) {
|
|
57
|
+
return this.client.get(`/api/getplayerinventory?userid=${id}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=sdtdAPIClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sdtdAPIClient.js","sourceRoot":"","sources":["../../../src/gameservers/7d2d/sdtdAPIClient.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAS1B,OAAO,EAAE,iBAAiB,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEzD,MAAM,OAAO,aAAa;IAGxB,YAAoB,MAA0B;QAA1B,WAAM,GAAN,MAAM,CAAoB;QAC5C,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;YACzB,OAAO,EAAE,IAAI,CAAC,GAAG;SAClB,CAAC,CAAC;QAEH,iBAAiB,CAAC,IAAI,CAAC,MAAM,EAAE;YAC7B,IAAI,EAAE,yBAAyB;YAC/B,IAAI,EAAE,0CAA0C;SACjD,CAAC,CAAC;QAEH,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;YAC3C,GAAG,CAAC,OAAO,CAAC,sBAAsB,CAAC,GAAG,MAAM,CAAC,SAAS,CAAC;YACvD,GAAG,CAAC,OAAO,CAAC,mBAAmB,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC;YAErD,OAAO,GAAG,CAAC;QACb,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,GAAG,CACnC,UAAU,QAAQ;YAChB,OAAO,QAAQ,CAAC;QAClB,CAAC,EACD,UAAU,KAAK;YACb,sFAAsF;YACtF,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;gBACnB,MAAM,eAAe,GAAG,IAAI,MAAM,CAAC,eAAe,CAAC,aAAa,EAAE;oBAChE,KAAK,EAAE,qCAAqC;oBAC5C,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAC,MAAM;oBAC7B,UAAU,EAAE,KAAK,CAAC,QAAQ,CAAC,UAAU;oBACrC,GAAG,EAAE,KAAK,CAAC,MAAM,CAAC,GAAG;iBACtB,CAAC,CAAC;gBACH,OAAO,OAAO,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;YACzC,CAAC;iBAAM,CAAC;gBACN,MAAM,eAAe,GAAG,IAAI,MAAM,CAAC,eAAe,CAAC,aAAa,EAAE;oBAChE,KAAK,EAAE,qCAAqC;oBAC5C,OAAO,EAAE,KAAK,CAAC,OAAO;oBACtB,GAAG,EAAE,KAAK,CAAC,MAAM,CAAC,GAAG;iBACtB,CAAC,CAAC;gBACH,OAAO,OAAO,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;YACzC,CAAC;QACH,CAAC,CACF,CAAC;IACJ,CAAC;IAED,IAAY,GAAG;QACb,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IAC1E,CAAC;IAED,KAAK,CAAC,QAAQ;QACZ,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IAC1C,CAAC;IAED,KAAK,CAAC,qBAAqB,CAAC,OAAe;QACzC,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,sCAAsC,OAAO,EAAE,CAAC,CAAC;IAC1E,CAAC;IAED,KAAK,CAAC,kBAAkB;QACtB,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;IACpD,CAAC;IAED,KAAK,CAAC,gBAAgB;QACpB,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;IAClD,CAAC;IAED,KAAK,CAAC,kBAAkB,CAAC,EAAU;QACjC,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,kCAAkC,EAAE,EAAE,CAAC,CAAC;IACjE,CAAC;CACF"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { TakaroDTO } from '@takaro/util';
|
|
2
|
+
export declare class MockConnectionInfo extends TakaroDTO<MockConnectionInfo> {
|
|
3
|
+
host: string;
|
|
4
|
+
name: string;
|
|
5
|
+
}
|
|
6
|
+
export declare const mockJsonSchema: {
|
|
7
|
+
$schema: string;
|
|
8
|
+
title: string;
|
|
9
|
+
type: string;
|
|
10
|
+
properties: {
|
|
11
|
+
host: {
|
|
12
|
+
type: string;
|
|
13
|
+
};
|
|
14
|
+
name: {
|
|
15
|
+
type: string;
|
|
16
|
+
default: string;
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
required: string[];
|
|
20
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
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
|
+
import { IsString } from 'class-validator';
|
|
11
|
+
import { TakaroDTO } from '@takaro/util';
|
|
12
|
+
export class MockConnectionInfo extends TakaroDTO {
|
|
13
|
+
}
|
|
14
|
+
__decorate([
|
|
15
|
+
IsString(),
|
|
16
|
+
__metadata("design:type", String)
|
|
17
|
+
], MockConnectionInfo.prototype, "host", void 0);
|
|
18
|
+
__decorate([
|
|
19
|
+
IsString(),
|
|
20
|
+
__metadata("design:type", String)
|
|
21
|
+
], MockConnectionInfo.prototype, "name", void 0);
|
|
22
|
+
export const mockJsonSchema = {
|
|
23
|
+
$schema: 'http://json-schema.org/draft-07/schema#',
|
|
24
|
+
title: 'MockConnectionInfo',
|
|
25
|
+
type: 'object',
|
|
26
|
+
properties: {
|
|
27
|
+
host: {
|
|
28
|
+
type: 'string',
|
|
29
|
+
},
|
|
30
|
+
name: {
|
|
31
|
+
type: 'string',
|
|
32
|
+
default: 'mock',
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
required: ['host'],
|
|
36
|
+
};
|
|
37
|
+
//# sourceMappingURL=connectionInfo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connectionInfo.js","sourceRoot":"","sources":["../../../src/gameservers/mock/connectionInfo.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,MAAM,OAAO,kBAAmB,SAAQ,SAA6B;CAKpE;AAHQ;IADN,QAAQ,EAAE;;gDACU;AAEd;IADN,QAAQ,EAAE;;gDACU;AAGvB,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,OAAO,EAAE,yCAAyC;IAClD,KAAK,EAAE,oBAAoB;IAC3B,IAAI,EAAE,QAAQ;IACd,UAAU,EAAE;QACV,IAAI,EAAE;YACJ,IAAI,EAAE,QAAQ;SACf;QACD,IAAI,EAAE;YACJ,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,MAAM;SAChB;KACF;IACD,QAAQ,EAAE,CAAC,MAAM,CAAC;CACnB,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { MockConnectionInfo } from './connectionInfo.js';
|
|
2
|
+
import { TakaroEmitter } from '../../TakaroEmitter.js';
|
|
3
|
+
import { Socket } from 'socket.io-client';
|
|
4
|
+
export declare class MockEmitter extends TakaroEmitter {
|
|
5
|
+
private config;
|
|
6
|
+
private io;
|
|
7
|
+
private scopedListener;
|
|
8
|
+
constructor(config: MockConnectionInfo, io: Socket);
|
|
9
|
+
start(): Promise<void>;
|
|
10
|
+
stop(): Promise<void>;
|
|
11
|
+
private listener;
|
|
12
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { logger } from '@takaro/util';
|
|
2
|
+
import { TakaroEmitter } from '../../TakaroEmitter.js';
|
|
3
|
+
import { EventMapping } from '@takaro/modules';
|
|
4
|
+
const log = logger('Mock');
|
|
5
|
+
export class MockEmitter extends TakaroEmitter {
|
|
6
|
+
constructor(config, io) {
|
|
7
|
+
super();
|
|
8
|
+
this.config = config;
|
|
9
|
+
this.io = io;
|
|
10
|
+
this.scopedListener = this.listener.bind(this);
|
|
11
|
+
}
|
|
12
|
+
async start() {
|
|
13
|
+
this.io.onAny(this.scopedListener);
|
|
14
|
+
}
|
|
15
|
+
async stop() {
|
|
16
|
+
this.io.offAny(this.scopedListener);
|
|
17
|
+
}
|
|
18
|
+
async listener(event, args) {
|
|
19
|
+
if (this.config.name !== args.name) {
|
|
20
|
+
// This event is not for us
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
log.debug(`Transmitting event ${event}`);
|
|
24
|
+
const dto = EventMapping[event];
|
|
25
|
+
if (dto) {
|
|
26
|
+
this.emit(event, new dto(args));
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
this.emit(event, args);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=emitter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emitter.js","sourceRoot":"","sources":["../../../src/gameservers/mock/emitter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAEvD,OAAO,EAAE,YAAY,EAAkB,MAAM,iBAAiB,CAAC;AAE/D,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;AAC3B,MAAM,OAAO,WAAY,SAAQ,aAAa;IAG5C,YAAoB,MAA0B,EAAU,EAAU;QAChE,KAAK,EAAE,CAAC;QADU,WAAM,GAAN,MAAM,CAAoB;QAAU,OAAE,GAAF,EAAE,CAAQ;QAF1D,mBAAc,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAIlD,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IACrC,CAAC;IAED,KAAK,CAAC,IAAI;QACR,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IACtC,CAAC;IAEO,KAAK,CAAC,QAAQ,CAAC,KAAqB,EAAE,IAAS;QACrD,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC;YACnC,2BAA2B;YAC3B,OAAO;QACT,CAAC;QACD,GAAG,CAAC,KAAK,CAAC,sBAAsB,KAAK,EAAE,CAAC,CAAC;QACzC,MAAM,GAAG,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;QAEhC,IAAI,GAAG,EAAE,CAAC;YACR,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;QAClC,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { IGamePlayer, IPosition } from '@takaro/modules';
|
|
2
|
+
import { BanDTO, CommandOutput, IGameServer, IItemDTO, IMessageOptsDTO, IPlayerReferenceDTO, TestReachabilityOutputDTO } from '../../interfaces/GameServer.js';
|
|
3
|
+
import { MockEmitter } from './emitter.js';
|
|
4
|
+
import { Socket } from 'socket.io-client';
|
|
5
|
+
import { MockConnectionInfo } from './connectionInfo.js';
|
|
6
|
+
import { Settings } from '@takaro/apiclient';
|
|
7
|
+
export declare class Mock implements IGameServer {
|
|
8
|
+
private settings;
|
|
9
|
+
private logger;
|
|
10
|
+
connectionInfo: MockConnectionInfo;
|
|
11
|
+
emitter: MockEmitter;
|
|
12
|
+
io: Socket;
|
|
13
|
+
constructor(config: MockConnectionInfo, settings?: Partial<Settings>);
|
|
14
|
+
getEventEmitter(): MockEmitter;
|
|
15
|
+
private getClient;
|
|
16
|
+
private requestFromServer;
|
|
17
|
+
getPlayer(player: IPlayerReferenceDTO): Promise<IGamePlayer | null>;
|
|
18
|
+
getPlayers(): Promise<IGamePlayer[]>;
|
|
19
|
+
getPlayerLocation(player: IPlayerReferenceDTO): Promise<IPosition | null>;
|
|
20
|
+
testReachability(): Promise<TestReachabilityOutputDTO>;
|
|
21
|
+
executeConsoleCommand(rawCommand: string): Promise<CommandOutput>;
|
|
22
|
+
sendMessage(message: string, opts: IMessageOptsDTO): Promise<any>;
|
|
23
|
+
teleportPlayer(player: IGamePlayer, x: number, y: number, z: number): Promise<any>;
|
|
24
|
+
kickPlayer(player: IGamePlayer, reason: string): Promise<any>;
|
|
25
|
+
banPlayer(options: BanDTO): Promise<any>;
|
|
26
|
+
unbanPlayer(player: IGamePlayer): Promise<any>;
|
|
27
|
+
listBans(): Promise<BanDTO[]>;
|
|
28
|
+
giveItem(player: IPlayerReferenceDTO, item: string, amount: number): Promise<void>;
|
|
29
|
+
listItems(): Promise<IItemDTO[]>;
|
|
30
|
+
getPlayerInventory(player: IPlayerReferenceDTO): Promise<IItemDTO[]>;
|
|
31
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
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
|
+
import { logger, traceableClass } from '@takaro/util';
|
|
11
|
+
import { TestReachabilityOutputDTO, } from '../../interfaces/GameServer.js';
|
|
12
|
+
import { MockEmitter } from './emitter.js';
|
|
13
|
+
import { io } from 'socket.io-client';
|
|
14
|
+
import assert from 'assert';
|
|
15
|
+
import { MockConnectionInfo } from './connectionInfo.js';
|
|
16
|
+
let Mock = class Mock {
|
|
17
|
+
constructor(config, settings = {}) {
|
|
18
|
+
this.settings = settings;
|
|
19
|
+
this.logger = logger('Mock');
|
|
20
|
+
this.connectionInfo = config;
|
|
21
|
+
if (!this.connectionInfo.name)
|
|
22
|
+
this.connectionInfo.name = 'default';
|
|
23
|
+
this.io = io(this.connectionInfo.host, {
|
|
24
|
+
query: {
|
|
25
|
+
name: config.name,
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
this.emitter = new MockEmitter(this.connectionInfo, this.io);
|
|
29
|
+
}
|
|
30
|
+
getEventEmitter() {
|
|
31
|
+
return this.emitter;
|
|
32
|
+
}
|
|
33
|
+
async getClient(timeout = 2500) {
|
|
34
|
+
if (this.io.connected) {
|
|
35
|
+
return this.io;
|
|
36
|
+
}
|
|
37
|
+
return Promise.race([
|
|
38
|
+
new Promise((resolve, reject) => {
|
|
39
|
+
const onConnect = () => {
|
|
40
|
+
this.io.off('connect_error', onConnectError);
|
|
41
|
+
resolve(this.io);
|
|
42
|
+
};
|
|
43
|
+
const onConnectError = (err) => {
|
|
44
|
+
this.io.off('connect', onConnect);
|
|
45
|
+
reject(err);
|
|
46
|
+
};
|
|
47
|
+
this.io.on('connect', onConnect);
|
|
48
|
+
this.io.on('connect_error', onConnectError);
|
|
49
|
+
}),
|
|
50
|
+
new Promise((_, reject) => {
|
|
51
|
+
setTimeout(() => {
|
|
52
|
+
this.io.off('connect');
|
|
53
|
+
this.io.off('connect_error');
|
|
54
|
+
reject(new Error(`Connection timed out after ${timeout}ms`));
|
|
55
|
+
}, timeout);
|
|
56
|
+
}),
|
|
57
|
+
]);
|
|
58
|
+
}
|
|
59
|
+
async requestFromServer(event, ...args) {
|
|
60
|
+
const client = await this.getClient();
|
|
61
|
+
return client.timeout(30000).emitWithAck(event, this.connectionInfo.name, ...args);
|
|
62
|
+
}
|
|
63
|
+
async getPlayer(player) {
|
|
64
|
+
return this.requestFromServer('getPlayer', player);
|
|
65
|
+
}
|
|
66
|
+
async getPlayers() {
|
|
67
|
+
return this.requestFromServer('getPlayers');
|
|
68
|
+
}
|
|
69
|
+
async getPlayerLocation(player) {
|
|
70
|
+
return this.requestFromServer('getPlayerLocation', player);
|
|
71
|
+
}
|
|
72
|
+
async testReachability() {
|
|
73
|
+
try {
|
|
74
|
+
const data = await this.requestFromServer('ping');
|
|
75
|
+
assert(data === 'pong');
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
if (!error || !(error instanceof Error)) {
|
|
79
|
+
return new TestReachabilityOutputDTO({
|
|
80
|
+
connectable: false,
|
|
81
|
+
reason: 'Unknown error',
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
if (error.name === 'AssertionError') {
|
|
85
|
+
return new TestReachabilityOutputDTO({
|
|
86
|
+
connectable: false,
|
|
87
|
+
reason: 'Server responded with invalid data',
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
return new TestReachabilityOutputDTO({
|
|
91
|
+
connectable: false,
|
|
92
|
+
reason: 'Unable to connect to server',
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
return new TestReachabilityOutputDTO({
|
|
96
|
+
connectable: true,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
async executeConsoleCommand(rawCommand) {
|
|
100
|
+
return this.requestFromServer('executeConsoleCommand', rawCommand);
|
|
101
|
+
}
|
|
102
|
+
async sendMessage(message, opts) {
|
|
103
|
+
return this.requestFromServer('sendMessage', message, opts);
|
|
104
|
+
}
|
|
105
|
+
async teleportPlayer(player, x, y, z) {
|
|
106
|
+
return this.requestFromServer('teleportPlayer', player, x, y, z);
|
|
107
|
+
}
|
|
108
|
+
async kickPlayer(player, reason) {
|
|
109
|
+
return this.requestFromServer('kickPlayer', player, reason);
|
|
110
|
+
}
|
|
111
|
+
async banPlayer(options) {
|
|
112
|
+
return this.requestFromServer('banPlayer', options);
|
|
113
|
+
}
|
|
114
|
+
async unbanPlayer(player) {
|
|
115
|
+
return this.requestFromServer('unbanPlayer', player);
|
|
116
|
+
}
|
|
117
|
+
async listBans() {
|
|
118
|
+
return this.requestFromServer('listBans');
|
|
119
|
+
}
|
|
120
|
+
async giveItem(player, item, amount) {
|
|
121
|
+
return this.requestFromServer('giveItem', player, item, amount);
|
|
122
|
+
}
|
|
123
|
+
async listItems() {
|
|
124
|
+
return this.requestFromServer('listItems');
|
|
125
|
+
}
|
|
126
|
+
async getPlayerInventory(player) {
|
|
127
|
+
return this.requestFromServer('getPlayerInventory', player);
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
Mock = __decorate([
|
|
131
|
+
traceableClass('game:mock'),
|
|
132
|
+
__metadata("design:paramtypes", [MockConnectionInfo, Object])
|
|
133
|
+
], Mock);
|
|
134
|
+
export { Mock };
|
|
135
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/gameservers/mock/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { TakaroDTO } from '@takaro/util';
|
|
2
|
+
export declare class RustConnectionInfo extends TakaroDTO<RustConnectionInfo> {
|
|
3
|
+
readonly host: string;
|
|
4
|
+
readonly rconPort: string;
|
|
5
|
+
readonly rconPassword: string;
|
|
6
|
+
readonly useTls: boolean;
|
|
7
|
+
}
|
|
8
|
+
export declare const rustJsonSchema: {
|
|
9
|
+
$schema: string;
|
|
10
|
+
title: string;
|
|
11
|
+
type: string;
|
|
12
|
+
properties: {
|
|
13
|
+
host: {
|
|
14
|
+
type: string;
|
|
15
|
+
};
|
|
16
|
+
rconPort: {
|
|
17
|
+
type: string;
|
|
18
|
+
};
|
|
19
|
+
rconPassword: {
|
|
20
|
+
type: string;
|
|
21
|
+
};
|
|
22
|
+
useTls: {
|
|
23
|
+
type: string;
|
|
24
|
+
default: boolean;
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
required: string[];
|
|
28
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
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
|
+
import { IsString, IsNumber, IsBoolean } from 'class-validator';
|
|
11
|
+
import { TakaroDTO } from '@takaro/util';
|
|
12
|
+
export class RustConnectionInfo extends TakaroDTO {
|
|
13
|
+
}
|
|
14
|
+
__decorate([
|
|
15
|
+
IsString(),
|
|
16
|
+
__metadata("design:type", String)
|
|
17
|
+
], RustConnectionInfo.prototype, "host", void 0);
|
|
18
|
+
__decorate([
|
|
19
|
+
IsNumber(),
|
|
20
|
+
__metadata("design:type", String)
|
|
21
|
+
], RustConnectionInfo.prototype, "rconPort", void 0);
|
|
22
|
+
__decorate([
|
|
23
|
+
IsString(),
|
|
24
|
+
__metadata("design:type", String)
|
|
25
|
+
], RustConnectionInfo.prototype, "rconPassword", void 0);
|
|
26
|
+
__decorate([
|
|
27
|
+
IsBoolean(),
|
|
28
|
+
__metadata("design:type", Boolean)
|
|
29
|
+
], RustConnectionInfo.prototype, "useTls", void 0);
|
|
30
|
+
export const rustJsonSchema = {
|
|
31
|
+
$schema: 'http://json-schema.org/draft-07/schema#',
|
|
32
|
+
title: 'RustConnectionInfo',
|
|
33
|
+
type: 'object',
|
|
34
|
+
properties: {
|
|
35
|
+
host: {
|
|
36
|
+
type: 'string',
|
|
37
|
+
},
|
|
38
|
+
rconPort: {
|
|
39
|
+
type: 'number',
|
|
40
|
+
},
|
|
41
|
+
rconPassword: {
|
|
42
|
+
type: 'string',
|
|
43
|
+
},
|
|
44
|
+
useTls: {
|
|
45
|
+
type: 'boolean',
|
|
46
|
+
default: false,
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
required: ['host', 'rconPort', 'rconPassword', 'useTls'],
|
|
50
|
+
};
|
|
51
|
+
//# sourceMappingURL=connectionInfo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connectionInfo.js","sourceRoot":"","sources":["../../../src/gameservers/rust/connectionInfo.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,MAAM,OAAO,kBAAmB,SAAQ,SAA6B;CASpE;AAPiB;IADf,QAAQ,EAAE;;gDACmB;AAEd;IADf,QAAQ,EAAE;;oDACuB;AAElB;IADf,QAAQ,EAAE;;wDAC2B;AAEtB;IADf,SAAS,EAAE;;kDACqB;AAGnC,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,OAAO,EAAE,yCAAyC;IAClD,KAAK,EAAE,oBAAoB;IAC3B,IAAI,EAAE,QAAQ;IACd,UAAU,EAAE;QACV,IAAI,EAAE;YACJ,IAAI,EAAE,QAAQ;SACf;QACD,QAAQ,EAAE;YACR,IAAI,EAAE,QAAQ;SACf;QACD,YAAY,EAAE;YACZ,IAAI,EAAE,QAAQ;SACf;QACD,MAAM,EAAE;YACN,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,KAAK;SACf;KACF;IACD,QAAQ,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,cAAc,EAAE,QAAQ,CAAC;CACzD,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import WebSocket from 'ws';
|
|
2
|
+
import { RustConnectionInfo } from './connectionInfo.js';
|
|
3
|
+
import { TakaroEmitter } from '../../TakaroEmitter.js';
|
|
4
|
+
export declare enum RustEventType {
|
|
5
|
+
DEFAULT = "Generic",
|
|
6
|
+
WARNING = "Warning",
|
|
7
|
+
CHAT = "Chat"
|
|
8
|
+
}
|
|
9
|
+
export interface RustEvent {
|
|
10
|
+
Message: string;
|
|
11
|
+
Identifier: number;
|
|
12
|
+
Type: RustEventType;
|
|
13
|
+
Stacktrace: string;
|
|
14
|
+
}
|
|
15
|
+
export declare class RustEmitter extends TakaroEmitter {
|
|
16
|
+
private config;
|
|
17
|
+
private ws;
|
|
18
|
+
private log;
|
|
19
|
+
constructor(config: RustConnectionInfo);
|
|
20
|
+
static getClient(config: RustConnectionInfo): Promise<WebSocket>;
|
|
21
|
+
start(): Promise<void>;
|
|
22
|
+
stop(): Promise<void>;
|
|
23
|
+
parseMessage(e: RustEvent): Promise<void>;
|
|
24
|
+
private handlePlayerConnected;
|
|
25
|
+
private handlePlayerDisconnected;
|
|
26
|
+
private handleChatMessage;
|
|
27
|
+
private handlePlayerDeath;
|
|
28
|
+
private handleEntityKilled;
|
|
29
|
+
listener(data: string): Promise<void>;
|
|
30
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import WebSocket from 'ws';
|
|
2
|
+
import { logger, errors } from '@takaro/util';
|
|
3
|
+
import { TakaroEmitter } from '../../TakaroEmitter.js';
|
|
4
|
+
import { EventChatMessage, EventEntityKilled, EventLogLine, EventPlayerConnected, EventPlayerDeath, EventPlayerDisconnected, GameEvents, } from '@takaro/modules';
|
|
5
|
+
export var RustEventType;
|
|
6
|
+
(function (RustEventType) {
|
|
7
|
+
RustEventType["DEFAULT"] = "Generic";
|
|
8
|
+
RustEventType["WARNING"] = "Warning";
|
|
9
|
+
RustEventType["CHAT"] = "Chat";
|
|
10
|
+
})(RustEventType || (RustEventType = {}));
|
|
11
|
+
var RustTypesType;
|
|
12
|
+
(function (RustTypesType) {
|
|
13
|
+
RustTypesType[RustTypesType["PLAYER_CONNECTED"] = 0] = "PLAYER_CONNECTED";
|
|
14
|
+
RustTypesType[RustTypesType["PLAYER_DISCONNECTED"] = 1] = "PLAYER_DISCONNECTED";
|
|
15
|
+
RustTypesType[RustTypesType["CHAT_MESSAGE"] = 2] = "CHAT_MESSAGE";
|
|
16
|
+
RustTypesType[RustTypesType["PLAYER_DEATH"] = 3] = "PLAYER_DEATH";
|
|
17
|
+
RustTypesType[RustTypesType["ENTITY_KILLED"] = 4] = "ENTITY_KILLED";
|
|
18
|
+
})(RustTypesType || (RustTypesType = {}));
|
|
19
|
+
export class RustEmitter extends TakaroEmitter {
|
|
20
|
+
constructor(config) {
|
|
21
|
+
super();
|
|
22
|
+
this.config = config;
|
|
23
|
+
this.ws = null;
|
|
24
|
+
this.log = logger('rust:ws');
|
|
25
|
+
}
|
|
26
|
+
static async getClient(config) {
|
|
27
|
+
const log = logger('rust:ws');
|
|
28
|
+
const protocol = config.useTls ? 'wss' : 'ws';
|
|
29
|
+
const client = new WebSocket(`${protocol}://${config.host}:${config.rconPort}/${config.rconPassword}`);
|
|
30
|
+
log.debug('getClient', {
|
|
31
|
+
host: config.host,
|
|
32
|
+
port: config.rconPort,
|
|
33
|
+
});
|
|
34
|
+
return Promise.race([
|
|
35
|
+
new Promise((resolve, reject) => {
|
|
36
|
+
client?.on('error', (err) => {
|
|
37
|
+
log.warn('getClient', err);
|
|
38
|
+
client?.close();
|
|
39
|
+
return reject(err);
|
|
40
|
+
});
|
|
41
|
+
client?.on('unexpected-response', (req, res) => {
|
|
42
|
+
log.debug('unexpected-response', {
|
|
43
|
+
req,
|
|
44
|
+
res,
|
|
45
|
+
});
|
|
46
|
+
reject(new errors.InternalServerError());
|
|
47
|
+
});
|
|
48
|
+
client?.on('open', () => {
|
|
49
|
+
log.debug('Connection opened');
|
|
50
|
+
if (client) {
|
|
51
|
+
return resolve(client);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
}),
|
|
55
|
+
new Promise((_, reject) => {
|
|
56
|
+
setTimeout(() => reject(new errors.WsTimeOutError('Timeout')), 5000);
|
|
57
|
+
}),
|
|
58
|
+
]);
|
|
59
|
+
}
|
|
60
|
+
async start() {
|
|
61
|
+
this.ws = await RustEmitter.getClient(this.config);
|
|
62
|
+
this.ws?.on('message', (m) => {
|
|
63
|
+
this.listener(m.toString());
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
async stop() {
|
|
67
|
+
this.ws?.close();
|
|
68
|
+
this.log.debug('Websocket connection has been closed');
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
async parseMessage(e) {
|
|
72
|
+
if (e.Message.includes('[Hook Parser]')) {
|
|
73
|
+
const parsed = JSON.parse(e.Message.replace('[Hook Parser]', ''));
|
|
74
|
+
let dto = null;
|
|
75
|
+
switch (parsed.type) {
|
|
76
|
+
case RustTypesType.PLAYER_CONNECTED:
|
|
77
|
+
dto = await this.handlePlayerConnected(parsed.data);
|
|
78
|
+
break;
|
|
79
|
+
case RustTypesType.PLAYER_DISCONNECTED:
|
|
80
|
+
dto = await this.handlePlayerDisconnected(parsed.data);
|
|
81
|
+
break;
|
|
82
|
+
case RustTypesType.CHAT_MESSAGE:
|
|
83
|
+
dto = await this.handleChatMessage(parsed.data);
|
|
84
|
+
break;
|
|
85
|
+
case RustTypesType.PLAYER_DEATH:
|
|
86
|
+
dto = await this.handlePlayerDeath(parsed.data);
|
|
87
|
+
break;
|
|
88
|
+
case RustTypesType.ENTITY_KILLED:
|
|
89
|
+
dto = await this.handleEntityKilled(parsed.data);
|
|
90
|
+
break;
|
|
91
|
+
default:
|
|
92
|
+
this.log.warn('Unknown event type', parsed);
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
if (!dto) {
|
|
96
|
+
this.log.warn('dto undefined, could not determine type?', parsed);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
await dto.validate({
|
|
100
|
+
whitelist: false,
|
|
101
|
+
});
|
|
102
|
+
this.emit(dto.type, dto);
|
|
103
|
+
}
|
|
104
|
+
this.emit(GameEvents.LOG_LINE, new EventLogLine({
|
|
105
|
+
msg: e.Message,
|
|
106
|
+
}));
|
|
107
|
+
}
|
|
108
|
+
async handlePlayerConnected(data) {
|
|
109
|
+
const event = new EventPlayerConnected(data);
|
|
110
|
+
if (event.player.steamId) {
|
|
111
|
+
event.player.gameId = event.player.steamId;
|
|
112
|
+
}
|
|
113
|
+
return event;
|
|
114
|
+
}
|
|
115
|
+
async handlePlayerDisconnected(data) {
|
|
116
|
+
const event = new EventPlayerDisconnected(data);
|
|
117
|
+
if (event.player.steamId) {
|
|
118
|
+
event.player.gameId = event.player.steamId;
|
|
119
|
+
}
|
|
120
|
+
return event;
|
|
121
|
+
}
|
|
122
|
+
async handleChatMessage(data) {
|
|
123
|
+
delete data.channel;
|
|
124
|
+
const event = new EventChatMessage(data);
|
|
125
|
+
if (event.player) {
|
|
126
|
+
if (event.player.steamId) {
|
|
127
|
+
event.player.gameId = event.player.steamId;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return event;
|
|
131
|
+
}
|
|
132
|
+
async handlePlayerDeath(data) {
|
|
133
|
+
const event = new EventPlayerDeath(data);
|
|
134
|
+
if (event.player.steamId) {
|
|
135
|
+
event.player.gameId = event.player.steamId;
|
|
136
|
+
}
|
|
137
|
+
if (event.attacker && event.attacker.steamId) {
|
|
138
|
+
event.attacker.gameId = event.attacker.steamId;
|
|
139
|
+
}
|
|
140
|
+
return event;
|
|
141
|
+
}
|
|
142
|
+
async handleEntityKilled(data) {
|
|
143
|
+
const event = new EventEntityKilled(data);
|
|
144
|
+
if (event.player.steamId) {
|
|
145
|
+
event.player.gameId = event.player.steamId;
|
|
146
|
+
}
|
|
147
|
+
return event;
|
|
148
|
+
}
|
|
149
|
+
async listener(data) {
|
|
150
|
+
try {
|
|
151
|
+
const event = JSON.parse(data);
|
|
152
|
+
await this.parseMessage(event);
|
|
153
|
+
this.log.debug('event: ', event);
|
|
154
|
+
}
|
|
155
|
+
catch (error) {
|
|
156
|
+
this.log.error('Error handling message from game server', error);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
//# sourceMappingURL=emitter.js.map
|