h1z1-server 0.45.0 → 0.45.2-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.
package/config.yaml ADDED
@@ -0,0 +1,174 @@
1
+ server:
2
+ welcomeMessage: "Welcome to H1emu! :D"
3
+ adminMessage: "You are an Admin!"
4
+ proximityItemsDistance: 2
5
+ interactionDistance: 3
6
+ charactersRenderDistance: 350
7
+ tickRate: 2000
8
+ worldRoutineRate: 10000
9
+ enableLoginServerKickRequests: true
10
+ rebootTime: 48 # hours (0 to disable)
11
+ rebootWarnTime: 600 # seconds
12
+ isPvE: false
13
+ isHeadshotOnly: false
14
+ isFirstPersonOnly: false
15
+ isNoBuildInPois: true
16
+ baseConstructionDamage: 34000
17
+
18
+ # Rcon
19
+
20
+ rcon:
21
+ password: ""
22
+ port: 0
23
+
24
+ # VoiceChat
25
+
26
+ voicechat:
27
+ useVoiceChatV2: false
28
+ joinVoiceChatOnConnect: false
29
+ serverAccessToken: ""
30
+
31
+ # Fairplay / anticheat config
32
+
33
+ fairplay:
34
+ useFairplay: true
35
+ maxPing: 250
36
+
37
+ # Removing an entry below will allow clients with a certain rejectionFlag to join
38
+ # ex. Removing "5 # UNVERIFIED" will allow users with an unverified h1emu status to join
39
+
40
+ # by default, globally banned, hwid banned, vpn detected, and unverified clients will have their
41
+ # connections rejected
42
+ acceptedRejectionTypes:
43
+ # LOCAL_BAN, SERVER_LOCKED, and SERVER_REBOOT are always accepted
44
+ - 2 # GLOBAL_BAN
45
+ - 3 # VPN
46
+ - 4 # HWID
47
+ - 5 # UNVERIFIED
48
+
49
+ useAssetValidation: true
50
+ # how long the client has to send it's hashes before it's kicked (3 min default)
51
+ hashSubmissionTimeout: 180000
52
+
53
+ # clients with these packs are allowed to join, but they are optional (must be in numerical order)
54
+ allowedPacks:
55
+ #- file_name: ""
56
+ # crc32_hash: ""
57
+
58
+ # clients without these packs will be kicked (must be in numerical order)
59
+ requiredPacks:
60
+ #- file_name: ""
61
+ # crc32_hash: ""
62
+
63
+ weather:
64
+ defaultTemplate: "h1emubaseweather"
65
+ dynamicEnabled: true
66
+
67
+ # Anything to do with loot, vehicle, and npc spawning / despawning
68
+ worldobjects:
69
+ # Respawn timers
70
+
71
+ hasCustomLootRespawnTime: false
72
+ lootRespawnTimer: 1200000 # 30 minutes
73
+ vehicleRespawnTimer: 600000 # 10 minutes
74
+ npcRespawnTimer: 600000 # 10 minutes
75
+
76
+ # Despawn timers
77
+
78
+ # Player dropped items on the ground
79
+ itemDespawnTimer: 600000 # 10 minutes
80
+ # Spawned objects on the ground
81
+ lootDespawnTimer: 2400000 # 40 minutes
82
+ deadNpcDespawnTimer: 600000 # 10 minutes
83
+ lootbagDespawnTimer: 1800000 # 30 minutes
84
+
85
+ # Misc
86
+ minAirdropSurvivors: 10
87
+ vehicleSpawnCap: 120
88
+ # How far any other vehicle has to be for another to spawn
89
+ vehicleSpawnRadius: 50
90
+ # How far another spawned npc has to be for another to spawn
91
+ npcSpawnRadius: 3
92
+ chanceNpc: 100 # To be reworked: 100 max
93
+ chanceScreamer: 5 # To be reworked: 1000 max
94
+
95
+ chanceWornLetter: 1 # 100 max
96
+
97
+ waterSourceRefillAmount: 2
98
+ waterSourceReplenishTimer: 300000 # 5 minutes
99
+
100
+ crowbarHitRewardChance: 20 # 100 max
101
+ crowbarHitDamage: 10 # Default 25
102
+
103
+ # Trees, blackberry bushes, and sticks
104
+ speedtree:
105
+ minBlackberryHarvest: 1
106
+ maxBlackberryHarvest: 2
107
+ # from blackberry bushes only
108
+ branchHarvestChance: 0.1 # maximum of 1 for 100% chance
109
+
110
+ minStickHarvest: 1
111
+ maxStickHarvest: 2
112
+
113
+ treeRespawnTimeMS: 1800000 # 30 minutes
114
+ minWoodLogHarvest: 2
115
+ maxWoodLogHarvest: 6
116
+ minTreeHits: 12 # minimum hits it takes to chop a tree
117
+ maxTreeHits: 20 # maximum hits it takes to chop a tree
118
+
119
+ construction:
120
+ # allowPOIPlacement: false - deprecated in favor of isNoBuildInPOIs ^
121
+ allowStackedPlacement: false
122
+ allowOutOfBoundsPlacement: false
123
+ placementRange: 30
124
+ spawnPointBlockedPlacementRange: 25
125
+ vehicleSpawnPointBlockedPlacementRange: 30
126
+ playerFoundationBlockedPlacementRange: 70
127
+ playerShackBlockedPlacementRange: 20
128
+
129
+ decay:
130
+ decayTickInterval: 1200000 # 20 minutes per decay tick
131
+ constructionDamageTicks: 3 # damage structures every hour
132
+
133
+ # with default values it'll take 10 days for a base to fully decay
134
+ ticksToFullDecay: 240 # how many decay ticks * constructionDamageTicks it takes to fully decay any construction entity.
135
+
136
+ # unused for now but is planned
137
+ worldFreeplaceDecayMultiplier: 2 # used to multiply decay damage for freeplace constuction with no parent
138
+
139
+ ##### DEPRECATED - NO LONGER DOES ANYTHING #####
140
+ baseConstructionDamage: 125000 # construction damage per required ticks
141
+ repairBoxHealValue: 1000000 # heals base to full condition
142
+ ##### #####
143
+
144
+ vehicleDamageTicks: 3 # damage vehicles every hour
145
+ vacantFoundationTicks: 3 # destroy empty foundations after 1 hour
146
+ griefFoundationTimer: 72 # destroy grief foundations after 3 days (72 hours)
147
+ griefCheckSlotAmount: 4 # must have a minimum of 4 wall slots to avoid anti-grief
148
+ baseVehicleDamage: 2000 # 2% damage per 3 ticks (1 hour)
149
+ maxVehiclesPerArea: 2 # the max amount of vehicles that can be in an area before they start taking more damage
150
+ vehicleDamageRange: 25 # how large of a range to detect maxVehiclesPerArea
151
+ dailyRepairMaterials:
152
+ - itemDefinitionId: 16 # wood log
153
+ requiredCount: 1
154
+ - itemDefinitionId: 109 # wood plank
155
+ requiredCount: 10
156
+ - itemDefinitionId: 135 # nail
157
+ requiredCount: 4
158
+ - itemDefinitionId: 141 # metal bracket
159
+ requiredCount: 4
160
+ - itemDefinitionId: 46 # metal sheet
161
+ requiredCount: 1
162
+ - itemDefinitionId: 114 # metal shard
163
+ requiredCount: 8
164
+ - itemDefinitionId: 111 # wood stick
165
+ requiredCount: 2
166
+
167
+ smelting:
168
+ burnTime: 120000 # consume fuel every 120 seconds
169
+ smeltTime: 7000 # smelt 1 item every 7 seconds
170
+ gametime:
171
+ timeFrozen: false # Froze ingameTime
172
+ nightTimeMultiplier: 2 # This way night time pass 2 times faster than daytime
173
+ timeMultiplier: 36 # 1 hour IRL = 36 hours ingame, so 20 min for a full day
174
+ baseTime: 6 # server ingameTime start at 6 AM, 18 = 6PM
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "h1z1-server",
3
- "version": "0.45.0",
3
+ "version": "0.45.2-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",
@@ -14,8 +14,8 @@
14
14
  },
