h1z1-server 0.47.2-3 → 0.47.2-4

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.
@@ -1025,21 +1025,26 @@
1025
1025
  },
1026
1026
  {
1027
1027
  "file_name": "Assets_256.pack",
1028
- "crc32_hash": "600179b5",
1029
- "old_crc32_hash": "47ce5604"
1028
+ "crc32_hash": "396f3599"
1030
1029
  },
1031
1030
  {
1032
1031
  "file_name": "Assets_257.pack",
1033
- "crc32_hash": "329599bc",
1034
- "old_crc32_hash": "bc999532"
1032
+ "crc32_hash": "bc999532"
1035
1033
  },
1036
1034
  {
1037
1035
  "file_name": "Assets_258.pack",
1038
- "crc32_hash": "7f2a6b5b",
1039
- "old_crc32_hash": "5b6b2a7f"
1036
+ "crc32_hash": "5b6b2a7f"
1040
1037
  },
1041
1038
  {
1042
1039
  "file_name": "Assets_259.pack",
1043
- "crc32_hash": "83625ea7"
1040
+ "crc32_hash": "a75e6283"
1041
+ },
1042
+ {
1043
+ "file_name": "Assets_260.pack",
1044
+ "crc32_hash": "7b106055"
1045
+ },
1046
+ {
1047
+ "file_name": "Assets_261.pack",
1048
+ "crc32_hash": "bfdc08a2"
1044
1049
  }
1045
1050
  ]
@@ -28,7 +28,32 @@
28
28
  [ -640.54, -887.64 ],
29
29
  [ -390.89, -589.56 ],
30
30
  [ -320.35, -672.29 ]
31
+ ],
32
+ [
33
+ [ -645.47, -1064.84 ],
34
+ [ -608.10, -1129.32 ],
35
+ [ -497.60, -1098.69 ],
36
+ [ -643.53, -1001.91 ]
37
+ ],
38
+ [
39
+ [ -663.98, -1029.62 ],
40
+ [ -508.54, -1076.45 ],
41
+ [ -510.59, -943.35 ],
42
+ [ -632.18, -914.25 ]
43
+ ],
44
+ [
45
+ [ -186.76, -257.98 ],
46
+ [ -275.67, -258.77 ],
47
+ [ -290.84, -384.00 ],
48
+ [ -228.99, -432.44 ]
49
+ ],
50
+ [
51
+ [ -171.77, -361.53 ],
52
+ [ -180.44, -261.37 ],
53
+ [ 278.91, -261.43 ],
54
+ [ 317.98, -370.07 ]
31
55
  ]
56
+
32
57
  ],
33
58
  "position": [
34
59
  -33.53,
@@ -68,7 +93,14 @@
68
93
  [ -577.3099975585938, -1889.8499755859375 ],
69
94
  [ -577.2699890136719, -1423.489990234375 ],
70
95
  [ -802.4400024414062, -1423.9599609375 ]
96
+ ],
97
+ [
98
+ [ -760.92, -1881.45 ],
99
+ [ -668.07, -1883.43 ],
100
+ [ -670.22, -1949.24 ],
101
+ [ -754.64, -1953.45 ]
71
102
  ]
103
+
72
104
  ],
73
105
  "shackBounds": [
74
106
  [
@@ -96,6 +128,18 @@
96
128
  [ -1547.49, 1569.51 ],
97
129
  [ -1572.25, 2142.52 ],
98
130
  [ -1020.29, 2169.41 ]
131
+ ],
132
+ [
133
+ [ -1533.59, 2196.56 ],
134
+ [ -1647.51, 2192.82 ],
135
+ [ -1685.52, 2027.15 ],
136
+ [ -1533.23, 1970.22 ]
137
+ ],
138
+ [
139
+ [ -1528.96, 1971.86 ],
140
+ [ -1522.09, 1722.79 ],
141
+ [ -1661.44, 1715.26 ],
142
+ [ -1680.73, 2059.90 ]
99
143
  ]
100
144
  ],
101
145
  "position": [
@@ -156,7 +200,14 @@
156
200
  [ 998.58, 3052.92 ],
157
201
  [ 772.8, 3238.51 ],
158
202
  [ 893.14, 3351.8 ]
203
+ ],
204
+ [
205
+ [ 2126.06, -969.45 ],
206
+ [ 2125.57, -1064.08 ],
207
+ [ 2104.45, -1062.47 ],
208
+ [ 2104.54, -964.39 ]
159
209
  ]
