h1z1-server 0.36.2 → 0.36.3-0

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 (40) hide show
  1. package/config.yaml +27 -0
  2. package/data/2016/dataSources/AllowedFileHashes.json +1 -1
  3. package/package.json +13 -13
  4. package/src/packets/ClientProtocol/ClientProtocol_1080/dto.ts +1 -1
  5. package/src/packets/ClientProtocol/ClientProtocol_1080/shared.ts +1 -2
  6. package/src/servers/LoginServer/loginserver.test.ts +0 -1
  7. package/src/servers/LoginServer/loginserver.ts +5 -7
  8. package/src/servers/LoginZoneConnection/shared/lzconnectionclient.ts +2 -4
  9. package/src/servers/SoeServer/soeserver.ts +1 -1
  10. package/src/servers/ZoneServer2016/data/loadouts.ts +0 -6
  11. package/src/servers/ZoneServer2016/data/lootspawns.ts +150 -13
  12. package/src/servers/ZoneServer2016/entities/basefullcharacter.ts +4 -30
  13. package/src/servers/ZoneServer2016/entities/character.ts +3 -0
  14. package/src/servers/ZoneServer2016/entities/destroyable.ts +2 -3
  15. package/src/servers/ZoneServer2016/entities/lootableprop.ts +10 -10
  16. package/src/servers/ZoneServer2016/handlers/commands/commands.ts +91 -9
  17. package/src/servers/ZoneServer2016/managers/accountinventorymanager.test.ts +202 -0
  18. package/src/servers/ZoneServer2016/managers/accountinventorymanager.ts +158 -0
  19. package/src/servers/ZoneServer2016/managers/chatmanager.ts +13 -16
  20. package/src/servers/ZoneServer2016/managers/craftmanager.ts +39 -4
  21. package/src/servers/ZoneServer2016/managers/decaymanager.test.ts +0 -1
  22. package/src/servers/ZoneServer2016/managers/groupmanager.ts +114 -43
  23. package/src/servers/ZoneServer2016/managers/playtimemanager.test.ts +73 -0
  24. package/src/servers/ZoneServer2016/managers/playtimemanager.ts +42 -0
  25. package/src/servers/ZoneServer2016/managers/rewardmanager.test.ts +35 -0
  26. package/src/servers/ZoneServer2016/managers/rewardmanager.ts +95 -0
  27. package/src/servers/ZoneServer2016/managers/weathermanager.ts +1 -1
  28. package/src/servers/ZoneServer2016/managers/worlddatamanager.test.ts +0 -1
  29. package/src/servers/ZoneServer2016/managers/worlddatamanager.ts +11 -112
  30. package/src/servers/ZoneServer2016/managers/worlddatamanagerthread.ts +0 -9
  31. package/src/servers/ZoneServer2016/managers/worldobjectmanager.ts +0 -1
  32. package/src/servers/ZoneServer2016/models/enums.ts +2 -0
  33. package/src/servers/ZoneServer2016/zonepackethandlers.ts +77 -44
  34. package/src/servers/ZoneServer2016/zoneserver.ts +143 -116
  35. package/src/types/savedata.ts +3 -0
  36. package/src/types/zone2016packets.ts +2 -4
  37. package/src/types/zoneserver.ts +6 -1
  38. package/src/utils/enums.ts +1 -0
  39. package/src/utils/utils.ts +20 -0
  40. package/src/servers/ZoneServer2016/classes/accountinventory.ts +0 -25
