Skip to content

Commit

Permalink
Merge branch 'release/0.40.4'
Browse files Browse the repository at this point in the history
  • Loading branch information
QuentinGruber committed Nov 22, 2024
2 parents 991e8be + b120389 commit bd86eb6
Show file tree
Hide file tree
Showing 12 changed files with 268,383 additions and 16,845 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/dev-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [ 22.x]
node-version: [ 22.x,23.x]
steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
Expand All @@ -56,7 +56,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [22.9.0, 22.x]
node-version: [22.9.0, 22.x, 23.x]
steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
Expand All @@ -72,7 +72,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [22.9.0, 22.x]
node-version: [22.9.0, 22.x, 23.x]
steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
Expand All @@ -86,7 +86,7 @@ jobs:
runs-on: windows-latest
strategy:
matrix:
node-version: [22.9.0, 22.x]
node-version: [22.9.0, 22.x, 23.x]
steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
Expand Down
1 change: 1 addition & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@
"skipFiles": [
"<node_internals>/**"
],
"runtimeArgs": ["--no-warnings", "--experimental-require-module"],
"program": "${workspaceFolder}/out/servers/ZoneServer2016/zoneserver.js",
"outFiles": [
"${workspaceFolder}/out/**/*.js"
Expand Down
285,043 changes: 268,278 additions & 16,765 deletions data/2016/zoneData/Z1_lootableProps.json

Large diffs are not rendered by default.

15 changes: 8 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
{
"name": "h1z1-server",
"version": "0.40.3",
"version": "0.40.4",
"description": "Library for emulating h1z1 servers",
"author": "Quentin Gruber <[email protected]> (http://github.com/quentingruber)",
"license": "GPL-3.0-only",
"main": "h1z1-server.js",
"engines": {
"node": ">=0.17.0 <23"
"node": ">=0.22.0 <24"
},
"bin": {
"h1z1-server-demo": "scripts/h1z1-server-demo.js",
Expand All @@ -18,7 +18,7 @@
"@types/ws": "8.5.12",
"debug": "4.3.6",
"h1emu-ai": "^0.0.8",
"h1emu-core": "1.2.8",
"h1emu-core": "1.3.0",
"h1z1-dataschema": "1.9.0",
"js-yaml": "4.1.0",
"mongodb": "6.8.0",
Expand Down
54 changes: 41 additions & 13 deletions src/servers/SoeServer/soeoutputstream.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { EventEmitter } from "node:events";
import { RC4 } from "h1emu-core";
import { wrappedUint16 } from "../../utils/utils";
import { dataCache, dataCacheMap } from "types/soeserver";
import { MAX_UINT16 } from "../../utils/constants";

const debug = require("debug")("SOEOutputStream");

Expand Down Expand Up @@ -45,7 +46,8 @@ export class SOEOutputStream extends EventEmitter {
this._cache[sequence] = {
data: data,
fragment: isFragment,
sequence: sequence
sequence: sequence,
resendCounter: 0
};
}

Expand Down Expand Up @@ -151,27 +153,53 @@ export class SOEOutputStream extends EventEmitter {
}

ack(sequence: number, unAckData: Map<number, number>): void {
// delete all data / timers cached for the sequences behind the given ack sequence
while (this.lastAck.get() !== wrappedUint16.wrap(sequence)) {
const lastAck = this.lastAck.get();
this.removeFromCache(lastAck);
unAckData.delete(lastAck);
this.lastAck.increment();
// So we clear the last ack at the end of the loop without incrementing it
if (this.lastAck.get() === wrappedUint16.wrap(sequence)) {
const lastAck = this.lastAck.get();
this.removeFromCache(lastAck);
unAckData.delete(lastAck);
const wrappedSequence = wrappedUint16.wrap(sequence);
const wrapThreshold = MAX_UINT16 / 2;

// Determine if wrappedSequence is ahead of lastAck, including wrap-around handling
const isSequenceAhead =
wrappedSequence > this.lastAck.get() ||
(wrappedSequence < this.lastAck.get() &&
this.lastAck.get() - wrappedSequence > wrapThreshold);

// If the sequence is ahead, delete all cached data/timers up to the given ack sequence
if (isSequenceAhead) {
while (this.lastAck.get() !== wrappedSequence) {
this.removeFromCache(this.lastAck.get());
unAckData.delete(this.lastAck.get());
this.lastAck.increment();
if (this.lastAck.get() === wrappedSequence) {
this.removeFromCache(this.lastAck.get());
unAckData.delete(this.lastAck.get());
}
}
} else {
// If an out-of-order ack is received, delete that specific entry if it exists
if (unAckData.has(wrappedSequence)) {
this.removeFromCache(wrappedSequence);
unAckData.delete(wrappedSequence);
}
}
// When we receive an ack, we can emit the event Reliable so the application can send more data

// Emit event to signal that acknowledged data can be removed and new data can be sent
this.emit(SOEOutputChannels.Reliable);
}

/*singleAck(sequence: number, unAckData: Map<number, number>): void {
const wrappedSequence = wrappedUint16.wrap(sequence);
this.removeFromCache(wrappedSequence);
unAckData.delete(wrappedSequence);
this.emit(SOEOutputChannels.Reliable);
}*/

getDataCache(sequence: number): dataCache {
return this._cache[sequence];
}

incrementDataCacheResend(sequence: number) {
this._cache[sequence].resendCounter++;
}

isUsingEncryption(): boolean {
return this._useEncryption;
}
Expand Down
83 changes: 41 additions & 42 deletions src/servers/SoeServer/soeserver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ export class SOEServer extends EventEmitter {
_waitTimeMs: number = 24;
keepAliveTimeoutTime: number = 40000;
private readonly _maxMultiBufferSize: number;
private _resendTimeout: number = 400;
private _resendTimeout: number = 250;
private _maxResentTries: number = 5;
_allowRawDataReception: boolean = false;
private _packetResetInterval: NodeJS.Timeout | undefined;
avgEventLoopLag: number = 0;
Expand Down Expand Up @@ -142,14 +143,14 @@ export class SOEServer extends EventEmitter {
const resendedSequences: Set<number> = new Set();
for (const [sequence, time] of client.unAckData) {
// if the packet is too old then we resend it
if (
time + this._resendTimeout + this._waitTimeMs + client.avgPing <
currentTime
) {
if (time + this._resendTimeout < currentTime) {
const dataCache = client.outputStream.getDataCache(sequence);
if (dataCache) {
if (dataCache.resendCounter >= this._maxResentTries) {
continue;
}
dataCache.resendCounter++;
client.stats.packetResend++;

const logicalPacket = this.createLogicalPacket(
dataCache.fragment ? SoeOpcode.DataFragment : SoeOpcode.Data,
{ sequence: sequence, data: dataCache.data }
Expand All @@ -163,14 +164,6 @@ export class SOEServer extends EventEmitter {
}
}
}
// if a packet is lost due to timeout then we increase the ping
// this will auto-fix when the connection goes well again
for (let index = 0; index < resends.length; index++) {
client.avgPing += 100;
if (client.avgPing > 5000) {
client.avgPing = 5000;
}
}

// check for possible accerated resends
for (const sequence of client.outputStream.outOfOrder) {
Expand All @@ -193,8 +186,6 @@ export class SOEServer extends EventEmitter {
}
const dataCache = client.outputStream.getDataCache(index);
if (dataCache) {
client.stats.packetResend++;

const logicalPacket = this.createLogicalPacket(
dataCache.fragment ? SoeOpcode.DataFragment : SoeOpcode.Data,
{ sequence: index, data: dataCache.data }
Expand Down Expand Up @@ -387,14 +378,23 @@ export class SOEServer extends EventEmitter {
case "OutOfOrder":
client.stats.packetsOutOfOrder++;
client.outputStream.outOfOrder.add(packet.sequence);
client.outputStream.removeFromCache(packet.sequence);
client.unAckData.delete(packet.sequence);
//client.outputStream.singleAck(packet.sequence, client.unAckData)
break;
case "Ack":
const mostWaitedPacketTime = client.unAckData.get(packet.sequence);
if (mostWaitedPacketTime) {
const currentLag = this.currentEventLoopLag || 0;
client.addPing(Date.now() - mostWaitedPacketTime - currentLag);
const dataCache = client.outputStream.getDataCache(packet.sequence);
if (dataCache) {
client.addPing(
Date.now() -
mostWaitedPacketTime -
currentLag +
this._resendTimeout *
client.outputStream.getDataCache(packet.sequence)
.resendCounter
);
}
}
client.outputStream.ack(packet.sequence, client.unAckData);
break;
Expand Down Expand Up @@ -572,7 +572,28 @@ export class SOEServer extends EventEmitter {
if (client.isDeleted) {
return;
}

const resends = this.getResends(client);
for (const resend of resends) {
client.stats.totalLogicalPacketSent++;
if (this._canBeBufferedIntoQueue(resend, client.waitingQueue)) {
client.waitingQueue.addPacket(resend);
} else {
const waitingQueuePacket = this.getClientWaitQueuePacket(
client,
client.waitingQueue
);
if (waitingQueuePacket) {
this._sendAndBuildPhysicalPacket(client, waitingQueuePacket);
}
if (this._canBeBufferedIntoQueue(resend, client.waitingQueue)) {
client.waitingQueue.addPacket(resend);
} else {
// if it still can't be buffered it means that the packet is too big so we send it directly
this._sendAndBuildPhysicalPacket(client, resend);
}
}
client.unAckData.delete(resend.sequence as number);
}
if (client.outputStream.isReliableAvailable()) {
const appPackets = this.getAvailableAppPackets(client);
client.delayedLogicalPackets.push(...appPackets);
Expand Down Expand Up @@ -625,28 +646,6 @@ export class SOEServer extends EventEmitter {
client.waitingQueue.addPacket(ackPacket);
}
}
const resends = this.getResends(client);
for (const resend of resends) {
client.stats.totalLogicalPacketSent++;
if (this._canBeBufferedIntoQueue(resend, client.waitingQueue)) {
client.waitingQueue.addPacket(resend);
} else {
const waitingQueuePacket = this.getClientWaitQueuePacket(
client,
client.waitingQueue
);
if (waitingQueuePacket) {
this._sendAndBuildPhysicalPacket(client, waitingQueuePacket);
}
if (this._canBeBufferedIntoQueue(resend, client.waitingQueue)) {
client.waitingQueue.addPacket(resend);
} else {
// if it still can't be buffered it means that the packet is too big so we send it directly
this._sendAndBuildPhysicalPacket(client, resend);
}
}
client.unAckData.delete(resend.sequence as number);
}
// if there is still some packets in the queue then we send them
const waitingQueuePacket = this.getClientWaitQueuePacket(
client,
Expand Down
2 changes: 1 addition & 1 deletion src/servers/ZoneServer2016/entities/character.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1770,7 +1770,7 @@ export class Character2016 extends BaseFullCharacter {
weaponDmgModifierShotgun = 10,
weaponDmgModifierSniper = 1,
headshotDmgMultiplierDefault = 4,
headshotDmgMultiplierShotgun = 1,
headshotDmgMultiplierShotgun = 2,
headshotDmgMultiplierSniper = 6;

switch (weaponDefinitionId) {
Expand Down
6 changes: 0 additions & 6 deletions src/servers/ZoneServer2016/handlers/commands/dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1041,12 +1041,6 @@ const dev: any = {
unknownBoolean1: Boolean(args[3])
});
},
poi: function (server: ZoneServer2016, client: Client, args: Array<string>) {
server.sendData(client, "POIChangeMessage", {
messageStringId: Number(args[1]) || 0,
id: Number(args[1]) || 0
});
},

vehicleaccess: function (
server: ZoneServer2016,
Expand Down
1 change: 1 addition & 0 deletions src/servers/ZoneServer2016/zoneserver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -956,6 +956,7 @@ export class ZoneServer2016 extends EventEmitter {
debug(`Receive Data ${[packet.name]}`);
}
if (packet.flag === GatewayChannels.UpdatePosition) {
if (packet.data.flags === 513) return;
const movingCharacter = this._characters[client.character.characterId];
if (movingCharacter) {
this.sendRawToAllOthersWithSpawnedCharacter(
Expand Down
1 change: 1 addition & 0 deletions src/types/soeserver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export type dataCache = {
data: Uint8Array;
fragment: boolean;
sequence: number;
resendCounter: number;
}
export type dataCacheMap = {
[sequence: number]: dataCache;
Expand Down
Loading

0 comments on commit bd86eb6

Please sign in to comment.