h1z1-server 0.23.1 → 0.23.2

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 (28) hide show
  1. package/package.json +1 -1
  2. package/src/packets/ClientProtocol/ClientProtocol_1080/command.ts +9 -1
  3. package/src/servers/ZoneServer2016/classes/baseItem.ts +16 -1
  4. package/src/servers/ZoneServer2016/classes/collectingentity.ts +6 -1
  5. package/src/servers/ZoneServer2016/classes/gridcell.ts +1 -3
  6. package/src/servers/ZoneServer2016/classes/loadoutcontainer.ts +1 -1
  7. package/src/servers/ZoneServer2016/classes/smeltingentity.ts +9 -4
  8. package/src/servers/ZoneServer2016/commands/commands.ts +32 -0
  9. package/src/servers/ZoneServer2016/data/Recipes.ts +10 -0
  10. package/src/servers/ZoneServer2016/data/lootspawns.ts +49 -25
  11. package/src/servers/ZoneServer2016/entities/baseentity.ts +7 -2
  12. package/src/servers/ZoneServer2016/entities/basefullcharacter.ts +17 -6
  13. package/src/servers/ZoneServer2016/entities/baselootableentity.ts +7 -2
  14. package/src/servers/ZoneServer2016/entities/constructionchildentity.ts +13 -2
  15. package/src/servers/ZoneServer2016/entities/constructiondoor.ts +109 -66
  16. package/src/servers/ZoneServer2016/entities/constructionparententity.ts +8 -2
  17. package/src/servers/ZoneServer2016/entities/doorentity.ts +7 -2
  18. package/src/servers/ZoneServer2016/entities/itemobject.ts +7 -2
  19. package/src/servers/ZoneServer2016/entities/lootableconstructionentity.ts +7 -2
  20. package/src/servers/ZoneServer2016/entities/lootableprop.ts +7 -1
  21. package/src/servers/ZoneServer2016/entities/plant.ts +7 -2
  22. package/src/servers/ZoneServer2016/entities/vehicle.ts +7 -2
  23. package/src/servers/ZoneServer2016/managers/craftmanager.ts +4 -1
  24. package/src/servers/ZoneServer2016/managers/worlddatamanager.ts +15 -6
  25. package/src/servers/ZoneServer2016/managers/worldobjectmanager.ts +9 -8
  26. package/src/servers/ZoneServer2016/zonepackethandlers.ts +41 -47
  27. package/src/servers/ZoneServer2016/zoneserver.ts +130 -122
  28. package/src/types/zone2016packets.ts +3 -1
