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.
- package/data/2016/dataSources/AllowedFileHashes.json +12 -7
- package/data/2016/zoneData/Z1_POIs.json +70 -2
- package/package.json +1 -1
- package/src/servers/SoeServer/soeclient.ts +12 -67
- package/src/servers/SoeServer/soeserver.ts +63 -77
- package/src/servers/ZoneServer2016/handlers/commands/commands.ts +31 -3
- package/src/servers/ZoneServer2016/zonepackethandlers.ts +30 -58
|
@@ -1025,21 +1025,26 @@
|
|
|
1025
1025
|
},
|
|
1026
1026
|
{
|
|
1027
1027
|
"file_name": "Assets_256.pack",
|
|
1028
|
-
"crc32_hash": "
|
|
1029
|
-
"old_crc32_hash": "47ce5604"
|
|
1028
|
+
"crc32_hash": "396f3599"
|
|
1030
1029
|
},
|
|
1031
1030
|
{
|
|
1032
1031
|
"file_name": "Assets_257.pack",
|
|
1033
|
-
"crc32_hash": "
|
|
1034
|
-
"old_crc32_hash": "bc999532"
|
|
1032
|
+
"crc32_hash": "bc999532"
|
|
1035
1033
|
},
|
|
1036
1034
|
{
|
|
1037
1035
|
"file_name": "Assets_258.pack",
|
|
1038
|
-
"crc32_hash": "
|
|
1039
|
-
"old_crc32_hash": "5b6b2a7f"
|
|
1036
|
+
"crc32_hash": "5b6b2a7f"
|
|
1040
1037
|
},
|
|
1041
1038
|
{
|
|
1042
1039
|
"file_name": "Assets_259.pack",
|
|
1043
|
-
"crc32_hash": "
|
|
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
|
@@ -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(),
|
|
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 {
|
|
138
|
-
|
|
139
|
-
|
|
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
|
-
|
|
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
|
|
155
|
-
`
|
|
156
|
-
`Avg ping
|
|
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 =
|
|
39
|
-
keepAliveTimeoutTime: number =
|
|
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
|
|
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
|
|
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
|
|
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)
|
|
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
|
-
//
|
|
168
|
+
// check for possible accerated resends
|
|
199
169
|
for (const sequence of client.outputStream.outOfOrder) {
|
|
200
|
-
if (sequence < lastAck)
|
|
201
|
-
|
|
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
|
-
},
|
|
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
|
-
//
|
|
570
|
+
// If there is a pending sending timer then we clear it
|
|
589
571
|
this._clearSendingTimer(client);
|
|
590
|
-
if (client.isDeleted)
|
|
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
|
-
|
|
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
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1599
|
+
|
|
1600
|
+
server.sendData(targetClient, "ClientUpdate.UpdateLocation", {
|
|
1581
1601
|
position: newPosition,
|
|
1582
1602
|
triggerLoadingScreen: false
|
|
1583
1603
|
});
|
|
1584
|
-
|
|
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
|
|
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
|
-
|
|
919
|
-
|
|
920
|
-
|
|
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
|
-
|
|
923
|
-
server.
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
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,
|