210
+
160
211
  ],
161
212
  "position": [
162
213
  903.74,
@@ -306,6 +357,12 @@
306
357
  [ 2538.46, 2625.97 ],
307
358
  [ 2534.93, 2524.98 ],
308
359
  [ 2679.31, 2521.07 ]
360
+ ],
361
+ [
362
+ [ 2021.53, 2063.35 ],
363
+ [ 2025.37, 1999.75 ],
364
+ [ 1902.34, 1996.83 ],
365
+ [ 1899.32, 2065.72 ]
309
366
  ]
310
367
 
311
368
  ],
@@ -369,8 +426,14 @@
369
426
  [
370
427
  [ 2013.54, -2982.74 ],
371
428
  [ 1966.49, -2661.38 ],
372
- [ 1600.39, -2674.76],
429
+ [ 1600.39, -2674.76 ],
373
430
  [ 1615.91, -2992.76 ]
431
+ ],
432
+ [
433
+ [ 1081.65, -2732.82 ],
434
+ [ 1017.16, -2729.49 ],
435
+ [ 1012.64, -2604.85 ],
436
+ [ 1088.91, -2589.99 ]
374
437
  ]
375
438
  ],
376
439
  "position": [
@@ -411,7 +474,11 @@
411
474
  [ -2966.89990234375, -2243.929931640625 ],
412
475
  [ -3218.27001953125, -2242.27001953125 ],
413
476
  [ -3198.72998046875, -1979.6300048828125 ]
414
- ]
477
+ ],
478
+ [ 2260.40, -1096.56 ],
479
+ [ 2064.92, -1095.95 ],
480
+ [ 2062.23, -930.79 ],
481
+ [ 2266.02, -932.53 ]
415
482
  ],
416
483
  "position": [
417
484
  -3102.32,
@@ -452,4 +519,5 @@
452
519
  1
453
520
  ]
454
521
  }
522
+
455
523
  ]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "h1z1-server",