@@ -519,6 +519,7 @@ export class ConstructionParentEntity extends ConstructionChildEntity {
519
519
  characterId: string,
520
520
  permission: ConstructionPermissionIds
521
521
  ) {
522
+ if (characterId == this.ownerCharacterId) return true;
522
523
  switch (permission) {
523
524
  case ConstructionPermissionIds.BUILD:
524
525
  return this.permissions[characterId]?.build;
@@ -530,8 +531,13 @@ export class ConstructionParentEntity extends ConstructionChildEntity {
530
531
  return this.permissions[characterId]?.visit;
531
532
  }
532
533
  }
533
-
534
- OnPlayerSelect(server: ZoneServer2016, client: ZoneClient2016) {
534
+ /* eslint-disable @typescript-eslint/no-unused-vars */
535
+ OnPlayerSelect(
536
+ server: ZoneServer2016,
537
+ client: ZoneClient2016,
538
+ isInstant?: boolean
539
+ /* eslint-enable @typescript-eslint/no-unused-vars */
540
+ ) {
535
541
  if (this.canUndoPlacement(server, client)) {
536
542
  this.destroy(server);
537
543
  client.character.lootItem(
@@ -140,8 +140,13 @@ export class DoorEntity extends BaseLightweightCharacter {
140
140
  this.openSound = openSound;
141
141
  this.closeSound = closeSound;
142
142
  }
143
-
144
- OnPlayerSelect(server: ZoneServer2016, client: ZoneClient2016) {
143
+ /* eslint-disable @typescript-eslint/no-unused-vars */
144
+ OnPlayerSelect(
145
+ server: ZoneServer2016,
146
+ client: ZoneClient2016,
147
+ isInstant?: boolean
148
+ /* eslint-enable @typescript-eslint/no-unused-vars */
149
+ ) {
145
150
  client; // eslint
146
151
  if (this.moving) {
147
152
  return;
@@ -62,8 +62,13 @@ export class ItemObject extends BaseLightweightCharacter {
62
62
  super(characterId, transientId, actorModelId, position, rotation, server);
63
63
  (this.spawnerId = spawnerId), (this.item = item);
64
64
  }
65
-
66
- OnPlayerSelect(server: ZoneServer2016, client: ZoneClient2016) {
65
+ /* eslint-disable @typescript-eslint/no-unused-vars */
66
+ OnPlayerSelect(
67
+ server: ZoneServer2016,
68
+ client: ZoneClient2016,
69
+ isInstant?: boolean
70
+ /* eslint-enable @typescript-eslint/no-unused-vars */
71
+ ) {
67
72
  server.pickupItem(client, this.characterId);
68
73
  }
69
74
 
@@ -142,8 +142,13 @@ export class LootableConstructionEntity extends BaseLootableEntity {
142
142
  ) || false
143
143
  );
144
144
  }
145
-
146
- OnPlayerSelect(server: ZoneServer2016, client: ZoneClient2016) {
145
+ /* eslint-disable @typescript-eslint/no-unused-vars */
146
+ OnPlayerSelect(
147
+ server: ZoneServer2016,
148
+ client: ZoneClient2016,
149
+ isInstant?: boolean
150
+ /* eslint-enable @typescript-eslint/no-unused-vars */
151
+ ) {
147
152
  if (this.canUndoPlacement(server, client)) {
148
153
  this.destroy(server);
149
154
  client.character.lootItem(
@@ -169,7 +169,13 @@ export class LootableProp extends BaseLootableEntity {
169
169
  this.loadoutId = 5;
170
170
  getContainerAndTime(this);
171
171
  }
172
- OnPlayerSelect(server: ZoneServer2016, client: ZoneClient2016) {
172
+ /* eslint-disable @typescript-eslint/no-unused-vars */
173
+ OnPlayerSelect(
174
+ server: ZoneServer2016,
175
+ client: ZoneClient2016,
176
+ isInstant?: boolean
177
+ /* eslint-enable @typescript-eslint/no-unused-vars */
178
+ ) {
173
179
  if (!client.searchedProps.includes(this)) {
174
180
  server.utilizeHudTimer(
175
181
  client,
@@ -116,8 +116,13 @@ export class Plant extends ItemObject {
116
116
  const timeToAdd = this.isFertilized ? this.growTime / 2 : this.growTime; // 4 or 8h based on fertilized or not
117
117
  this.nextStateTime = new Date().getTime() + timeToAdd;
118
118
  }
119
-
120
- OnPlayerSelect(server: ZoneServer2016, client: ZoneClient2016) {
119
+ /* eslint-disable @typescript-eslint/no-unused-vars */
120
+ OnPlayerSelect(
121
+ server: ZoneServer2016,
122
+ client: ZoneClient2016,
123
+ isInstant?: boolean
124
+ /* eslint-enable @typescript-eslint/no-unused-vars */
125
+ ) {
121
126
  if (this.growState != 3) return;
122
127
  if (!server._temporaryObjects[this.parentObjectCharacterId]) {
123
128
  server.deleteEntity(this.characterId, server._plants);
@@ -478,8 +478,13 @@ export class Vehicle2016 extends BaseLootableEntity {
478
478
  );
479
479
  }
480
480
  }
481
-
482
- OnPlayerSelect(server: ZoneServer2016, client: ZoneClient2016) {
481
+ /* eslint-disable @typescript-eslint/no-unused-vars */
482
+ OnPlayerSelect(
483
+ server: ZoneServer2016,
484
+ client: ZoneClient2016,
485
+ isInstant?: boolean
486
+ /* eslint-enable @typescript-eslint/no-unused-vars */
487
+ ) {
483
488
  !client.vehicle.mountedVehicle
484
489
  ? server.mountVehicle(client, this.characterId)
485
490
  : server.dismountVehicle(client);
@@ -34,7 +34,10 @@ function getCraftComponentsDataSource(client: Client): {
34
34
  if (inventory[item.itemDefinitionId]) {
35
35
  inventory[item.itemDefinitionId].stackCount += item.stackCount;
36
36
  } else {
37
- inventory[item.itemDefinitionId] = { ...item }; // push new itemstack
37
+ inventory[item.itemDefinitionId] = {
38
+ ...item,
39
+ stackCount: item.stackCount,
40
+ }; // push new itemstack
38
41
  }
39
42
  });
40
43
  });
@@ -972,9 +972,12 @@ export class WorldDataManager {
972
972
  JSON.stringify(construction, null, 2)
973
973
  );
974
974
  } else {
975
+ const tempCollection = server._db?.collection("construction-temp");
976
+ if (construction.length) await tempCollection?.insertMany(construction);
975
977
  const collection = server._db?.collection("construction");
976
- collection?.deleteMany({ serverId: server._worldId });
977
- if (construction.length) collection?.insertMany(construction);
978
+ await collection?.deleteMany({ serverId: server._worldId });
979
+ if (construction.length) await collection?.insertMany(construction);
980
+ await tempCollection?.deleteMany({ serverId: server._worldId });
978
981
  }
979
982
  }
980
983
 
@@ -1022,8 +1025,11 @@ export class WorldDataManager {
1022
1025
  );
1023
1026
  } else {
1024
1027
  const collection = server._db?.collection("crops");
1025
- collection?.deleteMany({ serverId: server._worldId });
1026
- if (crops.length) collection?.insertMany(crops);
1028
+ const tempCollection = server._db?.collection("crops-temp");
1029
+ if (crops.length) await tempCollection?.insertMany(crops);
1030
+ await collection?.deleteMany({ serverId: server._worldId });
1031
+ if (crops.length) await collection?.insertMany(crops);
1032
+ await tempCollection?.deleteMany({ serverId: server._worldId });
1027
1033
  }
1028
1034
  }
1029
1035
 
@@ -1120,8 +1126,11 @@ export class WorldDataManager {
1120
1126
  );
1121
1127
  } else {
1122
1128
  const collection = server._db?.collection("worldconstruction");
1123
- collection?.deleteMany({ serverId: server._worldId });
1124
- if (freeplace.length) collection?.insertMany(freeplace);
1129
+ const tempCollection = server._db?.collection("worldconstruction-temp");
1130
+ if (freeplace.length) await tempCollection?.insertMany(freeplace);
1131
+ await collection?.deleteMany({ serverId: server._worldId });
1132
+ if (freeplace.length) await collection?.insertMany(freeplace);
1133
+ await tempCollection?.deleteMany({ serverId: server._worldId });
1125
1134
  }
1126
1135
  }
1127
1136
 
@@ -134,6 +134,7 @@ export class WorldObjectManager {
134
134
  this.createLoot(server);
135
135
  this.createContainerLoot(server);
136
136
  this.lastLootRespawnTime = Date.now();
137
+ server.divideLargeCells(700);
137
138
  }
138
139
  if (this.lastNpcRespawnTime + this.npcRespawnTimer <= Date.now()) {
139
140
  this.createNpcs(server);
@@ -456,7 +457,9 @@ export class WorldObjectManager {
456
457
  createContainerLoot(server: ZoneServer2016) {
457
458
  for (const a in server._lootableProps) {
458
459
  const prop = server._lootableProps[a] as LootableProp;
459
- if (!!Object.keys(prop._containers["31"].items).length) continue; // skip if container is not empty
460
+ const container = prop.getContainer();
461
+ if (!container) continue;
462
+ if (!!Object.keys(container.items).length) continue; // skip if container is not empty
460
463
  const lootTable = containerLootSpawners[prop.lootSpawner];
461
464
  if (lootTable) {
462
465
  for (let x = 0; x < lootTable.maxItems; x++) {
@@ -464,11 +467,9 @@ export class WorldObjectManager {
464
467
  if (!item) continue;
465
468
  const chance = Math.floor(Math.random() * 100) + 1; // temporary spawnchance
466
469
  let allow = true;
467
- Object.values(prop._containers["31"].items).forEach(
468
- (spawnedItem: BaseItem) => {
469
- if (item.item == spawnedItem.itemDefinitionId) allow = false; // dont allow the same item to be added twice
470
- }
471
- );
470
+ Object.values(container.items).forEach((spawnedItem: BaseItem) => {
471
+ if (item.item == spawnedItem.itemDefinitionId) allow = false; // dont allow the same item to be added twice
472
+ });
472
473
  if (allow) {
473
474
  if (chance <= item.weight) {
474
475
  const count = Math.floor(
@@ -480,7 +481,7 @@ export class WorldObjectManager {
480
481
  server.addContainerItemExternal(
481
482
  prop.mountedCharacter ? prop.mountedCharacter : "",
482
483
  server.generateItem(item.item),
483
- prop._containers["31"],
484
+ container,
484
485
  count
485
486
  );
486
487
  }
@@ -489,7 +490,7 @@ export class WorldObjectManager {
489
490
  }
490
491
  }
491
492
  }
492
- if (Object.keys(prop._containers["31"].items).length != 0) {
493
+ if (Object.keys(container.items).length != 0) {
493
494
  // mark prop as unsearched for clients
494
495
  Object.values(server._clients).forEach((client: ZoneClient2016) => {
495
496
  const index = client.searchedProps.indexOf(prop);
@@ -457,30 +457,23 @@ export class zonePacketHandlers {
457
457
  this.commandHandler.executeCommand(server, client, packet);
458
458
  }
459
459
  CommandInteractRequest(server: ZoneServer2016, client: Client, packet: any) {
460
- server.sendData(client, "Command.InteractionString", {
461
- guid: packet.data.guid,
462
- stringId: 5463,
463
- unknown4: 0,
464
- });
465
- server.sendData(client, "Command.InteractionList", {
466
- guid: packet.data.guid,
467
- unknownBoolean1: true,
468
- unknownArray1: [
469
- {
470
- unknownDword1: 11,
471
- unknownDword2: 0,
472
- unknownDword3: 5463,
473
- unknownDword4: 51,
474
- unknownDword5: 1,
475
- unknownDword6: 0,
476
- unknownDword7: 0,
477
- },
478
- ],
479
- unknownString1: "",
480
- unknownBoolean2: true,
481
- unknownArray2: [],
482
- unknownBoolean3: false,
483
- });
460
+ const entity = server.getEntity(packet.data.characterId);
461
+ if (!entity) return;
462
+ const isConstruction =
463
+ entity instanceof ConstructionParentEntity ||
464
+ entity instanceof ConstructionDoor;
465
+ if (
466
+ !isPosInRadius(
467
+ isConstruction ? 4 : server._interactionDistance,
468
+ client.character.state.position,
469
+ isConstruction
470
+ ? entity.fixedPosition || entity.state.position
471
+ : entity.state.position
472
+ )
473
+ )
474
+ return;
475
+
476
+ entity.OnPlayerSelect(server, client, packet.data.isInstant);
484
477
  }
485
478
  CommandInteractCancel(server: ZoneServer2016, client: Client, packet: any) {
486
479
  debug("Interaction Canceled");
@@ -824,23 +817,7 @@ export class zonePacketHandlers {
824
817
  entity.OnFullCharacterDataRequest(server, client);
825
818
  }
826
819
  CommandPlayerSelect(server: ZoneServer2016, client: Client, packet: any) {
827
- const entity = server.getEntity(packet.data.guid);
828
- if (!entity) return;
829
- const isConstruction =
830
- entity instanceof ConstructionParentEntity ||
831
- entity instanceof ConstructionDoor;
832
- if (
833
- !isPosInRadius(
834
- isConstruction ? 4 : server._interactionDistance,
835
- client.character.state.position,
836
- isConstruction
837
- ? entity.fixedPosition || entity.state.position
838
- : entity.state.position
839
- )
840
- )
841
- return;
842
-
843
- entity.OnPlayerSelect(server, client);
820
+ debug("Command.PlayerSelect");
844
821
  }
845
822
  LockssetLock(server: ZoneServer2016, client: Client, packet: any) {
846
823
  if (!client.character.currentInteractionGuid || packet.data.password === 1)
@@ -848,11 +825,19 @@ export class zonePacketHandlers {
848
825
  const doorEntity = server._constructionDoors[
849
826
  client.character.currentInteractionGuid
850
827
  ] as ConstructionDoor;
828
+ if (!doorEntity) return;
851
829
  if (doorEntity.ownerCharacterId === client.character.characterId) {
852
- doorEntity.passwordHash = packet.data.password;
853
- doorEntity.grantedAccess.push(client.character.characterId);
830
+ if (doorEntity.passwordHash != packet.data.password) {
831
+ doorEntity.passwordHash = packet.data.password;
832
+ doorEntity.grantedAccess = [];
833
+ doorEntity.grantedAccess.push(client.character.characterId);
834
+ }
835
+ return;
854
836
  }
855
- if (doorEntity.passwordHash === packet.data.password) {
837
+ if (
838
+ doorEntity.passwordHash === packet.data.password &&
839
+ !doorEntity.grantedAccess.includes(client.character.characterId)
840
+ ) {
856
841
  doorEntity.grantedAccess.push(client.character.characterId);
857
842
  }
858
843
  }
@@ -1301,7 +1286,10 @@ export class zonePacketHandlers {
1301
1286
  if (!characterId) {
1302
1287
  return;
1303
1288
  }
1304
- if (characterId == foundation.ownerCharacterId) return;
1289
+ if (characterId == foundation.ownerCharacterId) {
1290
+ server.sendAlert(client, "You can't edit your own permissions.");
1291
+ return;
1292
+ }
1305
1293
  const obj: ConstructionPermissions = foundation.permissions[characterId];
1306
1294
  switch (packet.data.permissionSlot) {
1307
1295
  case 1:
@@ -1363,6 +1351,10 @@ export class zonePacketHandlers {
1363
1351
  }
1364
1352
  }
1365
1353
 
1354
+ if (characterId == foundation.ownerCharacterId) {
1355
+ server.sendAlert(client, "You can't edit your own permissions.");
1356
+ return;
1357
+ }
1366
1358
  if (!characterId) return;
1367
1359
  let obj: ConstructionPermissions = foundation.permissions[characterId];
1368
1360
  if (!obj) {
@@ -1604,7 +1596,8 @@ export class zonePacketHandlers {
1604
1596
  if (
1605
1597
  !weaponItem.weapon?.ammoCount &&
1606
1598
  weaponItem.itemDefinitionId != Items.WEAPON_BOW_MAKESHIFT &&
1607
- weaponItem.itemDefinitionId != Items.WEAPON_BOW_RECURVE
1599
+ weaponItem.itemDefinitionId != Items.WEAPON_BOW_RECURVE &&
1600
+ weaponItem.itemDefinitionId != Items.WEAPON_BOW_WOOD
1608
1601
  )
1609
1602
  return;
1610
1603
  if (p.packet.firestate > 0) {
@@ -1731,7 +1724,8 @@ export class zonePacketHandlers {
1731
1724
 
1732
1725
  if (
1733
1726
  weaponItem.itemDefinitionId == Items.WEAPON_BOW_MAKESHIFT ||
1734
- weaponItem.itemDefinitionId == Items.WEAPON_BOW_RECURVE
1727
+ weaponItem.itemDefinitionId == Items.WEAPON_BOW_RECURVE ||
1728
+ weaponItem.itemDefinitionId == Items.WEAPON_BOW_WOOD
1735
1729
  ) {
1736
1730
  if (
1737
1731
  client.character.getEquippedWeapon().itemGuid !=