package/config.yaml ADDED
@@ -0,0 +1,27 @@
1
+ server:
2
+ welcomeMessage: "Welcome to local wsh! :D"
3
+ adminMessage: "You are an Admin!"
4
+ isPvE: false
5
+
6
+ rcon:
7
+ port: 55554
8
+ password: ""
9
+
10
+ # Fairplay / anticheat config
11
+ fairplay:
12
+ useFairplay: true
13
+ maxPing: 250
14
+
15
+ # Removing an entry below will allow clients with a certain rejectionFlag to join
16
+ # ex. Removing "5 # UNVERIFIED" will allow users with an unverified h1emu status to join
17
+
18
+ # by default, globally banned, hwid banned, vpn detected, and unverified clients will have their
19
+ # connections rejected
20
+ acceptedRejectionTypes:
21
+ # LOCAL_BAN, SERVER_LOCKED, and SERVER_REBOOT are always accepted
22
+ - 2 # GLOBAL_BAN
23
+ - 3 # VPN
24
+ - 4 # HWID
25
+ - 5 # UNVERIFIED
26
+
27
+ useAssetValidation: false
@@ -1024,6 +1024,6 @@
1024
1024
  },
1025
1025
  {
1026
1026
  "file_name": "Assets_256.pack",
1027
- "crc32_hash": "0f9d31cf"
1027
+ "crc32_hash": "c8b93131"
1028
1028
  }
1029
1029
  ]
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "h1z1-server",
3
- "version": "0.36.2",
3
+ "version": "0.36.3-0",
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
  "engines": {
9
- "node": ">=0.17.0 <21"
9
+ "node": ">=0.17.0 <23"
10
10
  },
11
11
  "bin": {
12
12
  "h1z1-server-demo": "scripts/h1z1-server-demo.js",
@@ -14,27 +14,27 @@
14
14
  },
15
15
  "dependencies": {
16
16
  "@types/js-yaml": "4.0.9",
17
- "@types/node": "20.11.19",
18
- "@types/ws": "8.5.10",
19
- "debug": "4.3.4",
17
+ "@types/node": "20.14.12",
18
+ "@types/ws": "8.5.11",
19
+ "debug": "4.3.6",
20
20
  "h1emu-core": "1.2.8",
21
- "h1z1-dataschema": "1.7.1",
21
+ "h1z1-dataschema": "1.7.2",
22
22
  "js-yaml": "4.1.0",
23
- "mongodb": "6.3.0",
23
+ "mongodb": "6.8.0",
24
24
  "threads": "1.7.0",
25
- "typescript": "5.3.3",
26
- "ws": "8.16.0"
25
+ "typescript": "5.5.4",
26
+ "ws": "8.18.0"
27
27
  },
28
28
  "directories": {
29
29
  "src": "./src"
30
30
  },
31
31
  "devDependencies": {
32
- "@typescript-eslint/eslint-plugin": "^7.0.2",
33
- "@typescript-eslint/parser": "^7.0.2",
32
+ "@typescript-eslint/eslint-plugin": "^7.13.1",
33
+ "@typescript-eslint/parser": "^7.13.1",
34
34
  "eslint": "^8.56.0",
35
- "prettier": "^3.2.5",
35
+ "prettier": "^3.3.3",
36
36
  "ts-node": "^10.9.2",
37
- "typedoc": "^0.25.8"
37
+ "typedoc": "^0.26.5"
38
38
  },
39
39
  "scripts": {
40
40
  "gen-packets-types": "npx ts-node ./scripts/genPacketsNames.ts",
@@ -55,7 +55,7 @@ export const dtoPackets: PacketStructures = [
55
55
  { name: "unknownDword1", type: "uint32", defaultValue: 0 },
56
56
  { name: "unknownBool1", type: "boolean", defaultValue: true },
57
57
  { name: "unknownBool2", type: "boolean", defaultValue: true },
58
- { name: "unknownBool3", type: "boolean", defaultValue: true }
58
+ { name: "invisibility", type: "boolean", defaultValue: true }
59
59
  ]
60
60
  },
