h1z1-server 0.14.2-3 → 0.14.2-7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/data/2015/sampleData/sendself.json +6 -32
  2. package/data/2016/dataSources/weather.json +76 -0
  3. package/package.json +9 -7
  4. package/scripts/demo/ZoneServer2015.js +9 -0
  5. package/scripts/demo/ZoneServer2016.js +8 -0
  6. package/scripts/demo/loginserver2015.js +4 -0
  7. package/scripts/demo/loginserver2016.js +8 -0
  8. package/scripts/h1z1-server-demo-2016.js +4 -0
  9. package/scripts/h1z1-server-demo.js +4 -0
  10. package/src/clients/gatewayclient.js +105 -105
  11. package/src/clients/loginclient.ts +227 -227
  12. package/src/clients/zoneclient.ts +166 -166
  13. package/src/packets/ClientProtocol/ClientProtocol_1080/h1z1packets.ts +7 -4
  14. package/src/packets/ClientProtocol/ClientProtocol_860/h1z1packets.ts +80 -48
  15. package/src/packets/LoginUdp/LoginUdp_11/loginTunnelPackets.ts +43 -43
  16. package/src/packets/LoginUdp/LoginUdp_11/loginpackets.ts +471 -471
  17. package/src/packets/LoginUdp/LoginUdp_9/loginTunnelPackets.ts +43 -43
  18. package/src/packets/LoginUdp/LoginUdp_9/loginpackets.ts +429 -429
  19. package/src/packets/gatewaypackets.ts +73 -73
  20. package/src/packets/packettable.ts +37 -37
  21. package/src/protocols/gatewayprotocol.ts +118 -118
  22. package/src/protocols/h1z1protocol.ts +10 -12
  23. package/src/servers/GatewayServer/gatewayserver.ts +133 -133
  24. package/src/servers/LoginServer/loginserver.ts +549 -549
  25. package/src/servers/SoeServer/soeclient.ts +48 -48
  26. package/src/servers/SoeServer/soeinputstream.ts +226 -226
  27. package/src/servers/SoeServer/soeoutputstream.ts +111 -111
  28. package/src/servers/SoeServer/soeserver.ts +436 -436
  29. package/src/servers/SoeServer/workers/udpServerWorker.ts +54 -54
  30. package/src/servers/ZoneServer/character.ts +66 -66
  31. package/src/servers/ZoneServer/commands/admin.ts +7 -1
  32. package/src/servers/ZoneServer/commands/dev.ts +6 -0
  33. package/src/servers/ZoneServer/commands/hax.ts +122 -8
  34. package/src/servers/ZoneServer/workers/createBaseEntities.ts +1047 -1046
  35. package/src/servers/ZoneServer/workers/dynamicWeather.ts +400 -400
  36. package/src/servers/ZoneServer/zoneclient.ts +4 -0
  37. package/src/servers/ZoneServer/zonepackethandlers.ts +38 -35
  38. package/src/servers/ZoneServer/zoneserver.ts +3 -2
  39. package/src/servers/ZoneServer2016/commands/admin.ts +21 -0
  40. package/src/servers/ZoneServer2016/commands/dev.ts +63 -44
  41. package/src/servers/ZoneServer2016/commands/hax.ts +77 -34
  42. package/src/servers/ZoneServer2016/workers/createBaseEntities.ts +956 -956
  43. package/src/servers/ZoneServer2016/workers/dynamicWeather.ts +1 -1
  44. package/src/servers/ZoneServer2016/workers/saveWorld.ts +27 -27
  45. package/src/servers/ZoneServer2016/zonepackethandlers.ts +17 -18
  46. package/src/servers/ZoneServer2016/zoneserver.ts +44 -38
  47. package/src/types/gatewayserver.ts +21 -21
  48. package/src/types/loginserver.ts +62 -62
  49. package/src/types/packets.ts +2470 -2470
  50. package/src/types/shared.ts +6 -6
  51. package/src/types/soeserver.ts +22 -22
  52. package/src/types/zoneserver.ts +6 -6
  53. package/src/utils/utils.ts +14 -2
  54. package/data/2016/sampleData/weather.json +0 -5780
@@ -75,22 +75,7 @@
75
75
  "unknownDword4": 0
76
76
  },
77
77
  "characterAchievements": [],