15
15
  "dependencies": {
16
16
  "@types/js-yaml": "4.0.9",
17
- "@types/node": "22.13.13",
18
- "@types/ws": "8.18.0",
17
+ "@types/node": "22.14.1",
18
+ "@types/ws": "8.18.1",
19
19
  "debug": "4.4.0",
20
20
  "h1emu-ai": "0.0.8",
21
21
  "h1emu-core": "1.3.2",
@@ -24,19 +24,19 @@
24
24
  "mongodb": "6.15.0",
25
25
  "recast-navigation": "0.34.0",
26
26
  "threads": "1.7.0",
27
- "typescript": "5.8.2",
27
+ "typescript": "5.8.3",
28
28
  "ws": "8.18.1"
29
29
  },
30
30
  "directories": {
31
31
  "src": "./src"
32
32
  },
33
33
  "devDependencies": {
34
- "oxlint": "^0.16.3",
35
34
  "cross-env": "^7.0.3",
36
35
  "globals": "^16.0.0",
36
+ "oxlint": "^0.16.6",
37
37
  "prettier": "^3.5.3",
38
38
  "tsx": "^4.19.3",
39
- "typedoc": "^0.28.1"
39
+ "typedoc": "^0.28.2"
40
40
  },
41
41
  "scripts": {
42
42
  "gen-packets-types": "tsx ./scripts/genPacketsNames.ts",
@@ -32,7 +32,9 @@ export enum ChallengeType {
32
32
  GLOBAL_DISARMAMENT,
33
33
  ROCKY,
34
34
  ROCKSTAR,
35
- IED
35
+ IED,
36
+ RANCHITO,
37
+ SWIZZLE
36
38
  }
37
39
  export enum ChallengeStatus {
38
40
  CURRENT = 1,
@@ -102,6 +104,14 @@ export class ChallengeManager {
102
104
  neededPoints: 1,
103
105
  pvpOnly: false
104
106
  },
107
+ {
108
+ type: ChallengeType.RANCHITO,
109
+ difficulty: ChallengeDifficulty.EASY,
110
+ name: "Wait... Why am i here again?",
111
+ description: "Visit Ranchito",
112
+ neededPoints: 1,
113
+ pvpOnly: false
114
+ },
105
115
  {
106
116
  type: ChallengeType.BRAIN_DEAD,
107
117
  difficulty: ChallengeDifficulty.MEDIUM,
@@ -151,6 +161,14 @@ export class ChallengeManager {
151
161
  neededPoints: 1,
152
162
  pvpOnly: false
153
163
  },
164
+ {
165
+ type: ChallengeType.SWIZZLE,
166
+ difficulty: ChallengeDifficulty.MEDIUM,
167
+ name: "Shady buisness",
168
+ description: "Consume some swizzle",
169
+ neededPoints: 1,
170
+ pvpOnly: false
171
+ },
154
172
  {
155
173
  type: ChallengeType.PV_PD_SURVIVAL,
156
174
  difficulty: ChallengeDifficulty.HARD,
@@ -333,14 +351,12 @@ export class ChallengeManager {
333
351
  }
334
352
 
335
353
  async affectChallenge(client: ZoneClient2016) {
336
- const today = new Date();
337
- const timeZoneOffset = today.getTimezoneOffset() * 60000; // Convert minutes to milliseconds
338
354
  const now = Date.now();
339
355
 
340
- const startOfDay = new Date(now - timeZoneOffset);
356
+ const startOfDay = new Date(now);
341
357
  startOfDay.setHours(0, 0, 0, 0);
342
358
 
343
- const endOfDay = new Date(now - timeZoneOffset);
359
+ const endOfDay = new Date(now);
344
360
  endOfDay.setHours(23, 59, 59, 999);
345
361
 
346
362
  const challengesToday = await this.challengesCollection
@@ -371,8 +387,8 @@ export class ChallengeManager {
371
387
  }
372
388
  const challengesAvailable = this.challenges.filter((v) => {
373
389
  return (
374
- ((!challengesTypesDoneToday.includes(v.type) && !v.pvpOnly) ||
375
- !this.server.isPvE) &&
390
+ !challengesTypesDoneToday.includes(v.type) &&
391
+ (!v.pvpOnly || !this.server.isPvE) &&
376
392
  v.difficulty === nextDifficultyChallenge
377
393
  );
378
394
  });
@@ -517,27 +517,32 @@ export class CraftManager {
517
517
  client.character.lootItem(server, server.generateItem(id, 1));
518
518
  });
519
519
  }
520
- if (recipeId === Items.IED) {
521
- server.challengeManager.registerChallengeProgression(
522
- client,
523
- ChallengeType.IED,
524
- 1
525
- );
526
- }
527
- if (recipeId === Items.FOUNDATION) {
528
- server.challengeManager.registerChallengeProgression(
529
- client,
530
- ChallengeType.MY_LAND,
531
- 1
532
- );
533
- }
534
- if (recipeId === Items.SHACK) {
535
- server.challengeManager.registerChallengeProgression(
536
- client,
537
- ChallengeType.MY_HOME,
538
- 1
539
- );
520
+ switch (recipeId) {
521
+ case Items.IED:
522
+ server.challengeManager.registerChallengeProgression(
523
+ client,
524
+ ChallengeType.IED,
525
+ 1
526
+ );
527
+ break;
528
+
529
+ case Items.FOUNDATION:
530
+ server.challengeManager.registerChallengeProgression(
531
+ client,
532
+ ChallengeType.MY_LAND,
533
+ 1
534
+ );
535
+ break;
536
+
537
+ case Items.SHACK:
538
+ server.challengeManager.registerChallengeProgression(
539
+ client,
540
+ ChallengeType.MY_HOME,
541
+ 1
542
+ );
543
+ break;
540
544
  }
545
+
541
546
  return true;
542
547
  //#endregion
543
548
  }
@@ -23,7 +23,6 @@ interface WeightedItem {
23
23
  export class RandomEventsManager {
24
24
  interval?: NodeJS.Timeout;
25
25
  // managed by config
26
- // TODO:
27
26
  enabled: boolean = true;
28
27
  constructor(public server: ZoneServer2016) {}
29
28
  start() {
@@ -61,7 +60,6 @@ export class RandomEventsManager {
61
60
  { value: "Supplier", weight: 20 }
62
61
  ];
63
62
  const airdropType = this.weightedRandom(airdropTypes);
64
- console.log(airdropType);
65
63
  this.server.spawnAirdrop(pos, airdropType);
66
64
  const cellName = getCellName(cellIndex, 10);
67
65
  this.server.sendAlertToAll(`Random airdrop on ${cellName}`);
@@ -523,6 +523,16 @@ export class WorldObjectManager {
523
523
  effectTime: 60
524
524
  }
525
525
  );
526
+
527
+ if (
528
+ isPosInRadius(
529
+ 3,
530
+ c.character.state.position,
531
+ server._airdrop.destinationPos
532
+ )
533
+ ) {
534
+ server.killCharacter(c, { damage: 99999, entity: "aidrop" });
535
+ }
526
536
  }
527
537
  }
528
538
  server._lootbags[characterId] = lootbag;
@@ -1948,7 +1948,10 @@ export class ZoneServer2016 extends EventEmitter {
1948
1948
  const start = performance.now();
1949
1949
  this.aiManager.run();
1950
1950
  const end = performance.now();
1951
- console.log(`H1emu-ai took ${end - start}ms`);
1951
+ const duration = end - start;
1952
+ if (duration >= 1) {
1953
+ console.log(`H1emu-ai took ${duration}ms`);
1954
+ }
1952
1955
  } else {
1953
1956
  this.aiManager.run();
1954
1957
  }
@@ -4212,6 +4215,13 @@ export class ZoneServer2016 extends EventEmitter {
4212
4215
  id: point.POIid
4213
4216
  });
4214
4217
  client.currentPOI = point.stringId;
4218
+ if (point.POIid === 13) {
4219
+ this.challengeManager.registerChallengeProgression(
4220
+ client,
4221
+ ChallengeType.RANCHITO,
4222
+ 1
4223
+ );
4224
+ }
4215
4225
  }
4216
4226
  }
4217
4227
  });
@@ -7379,6 +7389,11 @@ export class ZoneServer2016 extends EventEmitter {
7379
7389
  sniffPass(client: Client, character: BaseFullCharacter, item: BaseItem) {
7380
7390
  if (!this.removeInventoryItem(character, item)) return;
7381
7391
  if (item.itemDefinitionId === Items.SWIZZLE) {
7392
+ this.challengeManager.registerChallengeProgression(
7393
+ client,
7394
+ ChallengeType.SWIZZLE,
7395
+ 1
7396
+ );
7382
7397
  this.applyMovementModifier(client, MovementModifiers.SWIZZLE);
7383
7398
  } else {
7384
7399
  this.applyMovementModifier(client, MovementModifiers.ADRENALINE);