3
- "version": "0.47.2-3",
3
+ "version": "0.47.2-4",
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",
@@ -40,7 +40,6 @@ export default class SOEClient {
40
40
  waitingQueue: PacketsQueue = new PacketsQueue();
41
41
  protocolName: string = "unset";
42
42
  unAckData: Map<number, number> = new Map();
43
- lostPackets: number[] = [];
44
43
  lastAckSend: wrappedUint16 = new wrappedUint16(-1);
45
44
  inputStream: SOEInputStream;
46
45
  outputStream: SOEOutputStream;
@@ -59,8 +58,6 @@ export default class SOEClient {
59
58
  sendingTimer: NodeJS.Timeout | null = null;
60
59
  private _statsResetTimer: NodeJS.Timer;
61
60
  delayedLogicalPackets: LogicalPacket[] = [];
62
- finishedLoading: boolean = false;
63
- statsResettedRecently: boolean = false;
64
61
  constructor(remote: RemoteInfo, crcSeed: number, cryptoKey: Uint8Array) {
65
62
  this.soeClientId = SOEClient.getClientId(remote);
66
63
  this.address = remote.address;
@@ -74,7 +71,7 @@ export default class SOEClient {
74
71
  } else {
75
72
  this.outputStream = new SOEOutputStream(cryptoKey);
76
73
  }
77
- this._statsResetTimer = setInterval(() => this._resetStats(), 10000);
74
+ this._statsResetTimer = setInterval(() => this._resetStats(), 60000);
78
75
  }
79
76
  static getClientId(remote: RemoteInfo): string {
80
77
  return remote.address + ":" + remote.port;
@@ -83,78 +80,26 @@ export default class SOEClient {
83
80
  // wierd stuff with the new global Symbol used with the using keyword, skipping that headache for now
84
81
  clearInterval(this._statsResetTimer as unknown as number);
85
82
  }
86
- private getDynamicWaitTime(): number {
87
- if (!this.finishedLoading) return 30;
88
-
89
- const ping = this.avgPing || 0;
90
- const minPing = 50;
91
- const maxPing = 250;
92
- const minWait = 4;
93
- const maxWait = 12;
94
-
95
- // Calculate ratio (0–1) and clamp to range
96
- const ratio = Math.max(
97
- 0,
98
- Math.min(1, (ping - minPing) / (maxPing - minPing))
99
- );
100
-
101
- // Calculate wait time in the range 4–12 ms
102
- const waitTime = minWait + ratio * (maxWait - minWait);
103
-
104
- return Math.round(waitTime);
105
- }
106
83
  private _resetStats() {
107
- // Reset network statistics and set a temporary flag
108
84
  this.stats.totalPhysicalPacketSent = 0;
109
85
  this.stats.packetsOutOfOrder = 0;
110
86
  this.stats.packetResend = 0;
111
87
  this.stats.totalLogicalPacketSent = 0;
112
- this.statsResettedRecently = true;
113
- setTimeout(() => {
114
- this.statsResettedRecently = false;
115
- }, 5000);
116
- }
117
-
118
- seqDiff(a: number, b: number): number {
119
- // Difference with uint16 (65536) overflow handling
120
- return (a - b + 65536) % 65536;
121
- }
122
-
123
- getNetworkQuality(): number {
124
- const lastAckSeq = this.outputStream.lastAck.get();
125
- let packetLoss = 0;
126
-
127
- // Count lost packets within the last 100 sequence numbers
128
- for (const sequence of this.lostPackets) {
129
- if (this.seqDiff(lastAckSeq, sequence) <= 100) {
130
- packetLoss++;
131
- }
132
- }
133
-
134
- return packetLoss;
135
88
  }
136
89
  getNetworkStats(): string[] {
137
- const { totalLogicalPacketSent, packetResend, packetsOutOfOrder } =
138
- this.stats;
139
- const totalPackets = totalLogicalPacketSent + packetResend;
140
-
90
+ const {
91
+ totalPhysicalPacketSent: totalPacketSent,
92
+ packetResend,
93
+ packetsOutOfOrder
94
+ } = this.stats;
95
+ const packetLossRate =
96
+ Number((packetResend / totalPacketSent).toFixed(3)) * 100;
141
97
  const packetOutOfOrderRate =
142
- totalPackets > 0
143
- ? Number(((packetsOutOfOrder / totalPackets) * 100).toFixed(1))
144
- : 0;
145
-
146
- const lastAckSeq = this.outputStream.lastAck.get();
147
- let packetLoss = 0;
148
-
149
- for (const sequence of this.lostPackets) {
150
- if (this.seqDiff(lastAckSeq, sequence) <= 100) packetLoss++;
151
- }
152
-
98
+ Number((packetsOutOfOrder / totalPacketSent).toFixed(3)) * 100;
153
99
  return [
154
- `Packet loss rate: ${packetLoss}%`,
155
- `Out-of-order rate: ${packetOutOfOrderRate}%`,
156
- `Avg ping: ${this.avgPing}ms`,
157
- `Wait Time: ${this.getDynamicWaitTime().toFixed(2)}ms`
100
+ `Packet loss rate ${packetLossRate}%`,
101
+ `Packet outOfOrder rate ${packetOutOfOrderRate}%`,
102
+ `Avg ping ${this.avgPing}ms`
158
103
  ];
159
104
  }
160
105
  addPing(ping: number) {
@@ -35,8 +35,8 @@ export class SOEServer extends EventEmitter {
35
35
  private _connectionv6: dgram.Socket;
36
36
  private readonly _crcSeed: number = Math.floor(Math.random() * 255);
37
37
  private _crcLength: crc_length_options = 2;
38
- _waitTimeMs: number = 2;
39
- keepAliveTimeoutTime: number = 30000;
38
+ _waitTimeMs: number = 24;
39
+ keepAliveTimeoutTime: number = 40000;
40
40
  private readonly _maxMultiBufferSize: number;
41
41
  private _resendTimeout: number = 250;
42
42
  private _maxResentTries: number = 24;
@@ -95,25 +95,6 @@ export class SOEServer extends EventEmitter {
95
95
  }
96
96
  }
97
97
 
98
- private getDynamicWaitTime(client: SOEClient): number {
99
- if (!client.finishedLoading) return 30;
100
-
101
- const ping = client.avgPing || 0;
102
- const minPing = 50;
103
- const maxPing = 250;
104
- const minWait = 4;
105
- const maxWait = 12;
106
-
107
- // Calculate ratio (0–1) and clamp to range
108
- const ratio = Math.max(
109
- 0,
110
- Math.min(1, (ping - minPing) / (maxPing - minPing))
111
- );
112
-
113
- // Calculate wait time in the range 4–12 ms
114
- return Math.round(minWait + ratio * (maxWait - minWait));
115
- }
116
-
117
98
  getNetworkStats() {
118
99
  const avgServerLag =
119
100
  this.avgEventLoopLag > 1
@@ -155,50 +136,48 @@ export class SOEServer extends EventEmitter {
155
136
  }
156
137
  }
157
138
 
158
- // Get an array of packets that need to be resent
139
+ // Get an array of packet that we need to resend
159
140
  getResends(client: Client): LogicalPacket[] {
160
141
  const currentTime = Date.now();
161
142
  const resends: LogicalPacket[] = [];
162
- const resendedSequences = new Set<number>();
163
- const lastAck = client.outputStream.lastAck.get();
164
-
165
- // Helper to calculate resend timeout
166
- const getResendTimeout = () =>
167
- Math.min(Math.max(client.avgPing + this._resendTimeout, 100), 400);
168
-
169
- // Track lost packets for this round to avoid duplicates
170
- const lostPacketsSet = new Set(client.lostPackets);
171
-
143
+ const resendedSequences: Set<number> = new Set();
172
144
  for (const [sequence, time] of client.unAckData) {
173
- if (time + getResendTimeout() < currentTime) {
145
+ // if the packet is too old then we resend it
146
+ if (time + this._resendTimeout + client.avgPing < currentTime) {
174
147
  const dataCache = client.outputStream.getDataCache(sequence);
175
148
  if (dataCache) {
176
- if (dataCache.resendCounter >= this._maxResentTries) continue;
149
+ if (dataCache.resendCounter >= this._maxResentTries) {
150
+ continue;
151
+ }
177
152
  dataCache.resendCounter++;
178
153
  client.stats.packetResend++;
179
154
  const logicalPacket = this.createLogicalPacket(
180
155
  dataCache.fragment ? SoeOpcode.DataFragment : SoeOpcode.Data,
181
- { sequence, data: dataCache.data }
156
+ { sequence: sequence, data: dataCache.data }
182
157
  );
183
158
  if (logicalPacket) {
184
159
  resendedSequences.add(sequence);
185
160
  resends.push(logicalPacket);
186
- if (
187
- logicalPacket.sequence !== undefined &&
188
- !lostPacketsSet.has(logicalPacket.sequence)
189
- ) {
190
- client.lostPackets.push(logicalPacket.sequence);
191
- lostPacketsSet.add(logicalPacket.sequence);
192
- }
193
161
  }
162
+ } else {
163
+ // If the data cache is not found it means that the packet has been acked
194
164
  }
195
165
  }
196
166
  }
197
167
 
198
- // Accelerated resends for out-of-order packets
168
+ // check for possible accerated resends
199
169
  for (const sequence of client.outputStream.outOfOrder) {
200
- if (sequence < lastAck) continue;
201
- for (let index = lastAck; index < sequence; index++) {
170
+ if (sequence < client.outputStream.lastAck.get()) {
171
+ continue;
172
+ }
173
+
174
+ // resend every packets between the last ack and the out of order packet
175
+ for (
176
+ let index = client.outputStream.lastAck.get();
177
+ index < sequence;
178
+ index++
179
+ ) {
180
+ // If that sequence has been out of order acked or resended then we don't resend it again
202
181
  if (
203
182
  client.outputStream.outOfOrder.has(index) ||
204
183
  resendedSequences.has(index)
@@ -214,13 +193,16 @@ export class SOEServer extends EventEmitter {
214
193
  if (logicalPacket) {
215
194
  resendedSequences.add(index);
216
195
  resends.push(logicalPacket);
217
- client.stats.packetsOutOfOrder++;
218
196
  }
197
+ } else {
198
+ // well if it's not in the cache then it means that it has been acked
219
199
  }
220
200
  }
221
201
  }
222
202
 
203
+ // clear out of order array
223
204
  client.outputStream.outOfOrder.clear();
205
+
224
206
  return resends;
225
207
  }
226
208
 
@@ -314,10 +296,9 @@ export class SOEServer extends EventEmitter {
314
296
  // activate the sending timer if it's not already activated
315
297
  private _activateSendingTimer(client: SOEClient, additonalTime: number = 0) {
316
298
  if (!client.sendingTimer) {
317
- const waitTime = this.getDynamicWaitTime(client) + additonalTime;
318
299
  client.sendingTimer = setTimeout(() => {
319
300
  this.sendingProcess(client);
320
- }, waitTime);
301
+ }, this._waitTimeMs + additonalTime);
321
302
  }
322
303
  }
323
304
 
@@ -395,6 +376,7 @@ export class SOEServer extends EventEmitter {
395
376
  );
396
377
  break;
397
378
  case "OutOfOrder":
379
+ client.stats.packetsOutOfOrder++;
398
380
  client.outputStream.outOfOrder.add(packet.sequence);
399
381
  //client.outputStream.singleAck(packet.sequence, client.unAckData)
400
382
  break;
@@ -585,17 +567,18 @@ export class SOEServer extends EventEmitter {
585
567
  return appPackets;
586
568
  }
587
569
  private sendingProcess(client: Client) {
588
- // Clear any pending sending timer
570
+ // If there is a pending sending timer then we clear it
589
571
  this._clearSendingTimer(client);
590
- if (client.isDeleted) return;
591
-
572
+ if (client.isDeleted) {
573
+ return;
574
+ }
592
575
  const resends = this.getResends(client);
593
576
  for (const resend of resends) {
594
577
  client.stats.totalLogicalPacketSent++;
595
578
  if (this._canBeBufferedIntoQueue(resend, client.waitingQueue)) {
596
579
  client.waitingQueue.addPacket(resend);
597
580
  } else {
598
- let waitingQueuePacket = this.getClientWaitQueuePacket(
581
+ const waitingQueuePacket = this.getClientWaitQueuePacket(
599
582
  client,
600
583
  client.waitingQueue
601
584
  );
@@ -605,6 +588,7 @@ export class SOEServer extends EventEmitter {
605
588
  if (this._canBeBufferedIntoQueue(resend, client.waitingQueue)) {
606
589
  client.waitingQueue.addPacket(resend);
607
590
  } else {
591
+ // if it still can't be buffered it means that the packet is too big so we send it directly
608
592
  this._sendAndBuildPhysicalPacket(client, resend);
609
593
  }
610
594
  }
@@ -615,48 +599,55 @@ export class SOEServer extends EventEmitter {
615
599
  client.delayedLogicalPackets.push(...appPackets);
616
600
  }
617
601
 
618
- // Process delayed logical packets
619
- while (client.delayedLogicalPackets.length > 0) {
620
- const packet = client.delayedLogicalPackets.shift();
621
- if (!packet) break;
622
- if (this._canBeBufferedIntoQueue(packet, client.waitingQueue)) {
623
- client.waitingQueue.addPacket(packet);
624
- } else {
625
- let waitingQueuePacket = this.getClientWaitQueuePacket(
626
- client,
627
- client.waitingQueue
628
- );
629
- if (waitingQueuePacket) {
630
- this._sendAndBuildPhysicalPacket(client, waitingQueuePacket);
602
+ if (client.delayedLogicalPackets.length > 0) {
603
+ for (
604
+ let index = 0;
605
+ index < client.delayedLogicalPackets.length;
606
+ index++
607
+ ) {
608
+ const packet = client.delayedLogicalPackets.shift();
609
+ if (!packet) {
610
+ break;
631
611
  }
632
612
  if (this._canBeBufferedIntoQueue(packet, client.waitingQueue)) {
633
613
  client.waitingQueue.addPacket(packet);
634
614
  } else {
635
- this._sendAndBuildPhysicalPacket(client, packet);
615
+ // sends the already buffered packets
616
+ const waitingQueuePacket = this.getClientWaitQueuePacket(
617
+ client,
618
+ client.waitingQueue
619
+ );
620
+ if (waitingQueuePacket) {
621
+ this._sendAndBuildPhysicalPacket(client, waitingQueuePacket);
622
+ }
623
+ if (this._canBeBufferedIntoQueue(packet, client.waitingQueue)) {
624
+ client.waitingQueue.addPacket(packet);
625
+ } else {
626
+ // if it still can't be buffered it means that the packet is too big so we send it directly
627
+ this._sendAndBuildPhysicalPacket(client, packet);
628
+ }
636
629
  }
637
630
  }
638
631
  }
639
- // Handle ack packet
640
632
  const ackPacket = this.getAck(client);
641
633
  if (ackPacket) {
642
634
  client.stats.totalLogicalPacketSent++;
643
635
  if (this._canBeBufferedIntoQueue(ackPacket, client.waitingQueue)) {
644
636
  client.waitingQueue.addPacket(ackPacket);
645
637
  } else {
646
- let waitingQueuePacket = this.getClientWaitQueuePacket(
638
+ const waitingQueuePacket = this.getClientWaitQueuePacket(
647
639
  client,
648
640
  client.waitingQueue
649
641
  );
650
642
  if (waitingQueuePacket) {
651
643
  this._sendAndBuildPhysicalPacket(client, waitingQueuePacket);
652
644
  }
653
- // Ack packets are always small enough to fit after clearing
645
+ // no additionnal check needed here because ack packets have a fixed size
654
646
  client.waitingQueue.addPacket(ackPacket);
655
647
  }
656
648
  }
657
-
658
- // Send any remaining packets in the waiting queue
659
- let waitingQueuePacket = this.getClientWaitQueuePacket(
649
+ // if there is still some packets in the queue then we send them
650
+ const waitingQueuePacket = this.getClientWaitQueuePacket(
660
651
  client,
661
652
  client.waitingQueue
662
653
  );
@@ -664,11 +655,6 @@ export class SOEServer extends EventEmitter {
664
655
  this._sendAndBuildPhysicalPacket(client, waitingQueuePacket);
665
656
  }
666
657
 
667
- // Trim lostPackets to last 100 if needed
668
- //if (client.lostPackets.length > 100) {
669
- // client.lostPackets.splice(0, client.lostPackets.length - 100);
670
- //}
671
-
672
658
  if (client.unAckData.size > 0) {
673
659
  this._activateSendingTimer(client);
674
660
  }
@@ -1554,6 +1554,8 @@ export const commands: Array<Command> = [
1554
1554
  execute: (server: ZoneServer2016, client: Client, args: Array<string>) => {
1555
1555
  const direction = (args[0] || "up").toLowerCase(); // Default direction is "up"
1556
1556
  const heightInput = args[1];
1557
+ const playerName = args[2]; // Optional player name
1558
+
1557
1559
  const height = heightInput !== undefined ? parseFloat(heightInput) : 50;
1558
1560
  if (isNaN(height)) {
1559
1561
  server.sendChatText(
@@ -1562,7 +1564,24 @@ export const commands: Array<Command> = [
1562
1564
  );
1563
1565
  return;
1564
1566
  }
1565
- const newPosition = new Float32Array(client.character.state.position);
1567
+
1568
+ // Determine target client
1569
+ let targetClient = client;
1570
+ if (playerName) {
1571
+ const foundClient = server.getClientByNameOrLoginSession(playerName);
1572
+ if (server.playerNotFound(client, playerName, foundClient)) {
1573
+ return;
1574
+ }
1575
+ if (!foundClient || !(foundClient instanceof Client)) {
1576
+ server.sendChatText(client, "Client not found.");
1577
+ return;
1578
+ }
1579
+ targetClient = foundClient;
1580
+ }
1581
+
1582
+ const newPosition = new Float32Array(
1583
+ targetClient.character.state.position
1584
+ );
1566
1585
  switch (direction) {
1567
1586
  case "up":
1568
1587
  newPosition[1] += height;
@@ -1577,11 +1596,20 @@ export const commands: Array<Command> = [
1577
1596
  );
1578
1597
  return;
1579
1598
  }
1580
- server.sendData(client, "ClientUpdate.UpdateLocation", {
1599
+
1600
+ server.sendData(targetClient, "ClientUpdate.UpdateLocation", {
1581
1601
  position: newPosition,
1582
1602
  triggerLoadingScreen: false
1583
1603
  });
1584
- server.sendChatText(client, `Moved ${direction} by ${height}`);
1604
+
1605
+ if (targetClient === client) {
1606
+ server.sendChatText(client, `Moved ${direction} by ${height}`);
1607
+ } else {
1608
+ server.sendChatText(
1609
+ client,
1610
+ `Moved ${targetClient.character.name} ${direction} by ${height}`
1611
+ );
1612
+ }
1585
1613
  }
1586
1614
  },
1587
1615
  {
@@ -324,18 +324,6 @@ export class ZonePacketHandlers {
324
324
  if (!server.hookManager.checkHook("OnClientFinishedLoading", client)) {
325
325
  return;
326
326
  }
327
-
328
- if (!client.firstLoading) {
329
- setTimeout(() => {
330
- const soeClient = server._gatewayServer._soeServer.getSoeClient(
331
- client.soeClientId
332
- );
333
- if (soeClient) {
334
- soeClient.finishedLoading = true;
335
- }
336
- }, 5000);
337
- }
338
-
339
327
  if (client.character.awaitingTeleportLocation) {
340
328
  const awaitingPos = client.character.awaitingTeleportLocation;
341
329
  setTimeout(() => {
@@ -903,59 +891,43 @@ export class ZonePacketHandlers {
903
891
  client: Client,
904
892
  packet: ReceivedPacket<ClientUpdateMonitorTimeDrift>
905
893
  ) {
906
- const soeClient = server._gatewayServer._soeServer.getSoeClient(
907
- client.soeClientId
908
- );
909
- if (!soeClient) return;
910
-
911
- const packetLoss = soeClient.getNetworkQuality();
912
- if (packetLoss == undefined) return;
913
-
914
- const name = client.character.name;
915
-
916
- // Lock weapon if packet loss is too high
894
+ /*const message = packet.data.message || "";
917
895
  if (
918
- !client.isWeaponLock &&
919
- packetLoss >= server.maxPacketLoss &&
920
- !server.isSaving
896
+ packet.data.file ===
897
+ server.fairPlayManager.fairPlayValues?.requiredFile2 &&
898
+ //!client.clientLogs.includes(packet.data.message) && TODO: FIX THIS SINCE IT NEVER WORKED -Meme
899
+ !client.isAdmin
921
900
  ) {
922
- client.isWeaponLock = true;
923
- server.sendAlert(
924
- client,
925
- "Your network quality falls below acceptable standards. Your shots will not register"
926
- );
927
- for (const c of Object.values(server._clients)) {
928
- if (c.isAdmin && c.isDebugMode) {
929
- server.chatManager.sendChatText(
930
- server,
931
- c,
932
- `Fairplay: ${name} network quality falls below acceptable standards`,
933
- false
934
- );
935
- }
936
- }
937
- return;
938
- }
939
-
940
- // Unlock weapon if packet loss has improved
941
- if (client.isWeaponLock && packetLoss < server.maxPacketLoss) {
942
- if (soeClient.statsResettedRecently) return;
943
- client.isWeaponLock = false;
944
- server.sendAlert(
945
- client,
946
- "Your network quality has improved. Your shots will now register properly"
947
- );
948
- for (const c of Object.values(server._clients)) {
949
- if (c.isAdmin && c.isDebugMode) {
950
- server.chatManager.sendChatText(
951
- server,
952
- c,
953
- `Fairplay: ${name} network quality has improved`,
901
+ const obj = { log: message, isSuspicious: false };
902
+ for (let x = 0; x < server.fairPlayManager._suspiciousList.length; x++) {
903
+ if (
904
+ message
905
+ .toLowerCase()
906
+ .includes(server.fairPlayManager._suspiciousList[x].toLowerCase())
907
+ ) {
908
+ obj.isSuspicious = true;
909
+ if (!server._soloMode) {
910
+ logClientActionToMongo(
911
+ server._db?.collection(DB_COLLECTIONS.FAIRPLAY) as Collection,
912
+ client,
913
+ server._worldId,
914
+ {
915
+ type: "suspicious software",
916
+ suspicious: server.fairPlayManager._suspiciousList[x]
917
+ }
918
+ );
919
+ }
920
+ server.sendChatTextToAdmins(
921
+ `FairPlay: kicking ${client.character.name} for using suspicious software - ${server.fairPlayManager._suspiciousList[x]}`,
954
922
  false
955
923
  );
924
+ server.kickPlayer(client);
925
+ break;
956
926
  }
957
927
  }
928
+ client.clientLogs.push(obj);
958
929
  }
930
+ debug(packet);*/
959
931
  }
960
932
  ClientLog(
961
933
  server: ZoneServer2016,