78
- "acquaintances": [
79
- {
80
- "guid": "0x0000000000000001",
81
- "name": "easter egg 1",
82
- "type": 1,
83
- "elapsedTime": "0x427794947C610000",
84
- "online": true
85
- },
86
- {
87
- "guid": "0x0000000000000002",
88
- "name": "easter egg 2",
89
- "type": 2,
90
- "elapsedTime": "0x427794947C610000",
91
- "online": false
92
- }
93
- ],
78
+ "acquaintances": [],
94
79
  "mounts": [],
95
80
  "unknownCoinStoreData": {
96
81
  "unknownBoolean1": 0,
@@ -124,7 +109,7 @@
124
109
  },
125
110
  "acquireTimers": {
126
111
  "unknownArray1": [],
127
- "unknownDword1": 0
112
+ "unknownWord": 0
128
113
  },
129
114
  "unknownSchema2525": {
130
115
  "unknownDword1": 0,
@@ -191,7 +176,9 @@
191
176
  "unknownByte1": 0
192
177
  },
193
178
  "unknownDword5454qq2sfs44": [],
194
- "loadoutStuff": [],
179
+ "loadoutStuff": {
180
+
181
+ },
195
182
  "unknownDword54542sfs44": 0,
196
183
  "LocksPermissions": [],
197
184
  "missionData": {
@@ -211,20 +198,7 @@
211
198
  "unknownDword1": 0
212
199
  },
213
200
  "skills": [],
214
- "EquippedContainers": [
215
- {
216
- "unknownDword1": 2,
217
- "unknownQword1": "0x0000000000000001",
218
- "unknownDword2": 3,
219
- "unknownQword2": "0x0000000000000002",
220
- "unknownDword3": 4,
221
- "unknownArray1": [],
222
- "unknownBoolean": true,
223
- "unknownDword4": 5,
224
- "unknownDword5": 6,
225
- "unknownDword6": 7
226
- }
227
- ],
201
+ "EquippedContainers": [],
228
202
  "unknownBoolean8": true,
229
203
  "unknownQword1": "0x0000000000000000",
230
204
  "unknownDword37": 0,
