h1z1-server 0.23.3-2 → 0.23.3-4

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.
@@ -2866,7 +2866,6 @@
2866
2866
  "IS_ARMOR": 0,
2867
2867
  "PASSIVE_EQUIP_SLOT_GROUP_ID": 0,
2868
2868
  "SCRAP_VALUE_OVERRIDE": 0,
2869
- "WORLD_MODEL_ID": 2,
2870
2869
  "PICKUP_EFFECT": 5151
2871
2870
  },
2872
2871
  "40": {
@@ -22561,7 +22560,8 @@
22561
22560
  "IS_ARMOR": 0,
22562
22561
  "PASSIVE_EQUIP_SLOT_GROUP_ID": 0,
22563
22562
  "SCRAP_VALUE_OVERRIDE": 0,
22564
- "PICKUP_EFFECT": 5151
22563
+ "PICKUP_EFFECT": 5151,
22564
+ "WORLD_MODEL_ID": 8019
22565
22565
  },
22566
22566
  "1536": {
22567
22567
  "NAME": "Hammer",
@@ -60885,7 +60885,8 @@
60885
60885
  "IS_ARMOR": 0,
60886
60886
  "PASSIVE_EQUIP_SLOT_GROUP_ID": 0,
60887
60887
  "SCRAP_VALUE_OVERRIDE": 0,
60888
- "PICKUP_EFFECT": 5151
60888
+ "PICKUP_EFFECT": 5151,
60889
+ "WORLD_MODEL_ID": 9583
60889
60890
  },
60890
60891
  "2274": {
60891
60892
  "NAME": "Police Body Armor",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "h1z1-server",
3
- "version": "0.23.3-2",
3
+ "version": "0.23.3-4",
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",
@@ -35,7 +35,7 @@ export const voicePackets: any = [
35
35
  ],
36
36
  },
37
37
  ],
38
- ["Voice.LeaveChannel", 0x8202, {}],
39
- ["Voice.RadioChannel", 0x8207, {}],
40
- ["Voice.LeaveRadio", 0x8208, {}],
38
+ ["Voice.LeaveChannel", 0x8202, { fields: [] }],
39
+ ["Voice.RadioChannel", 0x8207, { fields: [] }],
40
+ ["Voice.LeaveRadio", 0x8208, { fields: [] }],
41
41
  ];
@@ -128,6 +128,26 @@ const packets = [
128
128
  ],
129
129
  },
130
130
  ],
131
+ [
132
+ "ClientIsAdminRequest",
133
+ 0x14,
134
+ {
135
+ fields: [
136
+ { name: "reqId", type: "uint32", defaultValue: 0 },
137
+ { name: "guid", type: "uint64string", defaultValue: 0 },
138
+ ],
139
+ },
140
+ ],
141
+ [
142
+ "ClientIsAdminReply",
143
+ 0x15,
144
+ {
145
+ fields: [
146
+ { name: "reqId", type: "uint32", defaultValue: 0 },
147
+ { name: "status", type: "boolean", defaultValue: 0 },
148
+ ],
149
+ },
150
+ ],
131
151
  ];
132
152
 
133
153
  export const [H1emuPacketsPacketTypes, H1emuPacketsPackets] =
