h1z1-server 0.32.2 → 0.32.3

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.
@@ -59,8 +59,8 @@
59
59
  "bounds": [
60
60
  [
61
61
  [ -721.030029296875, -1885.239990234375 ],
62
- [ -535.3099975585938, -1889.8499755859375 ],
63
- [ -492.2699890136719, -1419.489990234375 ],
62
+ [ -584.3099975585938, -1889.8499755859375 ],
63
+ [ -611.2699890136719, -1419.489990234375 ],
64
64
  [ -719.4400024414062, -1423.9599609375 ]
65
65
  ]
66
66
  ],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "h1z1-server",
3
- "version": "0.32.2",
3
+ "version": "0.32.3",
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",
@@ -45,7 +45,7 @@ import {
45
45
  randomIntFromInterval,
46
46
  _,
47
47
  checkConstructionInRange,
48
- getCurrentTimeWrapper
48
+ getCurrentServerTimeWrapper
49
49
  } from "../../../utils/utils";
50
50
  import { BaseItem } from "../classes/baseItem";
51
51
  import { BaseLootableEntity } from "./baselootableentity";
@@ -165,6 +165,7 @@ export class Character2016 extends BaseFullCharacter {
165
165
  spawnGridData: number[] = [];
166
166
  lastJumpTime: number = 0;
167
167
  lastSitTime: number = 0;
168
+ lastCraftTime: number = 0;
168
169
  sitCount: number = 0;
169
170
  weaponStance: number = 1;
170
171
  stance?: StanceFlags;
@@ -499,10 +500,12 @@ export class Character2016 extends BaseFullCharacter {
499
500
  this.checkResource(server, ResourceIds.HUNGER, () => {
500
501
  this.damage(server, { entity: "Character.Hunger", damage: 100 });
501
502
  });
502
- const indexHunger = this.resourceHudIndicators.indexOf("STARVING");
503
+ const indexHunger = this.resourceHudIndicators.indexOf(
504
+ ResourceIndicators.STARVING
505
+ );
503
506
  if (hunger == 0) {
504
507
  if (indexHunger <= -1) {
505
- this.resourceHudIndicators.push("STARVING");
508
+ this.resourceHudIndicators.push(ResourceIndicators.STARVING);
506
509
  server.sendHudIndicators(client);
507
510
  }
508
511
  } else {
@@ -511,11 +514,12 @@ export class Character2016 extends BaseFullCharacter {
511
514
  server.sendHudIndicators(client);
512
515
  }
513
516
  }
514
- const indexFoodPoison =
515
- this.resourceHudIndicators.indexOf("FOOD POISONING");
517
+ const indexFoodPoison = this.resourceHudIndicators.indexOf(
518
+ ResourceIndicators.FOOD_POISONING
519
+ );
516
520
  if (this.isPoisoned) {
517
521
  if (indexFoodPoison <= -1) {
518
- this.resourceHudIndicators.push("FOOD POISONING");
522
+ this.resourceHudIndicators.push(ResourceIndicators.FOOD_POISONING);
519
523
  server.sendHudIndicators(client);
520
524
  }
521
525
  } else {
@@ -530,10 +534,12 @@ export class Character2016 extends BaseFullCharacter {
530
534
  this.checkResource(server, ResourceIds.HYDRATION, () => {
531
535
  this.damage(server, { entity: "Character.Hydration", damage: 100 });
532
536
  });
533
- const indexDehydrated = this.resourceHudIndicators.indexOf("DEHYDRATED");
537
+ const indexDehydrated = this.resourceHudIndicators.indexOf(
538
+ ResourceIndicators.DEHYDRATED
539
+ );
534
540
  if (hydration == 0) {
535
541
  if (indexDehydrated <= -1) {
536
- this.resourceHudIndicators.push("DEHYDRATED");
542
+ this.resourceHudIndicators.push(ResourceIndicators.DEHYDRATED);
537
543
  server.sendHudIndicators(client);
538
544
  }
539
545
  } else {
@@ -1416,7 +1422,7 @@ export class Character2016 extends BaseFullCharacter {
1416
1422
  },
1417
1423
  positionUpdate: {
1418
1424
  ...this.positionUpdate,
1419
- sequenceTime: getCurrentTimeWrapper().getTruncatedU32(),
1425
+ sequenceTime: getCurrentServerTimeWrapper().getTruncatedU32(),
1420
1426
  position: this.state.position, // trying to fix invisible characters/vehicles until they move
1421
1427
  stance: 66561
1422
1428
  },
@@ -15,6 +15,7 @@ import {
15
15
  ConstructionPermissionIds,
16
16
  Effects,
17
17
  Items,
18
+ ResourceIndicators,
18
19
  StringIds
19
20
  } from "../models/enums";
20
21
  import { DamageInfo, HudIndicator } from "types/zoneserver";
@@ -299,7 +300,7 @@ export class LootableConstructionEntity extends BaseLootableEntity {
299
300
  }
300
301
 
301
302
  let hudIndicator: HudIndicator | undefined = undefined;
302
- hudIndicator = server._hudIndicators["BEES!"];
303
+ hudIndicator = server._hudIndicators[ResourceIndicators.BEES];
303
304
 
304
305
  if (!hudIndicator) return;
305
306
 
@@ -292,18 +292,45 @@ export class Npc extends BaseFullCharacter {
292
292
  client: ZoneClient2016,
293
293
  rewardItems: { itemDefId: number; weight: number }[]
294
294
  ) {
295
- const totalWeight = rewardItems.reduce((sum, item) => sum + item.weight, 0);
296
- const randomValue = Math.random() * totalWeight;
297
- let count = 1;
295
+ const ranges = [];
296
+ const preRewardedItems: number[] = [];
297
+
298
298
  let cumulativeWeight = 0;
299
299
  for (const reward of rewardItems) {
300
- cumulativeWeight += reward.weight;
301
- if (randomValue <= cumulativeWeight) {
300
+ const range = {
301
+ start: cumulativeWeight,
302
+ end: cumulativeWeight + reward.weight,
303
+ item: reward
304
+ };
305
+ ranges.push(range);
306
+ cumulativeWeight = range.end;
307
+ }
308
+
309
+ const totalWeight = rewardItems.reduce((sum, item) => sum + item.weight, 0);
310
+ let count = 1;
311
+
312
+ let selectedRange = ranges[0];
313
+ for (let i = 0; i < rewardItems.length; i++) {
314
+ const randomValue = Math.random() * totalWeight;
315
+ for (const range of ranges) {
316
+ if (randomValue >= range.start && randomValue < range.end) {
317
+ selectedRange = range;
318
+ break; // Break out of the loop once a range is chosen
319
+ }
320
+ }
321
+
322
+ if (!preRewardedItems.includes(selectedRange.item.itemDefId)) {
323
+ preRewardedItems.push(selectedRange.item.itemDefId);
324
+
302
325
  if (Math.random() <= 0.4) {
303
326
  // 40% chance to spawn double rewards
304
327
  count = 2;
305
328
  }
306
- const rewardItem = server.generateItem(reward.itemDefId, count);
329
+
330
+ const rewardItem = server.generateItem(
331
+ selectedRange.item.itemDefId,
332
+ count
333
+ );
307
334
  if (rewardItem) client.character.lootContainerItem(server, rewardItem);
308
335
  }
309
336
  }
@@ -13,7 +13,7 @@
13
13
 
14
14
  import {
15
15
  createPositionUpdate,
16
- getCurrentTimeWrapper
16
+ getCurrentServerTimeWrapper
17
17
  } from "../../../utils/utils";
18
18
  import { VehicleIds } from "../models/enums";
19
19
  import { ZoneServer2016 } from "../zoneserver";
@@ -121,7 +121,7 @@ export class Plane extends Vehicle2016 {
121
121
  },
122
122
  positionUpdate: {
123
123
  ...this.positionUpdate,
124
- sequenceTime: getCurrentTimeWrapper().getTruncatedU32(),
124
+ sequenceTime: getCurrentServerTimeWrapper().getTruncatedU32(),
125
125
  position: this.state.position // trying to fix invisible characters/vehicles until they move
126
126
  },
127
127
  unknownArray1: [],
@@ -2,7 +2,7 @@ import test, { after } from "node:test";
2
2
  import { ZoneServer2016 } from "../zoneserver";
3
3
  import { Vehicle2016 } from "./vehicle";
4
4
  import { DamageInfo } from "types/zoneserver";
5
- import { getCurrentTimeWrapper } from "../../../utils/utils";
5
+ import { getCurrentServerTimeWrapper } from "../../../utils/utils";
6
6
  import assert from "node:assert";
7
7
 
8
8
  test("Damage-pve", { timeout: 10000 }, async (t) => {
@@ -19,7 +19,7 @@ test("Damage-pve", { timeout: 10000 }, async (t) => {
19
19
  new Float32Array([0, 0, 0]),
20
20
  new Float32Array([0, 0, 0]),
21
21
  zone,
22
- getCurrentTimeWrapper().getTruncatedU32(),
22
+ getCurrentServerTimeWrapper().getTruncatedU32(),
23
23
  3
24
24
  );
25
25
  await t.test("Damage from entity", async () => {
@@ -52,7 +52,7 @@ test("Damage-pvp", { timeout: 10000 }, async (t) => {
52
52
  new Float32Array([0, 0, 0]),
53
53
  new Float32Array([0, 0, 0]),
54
54
  zone,
55
- getCurrentTimeWrapper().getTruncatedU32(),
55
+ getCurrentServerTimeWrapper().getTruncatedU32(),
56
56
  3
57
57
  );
58
58
  await t.test("Damage from entity", async () => {
@@ -26,7 +26,7 @@ import {
26
26
  isPosInRadius,
27
27
  toHex,
28
28
  randomIntFromInterval,
29
- getCurrentTimeWrapper
29
+ getCurrentServerTimeWrapper
30
30
  } from "../../../../utils/utils";
31
31
  import { ExplosiveEntity } from "../../entities/explosiveentity";
32
32
  import { Npc } from "../../entities/npc";
@@ -131,9 +131,7 @@ export const commands: Array<Command> = [
131
131
  } = server;
132
132
  const serverVersion = require("../../../../../package.json").version;
133
133
  server.sendChatText(client, `h1z1-server V${serverVersion}`, true);
134
- const uptimeMin =
135
- getCurrentTimeWrapper().getMinutes() -
136
- server._serverStartTime.getMinutes();
134
+ const uptimeMin = getCurrentServerTimeWrapper().getMinutes();
137
135
 
138
136
  server.sendChatText(
139
137
  client,
@@ -1784,7 +1782,7 @@ export const commands: Array<Command> = [
1784
1782
  },
1785
1783
  positionUpdate: {
1786
1784
  ...client.character.positionUpdate,
1787
- sequenceTime: getCurrentTimeWrapper().getTruncatedU32(),
1785
+ sequenceTime: getCurrentServerTimeWrapper().getTruncatedU32(),
1788
1786
  position: client.character.state.position,
1789
1787
  stance: client.character.stance
1790
1788
  },
@@ -18,7 +18,10 @@ import { SpawnCell } from "../../classes/spawncell";
18
18
  import { ZoneClient2016 as Client } from "../../classes/zoneclient";
19
19
  import { ZoneServer2016 } from "../../zoneserver";
20
20
  import { InternalCommand, PermissionLevels } from "./types";
21
- import { getCurrentTimeWrapper, isPosInRadius } from "../../../../utils/utils";
21
+ import {
22
+ getCurrentServerTimeWrapper,
23
+ isPosInRadius
24
+ } from "../../../../utils/utils";
22
25
  import { OBSERVER_GUID } from "../../../../utils/constants";
23
26
  import {
24
27
  CharacterRespawn,
@@ -66,7 +69,7 @@ export const internalCommands: Array<InternalCommand> = [
66
69
  client.character.state.position,
67
70
  client.character.state.lookAt,
68
71
  server,
69
- getCurrentTimeWrapper().getTruncatedU32(),
72
+ getCurrentServerTimeWrapper().getTruncatedU32(),
70
73
  VehicleIds.SPECTATE
71
74
  );
72
75
  for (const a in server._clients) {
@@ -176,7 +179,7 @@ export const internalCommands: Array<InternalCommand> = [
176
179
  position,
177
180
  client.character.state.lookAt,
178
181
  server,
179
- getCurrentTimeWrapper().getTruncatedU32(),
182
+ getCurrentServerTimeWrapper().getTruncatedU32(),
180
183
  vehicleId
181
184
  );
182
185
  server.worldObjectManager.createVehicle(server, vehicle);
@@ -466,10 +466,10 @@ export class CraftManager {
466
466
  if (!remainingItems) break;
467
467
  }
468
468
  }
469
-
469
+ client.character.lastCraftTime = Date.now();
470
470
  client.character.lootItem(
471
471
  server,
472
- server.generateItem(recipeId, craftCount)
472
+ server.generateItem(recipeId, craftCount, client.character.lastCraftTime)
473
473
  );
474
474
  if (recipe.leftOverItems) {
475
475
  recipe.leftOverItems.forEach((id: number) => {
@@ -24,7 +24,7 @@ import {
24
24
  } from "../../../utils/enums";
25
25
  import {
26
26
  decrypt,
27
- getCurrentTimeWrapper,
27
+ getCurrentServerTimeWrapper,
28
28
  getDistance,
29
29
  getDistance1d,
30
30
  getDistance2d,
@@ -196,7 +196,7 @@ export class FairPlayManager {
196
196
  new Date().getTime()
197
197
  ) {
198
198
  const drift = Math.abs(
199
- sequenceTime - getCurrentTimeWrapper().getTruncatedU32()
199
+ sequenceTime - getCurrentServerTimeWrapper().getTruncatedU32()
200
200
  );
201
201
  if (drift > this.fairPlayValues.maxTimeDrift) {
202
202
  server.kickPlayer(client);
@@ -279,7 +279,7 @@ export class FairPlayManager {
279
279
  if (client.isAdmin || !this.useFairPlay) return false;
280
280
  if (!server.isSaving) {
281
281
  const drift = Math.abs(
282
- sequenceTime - getCurrentTimeWrapper().getTruncatedU32()
282
+ sequenceTime - getCurrentServerTimeWrapper().getTruncatedU32()
283
283
  );
284
284
  if (drift > 10000) {
285
285
  server.kickPlayer(client);
@@ -13,7 +13,7 @@
13
13
 
14
14
  import {
15
15
  TimeWrapper,
16
- getCurrentTimeWrapper,
16
+ getCurrentServerTimeWrapper,
17
17
  toInt
18
18
  } from "../../../utils/utils";
19
19
 
@@ -44,7 +44,7 @@ export class IngameTimeManager {
44
44
  }
45
45
 
46
46
  updateTime() {
47
- const currentTime = getCurrentTimeWrapper();
47
+ const currentTime = getCurrentServerTimeWrapper();
48
48
  if (!this.lastIngameTimeUpdate) {
49
49
  this.lastIngameTimeUpdate = currentTime;
50
50
  }
@@ -17,7 +17,7 @@ import { Weather2016, WeatherTemplate } from "types/zoneserver";
17
17
  import {
18
18
  randomIntFromInterval,
19
19
  _,
20
- getCurrentTimeWrapper
20
+ getCurrentServerTimeWrapper
21
21
  } from "../../../utils/utils";
22
22
  import { ZoneClient2016 as Client } from "../classes/zoneclient";
23
23
  import { ZoneServer2016 } from "../zoneserver";
@@ -192,7 +192,7 @@ export class WeatherManager {
192
192
  this.dynamicWorker = setTimeout(() => {
193
193
  if (!this.dynamicEnabled) return;
194
194
  this.weather = this.dynamicWeather(
195
- getCurrentTimeWrapper().getFull(),
195
+ getCurrentServerTimeWrapper().getFull(),
196
196
  server._serverStartTime.getFull(),
197
197
  server.inGameTimeManager.timeMultiplier
198
198
  );
@@ -36,7 +36,7 @@ import {
36
36
  } from "types/savedata";
37
37
  import {
38
38
  getAppDataFolderPath,
39
- getCurrentTimeWrapper,
39
+ getCurrentServerTimeWrapper,
40
40
  initMongo,
41
41
  removeUntransferableFields,
42
42
  toBigHex
@@ -1138,7 +1138,7 @@ export class WorldDataManager {
1138
1138
  new Float32Array(entityData.position),
1139
1139
  new Float32Array(entityData.rotation),
1140
1140
  server,
1141
- getCurrentTimeWrapper().getTruncatedU32(),
1141
+ getCurrentServerTimeWrapper().getTruncatedU32(),
1142
1142
  entityData.vehicleId
1143
1143
  );
1144
1144
  vehicle._resources = entityData._resources;
@@ -29,7 +29,7 @@ import {
29
29
  isPosInRadius,
30
30
  randomIntFromInterval,
31
31
  fixEulerOrder,
32
- getCurrentTimeWrapper
32
+ getCurrentServerTimeWrapper
33
33
  } from "../../../utils/utils";
34
34
  import {
35
35
  EquipSlots,
@@ -875,7 +875,7 @@ export class WorldObjectManager {
875
875
  new Float32Array(dataVehicle.position),
876
876
  new Float32Array(dataVehicle.rotation),
877
877
  server,
878
- getCurrentTimeWrapper().getTruncatedU32(),
878
+ getCurrentServerTimeWrapper().getTruncatedU32(),
879
879
  dataVehicle.vehicleId
880
880
  );
881
881
  vehicleData.positionUpdate.orientation = dataVehicle.orientation;
@@ -1043,7 +1043,7 @@ export class WorldObjectManager {
1043
1043
  if (item.item == spawnedItem.itemDefinitionId) allow = false; // dont allow the same item to be added twice
1044
1044
  });
1045
1045
  if (allow) {
1046
- if (chance <= item.weight) {
1046
+ if (chance <= lootTable.spawnChance) {
1047
1047
  const count = Math.floor(
1048
1048
  Math.random() *
1049
1049
  (item.spawnCount.max - item.spawnCount.min + 1) +
@@ -345,7 +345,7 @@ export enum ResourceTypes {
345
345
 
346
346
  export enum ResourceIndicators {
347
347
  BLEEDING_LIGHT = "BLEEDING_LIGHT",
348
- BLEEDING_MODERATE = "BLEEDING_MODERATOR",
348
+ BLEEDING_MODERATE = "BLEEDING_MODERATE",
349
349
  BLEEDING_SEVERE = "BLEEDING_SEVERE",
350
350
  TIRED = "TIRED",
351
351
  VERY_TIRED = "VERY_TIRED",
@@ -361,7 +361,9 @@ export enum ResourceIndicators {
361
361
  DEHYDRATED = "DEHYDRATED",
362
362
  STARVING = "STARVING",
363
363
  COMFORT_PLUS = "COMFORT +",
364
- COMFORT_PLUSPLUS = "COMFORT ++"
364
+ COMFORT_PLUSPLUS = "COMFORT ++",
365
+ FOOD_POISONING = "FOOD POISONING",
366
+ BEES = "BEES!"
365
367
  }
366
368
 
367
369
  export enum Abilities {
@@ -917,7 +919,9 @@ export enum WeaponDefinitionIds {
917
919
  WEAPON_MAGNUM = 1388,
918
920
  WEAPON_R380 = 1400,
919
921
  WEAPON_M9 = 1401,
920
- WEAPON_1911 = 2
922
+ WEAPON_1911 = 2,
923
+ WEAPON_CROWBAR = 9,
924
+ WEAPON_HAMMER = 1396
921
925
  }
922
926
 
923
927
  export enum Skins_Shirt {
@@ -29,7 +29,7 @@ import {
29
29
  getDistance1d,
30
30
  isPosInRadiusWithY,
31
31
  checkConstructionInRange,
32
- getCurrentTimeWrapper
32
+ getCurrentServerTimeWrapper
33
33
  } from "../../utils/utils";
34
34
 
35
35
  import { CraftManager } from "./managers/craftmanager";
@@ -249,7 +249,7 @@ export class ZonePacketHandlers {
249
249
  guid2: "0x0000000000000000",
250
250
  guid3: "0x0000000040000000",
251
251
  guid4: "0x0000000000000000",
252
- gameTime: getCurrentTimeWrapper().getTruncatedU32()
252
+ gameTime: getCurrentServerTimeWrapper().getTruncatedU32()
253
253
  }
254
254
  );
255
255
 
@@ -823,7 +823,7 @@ export class ZonePacketHandlers {
823
823
  client: Client,
824
824
  packet: ReceivedPacket<Synchronization>
825
825
  ) {
826
- const currentTime = getCurrentTimeWrapper();
826
+ const currentTime = getCurrentServerTimeWrapper();
827
827
  const serverTime = currentTime.getFullString();
828
828
  const reflectedPacket: Synchronization = {
829
829
  ...packet.data,
@@ -94,7 +94,7 @@ import {
94
94
  getAngle,
95
95
  getDistance2d,
96
96
  TimeWrapper,
97
- getCurrentTimeWrapper
97
+ getCurrentServerTimeWrapper
98
98
  } from "../../utils/utils";
99
99
 
100
100
  import { Db, MongoClient, WithId } from "mongodb";
@@ -1661,7 +1661,7 @@ export class ZoneServer2016 extends EventEmitter {
1661
1661
  this.smeltingManager.checkSmeltables(this);
1662
1662
  this.smeltingManager.checkCollectors(this);
1663
1663
  this.decayManager.run(this);
1664
- this._serverStartTime = getCurrentTimeWrapper();
1664
+ this._serverStartTime = getCurrentServerTimeWrapper();
1665
1665
  this.weatherManager.startWeatherWorker(this);
1666
1666
  this.inGameTimeManager.start();
1667
1667
  this._gatewayServer.start();
@@ -3835,7 +3835,7 @@ export class ZoneServer2016 extends EventEmitter {
3835
3835
  this.sendData<WeaponWeapon>(client, "Weapon.Weapon", {
3836
3836
  weaponPacket: {
3837
3837
  packetName: packetName,
3838
- gameTime: getCurrentTimeWrapper().getTruncatedU32(),
3838
+ gameTime: getCurrentServerTimeWrapper().getTruncatedU32(),
3839
3839
  packet: obj
3840
3840
  }
3841
3841
  });
@@ -3850,7 +3850,7 @@ export class ZoneServer2016 extends EventEmitter {
3850
3850
  this.sendData<WeaponWeapon>(client, "Weapon.Weapon", {
3851
3851
  weaponPacket: {
3852
3852
  packetName: "Weapon.RemoteWeapon",
3853
- gameTime: getCurrentTimeWrapper().getTruncatedU32(),
3853
+ gameTime: getCurrentServerTimeWrapper().getTruncatedU32(),
3854
3854
  remoteWeaponPacket: {
3855
3855
  packetName: packetName,
3856
3856
  transientId: transientId,
@@ -3874,7 +3874,7 @@ export class ZoneServer2016 extends EventEmitter {
3874
3874
  {
3875
3875
  weaponPacket: {
3876
3876
  packetName: "Weapon.RemoteWeapon",
3877
- gameTime: getCurrentTimeWrapper().getTruncatedU32(),
3877
+ gameTime: getCurrentServerTimeWrapper().getTruncatedU32(),
3878
3878
  remoteWeaponPacket: {
3879
3879
  packetName: packetName,
3880
3880
  transientId: transientId,
@@ -3895,7 +3895,7 @@ export class ZoneServer2016 extends EventEmitter {
3895
3895
  this.sendData<WeaponWeapon>(client, "Weapon.Weapon", {
3896
3896
  weaponPacket: {
3897
3897
  packetName: "Weapon.RemoteWeapon",
3898
- gameTime: getCurrentTimeWrapper().getTruncatedU32(),
3898
+ gameTime: getCurrentServerTimeWrapper().getTruncatedU32(),
3899
3899
  remoteWeaponPacket: {
3900
3900
  packetName: "RemoteWeapon.Update",
3901
3901
  transientId: transientId,
@@ -3924,7 +3924,7 @@ export class ZoneServer2016 extends EventEmitter {
3924
3924
  {
3925
3925
  weaponPacket: {
3926
3926
  packetName: "Weapon.RemoteWeapon",
3927
- gameTime: getCurrentTimeWrapper().getTruncatedU32(),
3927
+ gameTime: getCurrentServerTimeWrapper().getTruncatedU32(),
3928
3928
  remoteWeaponPacket: {
3929
3929
  packetName: "RemoteWeapon.Update",
3930
3930
  transientId: transientId,
@@ -5408,11 +5408,13 @@ export class ZoneServer2016 extends EventEmitter {
5408
5408
  *
5409
5409
  * @param {number} itemDefinitionId - The itemDefinitionId of the item to generate.
5410
5410
  * @param {number} [count=1] - The count of the item.
5411
+ * @param {number} [lastGeneratedTime=0] - The last generated time of the item.
5411
5412
  * @returns {BaseItem|undefined} The generated item, or undefined if the item definition is invalid.
5412
5413
  */
5413
5414
  generateItem(
5414
5415
  itemDefinitionId: number,
5415
- count: number = 1
5416
+ count: number = 1,
5417
+ lastGeneratedTime: number = 0
5416
5418
  ): BaseItem | undefined {
5417
5419
  const itemDefinition = this.getItemDefinition(itemDefinitionId);
5418
5420
  if (!itemDefinition) {
@@ -5422,10 +5424,10 @@ export class ZoneServer2016 extends EventEmitter {
5422
5424
  return;
5423
5425
  }
5424
5426
  const generatedGuid = toBigHex(this.generateItemGuid());
5425
- let durability: number = 2000;
5427
+ let durability: number;
5426
5428
  switch (true) {
5427
5429
  case this.isWeapon(itemDefinitionId):
5428
- durability = Math.floor(Math.random() * 2000);
5430
+ durability = 2000;
5429
5431
  break;
5430
5432
  case this.isArmor(itemDefinitionId):
5431
5433
  durability = 1000;
@@ -5436,6 +5438,9 @@ export class ZoneServer2016 extends EventEmitter {
5436
5438
  case this.isConvey(itemDefinitionId):
5437
5439
  durability = Math.floor(Math.random() * 5400);
5438
5440
  break;
5441
+ default:
5442
+ durability = 2000;
5443
+ break;
5439
5444
  }
5440
5445
 
5441
5446
  const weaponDefinitionId = itemDefinition.PARAM1;
@@ -5446,6 +5451,22 @@ export class ZoneServer2016 extends EventEmitter {
5446
5451
  case WeaponDefinitionIds.WEAPON_BLAZE:
5447
5452
  case WeaponDefinitionIds.WEAPON_PURGE:
5448
5453
  durability = 1000;
5454
+ break;
5455
+ case WeaponDefinitionIds.WEAPON_HAMMER:
5456
+ case WeaponDefinitionIds.WEAPON_CROWBAR:
5457
+ case WeaponDefinitionIds.WEAPON_308:
5458
+ case WeaponDefinitionIds.WEAPON_SHOTGUN:
5459
+ case WeaponDefinitionIds.WEAPON_AK47:
5460
+ case WeaponDefinitionIds.WEAPON_AR15:
5461
+ case WeaponDefinitionIds.WEAPON_1911:
5462
+ case WeaponDefinitionIds.WEAPON_M9:
5463
+ case WeaponDefinitionIds.WEAPON_MAGNUM:
5464
+ case WeaponDefinitionIds.WEAPON_R380:
5465
+ if (Date.now() - lastGeneratedTime <= 200) break;
5466
+ do {
5467
+ durability = Math.floor(Math.random() * 2000);
5468
+ } while (durability < 250);
5469
+ break;
5449
5470
  }
5450
5471
  const itemData: BaseItem = new BaseItem(
5451
5472
  itemDefinitionId,
@@ -6249,7 +6270,7 @@ export class ZoneServer2016 extends EventEmitter {
6249
6270
  moved,
6250
6271
  client.character.state.lookAt,
6251
6272
  this,
6252
- getCurrentTimeWrapper().getTruncatedU32(),
6273
+ getCurrentServerTimeWrapper().getTruncatedU32(),
6253
6274
  VehicleIds.OFFROADER
6254
6275
  );
6255
6276
  const cargo = new Plane(
@@ -6259,7 +6280,7 @@ export class ZoneServer2016 extends EventEmitter {
6259
6280
  new Float32Array([pos[0], pos[1] - 20, pos[2], 1]),
6260
6281
  client.character.state.lookAt,
6261
6282
  this,
6262
- getCurrentTimeWrapper().getTruncatedU32(),
6283
+ getCurrentServerTimeWrapper().getTruncatedU32(),
6263
6284
  VehicleIds.PICKUP
6264
6285
  );
6265
6286
  this._airdrop = {
@@ -7257,7 +7278,7 @@ export class ZoneServer2016 extends EventEmitter {
7257
7278
  }
7258
7279
  }
7259
7280
  const drift = Math.abs(
7260
- packet.gameTime - getCurrentTimeWrapper().getTruncatedU32()
7281
+ packet.gameTime - getCurrentServerTimeWrapper().getTruncatedU32()
7261
7282
  );
7262
7283
  if (drift > this.fairPlayManager.maxPing + 200) {
7263
7284
  this.sendChatText(
@@ -34,6 +34,8 @@ import { ZoneClient2016 } from "servers/ZoneServer2016/classes/zoneclient";
34
34
  import * as crypto from "crypto";
35
35
  import { ZoneClient } from "servers/ZoneServer2015/classes/zoneclient";
36
36
 
37
+ const startTime = Date.now();
38
+
37
39
  /**
38
40
  * Represents a custom implementation of lodash library.
39
41
  */
@@ -1470,14 +1472,22 @@ export class TimeWrapper {
1470
1472
  }
1471
1473
 
1472
1474
  getTruncatedU32() {
1473
- return this.fullTimeMs & MAX_UINT32;
1475
+ const truncated = this.fullTimeMs & MAX_UINT32;
1476
+ return truncated >= 0 ? truncated : truncated >>> 0;
1474
1477
  }
1475
1478
 
1476
1479
  getTruncatedU32String() {
1477
- return Int64String(this.fullTimeMs & MAX_UINT32);
1480
+ const truncated = this.fullTimeMs & MAX_UINT32;
1481
+ return truncated >= 0
1482
+ ? Int64String(truncated)
1483
+ : Int64String(truncated >>> 0);
1478
1484
  }
1479
1485
  }
1480
1486
 
1481
- export function getCurrentTimeWrapper() {
1487
+ export function getCurrentServerTimeWrapper() {
1488
+ return new TimeWrapper(Date.now() - startTime);
1489
+ }
1490
+
1491
+ export function getCurrentRealTimeWrapper() {
1482
1492
  return new TimeWrapper(Date.now());
1483
1493
  }