@@ -0,0 +1,76 @@
1
+ {
2
+ "H1emuBaseWeather": {
3
+ "templateName": "H1emuBaseWeather",
4
+ "name": "sky_Z_clouds.dds",
5
+ "unknownDword1": 0,
6
+ "unknownDword2": 0,
7
+ "skyBrightness1": 1,
8
+ "skyBrightness2": 1,
9
+ "snow": 0,
10
+ "snowMap": 0,
11
+ "colorGradient": 0.7,
12
+ "unknownDword8": 0.16,
13
+ "unknownDword9": 0.68,
14
+ "unknownDword10": 0.08,
15
+ "unknownDword11": 0,
16
+ "unknownDword12": 0,
17
+ "sunAxisX": 0,
18
+ "sunAxisY": 0,
19
+ "unknownDword15": 0,
20
+ "windDirectionX": 100,
21
+ "windDirectionY": 200,
22
+ "windDirectionZ": 300,
23
+ "wind": 5,
24
+ "unknownDword20": 0,
25
+ "unknownDword21": 0,
26
+ "unknownDword22": 0,
27
+ "unknownDword23": 0,
28
+ "unknownDword24": 0,
29
+ "unknownDword25": 0,
30
+ "unknownDword26": 0,
31
+ "unknownDword27": 0,
32
+ "unknownDword28": 0,
33
+ "unknownDword29": 0,
34
+ "AOSize": 0.1,
35
+ "AOGamma": 0.8,
36
+ "AOBlackpoint": 0.2,
37
+ "unknownDword33": 1
38
+ },
39
+ "sunset": {
40
+ "templateName": "sunset",
41
+ "name": "sky_Z_clouds.dds",
42
+ "unknownDword1": 0,
43
+ "unknownDword2": 0,
44
+ "skyBrightness1": 1,
45
+ "skyBrightness2": 1,
46
+ "snow": 123,
47
+ "snowMap": 50,
48
+ "colorGradient": 0.10946120217169808,
49
+ "unknownDword8": 0.5753179865655127,
50
+ "unknownDword9": 0.4527050241187167,
51
+ "unknownDword10": 0.6209641091327527,
52
+ "unknownDword11": 0,
53
+ "unknownDword12": 0,
54
+ "sunAxisX": 274,
55
+ "sunAxisY": 23,
56
+ "unknownDword15": 0,
57
+ "windDirectionX": 193,
58
+ "windDirectionY": 44,
59
+ "windDirectionZ": 98,
60
+ "wind": 9,
61
+ "unknownDword20": 0,
62
+ "unknownDword21": 0,
63
+ "unknownDword22": 0,
64
+ "unknownDword23": 0,
65
+ "unknownDword24": 0,
66
+ "unknownDword25": 0,
67
+ "unknownDword26": 0,
68
+ "unknownDword27": 0,
69
+ "unknownDword28": 0,
70
+ "unknownDword29": 0,
71
+ "AOSize": 0.3603743861432199,
72
+ "AOGamma": 0.1650277968581435,
73
+ "AOBlackpoint": 1.5307335036980811,
74
+ "unknownDword33": 0
75
+ }
76
+ }
package/package.json CHANGED
@@ -1,12 +1,14 @@
1
1
  {
2
2
  "name": "h1z1-server",
3
- "version": "0.14.2-3",
3
+ "version": "0.14.2-7",
4
4
  "description": "Library for emulating h1z1 servers",
5
5
  "author": "Quentin Gruber <quentingruber@gmail.com> (http://github.com/quentingruber)",
6
6
  "license": "GPL-3.0-only",
7
7
  "main": "h1z1-server.js",
8
8
  "bin": {
9
- "if-env": "scripts/if-env.js"
9
+ "if-env": "scripts/if-env.js",
10
+ "h1z1-server-demo": "scripts/h1z1-server-demo.js",
11
+ "h1z1-server-demo-2016": "scripts/h1z1-server-demo-2016.js"
10
12
  },
11
13
  "dependencies": {
12
14
  "@swc/cli": "0.1.40",
@@ -15,13 +17,13 @@
15
17
  "@types/node": "16.7.9",
16
18
  "debug": "4.3.2",
17
19
  "eul2quat": "1.0.0",
18
- "h1emu-core": "0.4.0",
19
- "h1z1-dataschema": "1.4.1",
20
- "mongodb": "4.1.1",
20
+ "h1emu-core": "0.5.0",
21
+ "h1z1-dataschema": "1.5.4",
22
+ "mongodb": "4.1.2",
21
23
  "mongodb-restore-dump": "1.0.1",
22
24
  "terser-output": "1.0.3",
23
25
  "typedoc": "0.21.9",
24
- "typescript": "4.4.2",
26
+ "typescript": "4.4.3",
25
27
  "v8-compile-cache": "2.3.0"
26
28
  },
27
29
  "directories": {
@@ -29,7 +31,7 @@
29
31
  },
30
32
  "devDependencies": {
31
33
  "chokidar": "3.5.2",
32
- "prettier": "2.4.0",
34
+ "prettier": "2.4.1",
33
35
  "ts-node": "10.2.1"
34
36
  },
35
37
  "scripts": {
@@ -0,0 +1,9 @@
1
+ process.env.DEBUG = "ZoneServer";
2
+ const { ZoneServer } = require("../../h1z1-server");
3
+ const Zone = new ZoneServer(
4
+ 1117,
5
+ new Buffer.from("F70IaxuU8C/w7FPXY1ibXw==", "base64"),
6
+ process.env.MONGO_URL,
7
+ Number(process.env.WORLD_ID)
8
+ );
9
+ Zone.start();
@@ -0,0 +1,8 @@
1
+ process.env.DEBUG = "ZoneServer";
2
+ const H1Z1servers = require("../../h1z1-server");
3
+ const { Base64 } = require("js-base64");
4
+ var Zone = new H1Z1servers.ZoneServer2016(
5
+ 1117,
6
+ Base64.toUint8Array("F70IaxuU8C/w7FPXY1ibXw==")
7
+ );
8
+ Zone.start();
@@ -0,0 +1,4 @@
1
+ process.env.DEBUG = "*";
2
+ const { LoginServer } = require("../../h1z1-server");
3
+ const server = new LoginServer(1115, process.env.MONGO_URL);
4
+ server.start();
@@ -0,0 +1,8 @@
1
+ process.env.DEBUG = "*";
2
+ const H1Z1servers = require("../../h1z1-server");
3
+ var server = new H1Z1servers.LoginServer(
4
+ 1115, // <- server port
5
+ "" // <- MongoDB address ( if blank server start in solo mode )
6
+ );
7
+ server._protocol = new H1Z1servers.LoginProtocol("LoginUdp_11");
8
+ server.start();
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ const { Worker } = require("worker_threads");
3
+ new Worker(`${__dirname}/demo/loginserver2016.js`)
4
+ new Worker(`${__dirname}./demo/ZoneServer2016.js`)
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ const { Worker } = require("worker_threads");
3
+ new Worker(`${__dirname}/demo/loginserver2015.js`)
4
+ new Worker(`${__dirname}/demo/ZoneServer2015.js`)
@@ -1,105 +1,105 @@
1
- // ======================================================================
2
- //
3
- // GNU GENERAL PUBLIC LICENSE
4
- // Version 3, 29 June 2007
5
- // copyright (c) 2020 - 2021 Quentin Gruber
6
- // copyright (c) 2021 H1emu community
7
- //
8
- // https://github.com/QuentinGruber/h1z1-server
9
- // https://www.npmjs.com/package/h1z1-server
10
- //
11
- // Based on https://github.com/psemu/soe-network
12
- // ======================================================================
13
-
14
- var EventEmitter = require("events").EventEmitter,
15
- SOEClient = require("./soeclient").SOEClient,
16
- fs = require("fs"),
17
- util = require("util"),
18
- GatewayProtocol = require("../protocols/gatewayprotocol").GatewayProtocol,
19
- GatewayPackets = require("../protocols/gatewayprotocol").GatewayPackets,
20
- debug = require("debug")("GatewayClient");
21
-
22
- function GatewayClientError(message) {
23
- this.name = this.constructor.name;
24
- this.message = message;
25
- }
26
-
27
- util.inherits(GatewayClientError, Error);
28
-
29
- class GatewayClient {
30
- constructor(serverAddress, serverPort, key, localPort) {
31
- EventEmitter.call(this);
32
-
33
- var soeClient = (this._soeClient = new SOEClient(
34
- "ExternalGatewayApi_3",
35
- serverAddress,
36
- serverPort,
37
- key,
38
- localPort
39
- ));
40
- var protocol = (this._protocol = new GatewayProtocol());
41
- var me = this;
42
-
43
- soeClient.on("appdata", function (err, data) {
44
- var packet = protocol.parse(data);
45
- var result = packet.result;
46
-
47
- switch (packet.name) {
48
- case "LoginReply":
49
- if (result.loggedIn) {
50
- me.emit("login", null, result);
51
- } else {
52
- me.emit("login", new GatewayClientError("Login failed"));
53
- }
54
- break;
55
- case "TunnelPacketToExternalConnection":
56
- me.emit("tunneldata", null, packet.tunnelData, packet.flags);
57
- break;
58
- }
59
- });
60
-
61
- soeClient.on("connect", function (err, result) {
62
- debug("Connected to login server");
63
- soeClient.toggleEncryption(false);
64
- me.emit("connect", err, result);
65
- });
66
-
67
- soeClient.on("disconnect", function (err, result) {
68
- debug("Disconnected");
69
- me.emit("disconnect", err, result);
70
- });
71
- }
72
- connect(callback) {
73
- debug("Connecting to gateway server");
74
- this._soeClient.connect();
75
- }
76
- sendTunnelData(tunnelData, channel) {
77
- channel = channel || 0;
78
- debug("Sending tunnel data to gateway server");
79
- var data = this._protocol.pack("TunnelPacketFromExternalConnection", {
80
- channel: channel,
81
- tunnelData: tunnelData,
82
- });
83
- //fs.writeFileSync("dump/out_tunneldata_" + (tunnelCount++) + ".dat", data);
84
- this._soeClient.sendAppData(data, true);
85
- }
86
- login(characterId, ticket, clientProtocol, clientBuild) {
87
- debug("Sending login request");
88
- var data = this._protocol.pack("LoginRequest", {
89
- characterId: characterId,
90
- ticket: ticket,
91
- clientProtocol: clientProtocol,
92
- clientBuild: clientBuild,
93
- });
94
- //fs.writeFileSync("loginrequest.dat", data);
95
- this._soeClient.sendAppData(data, false);
96
- this._soeClient.toggleEncryption(true);
97
- }
98
- disconnect() {}
99
- }
100
-
101
- util.inherits(GatewayClient, EventEmitter);
102
-
103
- var tunnelCount = 0;
104
-
105
- exports.GatewayClient = GatewayClient;
1
+ // ======================================================================
2
+ //
3
+ // GNU GENERAL PUBLIC LICENSE
4
+ // Version 3, 29 June 2007
5
+ // copyright (c) 2020 - 2021 Quentin Gruber
6
+ // copyright (c) 2021 H1emu community
7
+ //
8
+ // https://github.com/QuentinGruber/h1z1-server
9
+ // https://www.npmjs.com/package/h1z1-server
10
+ //
11
+ // Based on https://github.com/psemu/soe-network
12
+ // ======================================================================
13
+
14
+ var EventEmitter = require("events").EventEmitter,
15
+ SOEClient = require("./soeclient").SOEClient,
16
+ fs = require("fs"),
17
+ util = require("util"),
18
+ GatewayProtocol = require("../protocols/gatewayprotocol").GatewayProtocol,
19
+ GatewayPackets = require("../protocols/gatewayprotocol").GatewayPackets,
20
+ debug = require("debug")("GatewayClient");
21
+
22
+ function GatewayClientError(message) {
23
+ this.name = this.constructor.name;
24
+ this.message = message;
25
+ }
26
+
27
+ util.inherits(GatewayClientError, Error);
28
+
29
+ class GatewayClient {
30
+ constructor(serverAddress, serverPort, key, localPort) {
31
+ EventEmitter.call(this);
32
+
33
+ var soeClient = (this._soeClient = new SOEClient(
34
+ "ExternalGatewayApi_3",
35
+ serverAddress,
36
+ serverPort,
37
+ key,
38
+ localPort
39
+ ));
40
+ var protocol = (this._protocol = new GatewayProtocol());
41
+ var me = this;
42
+
43
+ soeClient.on("appdata", function (err, data) {
44
+ var packet = protocol.parse(data);
45
+ var result = packet.result;
46
+
47
+ switch (packet.name) {
48
+ case "LoginReply":
49
+ if (result.loggedIn) {
50
+ me.emit("login", null, result);
51
+ } else {
52
+ me.emit("login", new GatewayClientError("Login failed"));
53
+ }
54
+ break;
55
+ case "TunnelPacketToExternalConnection":
56
+ me.emit("tunneldata", null, packet.tunnelData, packet.flags);
57
+ break;
58
+ }
59
+ });
60
+
61
+ soeClient.on("connect", function (err, result) {
62
+ debug("Connected to login server");
63
+ soeClient.toggleEncryption(false);
64
+ me.emit("connect", err, result);
65
+ });
66
+
67
+ soeClient.on("disconnect", function (err, result) {
68
+ debug("Disconnected");
69
+ me.emit("disconnect", err, result);
70
+ });
71
+ }
72
+ connect(callback) {
73
+ debug("Connecting to gateway server");
74
+ this._soeClient.connect();
75
+ }
76
+ sendTunnelData(tunnelData, channel) {
77
+ channel = channel || 0;
78
+ debug("Sending tunnel data to gateway server");
79
+ var data = this._protocol.pack("TunnelPacketFromExternalConnection", {
80
+ channel: channel,
81
+ tunnelData: tunnelData,
82
+ });
83
+ //fs.writeFileSync("dump/out_tunneldata_" + (tunnelCount++) + ".dat", data);
84
+ this._soeClient.sendAppData(data, true);
85
+ }
86
+ login(characterId, ticket, clientProtocol, clientBuild) {
87
+ debug("Sending login request");
88
+ var data = this._protocol.pack("LoginRequest", {
89
+ characterId: characterId,
90
+ ticket: ticket,
91
+ clientProtocol: clientProtocol,
92
+ clientBuild: clientBuild,
93
+ });
94
+ //fs.writeFileSync("loginrequest.dat", data);
95
+ this._soeClient.sendAppData(data, false);
96
+ this._soeClient.toggleEncryption(true);
97
+ }
98
+ disconnect() {}
99
+ }
100
+
101
+ util.inherits(GatewayClient, EventEmitter);
102
+
103
+ var tunnelCount = 0;
104
+
105
+ exports.GatewayClient = GatewayClient;
@@ -1,227 +1,227 @@
1
- // ======================================================================
2
- //
3
- // GNU GENERAL PUBLIC LICENSE
4
- // Version 3, 29 June 2007
5
- // copyright (c) 2020 - 2021 Quentin Gruber
6
- // copyright (c) 2021 H1emu community
7
- //
8
- // https://github.com/QuentinGruber/h1z1-server
9
- // https://www.npmjs.com/package/h1z1-server
10
- //
11
- // Based on https://github.com/psemu/soe-network
12
- // ======================================================================
13
-
14
- import { EventEmitter } from "events";
15
-
16
- import { SOEClient } from "./soeclient";
17
- import { LoginProtocol } from "../protocols/loginprotocol";
18
- const loginProtocolName = "LoginUdp_9";
19
- const debug = require("debug")("LoginClient");
20
-
21
- interface SoeClient {
22
- on: Function;
23
- emit: Function;
24
- connect: Function;
25
- start: Function;
26
- stop: Function;
27
- _sessionId: number;
28
- _protocol: LoginProtocol;
29
- _sendPacket: Function;
30
- sendAppData: Function;
31
- toggleEncryption: Function;
32
- toggleDataDump: Function;
33
- }
34
-
35
- interface LoginProtocolInterface {
36
- parse: Function;
37
- pack: Function;
38
- }
39
-
40
- export class LoginClient extends EventEmitter {
41
- _gameId: number;
42
- _environment: string;
43
- _soeClient: any;
44
- _protocol: LoginProtocolInterface;
45
-
46
- constructor(
47
- gameId: number,
48
- environment: string,
49
- serverAddress: string,
50
- serverPort: number,
51
- loginKey: Uint8Array,
52
- localPort: number
53
- ) {
54
- super();
55
- this._gameId = gameId;
56
- this._environment = environment;
57
- this._soeClient = new SOEClient(
58
- loginProtocolName,
59
- serverAddress,
60
- serverPort,
61
- loginKey,
62
- localPort
63
- );
64
- this._protocol = new LoginProtocol();
65
- var n = 0;
66
- this._soeClient.on("connect", (err: string, result: string) => {
67
- debug("Connected to login server");
68
- this.login("FiNgErPrInT");
69
- });
70
- this._soeClient.on("disconnect", (err: string, result: string) => {
71
- debug("Disconnected");
72
- });
73
- this._soeClient.on("appdata", (err: string, data: Buffer) => {
74
- n++;
75
- var packet, result;
76
- try {
77
- packet = this._protocol.parse(data);
78
- } catch (e) {
79
- debug("Failed parsing app data loginclient_appdata_" + n + ".dat");
80
- return;
81
- }
82
-
83
- result = packet.result;
84
-
85
- switch (packet.name) {
86
- case "LoginReply":
87
- if (result.status === 1) {
88
- this.emit("login", null, {
89
- loggedIn: result.loggedIn,
90
- isMember: result.isMember,
91
- });
92
- } else {
93
- this.emit("login", "Login failed");
94
- }
95
- break;
96
- case "ForceDisconnect":
97
- break;
98
- case "CharacterLoginReply":
99
- if (result.status === 1) {
100
- debug(JSON.stringify(result, null, 4));
101
- this.emit("characterlogin", null, result);
102
- } else {
103
- this.emit("characterlogin", "Character login failed");
104
- }
105
- break;
106
- case "CharacterCreateReply":
107
- if (result.status === 1) {
108
- this.emit("charactercreate", null, {
109
- characterId: result.characterId,
110
- });
111
- } else {
112
- this.emit("charactercreate", "Character create failed");
113
- }
114
- break;
115
- case "CharacterDeleteReply":
116
- if (result.status === 1) {
117
- this.emit("characterdelete", null, {});
118
- } else {
119
- this.emit("characterdelete", "Character delete failed");
120
- }
121
- break;
122
- case "CharacterSelectInfoReply":
123
- if (result.status === 1) {
124
- this.emit("characterinfo", null, result);
125
- } else {
126
- this.emit("characterinfo", "Character info failed");
127
- }
128
- break;
129
- case "ServerListReply":
130
- this.emit("serverlist", null, {
131
- servers: result.servers,
132
- });
133
- break;
134
- case "ServerUpdate":
135
- if (result.status === 1) {
136
- this.emit("serverupdate", null, result.server);
137
- } else {
138
- this.emit("serverupdate", "Server update failed");
139
- }
140
- break;
141
- case "TunnelAppPacketServerToClient":
142
- break;
143
- }
144
- });
145
- }
146
-
147
- connect() {
148
- debug("Connecting to login server");
149
- this._soeClient.connect();
150
- }
151
-
152
- async login(fingerprint: string) {
153
- async function SetupLoginRequest(
154
- fingerprint: any,
155
- sessionId: any,
156
- protocol: any
157
- ) {
158
- var data = await protocol.pack("LoginRequest", {
159
- sessionId: sessionId,
160
- systemFingerPrint: fingerprint,
161
- });
162
- return data;
163
- }
164
-
165
- var data = await SetupLoginRequest(
166
- fingerprint,
167
- this._soeClient._sessionId.toString(),
168
- this._protocol
169
- );
170
- debug("Sending login request");
171
- this._soeClient.sendAppData(data, true);
172
-
173
- this.emit("connect");
174
- }
175
-
176
- disconnect() {
177
- this.emit("disconnect");
178
- }
179
-
180
- requestServerList() {
181
- debug("Requesting server list");
182
- var data = this._protocol.pack("ServerListRequest");
183
- this._soeClient.sendAppData(data, true);
184
- }
185
-
186
- requestCharacterInfo() {
187
- debug("Requesting character info");
188
- var data = this._protocol.pack("CharacterSelectInfoRequest");
189
- this._soeClient.sendAppData(data, true);
190
- }
191
-
192
- requestCharacterLogin(characterId: string, serverId: number, payload: any) {
193
- debug("Requesting character login");
194
- var data = this._protocol.pack("CharacterLoginRequest", {
195
- characterId: characterId,
196
- serverId: serverId,
197
- payload: payload,
198
- });
199
- if (data) {
200
- this._soeClient.sendAppData(data, true);
201
- } else {
202
- debug("Could not pack character login request data");
203
- }
204
- }
205
-
206
- requestCharacterDelete = function () {};
207
-
208
- requestCharacterCreate() {
209
- debug("Requesting character create");
210
- var data = this._protocol.pack("CharacterCreateRequest", {
211
- serverId: 1,
212
- unknown: 0,
213
- payload: {
214
- empireId: 2,
215
- headType: 1,
216
- profileType: 3,
217
- gender: 1,
218
- characterName: "test",
219
- },
220
- });
221
- if (data) {
222
- this._soeClient.sendAppData(data, true);
223
- } else {
224
- debug("Could not pack character create request data");
225
- }
226
- }
227
- }
1
+ // ======================================================================
2
+ //
3
+ // GNU GENERAL PUBLIC LICENSE
4
+ // Version 3, 29 June 2007
5
+ // copyright (c) 2020 - 2021 Quentin Gruber
6
+ // copyright (c) 2021 H1emu community
7
+ //
8
+ // https://github.com/QuentinGruber/h1z1-server
9
+ // https://www.npmjs.com/package/h1z1-server
10
+ //
11
+ // Based on https://github.com/psemu/soe-network
12
+ // ======================================================================
13
+
14
+ import { EventEmitter } from "events";
15
+
16
+ import { SOEClient } from "./soeclient";
17
+ import { LoginProtocol } from "../protocols/loginprotocol";
18
+ const loginProtocolName = "LoginUdp_9";
19
+ const debug = require("debug")("LoginClient");
20
+
21
+ interface SoeClient {
22
+ on: Function;
23
+ emit: Function;
24
+ connect: Function;
25
+ start: Function;
26
+ stop: Function;
27
+ _sessionId: number;
28
+ _protocol: LoginProtocol;
29
+ _sendPacket: Function;
30
+ sendAppData: Function;
31
+ toggleEncryption: Function;
32
+ toggleDataDump: Function;
33
+ }
34
+
35
+ interface LoginProtocolInterface {
36
+ parse: Function;
37
+ pack: Function;
38
+ }
39
+
40
+ export class LoginClient extends EventEmitter {
41
+ _gameId: number;
42
+ _environment: string;
43
+ _soeClient: any;
44
+ _protocol: LoginProtocolInterface;
45
+
46
+ constructor(
47
+ gameId: number,
48
+ environment: string,
49
+ serverAddress: string,
50
+ serverPort: number,
51
+ loginKey: Uint8Array,
52
+ localPort: number
53
+ ) {
54
+ super();
55
+ this._gameId = gameId;
56
+ this._environment = environment;
57
+ this._soeClient = new SOEClient(
58
+ loginProtocolName,
59
+ serverAddress,
60
+ serverPort,
61
+ loginKey,
62
+ localPort
63
+ );
64
+ this._protocol = new LoginProtocol();
65
+ var n = 0;
66
+ this._soeClient.on("connect", (err: string, result: string) => {
67
+ debug("Connected to login server");
68
+ this.login("FiNgErPrInT");
69
+ });
70
+ this._soeClient.on("disconnect", (err: string, result: string) => {
71
+ debug("Disconnected");
72
+ });
73
+ this._soeClient.on("appdata", (err: string, data: Buffer) => {
74
+ n++;
75
+ var packet, result;
76
+ try {
77
+ packet = this._protocol.parse(data);
78
+ } catch (e) {
79
+ debug("Failed parsing app data loginclient_appdata_" + n + ".dat");
80
+ return;
81
+ }
82
+
83
+ result = packet.result;
84
+
85
+ switch (packet.name) {
86
+ case "LoginReply":
87
+ if (result.status === 1) {
88
+ this.emit("login", null, {
89
+ loggedIn: result.loggedIn,
90
+ isMember: result.isMember,
91
+ });
92
+ } else {
93
+ this.emit("login", "Login failed");
94
+ }
95
+ break;
96
+ case "ForceDisconnect":
97
+ break;
98
+ case "CharacterLoginReply":
99
+ if (result.status === 1) {
100
+ debug(JSON.stringify(result, null, 4));
101
+ this.emit("characterlogin", null, result);
102
+ } else {
103
+ this.emit("characterlogin", "Character login failed");
104
+ }
105
+ break;
106
+ case "CharacterCreateReply":
107
+ if (result.status === 1) {
108
+ this.emit("charactercreate", null, {
109
+ characterId: result.characterId,
110
+ });
111
+ } else {
112
+ this.emit("charactercreate", "Character create failed");
113
+ }
114
+ break;
115
+ case "CharacterDeleteReply":
116
+ if (result.status === 1) {
117
+ this.emit("characterdelete", null, {});
118
+ } else {
119
+ this.emit("characterdelete", "Character delete failed");
120
+ }
121
+ break;
122
+ case "CharacterSelectInfoReply":
123
+ if (result.status === 1) {
124
+ this.emit("characterinfo", null, result);
125
+ } else {
126
+ this.emit("characterinfo", "Character info failed");
127
+ }
128
+ break;
129
+ case "ServerListReply":
130
+ this.emit("serverlist", null, {
131
+ servers: result.servers,
132
+ });
133
+ break;
134
+ case "ServerUpdate":
135
+ if (result.status === 1) {
136
+ this.emit("serverupdate", null, result.server);
137
+ } else {
138
+ this.emit("serverupdate", "Server update failed");
139
+ }
140
+ break;
141
+ case "TunnelAppPacketServerToClient":
142
+ break;
143
+ }
144
+ });
145
+ }
146
+
147
+ connect() {
148
+ debug("Connecting to login server");
149
+ this._soeClient.connect();
150
+ }
151
+
152
+ async login(fingerprint: string) {
153
+ async function SetupLoginRequest(
154
+ fingerprint: any,
155
+ sessionId: any,
156
+ protocol: any
157
+ ) {
158
+ var data = await protocol.pack("LoginRequest", {
159
+ sessionId: sessionId,
160
+ systemFingerPrint: fingerprint,
161
+ });
162
+ return data;
163
+ }
164
+
165
+ var data = await SetupLoginRequest(
166
+ fingerprint,
167
+ this._soeClient._sessionId.toString(),
168
+ this._protocol
169
+ );
170
+ debug("Sending login request");
171
+ this._soeClient.sendAppData(data, true);
172
+
173
+ this.emit("connect");
174
+ }
175
+
176
+ disconnect() {
177
+ this.emit("disconnect");
178
+ }
179
+
180
+ requestServerList() {
181
+ debug("Requesting server list");
182
+ var data = this._protocol.pack("ServerListRequest");
183
+ this._soeClient.sendAppData(data, true);
184
+ }
185
+
186
+ requestCharacterInfo() {
187
+ debug("Requesting character info");
188
+ var data = this._protocol.pack("CharacterSelectInfoRequest");
189
+ this._soeClient.sendAppData(data, true);
190
+ }
191
+
192
+ requestCharacterLogin(characterId: string, serverId: number, payload: any) {
193
+ debug("Requesting character login");
194
+ var data = this._protocol.pack("CharacterLoginRequest", {
195
+ characterId: characterId,
196
+ serverId: serverId,
197
+ payload: payload,
198
+ });
199
+ if (data) {
200
+ this._soeClient.sendAppData(data, true);
201
+ } else {
202
+ debug("Could not pack character login request data");
203
+ }
204
+ }
205
+
206
+ requestCharacterDelete = function () {};
207
+
208
+ requestCharacterCreate() {
209
+ debug("Requesting character create");
210
+ var data = this._protocol.pack("CharacterCreateRequest", {
211
+ serverId: 1,
212
+ unknown: 0,
213
+ payload: {
214
+ empireId: 2,
215
+ headType: 1,
216
+ profileType: 3,
217
+ gender: 1,
218
+ characterName: "test",
219
+ },
220
+ });
221
+ if (data) {
222
+ this._soeClient.sendAppData(data, true);
223
+ } else {
224
+ debug("Could not pack character create request data");
225
+ }
226
+ }
227
+ }