@@ -30,7 +30,8 @@ export class H1emuLoginServer extends H1emuServer {
30
30
  break;
31
31
  case "CharacterCreateReply":
32
32
  case "CharacterExistReply":
33
- case "CharacterDeleteReply": {
33
+ case "CharacterDeleteReply":
34
+ case "ClientIsAdminReply": {
34
35
  this.emit("processInternalReq", packet, ["status"]);
35
36
  break;
36
37
  }
@@ -35,7 +35,7 @@ import { Worker } from "worker_threads";
35
35
  import { httpServerMessage } from "types/shared";
36
36
  import { LoginProtocol2016 } from "../../protocols/loginprotocol2016";
37
37
  import { crc_length_options } from "../../types/soeserver";
38
- import { DEFAULT_CRYPTO_KEY } from "../../utils/constants";
38
+ import { DB_NAME, DEFAULT_CRYPTO_KEY } from "../../utils/constants";
39
39
  import { healthThreadDecorator } from "../../servers/shared/workers/healthWorker";
40
40
  import {
41
41
  LoginReply,
@@ -52,7 +52,11 @@ import {
52
52
  import { LoginUdp_9packets } from "types/LoginUdp_9packets";
53
53
  import { getCharacterModelData } from "../shared/functions";
54
54
  import LoginClient from "servers/LoginServer/loginclient";
55
- import { GAME_VERSIONS, NAME_VALIDATION_STATUS } from "../../utils/enums";
55
+ import {
56
+ DB_COLLECTIONS,
57
+ GAME_VERSIONS,
58
+ NAME_VALIDATION_STATUS,
59
+ } from "../../utils/enums";
56
60
  import DataSchema from "h1z1-dataschema";
57
61
  import { applicationDataKOTK } from "../../packets/LoginUdp/LoginUdp_11/loginpackets";
58
62
  import { Resolver } from "dns";
@@ -183,7 +187,7 @@ export class LoginServer extends EventEmitter {
183
187
  );
184
188
  let status = 0;
185
189
  const { serverAddress: fullServerAddress } = await this._db
186
- .collection("servers")
190
+ .collection(DB_COLLECTIONS.SERVERS)
187
191
  .findOne({ serverId: serverId });
188
192
  const serverAddress = fullServerAddress.split(":")[0];
189
193
  if (serverAddress) {
@@ -216,19 +220,23 @@ export class LoginServer extends EventEmitter {
216
220
  const { population } = packet.data;
217
221
  const serverId = this._zoneConnections[client.clientId];
218
222
  const { maxPopulationNumber } = await this._db
219
- .collection("servers")
223
+ .collection(DB_COLLECTIONS.SERVERS)
220
224
  .findOne({ serverId: serverId });
221
- this._db?.collection("servers").findOneAndUpdate(
222
- { serverId: serverId },
223
- {
224
- $set: {
225
- populationNumber: population,
226
- populationLevel: Number(
227
- ((population / maxPopulationNumber) * 3).toFixed(0)
228
- ),
229
- },
230
- }
231
- );
225
+ this._db
226
+ ?.collection(DB_COLLECTIONS.SERVERS)
227
+ .findOneAndUpdate(
228
+ { serverId: serverId },
229
+ {
230
+ $set: {
231
+ populationNumber: population,
232
+ populationLevel: Number(
233
+ ((population / maxPopulationNumber) * 3).toFixed(
234
+ 0
235
+ )
236
+ ),
237
+ },
238
+ }
239
+ );
232
240
  break;
233
241
  }
234
242
  default:
@@ -276,7 +284,10 @@ export class LoginServer extends EventEmitter {
276
284
  }`
277
285
  );
278
286
  delete this._zoneConnections[client.clientId];
279
- if (client.serverId) {
287
+ if (
288
+ client.serverId &&
289
+ !Object.values(this._zoneConnections).includes(client.serverId)
290
+ ) {
280
291
  await this.updateServerStatus(client.serverId, false);
281
292
  }
282
293
  }
@@ -371,7 +382,7 @@ export class LoginServer extends EventEmitter {
371
382
  status: 1,
372
383
  };
373
384
  return await this._db
374
- .collection("characters-light")
385
+ .collection(DB_COLLECTIONS.CHARACTERS_LIGHT)
375
386
  .find(charactersQuery)
376
387
  .toArray();
377
388
  }
@@ -395,15 +406,15 @@ export class LoginServer extends EventEmitter {
395
406
  client.protocolName === "LoginUdp_9"
396
407
  ? GAME_VERSIONS.H1Z1_15janv_2015
397
408
  : GAME_VERSIONS.H1Z1_6dec_2016;
398
- console.warn(
399
- "Your session id is not a valid json string, please update your launcher to avoid this warning"
400
- );
409
+ //console.warn(
410
+ // "Your session id is not a valid json string, please update your launcher to avoid this warning"
411
+ //);
401
412
  }
402
413
  if (this._soloMode) {
403
414
  client.loginSessionId = String(sessionId);
404
415
  } else {
405
416
  const realSession = await this._db
406
- .collection("user-sessions")
417
+ .collection(DB_COLLECTIONS.USERS_SESSIONS)
407
418
  .findOne({ guid: sessionId });
408
419
  client.loginSessionId = realSession ? realSession.authKey : sessionId;
409
420
  }
@@ -449,7 +460,7 @@ export class LoginServer extends EventEmitter {
449
460
  let status = isValidCharacterName(characterName);
450
461
  if (!this._soloMode) {
451
462
  const blackListedEntry = await this._db
452
- .collection("blackListEntries")
463
+ .collection(DB_COLLECTIONS.BLACK_LIST_ENTRIES)
453
464
  .findOne({
454
465
  WORD: characterName.toUpperCase(),
455
466
  });
@@ -461,7 +472,7 @@ export class LoginServer extends EventEmitter {
461
472
  }
462
473
  } else {
463
474
  const duplicateCharacter = await this._db
464
- .collection("characters-light")
475
+ .collection(DB_COLLECTIONS.CHARACTERS_LIGHT)
465
476
  .findOne({
466
477
  "payload.name": characterName,
467
478
  serverId: baseResponse.serverId,
@@ -555,16 +566,18 @@ export class LoginServer extends EventEmitter {
555
566
  }
556
567
 
557
568
  async updateServerStatus(serverId: number, status: boolean) {
558
- const server = await this._db.collection("servers").findOneAndUpdate(
559
- { serverId: serverId },
560
- {
561
- $set: {
562
- allowedAccess: status,
563
- populationNumber: 0,
564
- populationLevel: 0,
565
- },
566
- }
567
- );
569
+ const server = await this._db
570
+ .collection(DB_COLLECTIONS.SERVERS)
571
+ .findOneAndUpdate(
572
+ { serverId: serverId },
573
+ {
574
+ $set: {
575
+ allowedAccess: status,
576
+ populationNumber: 0,
577
+ populationLevel: 0,
578
+ },
579
+ }
580
+ );
568
581
  this.clients.forEach((client: Client) => {
569
582
  if (client.gameVersion === server.value.gameVersion) {
570
583
  this.sendData(client, "ServerUpdate", {
@@ -576,7 +589,10 @@ export class LoginServer extends EventEmitter {
576
589
  }
577
590
 
578
591
  async updateServersStatus(): Promise<void> {
579
- const servers = await this._db.collection("servers").find().toArray();
592
+ const servers = await this._db
593
+ .collection(DB_COLLECTIONS.SERVERS)
594
+ .find()
595
+ .toArray();
580
596
 
581
597
  for (let index = 0; index < servers.length; index++) {
582
598
  const server: GameServer = servers[index];
@@ -593,7 +609,7 @@ export class LoginServer extends EventEmitter {
593
609
  let servers;
594
610
  if (!this._soloMode) {
595
611
  servers = await this._db
596
- .collection("servers")
612
+ .collection(DB_COLLECTIONS.SERVERS)
597
613
  .find({
598
614
  gameVersion: client.gameVersion,
599
615
  })
@@ -675,7 +691,7 @@ export class LoginServer extends EventEmitter {
675
691
  const characterId = packet.characterId;
676
692
  const characterQuery = { characterId: characterId };
677
693
  const charracterToDelete = await this._db
678
- .collection("characters-light")
694
+ .collection(DB_COLLECTIONS.CHARACTERS_LIGHT)
679
695
  .findOne(characterQuery);
680
696
  if (
681
697
  charracterToDelete &&
@@ -688,7 +704,7 @@ export class LoginServer extends EventEmitter {
688
704
  )) as number;
689
705
  if (deletionStatus) {
690
706
  await this._db
691
- .collection("characters-light")
707
+ .collection(DB_COLLECTIONS.CHARACTERS_LIGHT)
692
708
  .updateOne(characterQuery, {
693
709
  $set: {
694
710
  status: 0,
@@ -712,11 +728,13 @@ export class LoginServer extends EventEmitter {
712
728
  loginSessionId: string | undefined
713
729
  ): Promise<CharacterLoginReply> {
714
730
  const { serverAddress, populationNumber, maxPopulationNumber } =
715
- await this._db.collection("servers").findOne({ serverId: serverId });
731
+ await this._db
732
+ .collection(DB_COLLECTIONS.SERVERS)
733
+ .findOne({ serverId: serverId });
716
734
  const character = await this._db
717
- .collection("characters-light")
735
+ .collection(DB_COLLECTIONS.CHARACTERS_LIGHT)
718
736
  .findOne({ characterId: characterId });
719
- const connectionStatus =
737
+ let connectionStatus =
720
738
  Object.values(this._zoneConnections).includes(serverId) &&
721
739
  (populationNumber < maxPopulationNumber || !maxPopulationNumber);
722
740
  debug(`connectionStatus ${connectionStatus}`);
@@ -728,9 +746,16 @@ export class LoginServer extends EventEmitter {
728
746
  }
729
747
  const hiddenSession = connectionStatus
730
748
  ? await this._db
731
- .collection("user-sessions")
749
+ .collection(DB_COLLECTIONS.USERS_SESSIONS)
732
750
  .findOne({ authKey: loginSessionId })
733
751
  : { guid: "" };
752
+ connectionStatus = false;
753
+ if (!connectionStatus) {
754
+ // Admins bypass max pop
755
+ connectionStatus = (await this.askZone(serverId, "ClientIsAdminRequest", {
756
+ guid: hiddenSession?.guid,
757
+ })) as boolean;
758
+ }
734
759
  return {
735
760
  unknownQword1: "0x0",
736
761
  unknownDword1: 0,
@@ -936,7 +961,7 @@ export class LoginServer extends EventEmitter {
936
961
  } else {
937
962
  let sessionObj;
938
963
  const storedUserSession = await this._db
939
- ?.collection("user-sessions")
964
+ ?.collection(DB_COLLECTIONS.USERS_SESSIONS)
940
965
  .findOne({ authKey: client.loginSessionId, serverId: serverId });
941
966
  if (storedUserSession) {
942
967
  sessionObj = storedUserSession;
@@ -946,7 +971,9 @@ export class LoginServer extends EventEmitter {
946
971
  authKey: client.loginSessionId,
947
972
  guid: generateRandomGuid(),
948
973
  };
949
- await this._db?.collection("user-sessions").insertOne(sessionObj);
974
+ await this._db
975
+ ?.collection(DB_COLLECTIONS.USERS_SESSIONS)
976
+ .insertOne(sessionObj);
950
977
  }
951
978
  let newCharacterData;
952
979
  switch (client.gameVersion) {
@@ -974,7 +1001,7 @@ export class LoginServer extends EventEmitter {
974
1001
  : 0;
975
1002
 
976
1003
  if (creationStatus === 1) {
977
- await this._db.collection("characters-light").insertOne({
1004
+ await this._db.collection(DB_COLLECTIONS.CHARACTERS_LIGHT).insertOne({
978
1005
  authKey: client.loginSessionId,
979
1006
  serverId: serverId,
980
1007
  gameVersion: client.gameVersion,
@@ -1008,11 +1035,11 @@ export class LoginServer extends EventEmitter {
1008
1035
  debug("connected to mongo !");
1009
1036
  // if no collections exist on h1server database , fill it with samples
1010
1037
  const dbIsEmpty =
1011
- (await mongoClient.db("h1server").collections()).length < 1;
1038
+ (await mongoClient.db(DB_NAME).collections()).length < 1;
1012
1039
  if (dbIsEmpty) {
1013
1040
  await initMongo(mongoClient, debugName);
1014
1041
  }
1015
- this._db = mongoClient.db("h1server");
1042
+ this._db = mongoClient.db(DB_NAME);
1016
1043
  this.updateServersStatus();
1017
1044
  }
1018
1045
 
@@ -15,6 +15,8 @@ import { MongoClient } from "mongodb";
15
15
  import { httpServerMessage } from "types/shared";
16
16
  import { parentPort, workerData } from "worker_threads";
17
17
  import http from "http";
18
+ import { DB_COLLECTIONS } from "../../../utils/enums";
19
+ import { DB_NAME } from "../../../utils/constants";
18
20
  function sendMessageToServer(type: string, requestId: number, data: any) {
19
21
  const message: httpServerMessage = {
20
22
  type: type,
@@ -29,7 +31,7 @@ const { MONGO_URL, SERVER_PORT } = workerData;
29
31
  const client = new MongoClient(MONGO_URL, {
30
32
  maxPoolSize: 5,
31
33
  });
32
- const dbName = "h1server";
34
+ const dbName = DB_NAME;
33
35
  const db = client.db(dbName);
34
36
  client.connect();
35
37
  let requestCount = 0;
@@ -61,7 +63,7 @@ httpServer.on("request", async function (req, res) {
61
63
  const queryObject: any = queryString ? parseQueryString(queryString) : null;
62
64
  switch (path) {
63
65
  case "servers": {
64
- const collection = db.collection("servers");
66
+ const collection = db.collection(DB_COLLECTIONS.SERVERS);
65
67
  const serversArray = await collection.find().toArray();
66
68
  res.writeHead(200, { "Content-Type": "text/json" });
67
69
  res.write(JSON.stringify(serversArray));
@@ -36,7 +36,7 @@ import { ZoneClient as Client } from "./classes/zoneclient";
36
36
  import { h1z1PacketsType } from "../../types/packets";
37
37
  import { Vehicle } from "./classes/vehicle";
38
38
  import { Resolver } from "dns";
39
- import { DEFAULT_CRYPTO_KEY } from "../../utils/constants";
39
+ import { DB_NAME, DEFAULT_CRYPTO_KEY } from "../../utils/constants";
40
40
 
41
41
  process.env.isBin && require("./workers/dynamicWeather");
42
42
 
@@ -658,12 +658,11 @@ export class ZoneServer2015 extends EventEmitter {
658
658
  }
659
659
  debug("connected to mongo !");
660
660
  // if no collections exist on h1server database , fill it with samples
661
- const dbIsEmpty =
662
- (await mongoClient.db("h1server").collections()).length < 1;
661
+ const dbIsEmpty = (await mongoClient.db(DB_NAME).collections()).length < 1;
663
662
  if (dbIsEmpty) {
664
663
  await initMongo(mongoClient, debugName);
665
664
  }
666
- this._db = mongoClient.db("h1server");
665
+ this._db = mongoClient.db(DB_NAME);
667
666
  }
668
667
 
669
668
  async start(): Promise<void> {
@@ -36,6 +36,7 @@ export class ZoneClient2016 {
36
36
  time: 0,
37
37
  };
38
38
  speedWarnsNumber: number = 0;
39
+ allowedProjectiles: number = 0;
39
40
  pvpStats: {
40
41
  shotsFired: number;
41
42
  shotsHit: number;
@@ -60,6 +61,7 @@ export class ZoneClient2016 {
60
61
  vehicle: {
61
62
  mountedVehicle?: string;
62
63
  } = {};
64
+ radio: boolean = false;
63
65
  npcsToSpawnTimer!: NodeJS.Timeout;
64
66
  loginSessionId: string;
65
67
  pingTimer: NodeJS.Timeout | undefined;