h1z1-server 0.47.2-1 → 0.47.2-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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "h1z1-server",
3
- "version": "0.47.2-1",
3
+ "version": "0.47.2-2",
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",
@@ -1940,13 +1940,17 @@ export const basePackets: PacketStructures = [
1940
1940
  type: "uint64string",
1941
1941
  defaultValue: "0x0"
1942
1942
  },
1943
- { name: "unknownQword3", type: "uint64string", defaultValue: "" },
1943
+ {
1944
+ name: "unknownQword3",
1945
+ type: "uint64string",
1946
+ defaultValue: "0x0"
1947
+ },
1944
1948
  {
1945
1949
  name: "vehicleLoadoutRelatedDword",
1946
1950
  type: "uint32",
1947
1951
  defaultValue: 0
1948
1952
  },
1949
- { name: "unknownDword40", type: "int32", defaultValue: 0 },
1953
+ { name: "unknownDword40", type: "int32", defaultValue: -1 },
1950
1954
  { name: "isAdmin", type: "boolean", defaultValue: true },
1951
1955
  { name: "firstPersonOnly", type: "boolean", defaultValue: false },
1952
1956
  { name: "spectatorFlags", type: "uint8", defaultValue: 0 }
@@ -0,0 +1,111 @@
1
+ // Emote name to ID mapping
2
+ const emoteMap: { [Name: string]: number } = {
3
+ wavehello: 2,
4
+ wavebye: 3,
5
+ doublebird: 4,
6
+ point: 5,
7
+ agree: 6,
8
+ applause: 7,
9
+ beckon: 8,
10
+ cutthroat: 9,
11
+ salute: 10,
12
+ dancea: 11,
13
+ wavehellob: 12,
14
+ laugh: 13,
15
+ no: 14,
16
+ noway: 15,
17
+ handsup: 16,
18
+ sit: 17,
19
+ teabag: 18,
20
+ birdcannon: 20,
21
+ bootyslap: 21,
22
+ crotchchop: 22,
23
+ crybaby: 23,
24
+ grind: 24,
25
+ pelvicthrust: 25,
26
+ sarcasmdance: 26,
27
+ screwyou2: 27,
28
+ shimmydance: 28,
29
+ werenotworthy: 29,
30
+ beg: 30,
31
+ fisticuffs: 31,
32
+ flex: 32,
33
+ hump: 33,
34
+ flexpoint: 34,
35
+ listentothecrowd: 35,
36
+ airguitar: 36,
37
+ basicsalute: 37,
38
+ blowkiss: 38,
39
+ bow: 39,
40
+ buttscratchsniff: 40,
41
+ cheer: 41,
42
+ cold: 42,
43
+ confused: 43,
44
+ crazy: 44,
45
+ cry: 45,
46
+ curse: 46,
47
+ curtsey: 47,
48
+ doh: 48,
49
+ fingerwaggle: 49,
50
+ fistpump: 50,
51
+ frustrated: 51,
52
+ flustered: 52,
53
+ getattention: 53,
54
+ glare: 54,
55
+ handbeckon: 55,
56
+ happydance: 56,
57
+ hot: 57,
58
+ isitraining: 58,
59
+ jumphooray: 59,
60
+ loser: 60,
61
+ lookaway: 61,
62
+ listen: 62,
63
+ moon: 63,
64
+ neener: 64,
65
+ orate: 65,
66
+ pout: 66,
67
+ ponder: 67,
68
+ peer: 68,
69
+ royalwave: 69,
70
+ rudeslap: 70,
71
+ sad: 71,
72
+ scold: 72,
73
+ screwyoua: 73,
74
+ scream: 74,
75
+ shakefist: 75,
76
+ shakehead: 76,
77
+ shame: 77,
78
+ shieldeyes: 78,
79
+ shiverdownspine: 79,
80
+ shrugdance: 80,
81
+ sigh: 81,
82
+ singlefingerwaggle: 82,
83
+ sniff: 83,
84
+ stretch: 84,
85
+ square: 85,
86
+ sulk: 86,
87
+ swearoath: 87,
88
+ teabagb: 88,
89
+ tapfoot: 89,
90
+ teabaglight: 90,
91
+ threaten: 91,
92
+ thanks: 92,
93
+ thumbsdown: 93,
94
+ thumbsup: 94,
95
+ victory: 95,
96
+ violin: 96,
97
+ whistle: 97,
98
+ wave: 98,
99
+ wince: 99,
100
+ woohoo: 100,
101
+ raisecrown: 101,
102
+ thriller: 102
103
+ };
104
+
105
+ // Default emotes that don't require ownership
106
+ const defaultEmotes = [2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
107
+
108
+ // Array of emote names for listing
109
+ const emoteNames: string[] = Object.keys(emoteMap);
110
+
111
+ export { emoteMap, emoteNames, defaultEmotes };
@@ -39,6 +39,7 @@ import {
39
39
  characterKitLoadout,
40
40
  characterVehicleKit
41
41
  } from "../../data/loadouts";
42
+ import { emoteMap, emoteNames, defaultEmotes } from "../../data/emotes";
42
43
  import {
43
44
  Effects,
44
45
  EquipSlots,
@@ -481,40 +482,29 @@ export const commands: Array<Command> = [
481
482
  {
482
483
  name: "emote",
483
484
  permissionLevel: PermissionLevels.DEFAULT,
484
- execute: (server: ZoneServer2016, client: Client, args: Array<string>) => {
485
- if (server.isPvE) {
486
- const animationId = Number(args[0]);
487
- if (!animationId || animationId > MAX_UINT32) {
488
- server.sendChatText(client, "Usage /emote <id>");
489
- return;
490
- }
485
+ execute: async (
486
+ server: ZoneServer2016,
487
+ client: Client,
488
+ args: Array<string>
489
+ ) => {
490
+ if (!args[0]) {
491
+ server.sendChatText(client, "Usage /emote <name>");
492
+ return;
493
+ }
491
494
 
492
- if (!server.isPvE) {
493
- switch (animationId) {
494
- case 18:
495
- case 21:
496
- case 29:
497
- case 30:
498
- case 39:
499
- case 88:
500
- case 34:
501
- case 35:
502
- case 43:
503
- case 46:
504
- case 51:
505
- case 58:
506
- case 68:
507
- case 95:
508
- case 97:
509
- case 101:
510
- case 102:
511
- server.sendChatText(
512
- client,
513
- "[ERROR] This emote has been disabled due to abuse."
514
- );
515
- return;
516
- }
517
- }
495
+ const emoteName = args[0].toLowerCase();
496
+ const animationId = emoteMap[emoteName];
497
+
498
+ if (!animationId) {
499
+ server.sendChatText(
500
+ client,
501
+ `Unknown emote: ${args[0]}. Use /emotelist to see available emotes.`
502
+ );
503
+ return;
504
+ }
505
+
506
+ // Check if this emote is in the allowed list (no ownership check needed)
507
+ if (defaultEmotes.includes(animationId)) {
518
508
  server.sendDataToAllWithSpawnedEntity(
519
509
  server._characters,
520
510
  client.character.characterId,
@@ -524,12 +514,89 @@ export const commands: Array<Command> = [
524
514
  animationId: animationId
525
515
  }
526
516
  );
527
- } else {
528
- server.sendChatText(
529
- client,
530
- "[ERROR] Emotes are currently disabled in PvP servers."
517
+ return;
518
+ }
519
+
520
+ // Check if player owns the emote as an account item
521
+ let hasEmote = false;
522
+
523
+ // Check all account items for emote
524
+ const accountItems =
525
+ await server.accountInventoriesManager.getAccountItems(
526
+ client.loginSessionId
531
527
  );
528
+ for (const accountItem of accountItems) {
529
+ if (accountItem && accountItem.itemDefinitionId) {
530
+ const itemDef = server.getItemDefinition(
531
+ accountItem.itemDefinitionId
532
+ );
533
+ if (itemDef && itemDef.PARAM1 === animationId) {
534
+ hasEmote = true;
535
+ break;
536
+ }
537
+ }
538
+ }
539
+
540
+ if (!hasEmote) {
541
+ server.sendChatText(client, "[ERROR] You don't own this emote");
542
+ return;
532
543
  }
544
+
545
+ server.sendDataToAllWithSpawnedEntity(
546
+ server._characters,
547
+ client.character.characterId,
548
+ "Animation.Play",
549
+ {
550
+ characterId: client.character.characterId,
551
+ animationId: animationId
552
+ }
553
+ );
554
+ }
555
+ },
556
+ {
557
+ name: "emotelist",
558
+ permissionLevel: PermissionLevels.DEFAULT,
559
+ execute: async (
560
+ server: ZoneServer2016,
561
+ client: Client,
562
+ args: Array<string>
563
+ ) => {
564
+ const ownedEmotes: string[] = [];
565
+
566
+ // Add default emotes that don't require ownership
567
+ for (const [emoteName, animationId] of Object.entries(emoteMap)) {
568
+ if (defaultEmotes.includes(animationId)) {
569
+ ownedEmotes.push(emoteName);
570
+ }
571
+ }
572
+
573
+ // Check account items for owned emotes
574
+ const accountItems =
575
+ await server.accountInventoriesManager.getAccountItems(
576
+ client.loginSessionId
577
+ );
578
+ for (const accountItem of accountItems) {
579
+ if (accountItem && accountItem.itemDefinitionId) {
580
+ const itemDef = server.getItemDefinition(
581
+ accountItem.itemDefinitionId
582
+ );
583
+ if (itemDef && itemDef.PARAM1) {
584
+ // Find emote name by animation ID
585
+ for (const [emoteName, animationId] of Object.entries(emoteMap)) {
586
+ if (
587
+ animationId === itemDef.PARAM1 &&
588
+ !defaultEmotes.includes(animationId)
589
+ ) {
590
+ ownedEmotes.push(emoteName);
591
+ break;
592
+ }
593
+ }
594
+ }
595
+ }
596
+ }
597
+
598
+ server.sendChatText(client, "Available emotes:", true);
599
+ server.sendChatText(client, ownedEmotes.sort().join(", "));
533
600
  }
534
601
  },
535
602
  {
@@ -1793,6 +1860,27 @@ export const commands: Array<Command> = [
1793
1860
  server.sendAlert(client, `Set debug mode to ${client.isDebugMode}`);
1794
1861
  }
1795
1862
  },
1863
+ {
1864
+ name: "setmaxpacketloss",
1865
+ permissionLevel: PermissionLevels.ADMIN,
1866
+ execute: (server: ZoneServer2016, client: Client, args: Array<string>) => {
1867
+ if (!args[0]) {
1868
+ server.sendChatText(client, "You must specify a value");
1869
+ return;
1870
+ }
1871
+ const packetloss = Number(args[0]);
1872
+ if (packetloss < 1) {
1873
+ server.sendChatText(client, "Minimum packet loss to specify is 1");
1874
+ return;
1875
+ }
1876
+ server.sendChatText(
1877
+ client,
1878
+ `Max packet loss set to ${packetloss} from ${server.maxPacketLoss}`,
1879
+ false
1880
+ );
1881
+ server.maxPacketLoss = packetloss;
1882
+ }
1883
+ },
1796
1884
  {
1797
1885
  name: "heal",
1798
1886
  permissionLevel: PermissionLevels.MODERATOR,
@@ -323,6 +323,18 @@ export class ZonePacketHandlers {
323
323
  if (!server.hookManager.checkHook("OnClientFinishedLoading", client)) {
324
324
  return;
325
325
  }
326
+
327
+ if (!client.firstLoading) {
328
+ setTimeout(() => {
329
+ const soeClient = server._gatewayServer._soeServer.getSoeClient(
330
+ client.soeClientId
331
+ );
332
+ if (soeClient) {
333
+ soeClient.finishedLoading = true;
334
+ }
335
+ }, 5000);
336
+ }
337
+
326
338
  if (client.character.awaitingTeleportLocation) {
327
339
  const awaitingPos = client.character.awaitingTeleportLocation;
328
340
  setTimeout(() => {
@@ -7940,7 +7940,7 @@ export class ZoneServer2016 extends EventEmitter {
7940
7940
  itemDefinition.ID,
7941
7941
  overrideProjectileId
7942
7942
  ? packet.packet.sessionProjectileCount +
7943
- parseInt(client.character.characterId.slice(-5), 16)
7943
+ parseInt(client.character.characterId.slice(-5), 16)
7944
7944
  : packet.packet.projectileUniqueId,
7945
7945
  client.character.characterId
7946
7946
  );