61
61
  {
@@ -2857,8 +2857,7 @@ export function pack2ByteLengthString(string: string) {
2857
2857
 
2858
2858
  export const accountItemSchema: PacketFields = [
2859
2859
  { name: "itemId", type: "uint64string", defaultValue: "0" },
2860
- { name: "itemDefinitionId", type: "uint32", defaultValue: 0 },
2861
- { name: "unknownDword2", type: "uint32", defaultValue: 0 }, // 44 for itemDefId 1871, 37 for itemDefId 37, ... (No idea where it comes from)
2860
+ { name: "itemDefinitionId", type: "uint64", defaultValue: 0 },
2862
2861
  { name: "itemCount", type: "uint32", defaultValue: 0 },
2863
2862
  { name: "itemGuid", type: "uint64string", defaultValue: "0" },
2864
2863
  { name: "unknownDword4", type: "uint32", defaultValue: 0 }
@@ -19,7 +19,6 @@ test("LoginServer-mongo", { timeout: 5000, skip: !isMongoTests }, async (t) => {
19
19
  await t.test("start", async () => {
20
20
  await loginServer.start();
21
21
  });
22
- // TODO: start should stop awaiting only when everything is really done
23
22
  await scheduler.yield();
24
23
  await t.test("stop", async () => {
25
24
  await loginServer.stop();
@@ -40,7 +40,7 @@ import { Worker } from "node:worker_threads";
40
40
  import { FileHash, httpServerMessage } from "types/shared";
41
41
  import { LoginProtocol2016 } from "../../protocols/loginprotocol2016";
42
42
  import { crc_length_options } from "../../types/soeserver";
43
- import { DB_NAME, DEFAULT_CRYPTO_KEY } from "../../utils/constants";
43
+ import { DB_NAME, DEFAULT_CRYPTO_KEY, MAX_UINT32 } from "../../utils/constants";
44
44
  import {
45
45
  LoginReply,
46
46
  CharacterSelectInfoReply,
@@ -1112,12 +1112,10 @@ export class LoginServer extends EventEmitter {
1112
1112
  ];
1113
1113
  const [address, port] = zoneConnectionString.split(":");
1114
1114
 
1115
- return {
1116
- address: address,
1117
- port: port,
1118
- clientId: zoneConnectionString,
1119
- serverId: 1 // TODO: that's a hack
1120
- } as any;
1115
+ const LZClient = new LZConnectionClient({ address, port: Number(port) });
1116
+ // Hack since the loginserver doesn't have a serverId
1117
+ LZClient.serverId = MAX_UINT32;
1118
+ return LZClient;
1121
1119
  }
1122
1120
 
1123
1121
  async askZone(
@@ -11,8 +11,6 @@
11
11
  // Based on https://github.com/psemu/soe-network
12
12
  // ======================================================================
13
13
 
14
- import { RemoteInfo } from "node:dgram";
15
-
16
14
  export class LZConnectionClient {
17
15
  sessionId: number = 0;
18
16
  address: string;
@@ -21,8 +19,8 @@ export class LZConnectionClient {
21
19
  clientId: string;
22
20
  lastPing: number = 0;
23
21
 
24
- constructor(remote: RemoteInfo) {
25
- this.address = remote.address;
22
+ constructor(remote: { address?: string; port: number }) {
23
+ this.address = remote.address ?? "";
26
24
  this.port = remote.port;
27
25
  this.clientId = `${remote.address}:${remote.port}`;
28
26
  }
@@ -412,7 +412,7 @@ export class SOEServer extends EventEmitter {
412
412
  );
413
413
 
414
414
  // client.outputStream.on(SOEOutputChannels.Raw, (data: Buffer) => {
415
- // TODO:
415
+ // unused in h1z1
416
416
  // });
417
417
  } else {
418
418
  client = this._clients.get(clientId) as SOEClient;
@@ -195,9 +195,3 @@ export const lootableContainerDefaultLoadouts = {
195
195
  repair_box: [{ item: Items.CONTAINER_REPAIR_BOX }],
196
196
  stash: [{ item: Items.CONTAINER_STASH }]
197
197
  };
198
-
199
- export const accountInventoryDefaultRewards = [
200
- { item: Items.REWARD_CRATE_WEARABLES, count: 3 },
201
- { item: Items.REWARD_CRATE_ALPHA_LAUNCH, count: 3 },
202
- { item: Items.MYSTERY_BAG_1, count: 2 }
203
- ];
@@ -220,7 +220,7 @@ export const lootTables: { [lootSpawner: string]: LootSpawner } = {
220
220
  ]
221
221
  },
222
222
  "ItemSpawner_Weapon_Bat01.adr": {
223
- spawnChance: 20,
223
+ spawnChance: 10,
224
224
  items: [
225
225
  {
226
226
  item: Items.WEAPON_BAT_WOOD,
@@ -311,7 +311,7 @@ export const lootTables: { [lootSpawner: string]: LootSpawner } = {
311
311
  ]
312
312
  },
313
313
  "ItemSpawner_Weapon_Bat02.adr": {
314
- spawnChance: 20,
314
+ spawnChance: 10,
315
315
  items: [
316
316
  {
317
317
  item: Items.WEAPON_BAT_ALUM,
@@ -482,6 +482,19 @@ export const lootTables: { [lootSpawner: string]: LootSpawner } = {
482
482
  }
483
483
  ]
484
484
  },
485
+ "ItemSpawner_Clothes_Helmet_Tactical_ChipsScratches.adr": {
486
+ spawnChance: 10,
487
+ items: [
488
+ {
489
+ item: Items.DEFAULT_TACTICAL_HELMET,
490
+ weight: 100,
491
+ spawnCount: {
492
+ min: 1,
493
+ max: 1
494
+ }
495
+ }
496
+ ]
497
+ },
485
498
  "ItemSpawner_Clothes_BaseballCap.adr": {
486
499
  spawnChance: 20,
487
500
  items: [
@@ -672,7 +685,7 @@ export const lootTables: { [lootSpawner: string]: LootSpawner } = {
672
685
  }
673
686
  },
674
687
  {
675
- item: Items.WATER_PURE,
688
+ item: Items.WATER_DIRTY,
676
689
  weight: 15,
677
690
  spawnCount: {
678
691
  min: 1,
@@ -769,7 +782,7 @@ export const lootTables: { [lootSpawner: string]: LootSpawner } = {
769
782
  },
770
783
  {
771
784
  item: Items.WEAPON_BAT_WOOD,
772
- weight: 15,
785
+ weight: 10,
773
786
  spawnCount: {
774
787
  min: 1,
775
788
  max: 1
@@ -777,7 +790,7 @@ export const lootTables: { [lootSpawner: string]: LootSpawner } = {
777
790
  },
778
791
  {
779
792
  item: Items.WEAPON_BAT_ALUM,
780
- weight: 15,
793
+ weight: 10,
781
794
  spawnCount: {
782
795
  min: 1,
783
796
  max: 1
@@ -1057,7 +1070,7 @@ export const lootTables: { [lootSpawner: string]: LootSpawner } = {
1057
1070
  }
1058
1071
  },
1059
1072
  {
1060
- item: Items.WATER_PURE,
1073
+ item: Items.WATER_DIRTY,
1061
1074
  weight: 10,
1062
1075
  spawnCount: {
1063
1076
  min: 1,
@@ -1199,6 +1212,30 @@ export const lootTables: { [lootSpawner: string]: LootSpawner } = {
1199
1212
  min: 1,
1200
1213
  max: 1
1201
1214
  }
1215
+ },
1216
+ {
1217
+ item: Items.GROUND_COFFEE,
1218
+ weight: 15,
1219
+ spawnCount: {
1220
+ min: 1,
1221
+ max: 1
1222
+ }
1223
+ },
1224
+ {
1225
+ item: Items.SUGAR,
1226
+ weight: 10,
1227
+ spawnCount: {
1228
+ min: 1,
1229
+ max: 1
1230
+ }
1231
+ },
1232
+ {
1233
+ item: Items.CANNED_FOOD26,
1234
+ weight: 7,
1235
+ spawnCount: {
1236
+ min: 1,
1237
+ max: 1
1238
+ }
1202
1239
  }
1203
1240
  ]
1204
1241
  },
@@ -1305,7 +1342,7 @@ export const lootTables: { [lootSpawner: string]: LootSpawner } = {
1305
1342
  }
1306
1343
  },
1307
1344
  {
1308
- item: Items.SHIRT_DEFAULT,
1345
+ item: Items.SHIRT_SCRUBS_GRAY,
1309
1346
  weight: 100,
1310
1347
  spawnCount: {
1311
1348
  min: 1,
@@ -1313,7 +1350,15 @@ export const lootTables: { [lootSpawner: string]: LootSpawner } = {
1313
1350
  }
1314
1351
  },
1315
1352
  {
1316
- item: Items.PANTS_DEFAULT,
1353
+ item: Items.PANTS_SCRUBS_GRAY,
1354
+ weight: 100,
1355
+ spawnCount: {
1356
+ min: 1,
1357
+ max: 1
1358
+ }
1359
+ },
1360
+ {
1361
+ item: Items.CAP_SCRUBS_GRAY,
1317
1362
  weight: 100,
1318
1363
  spawnCount: {
1319
1364
  min: 1,
@@ -2072,16 +2117,24 @@ export const containerLootSpawners: {
2072
2117
  min: 2,
2073
2118
  max: 10
2074
2119
  }
2120
+ },
2121
+ {
2122
+ item: Items.AMMO_12GA,
2123
+ weight: 20,
2124
+ spawnCount: {
2125
+ min: 1,
2126
+ max: 6
2127
+ }
2075
2128
  }
2076
2129
  ]
2077
2130
  },
2078
2131
  Locker: {
2079
- spawnChance: 100,
2132
+ spawnChance: 60,
2080
2133
  maxItems: 1,
2081
2134
  items: [
2082
2135
  {
2083
2136
  item: Items.BACKPACK_MILITARY_TAN,
2084
- weight: 35,
2137
+ weight: 25,
2085
2138
  spawnCount: {
2086
2139
  min: 1,
2087
2140
  max: 1
@@ -2097,7 +2150,15 @@ export const containerLootSpawners: {
2097
2150
  },
2098
2151
  {
2099
2152
  item: Items.KEVLAR_DEFAULT,
2100
- weight: 35,
2153
+ weight: 25,
2154
+ spawnCount: {
2155
+ min: 1,
2156
+ max: 1
2157
+ }
2158
+ },
2159
+ {
2160
+ item: Items.DEFAULT_TACTICAL_HELMET,
2161
+ weight: 25,
2101
2162
  spawnCount: {
2102
2163
  min: 1,
2103
2164
  max: 1
@@ -3427,6 +3488,82 @@ export const containerLootSpawners: {
3427
3488
  }
3428
3489
  ]
3429
3490
  },
3491
+ Washer: {
3492
+ spawnChance: 10,
3493
+ maxItems: 2,
3494
+ items: [
3495
+ {
3496
+ item: Items.SHIRT_DEFAULT,
3497
+ weight: 30,
3498
+ spawnCount: {
3499
+ min: 1,
3500
+ max: 1
3501
+ }
3502
+ },
3503
+ {
3504
+ item: Items.PANTS_DEFAULT,
3505
+ weight: 20,
3506
+ spawnCount: {
3507
+ min: 1,
3508
+ max: 1
3509
+ }
3510
+ },
3511
+ {
3512
+ item: Items.BASIC_HOODIE,
3513
+ weight: 10,
3514
+ spawnCount: {
3515
+ min: 1,
3516
+ max: 1
3517
+ }
3518
+ },
3519
+ {
3520
+ item: Items.CLOTH,
3521
+ weight: 5,
3522
+ spawnCount: {
3523
+ min: 1,
3524
+ max: 1
3525
+ }
3526
+ }
3527
+ ]
3528
+ },
3529
+ Dryer: {
3530
+ spawnChance: 10,
3531
+ maxItems: 2,
3532
+ items: [
3533
+ {
3534
+ item: Items.SHIRT_DEFAULT,
3535
+ weight: 30,
3536
+ spawnCount: {
3537
+ min: 1,
3538
+ max: 1
3539
+ }
3540
+ },
3541
+ {
3542
+ item: Items.PANTS_DEFAULT,
3543
+ weight: 20,
3544
+ spawnCount: {
3545
+ min: 1,
3546
+ max: 1
3547
+ }
3548
+ },
3549
+ {
3550
+ item: Items.BASIC_HOODIE,
3551
+ weight: 10,
3552
+ spawnCount: {
3553
+ min: 1,
3554
+ max: 1
3555
+ }
3556
+ },
3557
+ {
3558
+ item: Items.CLOTH,
3559
+ weight: 5,
3560
+ spawnCount: {
3561
+ min: 1,
3562
+ max: 1
3563
+ }
3564
+ }
3565
+ ]
3566
+ },
3430
3567
  // used for crate props
3431
3568
  Crate_buffed: {
3432
3569
  spawnChance: 60,
@@ -3457,7 +3594,7 @@ export const containerLootSpawners: {
3457
3594
  }
3458
3595
  },
3459
3596
  {
3460
- item: Items.WATER_PURE,
3597
+ item: Items.WATER_DIRTY,
3461
3598
  weight: 10,
3462
3599
  spawnCount: {
3463
3600
  min: 1,
@@ -3479,7 +3616,7 @@ export const containerLootSpawners: {
3479
3616
  }
3480
3617
  },
3481
3618
  {
3482
- item: Items.WATER_PURE,
3619
+ item: Items.WATER_DIRTY,
3483
3620
  weight: 10,
3484
3621
  spawnCount: {
3485
3622
  min: 1,
@@ -428,7 +428,7 @@ export abstract class BaseFullCharacter extends BaseLightweightCharacter {
428
428
  }
429
429
  const itemDefId = item.itemDefinitionId;
430
430
  if (server.isAccountItem(itemDefId) && client) {
431
- this.lootAccountItem(server, client, item, sendUpdate);
431
+ server.lootAccountItem(server, client, item, sendUpdate);
432
432
  } else if (this.getAvailableLoadoutSlot(server, itemDefId)) {
433
433
  if (client && client.character.initialized && sendUpdate) {
434
434
  server.sendData(client, "Reward.AddNonRewardItem", {
@@ -444,33 +444,6 @@ export abstract class BaseFullCharacter extends BaseLightweightCharacter {
444
444
  }
445
445
  }
446
446
 
447
- lootAccountItem(
448
- server: ZoneServer2016,
449
- client: ZoneClient2016,
450
- item: BaseItem,
451
- sendUpdate: boolean = false
452
- ) {
453
- const items = server._accountInventories[client.loginSessionId]?.items;
454
- if (!items) return;
455
- items[item.itemGuid] = item;
456
- server.sendData(client, "Items.AddEscrowAccountItem", {
457
- itemData: {
458
- itemId: item.itemGuid,
459
- itemDefinitionId: item.itemDefinitionId,
460
- itemCount: item.stackCount,
461
- itemGuid: item.itemGuid
462
- }
463
- });
464
-
465
- if (!sendUpdate) return;
466
- server.sendData(client, "Reward.AddNonRewardItem", {
467
- itemDefId: item.itemDefinitionId,
468
- iconId: server.getItemDefinition(item.itemDefinitionId)?.IMAGE_SET_ID,
469
- nameId: server.getItemDefinition(item.itemDefinitionId)?.NAME_ID,
470
- count: item.stackCount
471
- });
472
- }
473
-
474
447
  lootItemFromContainer(
475
448
  server: ZoneServer2016,
476
449
  sourceContainer: LoadoutContainer,
@@ -556,7 +529,9 @@ export abstract class BaseFullCharacter extends BaseLightweightCharacter {
556
529
  if (
557
530
  ammo &&
558
531
  loadoutItem.weapon.ammoCount > 0 &&
559
- loadoutItem.weapon.itemDefinitionId != Items.WEAPON_REMOVER
532
+ loadoutItem.weapon.itemDefinitionId != Items.WEAPON_REMOVER &&
533
+ server.getItemDefinition(loadoutItem.itemDefinitionId)?.ITEM_CLASS !=
534
+ ItemClasses.THROWABLES
560
535
  ) {
561
536
  this.lootContainerItem(server, ammo, ammo.stackCount, true);
562
537
  }
@@ -951,7 +926,6 @@ export abstract class BaseFullCharacter extends BaseLightweightCharacter {
951
926
  let slot = loadoutSlotItemClass?.SLOT;
952
927
  if (!slot) return 0;
953
928
  switch (itemDef?.ITEM_CLASS) {
954
- // TODO: Prevent equipping throwables until fixed
955
929
  case ItemClasses.THROWABLES:
956
930
  case ItemClasses.WEAPONS_LONG:
957
931
  case ItemClasses.WEAPONS_PISTOL:
@@ -101,6 +101,9 @@ export class Character2016 extends BaseFullCharacter {
101
101
  /** Used to update the status of the players resources */
102
102
  resourcesUpdater?: any;
103
103
  factionId = 2;
104
+ isInInventory: boolean = false;
105
+ playTime: number = 0;
106
+ lastDropPlaytime: number = 0;
104
107
  set godMode(state: boolean) {
105
108
  this.characterStates.invincibility = state;
106
109
  }
@@ -17,7 +17,6 @@ import { eul2quat } from "../../../utils/utils";
17
17
  import { Effects, ModelIds } from "../models/enums";
18
18
  import { AddLightweightNpc, AddSimpleNpc } from "types/zone2016packets";
19
19
  import { BaseSimpleNpc } from "./basesimplenpc";
20
- import { MAX_UINT32 } from "../../../utils/constants";
21
20
 
22
21
  function getDestroyedModels(actorModelId: ModelIds): number[] {
23
22
  switch (actorModelId) {
@@ -48,8 +47,8 @@ function getMaxHealth(actorModelId: ModelIds): number {
48
47
  case ModelIds.FENCES_WOOD_PLANKS_GREY_1X1:
49
48
  case ModelIds.FENCES_WOOD_PLANKS_GREY_POSTS_1X2:
50
49
  case ModelIds.FENCES_WOOD_PLANKS_GREY_GAP_1X1:
51
- // temp hack so it can't be destroyed ( or you really wanted to )
52
- return MAX_UINT32;
50
+ // temp hack so it can't be destroyed ( or you really wanted to )
51
+ // return MAX_UINT32;
53
52
  default:
54
53
  return 5000;
55
54
  }
@@ -118,6 +118,16 @@ function getContainerAndTime(entity: LootableProp) {
118
118
  entity.searchTime = 500;
119
119
  entity.lootSpawner = "Fridge";
120
120
  break;
121
+ case ModelIds.WASHER:
122
+ entity.containerId = Items.CONTAINER_WASHING_MACHINE;
123
+ entity.searchTime = 500;
124
+ entity.lootSpawner = "Washer";
125
+ break;
126
+ case ModelIds.DRYER:
127
+ entity.containerId = Items.CONTAINER_DRYER;
128
+ entity.searchTime = 500;
129
+ entity.lootSpawner = "Dryer";
130
+ break;
121
131
  case ModelIds.OTTOMAN_01:
122
132
  case ModelIds.OTTOMAN_02:
123
133
  entity.containerId = Items.CONTAINER_OTTOMAN;
@@ -181,16 +191,6 @@ function getContainerAndTime(entity: LootableProp) {
181
191
  entity.searchTime = 500;
182
192
  entity.lootSpawner = "Dresser";
183
193
  break;
184
- case ModelIds.WASHER:
185
- entity.containerId = Items.CONTAINER_WASHING_MACHINE;
186
- entity.searchTime = 500;
187
- entity.lootSpawner = "Washer_Dryer";
188
- break;
189
- case ModelIds.DRYER:
190
- entity.containerId = Items.CONTAINER_DRYER;
191
- entity.searchTime = 500;
192
- entity.lootSpawner = "Washer_Dryer";
193
- break;
194
194
  case ModelIds.FURNACE:
195
195
  entity.containerId = Items.CONTAINER_FURNACE;
196
196
  entity.searchTime = 0;