baltica 0.0.1 → 0.0.3
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/.github/workflows/publish.yml +88 -0
- package/dist/bridge/bridge-options.d.ts +9 -3
- package/dist/bridge/bridge-options.js +1 -0
- package/dist/bridge/bridge-player.d.ts +3 -0
- package/dist/bridge/bridge-player.js +14 -0
- package/dist/bridge/bridge.d.ts +1 -0
- package/dist/bridge/bridge.js +99 -41
- package/dist/client/client-data.js +26 -6
- package/dist/client/client-options.d.ts +5 -0
- package/dist/client/client-options.js +1 -0
- package/dist/client/client.d.ts +4 -3
- package/dist/client/client.js +48 -9
- package/dist/client/types/payload.d.ts +2 -2
- package/dist/client/types/payload.js +2 -1
- package/dist/client/worker/WorkerClient.d.ts +1 -0
- package/dist/client/worker/WorkerClient.js +5 -0
- package/dist/client/worker/worker.js +3 -6
- package/dist/network/auth.d.ts +1 -1
- package/dist/network/auth.js +80 -21
- package/dist/network/beta/auth.d.ts +51 -0
- package/dist/network/beta/auth.js +699 -0
- package/dist/network/level-chunk-packet.js +2 -2
- package/dist/network/packets/add-painting.d.ts +9 -0
- package/dist/network/packets/add-painting.js +41 -0
- package/dist/network/packets/index.d.ts +1 -0
- package/dist/network/packets/index.js +17 -0
- package/dist/server/player.d.ts +5 -2
- package/dist/server/player.js +40 -26
- package/dist/server/server-options.js +2 -2
- package/dist/server/server.d.ts +2 -1
- package/dist/server/server.js +14 -9
- package/dist/tools/bridge.js +36 -3
- package/dist/tools/bridge2.d.ts +1 -0
- package/dist/tools/bridge2.js +105 -0
- package/dist/tools/client.js +52 -26
- package/dist/tools/test.d.ts +1 -0
- package/dist/tools/test.js +8 -0
- package/package.json +8 -4
- package/src/bridge/bridge-options.ts +41 -0
- package/src/bridge/bridge-player.ts +56 -0
- package/src/bridge/bridge.ts +262 -0
- package/src/client/client-data.ts +219 -0
- package/src/client/client-options.ts +100 -0
- package/src/client/client.ts +364 -0
- package/src/client/index.ts +5 -0
- package/src/client/types/index.ts +3 -0
- package/src/client/types/login-data.ts +41 -0
- package/src/client/types/payload.ts +112 -0
- package/src/client/types/skin/Skin.d.ts +23 -0
- package/src/client/types/skin/Skin.json +112 -0
- package/src/client/types/skin/index.ts +1 -0
- package/src/client/worker/WorkerClient.ts +134 -0
- package/src/client/worker/index.ts +2 -0
- package/src/client/worker/worker.ts +132 -0
- package/src/index.ts +4 -0
- package/src/libs/emitter.ts +111 -0
- package/src/libs/index.ts +1 -0
- package/src/network/auth.ts +275 -0
- package/src/network/beta/auth.ts +927 -0
- package/src/network/client-cache-status.ts +28 -0
- package/src/network/index.ts +3 -0
- package/src/network/level-chunk-packet.ts +90 -0
- package/src/network/packet-compressor.ts +101 -0
- package/src/network/packet-encryptor.ts +109 -0
- package/src/network/packets/add-painting.ts +14 -0
- package/src/network/packets/index.ts +1 -0
- package/src/server/index.ts +3 -0
- package/src/server/player.ts +262 -0
- package/src/server/server-options.ts +41 -0
- package/src/server/server.ts +72 -0
- package/src/tools/bridge.ts +96 -0
- package/src/tools/bridge2.ts +151 -0
- package/src/tools/client.ts +98 -0
- package/src/tools/server.ts +8 -0
- package/src/tools/test.ts +8 -0
- package/tsconfig.json +20 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
name: Publish and Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- master
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
lint:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
steps:
|
|
12
|
+
- uses: actions/checkout@v4
|
|
13
|
+
- name: Set up Node.js
|
|
14
|
+
uses: actions/setup-node@v4
|
|
15
|
+
with:
|
|
16
|
+
node-version: '20.x'
|
|
17
|
+
- name: Install dependencies
|
|
18
|
+
run: npm install
|
|
19
|
+
- name: Run lint
|
|
20
|
+
run: npm run lint
|
|
21
|
+
|
|
22
|
+
build:
|
|
23
|
+
needs: [lint]
|
|
24
|
+
permissions:
|
|
25
|
+
id-token: write
|
|
26
|
+
contents: read
|
|
27
|
+
runs-on: ubuntu-latest
|
|
28
|
+
steps:
|
|
29
|
+
- name: Checkout repository
|
|
30
|
+
uses: actions/checkout@v4
|
|
31
|
+
- name: Set up Node.js
|
|
32
|
+
uses: actions/setup-node@v4
|
|
33
|
+
with:
|
|
34
|
+
node-version: '20.x'
|
|
35
|
+
- name: Install dependencies
|
|
36
|
+
run: npm install
|
|
37
|
+
- name: Build
|
|
38
|
+
run: npm run build
|
|
39
|
+
- name: Upload build artifacts
|
|
40
|
+
uses: actions/upload-artifact@v4
|
|
41
|
+
with:
|
|
42
|
+
name: dist
|
|
43
|
+
path: |
|
|
44
|
+
dist/
|
|
45
|
+
package.json
|
|
46
|
+
package-lock.json
|
|
47
|
+
|
|
48
|
+
publish-and-release:
|
|
49
|
+
needs: [build]
|
|
50
|
+
permissions:
|
|
51
|
+
id-token: write
|
|
52
|
+
contents: write
|
|
53
|
+
runs-on: ubuntu-latest
|
|
54
|
+
steps:
|
|
55
|
+
- name: Checkout repository
|
|
56
|
+
uses: actions/checkout@v4
|
|
57
|
+
- name: Download build artifacts
|
|
58
|
+
uses: actions/download-artifact@v4
|
|
59
|
+
with:
|
|
60
|
+
name: dist
|
|
61
|
+
- name: Set up Node.js
|
|
62
|
+
uses: actions/setup-node@v4
|
|
63
|
+
with:
|
|
64
|
+
node-version: '20.x'
|
|
65
|
+
registry-url: 'https://registry.npmjs.org'
|
|
66
|
+
- name: Check if package can be published
|
|
67
|
+
run: npm publish --dry-run --verbose
|
|
68
|
+
- name: Publish package
|
|
69
|
+
id: npm-publish
|
|
70
|
+
run: npm publish --access=public
|
|
71
|
+
env:
|
|
72
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
73
|
+
- name: Get version and Minecraft info
|
|
74
|
+
if: success()
|
|
75
|
+
id: package-info
|
|
76
|
+
run: |
|
|
77
|
+
echo "version=$(node -p "require('./package.json').version")" >> $GITHUB_OUTPUT
|
|
78
|
+
echo "minecraft=$(node -p "require('./package.json').minecraft")" >> $GITHUB_OUTPUT
|
|
79
|
+
- name: Create Release
|
|
80
|
+
if: success()
|
|
81
|
+
env:
|
|
82
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
83
|
+
run: |
|
|
84
|
+
gh release create v${{ steps.package-info.outputs.version }} \
|
|
85
|
+
--title "Release v${{ steps.package-info.outputs.version }} for Minecraft ${{ steps.package-info.outputs.minecraft }}" \
|
|
86
|
+
--notes "Release for Baltica v${{ steps.package-info.outputs.version }}
|
|
87
|
+
Compatible with Minecraft ${{ steps.package-info.outputs.minecraft }}" \
|
|
88
|
+
--target ${{ github.sha }}
|
|
@@ -4,19 +4,25 @@ import type { ClientCacheStatusPacket } from "../network/client-cache-status";
|
|
|
4
4
|
import { type ServerOptions } from "../server/server-options";
|
|
5
5
|
export type BridgePlayerEvents = {
|
|
6
6
|
[K in PacketNames as `clientbound-${K}`]: [
|
|
7
|
-
packet: InstanceType<(typeof Protocol)[K]
|
|
7
|
+
packet: InstanceType<(typeof Protocol)[K]>,
|
|
8
|
+
cancelled: boolean
|
|
8
9
|
];
|
|
9
10
|
} & {
|
|
10
11
|
[K in PacketNames as `serverbound-${K}`]: [
|
|
11
|
-
packet: InstanceType<(typeof Protocol)[K]
|
|
12
|
+
packet: InstanceType<(typeof Protocol)[K]>,
|
|
13
|
+
cancelled: boolean
|
|
12
14
|
];
|
|
13
15
|
} & {
|
|
14
|
-
"serverbound-ClientCacheStatusPacket": [
|
|
16
|
+
"serverbound-ClientCacheStatusPacket": [
|
|
17
|
+
packet: ClientCacheStatusPacket,
|
|
18
|
+
cancelled: boolean
|
|
19
|
+
];
|
|
15
20
|
};
|
|
16
21
|
export type BridgeOptions = ServerOptions & {
|
|
17
22
|
destination: {
|
|
18
23
|
host: string;
|
|
19
24
|
port: number;
|
|
20
25
|
};
|
|
26
|
+
offline: boolean;
|
|
21
27
|
};
|
|
22
28
|
export declare const defaultBridgeOptions: BridgeOptions;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { LevelChunkPacket } from "../network/level-chunk-packet";
|
|
1
2
|
import type { Client } from "../client";
|
|
2
3
|
import { Emitter } from "../libs";
|
|
3
4
|
import type { Player } from "../server";
|
|
@@ -8,6 +9,8 @@ export declare class BridgePlayer extends Emitter<BridgePlayerEvents> {
|
|
|
8
9
|
bridge: Bridge;
|
|
9
10
|
client: Client;
|
|
10
11
|
cacheStatus: boolean;
|
|
12
|
+
postStartGame: boolean;
|
|
13
|
+
levelChunkQueue: LevelChunkPacket[];
|
|
11
14
|
constructor(bridge: Bridge, player: Player);
|
|
12
15
|
prepare(): void;
|
|
13
16
|
getClient(): Client;
|
|
@@ -8,6 +8,20 @@ class BridgePlayer extends libs_1.Emitter {
|
|
|
8
8
|
super();
|
|
9
9
|
this.bridge = bridge;
|
|
10
10
|
this.player = player;
|
|
11
|
+
this.postStartGame = false;
|
|
12
|
+
this.levelChunkQueue = [];
|
|
13
|
+
this.once("clientbound-StartGamePacket", (packet) => {
|
|
14
|
+
this.postStartGame = true;
|
|
15
|
+
for (const chunk of this.levelChunkQueue) {
|
|
16
|
+
const eventName = "clientbound-LevelChunkPacket";
|
|
17
|
+
this.emit(eventName, chunk, false);
|
|
18
|
+
if ("binary" in packet) {
|
|
19
|
+
packet.binary = [];
|
|
20
|
+
}
|
|
21
|
+
const newBuffer = chunk.serialize();
|
|
22
|
+
this.player.send(newBuffer);
|
|
23
|
+
}
|
|
24
|
+
});
|
|
11
25
|
}
|
|
12
26
|
prepare() {
|
|
13
27
|
this.player.connection.on("disconnect", () => {
|
package/dist/bridge/bridge.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ export declare class Bridge extends Server {
|
|
|
10
10
|
options: BridgeOptions;
|
|
11
11
|
private clients;
|
|
12
12
|
private packetClassCache;
|
|
13
|
+
private packetSerializationCache;
|
|
13
14
|
private readonly debugLog;
|
|
14
15
|
constructor(options?: Partial<BridgeOptions>);
|
|
15
16
|
private initializePacketCache;
|
package/dist/bridge/bridge.js
CHANGED
|
@@ -1,19 +1,58 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
2
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
39
|
exports.Bridge = void 0;
|
|
4
40
|
const raknet_1 = require("@sanctumterra/raknet");
|
|
5
41
|
const protocol_1 = require("@serenityjs/protocol");
|
|
42
|
+
const Protocol = __importStar(require("@serenityjs/protocol"));
|
|
6
43
|
const client_1 = require("../client");
|
|
7
44
|
const client_cache_status_1 = require("../network/client-cache-status");
|
|
8
45
|
const level_chunk_packet_1 = require("../network/level-chunk-packet");
|
|
9
46
|
const server_1 = require("../server");
|
|
10
47
|
const bridge_options_1 = require("./bridge-options");
|
|
11
48
|
const bridge_player_1 = require("./bridge-player");
|
|
49
|
+
const disconnect_1 = __importDefault(require("@sanctumterra/raknet/dist/proto/packets/disconnect"));
|
|
12
50
|
class Bridge extends server_1.Server {
|
|
13
51
|
constructor(options = {}) {
|
|
14
52
|
super(options);
|
|
15
53
|
this.clients = new Map();
|
|
16
54
|
this.packetClassCache = new Map();
|
|
55
|
+
this.packetSerializationCache = new Map();
|
|
17
56
|
this.debugLog = false;
|
|
18
57
|
this.options = { ...bridge_options_1.defaultBridgeOptions, ...options };
|
|
19
58
|
this.prepare();
|
|
@@ -22,39 +61,32 @@ class Bridge extends server_1.Server {
|
|
|
22
61
|
initializePacketCache() {
|
|
23
62
|
const CLIENT_CACHE_STATUS_ID = 129;
|
|
24
63
|
this.packetClassCache.set(CLIENT_CACHE_STATUS_ID, client_cache_status_1.ClientCacheStatusPacket);
|
|
25
|
-
|
|
26
|
-
|
|
64
|
+
const levelChunkId = level_chunk_packet_1.LevelChunkPacket.id;
|
|
65
|
+
if (levelChunkId !== undefined) {
|
|
27
66
|
this.packetClassCache.set(levelChunkId, level_chunk_packet_1.LevelChunkPacket);
|
|
28
67
|
}
|
|
29
68
|
}
|
|
30
69
|
getPacketClass(id, PacketClass) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
CachedPacketClass =
|
|
36
|
-
client_cache_status_1.ClientCacheStatusPacket;
|
|
37
|
-
}
|
|
38
|
-
else if (PacketClass && typeof PacketClass === "function") {
|
|
39
|
-
CachedPacketClass = PacketClass;
|
|
40
|
-
}
|
|
41
|
-
if (CachedPacketClass) {
|
|
42
|
-
this.packetClassCache.set(id, CachedPacketClass);
|
|
43
|
-
}
|
|
70
|
+
if (!this.packetClassCache.has(id) &&
|
|
71
|
+
PacketClass &&
|
|
72
|
+
typeof PacketClass === "function") {
|
|
73
|
+
this.packetClassCache.set(id, PacketClass);
|
|
44
74
|
}
|
|
45
|
-
return
|
|
75
|
+
return this.packetClassCache.get(id);
|
|
46
76
|
}
|
|
47
77
|
processPacketCommon(buffer, player, isClientbound, sender) {
|
|
48
|
-
const CLIENT_CACHE_STATUS_ID = 129;
|
|
49
78
|
const id = (0, protocol_1.getPacketId)(buffer);
|
|
50
79
|
const PacketClass = protocol_1.Packets[id];
|
|
51
|
-
|
|
52
|
-
|
|
80
|
+
const packetName = PacketClass?.name ?? "ClientCacheStatusPacket";
|
|
81
|
+
const eventName = `${isClientbound ? "clientbound" : "serverbound"}-${packetName}`;
|
|
82
|
+
if (!PacketClass && id !== 129) {
|
|
53
83
|
sender.send(buffer);
|
|
54
84
|
return;
|
|
55
85
|
}
|
|
56
|
-
|
|
57
|
-
|
|
86
|
+
if (packetName === "LevelChunkPacket" && !player.postStartGame) {
|
|
87
|
+
player.levelChunkQueue.push(new level_chunk_packet_1.LevelChunkPacket(buffer).deserialize());
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
58
90
|
if (!player.hasListeners(eventName) &&
|
|
59
91
|
packetName !== "ClientCacheStatusPacket") {
|
|
60
92
|
sender.send(buffer);
|
|
@@ -69,41 +101,66 @@ class Bridge extends server_1.Server {
|
|
|
69
101
|
if (this.debugLog) {
|
|
70
102
|
raknet_1.Logger.info(`${isClientbound ? "Client -> BridgePlayer" : "BridgePlayer -> Client"} : ${packetName}`);
|
|
71
103
|
}
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
104
|
+
const cacheKey = `${id}-${buffer.toString("hex")}`;
|
|
105
|
+
let newBuffer = this.packetSerializationCache.get(cacheKey);
|
|
106
|
+
if (!newBuffer) {
|
|
107
|
+
const packet = new CachedPacketClass(buffer).deserialize();
|
|
108
|
+
if (packet instanceof client_cache_status_1.ClientCacheStatusPacket) {
|
|
109
|
+
packet.supported = false;
|
|
110
|
+
raknet_1.Logger.warn("Ignoring ClientCacheStatusPacket");
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
const cancelled = false;
|
|
114
|
+
player.emit(eventName, packet, cancelled);
|
|
115
|
+
if (cancelled)
|
|
116
|
+
return;
|
|
117
|
+
if ("binary" in packet) {
|
|
118
|
+
packet.binary = [];
|
|
119
|
+
}
|
|
120
|
+
newBuffer = packet.serialize();
|
|
121
|
+
this.packetSerializationCache.set(cacheKey, newBuffer);
|
|
81
122
|
}
|
|
82
|
-
|
|
83
|
-
sender.send(buffer.equals(newBuffer) ? buffer : newBuffer);
|
|
123
|
+
sender.send(newBuffer);
|
|
84
124
|
}
|
|
85
125
|
catch (e) {
|
|
86
|
-
|
|
126
|
+
raknet_1.Logger.error(`Failed to process ${packetName}`, e);
|
|
87
127
|
sender.send(buffer);
|
|
88
128
|
}
|
|
89
129
|
}
|
|
90
130
|
prepare() {
|
|
91
131
|
this.on("playerConnect", this.onConnect.bind(this));
|
|
92
132
|
this.raknet.options.maxPacketsPerSecond = 20000;
|
|
133
|
+
this.on("disconnect", (data, _player) => {
|
|
134
|
+
const disconnect = new Protocol.DisconnectPacket();
|
|
135
|
+
disconnect.hideDisconnectScreen = true;
|
|
136
|
+
disconnect.message = new Protocol.DisconnectMessage("Disconnected");
|
|
137
|
+
disconnect.reason = Protocol.DisconnectReason.Disconnected;
|
|
138
|
+
const address = _player.connection.getAddress();
|
|
139
|
+
const playerKey = `${address.address}:${address.port}`;
|
|
140
|
+
const player = this.clients.get(playerKey);
|
|
141
|
+
if (player) {
|
|
142
|
+
const rakDisconnect = new disconnect_1.default();
|
|
143
|
+
const frame = new raknet_1.Frame();
|
|
144
|
+
frame.orderChannel = 0;
|
|
145
|
+
frame.payload = rakDisconnect.serialize();
|
|
146
|
+
player.client.raknet.sendFrame(frame, raknet_1.Priority.Immediate);
|
|
147
|
+
player.client.send(disconnect);
|
|
148
|
+
}
|
|
149
|
+
});
|
|
93
150
|
}
|
|
94
151
|
onConnect(player) {
|
|
95
152
|
if (!(player.connection instanceof raknet_1.Connection))
|
|
96
153
|
return;
|
|
97
154
|
const bridgePlayer = new bridge_player_1.BridgePlayer(this, player);
|
|
98
|
-
|
|
155
|
+
const address = player.connection.getAddress();
|
|
156
|
+
const playerKey = `${address.address}:${address.port}`;
|
|
157
|
+
this.clients.set(playerKey, bridgePlayer);
|
|
99
158
|
this.emit("connect", bridgePlayer);
|
|
100
159
|
bridgePlayer.player.once("ClientCacheStatusPacket", (packet) => {
|
|
101
160
|
bridgePlayer.cacheStatus = packet.supported;
|
|
102
161
|
});
|
|
103
|
-
bridgePlayer.player.on("ClientToServerHandshakePacket", (
|
|
104
|
-
console.log("ClientToServerHandshakePacket");
|
|
162
|
+
bridgePlayer.player.on("ClientToServerHandshakePacket", () => {
|
|
105
163
|
this.onLogin(bridgePlayer);
|
|
106
|
-
return;
|
|
107
164
|
});
|
|
108
165
|
}
|
|
109
166
|
onLogin(player) {
|
|
@@ -111,25 +168,26 @@ class Bridge extends server_1.Server {
|
|
|
111
168
|
host: this.options.destination.host,
|
|
112
169
|
port: this.options.destination.port,
|
|
113
170
|
version: "1.21.50",
|
|
114
|
-
offline: false,
|
|
115
171
|
tokensFolder: "tokens",
|
|
116
172
|
viewDistance: 2,
|
|
117
173
|
worker: true,
|
|
174
|
+
offline: this.options.offline,
|
|
118
175
|
});
|
|
119
176
|
player.client = client;
|
|
120
177
|
client.cancelPastLogin = true;
|
|
121
178
|
client.removeAllListeners("ResourcePackStackPacket");
|
|
122
179
|
client.removeAllListeners("ResourcePacksInfoPacket");
|
|
123
180
|
client.removeAllListeners("PlayStatusPacket");
|
|
124
|
-
client.once("ResourcePacksInfoPacket", (
|
|
181
|
+
client.once("ResourcePacksInfoPacket", () => {
|
|
125
182
|
client.send(client_cache_status_1.ClientCacheStatusPacket.create(false));
|
|
126
183
|
});
|
|
127
|
-
player.once("serverbound-ResourcePackClientResponsePacket", (
|
|
184
|
+
player.once("serverbound-ResourcePackClientResponsePacket", () => {
|
|
128
185
|
player.player.send(client_cache_status_1.ClientCacheStatusPacket.create(false));
|
|
129
186
|
});
|
|
130
187
|
client.once("PlayStatusPacket", (packet) => {
|
|
131
|
-
if (packet.status !== protocol_1.PlayStatus.LoginSuccess)
|
|
188
|
+
if (packet.status !== protocol_1.PlayStatus.LoginSuccess) {
|
|
132
189
|
throw new Error("Login failed");
|
|
190
|
+
}
|
|
133
191
|
client.processPacket = (buffer) => {
|
|
134
192
|
this.processPacketCommon(buffer, player, true, player.player);
|
|
135
193
|
};
|
|
@@ -2,10 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ClientData = void 0;
|
|
4
4
|
const node_crypto_1 = require("node:crypto");
|
|
5
|
-
const node_util_1 = require("node:util");
|
|
6
5
|
const raknet_1 = require("@sanctumterra/raknet");
|
|
7
6
|
const protocol_1 = require("@serenityjs/protocol");
|
|
8
|
-
const
|
|
7
|
+
const fast_jwt_1 = require("fast-jwt");
|
|
9
8
|
const uuid_1345_1 = require("uuid-1345");
|
|
10
9
|
const login_data_1 = require("./types/login-data");
|
|
11
10
|
const payload_1 = require("./types/payload");
|
|
@@ -14,7 +13,6 @@ const algorithm = "ES384";
|
|
|
14
13
|
const curve = "secp384r1";
|
|
15
14
|
const pem = { format: "pem", type: "sec1" };
|
|
16
15
|
const der = { format: "der", type: "spki" };
|
|
17
|
-
const signAsync = (0, node_util_1.promisify)(jsonwebtoken_1.sign);
|
|
18
16
|
class ClientData {
|
|
19
17
|
constructor(client) {
|
|
20
18
|
this.client = client;
|
|
@@ -66,7 +64,15 @@ class ClientData {
|
|
|
66
64
|
header: { alg: algorithm, x5u: clientX509, typ: undefined },
|
|
67
65
|
};
|
|
68
66
|
}
|
|
69
|
-
|
|
67
|
+
const privateKeyPem = ecdhKeyPair.privateKey.export({
|
|
68
|
+
format: "pem",
|
|
69
|
+
type: "pkcs8",
|
|
70
|
+
});
|
|
71
|
+
const signer = (0, fast_jwt_1.createSigner)({
|
|
72
|
+
...signOptions,
|
|
73
|
+
key: privateKeyPem,
|
|
74
|
+
});
|
|
75
|
+
return signer(payload);
|
|
70
76
|
}
|
|
71
77
|
async createClientUserChain(privateKey) {
|
|
72
78
|
const { clientX509 } = this.loginData;
|
|
@@ -80,11 +86,24 @@ class ClientData {
|
|
|
80
86
|
PlayFabId: ClientData.nextUUID().replace(/-/g, "").slice(0, 16),
|
|
81
87
|
SelfSignedId: ClientData.nextUUID(),
|
|
82
88
|
};
|
|
83
|
-
|
|
89
|
+
if (privateKey.asymmetricKeyDetails?.namedCurve === "p384")
|
|
90
|
+
privateKey.asymmetricKeyDetails.namedCurve = "secp384r1";
|
|
91
|
+
// Deno sucks.
|
|
92
|
+
// Logger.info('Private Key details:', {
|
|
93
|
+
// type: privateKey.type,
|
|
94
|
+
// curve: privateKey.asymmetricKeyDetails?.namedCurve
|
|
95
|
+
// });
|
|
96
|
+
const privateKeyPem = privateKey.export({
|
|
97
|
+
format: "pem",
|
|
98
|
+
type: "pkcs8",
|
|
99
|
+
});
|
|
100
|
+
const signer = (0, fast_jwt_1.createSigner)({
|
|
84
101
|
algorithm,
|
|
85
102
|
header: { alg: algorithm, x5u: clientX509, typ: undefined },
|
|
86
103
|
noTimestamp: true,
|
|
104
|
+
key: privateKeyPem,
|
|
87
105
|
});
|
|
106
|
+
return signer(payload);
|
|
88
107
|
}
|
|
89
108
|
createSharedSecret(privateKey, publicKey) {
|
|
90
109
|
this.validateKeys(privateKey, publicKey);
|
|
@@ -93,7 +112,8 @@ class ClientData {
|
|
|
93
112
|
throw new Error("Invalid private key format. Named curve is missing.");
|
|
94
113
|
}
|
|
95
114
|
try {
|
|
96
|
-
const
|
|
115
|
+
const normalizedCurve = curve === "p384" ? "secp384r1" : curve;
|
|
116
|
+
const ecdh = (0, node_crypto_1.createECDH)(normalizedCurve);
|
|
97
117
|
const privateKeyJwk = privateKey.export({ format: "jwk" });
|
|
98
118
|
const publicKeyJwk = publicKey.export({ format: "jwk" });
|
|
99
119
|
if (!privateKeyJwk.d || !publicKeyJwk.x || !publicKeyJwk.y) {
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { CompressionMethod, InputMode } from "@serenityjs/protocol";
|
|
2
2
|
import type * as Protocol from "@serenityjs/protocol";
|
|
3
3
|
import type { ClientCacheStatusPacket } from "../network/client-cache-status";
|
|
4
|
+
import type { Advertisement } from "@sanctumterra/raknet";
|
|
5
|
+
import type { AddPaintingPacket } from "../network/packets";
|
|
4
6
|
export declare enum ProtocolList {
|
|
5
7
|
"1.21.50" = 766
|
|
6
8
|
}
|
|
@@ -42,6 +44,7 @@ type ClientOptions = {
|
|
|
42
44
|
offline: boolean;
|
|
43
45
|
worker: boolean;
|
|
44
46
|
loginOptions: LoginPacketOptions;
|
|
47
|
+
betaAuth: boolean;
|
|
45
48
|
};
|
|
46
49
|
declare const defaultClientOptions: ClientOptions;
|
|
47
50
|
type PacketNames = {
|
|
@@ -52,7 +55,9 @@ type ClientEvents = {
|
|
|
52
55
|
} & {
|
|
53
56
|
session: [];
|
|
54
57
|
ClientCacheStatus: [packet: ClientCacheStatusPacket];
|
|
58
|
+
AddPaintingPacket: [packet: AddPaintingPacket];
|
|
55
59
|
} & {
|
|
56
60
|
packet: [packet: InstanceType<(typeof Protocol)[PacketNames]>];
|
|
61
|
+
connect: [packet: Advertisement];
|
|
57
62
|
};
|
|
58
63
|
export { type ClientOptions, defaultClientOptions, type ClientEvents, type PacketNames, };
|
package/dist/client/client.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Client as RaknetClient } from "@sanctumterra/raknet";
|
|
2
|
-
import { DataPacket } from "@serenityjs/protocol";
|
|
1
|
+
import { type Advertisement, Client as RaknetClient } from "@sanctumterra/raknet";
|
|
2
|
+
import { DataPacket, type StartGamePacket } from "@serenityjs/protocol";
|
|
3
3
|
import { Emitter } from "../libs/emitter";
|
|
4
4
|
import { type Profile } from "../network";
|
|
5
5
|
import { PacketEncryptor } from "../network/packet-encryptor";
|
|
@@ -25,7 +25,7 @@ declare class Client extends Emitter<ClientEvents> {
|
|
|
25
25
|
runtimeEntityId: bigint;
|
|
26
26
|
cancelPastLogin: boolean;
|
|
27
27
|
constructor(options: Partial<ClientOptions>);
|
|
28
|
-
connect(): Promise<
|
|
28
|
+
connect(): Promise<[Advertisement, StartGamePacket]>;
|
|
29
29
|
private handleStartGamePacket;
|
|
30
30
|
private handleSetLocalPlayerAsInitializedPacket;
|
|
31
31
|
private handleEncapsulated;
|
|
@@ -39,6 +39,7 @@ declare class Client extends Emitter<ClientEvents> {
|
|
|
39
39
|
private handlePlayStatusPacket;
|
|
40
40
|
private handleResourcePacksInfoPacket;
|
|
41
41
|
startEncryption(iv: Buffer): void;
|
|
42
|
+
disconnect(): void;
|
|
42
43
|
sendMessage(text: string): void;
|
|
43
44
|
}
|
|
44
45
|
export { Client };
|
package/dist/client/client.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.Client = void 0;
|
|
4
7
|
const node_crypto_1 = require("node:crypto");
|
|
@@ -13,6 +16,8 @@ const packet_encryptor_1 = require("../network/packet-encryptor");
|
|
|
13
16
|
const client_data_1 = require("./client-data");
|
|
14
17
|
const client_options_1 = require("./client-options");
|
|
15
18
|
const worker_1 = require("./worker");
|
|
19
|
+
const packets_1 = require("../network/packets");
|
|
20
|
+
const disconnect_1 = __importDefault(require("@sanctumterra/raknet/dist/proto/packets/disconnect"));
|
|
16
21
|
class Client extends emitter_1.Emitter {
|
|
17
22
|
constructor(options) {
|
|
18
23
|
super();
|
|
@@ -37,6 +42,10 @@ class Client extends emitter_1.Emitter {
|
|
|
37
42
|
this.options.offline ? (0, network_1.createOfflineSession)(this) : (0, network_1.authenticate)(this);
|
|
38
43
|
}
|
|
39
44
|
async connect() {
|
|
45
|
+
while (!this.sessionReady) {
|
|
46
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
47
|
+
}
|
|
48
|
+
this.status = raknet_1.Status.Connecting;
|
|
40
49
|
this.packetCompressor = new network_1.PacketCompressor(this);
|
|
41
50
|
this.listen();
|
|
42
51
|
const advertisement = await this.raknet.connect();
|
|
@@ -50,6 +59,7 @@ class Client extends emitter_1.Emitter {
|
|
|
50
59
|
this.startGamePacket &&
|
|
51
60
|
this.sessionReady) {
|
|
52
61
|
clearInterval(interval);
|
|
62
|
+
this.emit("connect", advertisement);
|
|
53
63
|
resolve([advertisement, this.startGamePacket]);
|
|
54
64
|
}
|
|
55
65
|
}, 50);
|
|
@@ -63,7 +73,7 @@ class Client extends emitter_1.Emitter {
|
|
|
63
73
|
const radius = new protocol_1.RequestChunkRadiusPacket();
|
|
64
74
|
radius.radius = this.options.viewDistance;
|
|
65
75
|
radius.maxRadius = this.options.viewDistance;
|
|
66
|
-
this.
|
|
76
|
+
this.send(radius);
|
|
67
77
|
}
|
|
68
78
|
handleSetLocalPlayerAsInitializedPacket(packet) {
|
|
69
79
|
this.status = raknet_1.Status.Connected;
|
|
@@ -81,6 +91,8 @@ class Client extends emitter_1.Emitter {
|
|
|
81
91
|
}
|
|
82
92
|
sendPacket(packet, priority = raknet_1.Priority.Normal) {
|
|
83
93
|
try {
|
|
94
|
+
if (this.status === raknet_1.Status.Disconnected)
|
|
95
|
+
return;
|
|
84
96
|
const serialized = packet instanceof protocol_1.DataPacket ? packet.serialize() : packet;
|
|
85
97
|
const compressed = this.packetCompressor.compress(serialized, this.options.compressionMethod);
|
|
86
98
|
const frame = new raknet_1.Frame();
|
|
@@ -102,20 +114,28 @@ class Client extends emitter_1.Emitter {
|
|
|
102
114
|
/** Already decompressed packets */
|
|
103
115
|
processPacket(buffer) {
|
|
104
116
|
const id = (0, protocol_1.getPacketId)(buffer);
|
|
105
|
-
if (!protocol_1.Packets[id])
|
|
106
|
-
return raknet_1.Logger.warn(`Unknown Game packet ${id}`);
|
|
107
117
|
let PacketClass = protocol_1.Packets[id];
|
|
108
118
|
try {
|
|
109
119
|
if (id === protocol_1.Packet.LevelChunk) {
|
|
110
120
|
PacketClass = level_chunk_packet_1.LevelChunkPacket;
|
|
111
121
|
}
|
|
112
|
-
if (
|
|
113
|
-
|
|
114
|
-
this.emit(PacketClass.name, packet);
|
|
122
|
+
if (id === 22) {
|
|
123
|
+
PacketClass = packets_1.AddPaintingPacket;
|
|
115
124
|
}
|
|
116
|
-
if (
|
|
117
|
-
|
|
118
|
-
|
|
125
|
+
if (!protocol_1.Packets && !protocol_1.Packets[id])
|
|
126
|
+
return raknet_1.Logger.warn(`Unknown Game packet ${id}`);
|
|
127
|
+
// console.log('X - ', PacketClass.name, readPacket(this.options.version, buffer));
|
|
128
|
+
let deserializedPacket;
|
|
129
|
+
const hasSpecificListener = this.hasListeners(PacketClass.name);
|
|
130
|
+
const hasGenericListener = this.hasListeners("packet");
|
|
131
|
+
if (hasSpecificListener || hasGenericListener) {
|
|
132
|
+
deserializedPacket = new PacketClass(buffer).deserialize();
|
|
133
|
+
if (hasSpecificListener) {
|
|
134
|
+
this.emit(PacketClass.name, deserializedPacket);
|
|
135
|
+
}
|
|
136
|
+
if (hasGenericListener) {
|
|
137
|
+
this.emit("packet", deserializedPacket);
|
|
138
|
+
}
|
|
119
139
|
}
|
|
120
140
|
}
|
|
121
141
|
catch (error) {
|
|
@@ -200,6 +220,25 @@ class Client extends emitter_1.Emitter {
|
|
|
200
220
|
this.packetEncryptor = new packet_encryptor_1.PacketEncryptor(this, iv);
|
|
201
221
|
this._encryptionEnabled = true;
|
|
202
222
|
}
|
|
223
|
+
disconnect() {
|
|
224
|
+
const rakDisconnect = new disconnect_1.default();
|
|
225
|
+
const frame = new raknet_1.Frame();
|
|
226
|
+
frame.orderChannel = 0;
|
|
227
|
+
frame.payload = rakDisconnect.serialize();
|
|
228
|
+
this.raknet.sendFrame(frame, raknet_1.Priority.Immediate);
|
|
229
|
+
this.status = raknet_1.Status.Disconnected;
|
|
230
|
+
this.removeAllListeners();
|
|
231
|
+
this.raknet.cleanup();
|
|
232
|
+
if (this.raknet instanceof raknet_1.Client) {
|
|
233
|
+
this.raknet.removeAll();
|
|
234
|
+
this.raknet.removeAllAfter();
|
|
235
|
+
this.raknet.removeAllBefore();
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
this.raknet.dispose();
|
|
239
|
+
}
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
203
242
|
sendMessage(text) {
|
|
204
243
|
const textPacket = new protocol_1.TextPacket();
|
|
205
244
|
textPacket.filtered = "";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { Player } from "
|
|
1
|
+
import type { Player } from "../../server/player";
|
|
2
2
|
import type { Client } from "../client";
|
|
3
|
-
import type { AnimatedImageData, PersonaPieces, PieceTintColors } from "./skin";
|
|
3
|
+
import type { AnimatedImageData, PersonaPieces, PieceTintColors } from "./skin/Skin.d";
|
|
4
4
|
export type Payload = {
|
|
5
5
|
AnimatedImageData: AnimatedImageData[];
|
|
6
6
|
ArmSize: string;
|
|
@@ -87,5 +87,6 @@ const createDefaultPayload = (client) => {
|
|
|
87
87
|
};
|
|
88
88
|
exports.createDefaultPayload = createDefaultPayload;
|
|
89
89
|
const getRandomId = () => {
|
|
90
|
-
return Math.floor(Math.random() * Date.now() * Math.random() * 1000000) ^
|
|
90
|
+
return (Math.floor(Math.random() * Date.now() * Math.random() * 1000000) ^
|
|
91
|
+
Date.now());
|
|
91
92
|
};
|