h1z1-server 0.23.5 → 0.23.6

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "h1z1-server",
3
- "version": "0.23.5",
3
+ "version": "0.23.6",
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",
@@ -20,6 +20,7 @@ import {
20
20
  _,
21
21
  getDifference,
22
22
  isPosInRadius,
23
+ toHex,
23
24
  } from "../../../utils/utils";
24
25
  import { ExplosiveEntity } from "../entities/explosiveentity";
25
26
  import { Npc } from "../entities/npc";
@@ -530,6 +531,7 @@ export const commands: Array<Command> = [
530
531
  client.character.state.position = locationPosition;
531
532
  client.isLoading = true;
532
533
  client.characterReleased = false;
534
+ client.character.lastLoginDate = toHex(Date.now());
533
535
  server.sendData(client, "ClientUpdate.UpdateLocation", {
534
536
  position: locationPosition,
535
537
  triggerLoadingScreen: true,
@@ -562,6 +564,7 @@ export const commands: Array<Command> = [
562
564
  targetClient.character.state.position = client.character.state.position;
563
565
  targetClient.isLoading = true;
564
566
  targetClient.characterReleased = false;
567
+ targetClient.character.lastLoginDate = toHex(Date.now());
565
568
  server.sendData(targetClient, "ClientUpdate.UpdateLocation", {
566
569
  position: client.character.state.position,
567
570
  triggerLoadingScreen: true,
@@ -598,6 +601,7 @@ export const commands: Array<Command> = [
598
601
  client.character.state.position = targetClient.character.state.position;
599
602
  client.isLoading = true;
600
603
  client.characterReleased = false;
604
+ client.character.lastLoginDate = toHex(Date.now());
601
605
  server.sendData(client, "ClientUpdate.UpdateLocation", {
602
606
  position: targetClient.character.state.position,
603
607
  triggerLoadingScreen: true,
@@ -1511,7 +1515,7 @@ export const commands: Array<Command> = [
1511
1515
  );
1512
1516
  return;
1513
1517
  }
1514
- const name = args.join(" ").toString().toLowerCase();
1518
+ const name = args.join(" ").toString();
1515
1519
  const bannedClient = (
1516
1520
  await server._db
1517
1521
  ?.collection(DB_COLLECTIONS.BANNED)
@@ -22,14 +22,14 @@ function getRenderDistance(itemDefinitionId: number) {
22
22
  case Items.WORKBENCH_WEAPON:
23
23
  case Items.BEE_BOX:
24
24
  case Items.DEW_COLLECTOR:
25
- range = 250;
25
+ range = 100;
26
26
  break;
27
27
  case Items.STORAGE_BOX:
28
28
  case Items.ANIMAL_TRAP:
29
29
  range = 20;
30
30
  break;
31
31
  default:
32
- range = 350;
32
+ range = 300;
33
33
  break;
34
34
  }
35
35
  return range;
@@ -61,10 +61,10 @@ export class LootableConstructionEntity extends BaseLootableEntity {
61
61
  this.defaultLoadout = lootableContainerDefaultLoadouts.storage;
62
62
  if (subEntityType === "SmeltingEntity") {
63
63
  this.subEntity = new SmeltingEntity(this, server);
64
- this.npcRenderDistance = 250;
64
+ this.npcRenderDistance = 20; //this.npcRenderDistance = 250; lower render distances until next wipe (furnaces were invis and people have multiple at one one, causes lag)
65
65
  } else if (subEntityType === "CollectingEntity") {
66
66
  this.subEntity = new CollectingEntity(this, server);
67
- this.npcRenderDistance = 250;
67
+ this.npcRenderDistance = 20; //this.npcRenderDistance = 250;
68
68
  } else {
69
69
  this.npcRenderDistance = 20;
70
70
  }
@@ -98,15 +98,11 @@ export class DecayManager {
98
98
  | ConstructionChildEntity
99
99
  ) {
100
100
  const dictionary = server.getConstructionDictionary(entity.characterId);
101
+ if (!dictionary[entity.characterId]) return;
101
102
  entity.damage(server, {
102
103
  entity: "",
103
104
  damage: 125000,
104
105
  });
105
- if (entity.health <= 0) {
106
- entity.destroy(server);
107
- return;
108
- }
109
- if (!dictionary[entity.characterId]) return;
110
106
  server.updateResourceToAllWithSpawnedEntity(
111
107
  entity.characterId,
112
108
  entity.health,
@@ -114,6 +110,8 @@ export class DecayManager {
114
110
  ResourceTypes.CONDITION,
115
111
  dictionary
116
112
  );
113
+ if (entity.health > 0) return;
114
+ entity.destroy(server);
117
115
  }
118
116
 
119
117
  private contructionDecayDamage(server: ZoneServer2016) {
@@ -123,6 +121,15 @@ export class DecayManager {
123
121
  for (const a in server._worldSimpleConstruction) {
124
122
  this.decayDamage(server, server._worldSimpleConstruction[a]);
125
123
  }
124
+ for (const a in server._constructionSimple) {
125
+ this.decayDamage(server, server._constructionSimple[a]);
126
+ }
127
+ for (const a in server._lootableConstruction) {
128
+ this.decayDamage(server, server._lootableConstruction[a]);
129
+ }
130
+ for (const a in server._constructionDoors) {
131
+ this.decayDamage(server, server._constructionDoors[a]);
132
+ }
126
133
  for (const a in server._constructionFoundations) {
127
134
  const foundation = server._constructionFoundations[a];
128
135
  if (
@@ -132,32 +139,10 @@ export class DecayManager {
132
139
  ) {
133
140
  this.decayDamage(server, foundation);
134
141
  }
135
- Object.values(foundation.freeplaceEntities).forEach(
136
- (
137
- entity:
138
- | LootableConstructionEntity
139
- | ConstructionDoor
140
- | ConstructionChildEntity
141
- ) => {
142
- this.decayDamage(server, entity);
143
- }
144
- );
145
- Object.values(foundation.occupiedShelterSlots).forEach(
146
- (entity: ConstructionDoor | ConstructionChildEntity) => {
147
- if (entity instanceof ConstructionChildEntity) {
148
- this.decayChildEntity(server, entity);
149
- }
150
- }
151
- );
152
- Object.values(foundation.occupiedWallSlots).forEach(
153
- (entity: ConstructionDoor | ConstructionChildEntity) => {
154
- this.decayChildEntity(server, entity);
155
- }
156
- );
157
142
  }
158
143
  }
159
144
 
160
- private decayChildEntity(
145
+ /*private decayChildEntity(
161
146
  server: ZoneServer2016,
162
147
  entity: ConstructionChildEntity | ConstructionDoor
163
148
  ) {
@@ -179,5 +164,5 @@ export class DecayManager {
179
164
  );
180
165
  }
181
166
  this.decayDamage(server, entity);
182
- }
167
+ }*/
183
168
  }
@@ -36,7 +36,7 @@ import {
36
36
  fixDbTempData,
37
37
  getAppDataFolderPath,
38
38
  initMongo,
39
- isTransferable,
39
+ removeUntransferableFields,
40
40
  toBigHex,
41
41
  } from "../../../utils/utils";
42
42
  import { ZoneServer2016 } from "../zoneserver";
@@ -449,9 +449,8 @@ export class WorldDataManager {
449
449
  const character = characters[i];
450
450
  const characterSave = this.convertToCharacterSaveData(character, worldId);
451
451
  // TODO: this is a temp solution, a deepclone slow down the save process :(
452
- if (isTransferable(characterSave)) {
453
- charactersSaveData.push(characterSave);
454
- }
452
+ removeUntransferableFields(characterSave);
453
+ charactersSaveData.push(characterSave);
455
454
  }
456
455
  return charactersSaveData;
457
456
  }
@@ -91,6 +91,7 @@ import {
91
91
  isInsideSquare,
92
92
  getDifference,
93
93
  logClientActionToMongo,
94
+ removeUntransferableFields,
94
95
  } from "../../utils/utils";
95
96
 
96
97
  import { Collection, Db } from "mongodb";
@@ -168,7 +169,7 @@ export class ZoneServer2016 extends EventEmitter {
168
169
  _db!: Db;
169
170
  _soloMode = false;
170
171
  _useFairPlay = true;
171
- maxPing = 200;
172
+ maxPing = 250;
172
173
  _serverName = process.env.SERVER_NAME || "";
173
174
  readonly _mongoAddress: string;
174
175
  private readonly _clientProtocol = "ClientProtocol_1080";
@@ -1025,23 +1026,24 @@ export class ZoneServer2016 extends EventEmitter {
1025
1026
  );
1026
1027
  const worldConstructions: LootableConstructionSaveData[] = [];
1027
1028
  Object.values(this._worldLootableConstruction).forEach((entity) => {
1028
- worldConstructions.push(
1029
+ const lootableConstructionSaveData =
1029
1030
  WorldDataManager.getLootableConstructionSaveData(
1030
1031
  entity,
1031
1032
  this._worldId
1032
- )
1033
- );
1033
+ );
1034
+ removeUntransferableFields(lootableConstructionSaveData);
1035
+ worldConstructions.push(lootableConstructionSaveData);
1034
1036
  });
1035
1037
  const constructions: ConstructionParentSaveData[] = [];
1036
1038
 
1037
1039
  Object.values(this._constructionFoundations).forEach((entity) => {
1038
1040
  if (entity.itemDefinitionId != Items.FOUNDATION_EXPANSION) {
1039
- constructions.push(
1040
- WorldDataManager.getConstructionParentSaveData(
1041
- entity,
1042
- this._worldId
1043
- )
1041
+ const construction = WorldDataManager.getConstructionParentSaveData(
1042
+ entity,
1043
+ this._worldId
1044
1044
  );
1045
+ // isTransferable(construction) too complex will run on max recursive call error
1046
+ constructions.push(construction);
1045
1047
  }
1046
1048
  });
1047
1049
  const crops: PlantingDiameterSaveData[] = [];
@@ -1926,6 +1928,7 @@ export class ZoneServer2016 extends EventEmitter {
1926
1928
  }
1927
1929
  client.isLoading = true;
1928
1930
  client.characterReleased = false;
1931
+ client.character.lastLoginDate = toHex(Date.now());
1929
1932
  client.character.resetMetrics();
1930
1933
  client.character.isAlive = true;
1931
1934
  client.character.isRunning = false;
@@ -4231,22 +4234,21 @@ export class ZoneServer2016 extends EventEmitter {
4231
4234
  const permissions =
4232
4235
  iteratedFoundation.permissions[client.character.characterId];
4233
4236
  if (!permissions || !permissions.build) continue;
4237
+ if (iteratedFoundation.characterId == parentObjectCharacterId) {
4238
+ isInFoundation = true;
4239
+ break;
4240
+ }
4234
4241
  if (iteratedFoundation.bounds) {
4235
4242
  if (iteratedFoundation.isInside(position)) isInFoundation = true;
4236
4243
  }
4237
4244
  }
4238
- const allowedIds = [
4239
- Items.FOUNDATION_EXPANSION,
4240
- Items.FOUNDATION_RAMP,
4241
- Items.FOUNDATION_STAIRS,
4242
- ];
4245
+
4243
4246
  for (const a in this._constructionFoundations) {
4244
4247
  const foundation = this._constructionFoundations[a];
4245
4248
  let allowBuild = false;
4246
4249
  const permissions = foundation.permissions[client.character.characterId];
4247
4250
  if (permissions && permissions.build) allowBuild = true;
4248
4251
  if (
4249
- !allowedIds.includes(itemDefinitionId) &&
4250
4252
  !isInFoundation &&
4251
4253
  isPosInRadius(
4252
4254
  foundation.itemDefinitionId === Items.FOUNDATION ||
@@ -7201,6 +7203,8 @@ export class ZoneServer2016 extends EventEmitter {
7201
7203
  }
7202
7204
 
7203
7205
  checkZonePing(client: Client) {
7206
+ if (Number(client.character.lastLoginDate) + 30000 > new Date().getTime())
7207
+ return;
7204
7208
  const soeClient = this.getSoeClient(client.soeClientId);
7205
7209
  if (soeClient) {
7206
7210
  const ping = soeClient.avgPing;
@@ -7211,7 +7215,7 @@ export class ZoneServer2016 extends EventEmitter {
7211
7215
  `Your ping is very high: ${ping}. You may be kicked soon`
7212
7216
  );
7213
7217
  }
7214
- if (client.zonePings.length >= 10) {
7218
+ if (client.zonePings.length >= 15) {
7215
7219
  const averagePing =
7216
7220
  client.zonePings.reduce((a, b) => a + b, 0) / client.zonePings.length;
7217
7221
  if (averagePing >= this.maxPing) {
@@ -829,13 +829,19 @@ export async function fixDbTempData(
829
829
  await db?.collection(tempCollection).deleteMany({ serverId: worldId });
830
830
  }
831
831
 
832
- export function isTransferable(data: unknown): boolean {
833
- try {
834
- structuredClone(data);
835
- return true;
836
- } catch (e) {
837
- console.log(`can't clone ${data}`);
838
- console.log(e);
839
- return false;
832
+ export function removeUntransferableFields(data: any) {
833
+ const allowedTypes = ["string", "number", "boolean", "undefined", "bigint"];
834
+
835
+ for (const key in data) {
836
+ // eslint-disable-next-line no-prototype-builtins
837
+ if (data.hasOwnProperty(key)) {
838
+ const value = data[key];
839
+ if (typeof value === "object") {
840
+ removeUntransferableFields(value);
841
+ } else if (!allowedTypes.includes(typeof value)) {
842
+ console.log(`Invalid value type: ${typeof value}.`);
843
+ delete data[key];
844
+ }
845
+ }
840
846
  }
841
847
  }