A protocol library for Minecraft Java Edition in pure JavaScript
npm install packet-events-jsbash
npm install packet-events-js
`
Or clone the repository:
`bash
git clone https://github.com/FrannnnDev/PacketEvents-JS.git
cd PacketEvents-JS
`
Basic Usage
$3
`javascript
import { MinecraftClient, ProtocolVersion } from 'packet-events-js';
const client = new MinecraftClient({
host: 'mc.hypixel.net',
port: 25565,
version: ProtocolVersion.V1_21_11
});
const status = await client.ping();
console.log(Players: ${status.players.online}/${status.players.max});
console.log(Latency: ${status.latency}ms);
`
$3
`javascript
import {
MinecraftClient,
ProtocolVersion,
Logger,
LogLevel,
KeepAliveClientboundPacket,
KeepAliveServerboundPacket
} from 'packet-events-js';
Logger.setGlobalLevel(LogLevel.DEBUG);
const client = new MinecraftClient({
host: 'localhost',
port: 25565,
version: ProtocolVersion.V1_21_11,
username: 'MyBot',
offline: true
});
client.onPacket(KeepAliveClientboundPacket, async (event) => {
const response = new KeepAliveServerboundPacket();
response.keepAliveId = event.packet.keepAliveId;
await client.sendPacket(response);
});
await client.login();
console.log(Connected as ${client.playerName});
`
$3
`javascript
import { MinecraftEncryption, EncryptedConnection } from 'packet-events-js';
const keyPair = MinecraftEncryption.generateKeyPair();
console.log('Public Key:', keyPair.publicKey);
console.log('Private Key:', keyPair.privateKey);
const verifyToken = MinecraftEncryption.generateVerifyToken();
const sharedSecret = MinecraftEncryption.generateSharedSecret();
const encrypted = MinecraftEncryption.encryptRSA(keyPair.publicKey, sharedSecret);
const decrypted = MinecraftEncryption.decryptRSA(keyPair.privateKey, encrypted);
const aesEncrypted = MinecraftEncryption.encryptAES(sharedSecret, Buffer.from('Hello'));
const aesDecrypted = MinecraftEncryption.decryptAES(sharedSecret, aesEncrypted);
const serverHash = MinecraftEncryption.computeServerIdHash('', sharedSecret, keyPair.publicKey);
`
$3
`javascript
import { AuthHandler, ClientAuthHandler, AuthMode } from 'packet-events-js';
const serverAuth = new AuthHandler({ mode: AuthMode.ONLINE });
serverAuth.initialize();
const publicKey = serverAuth.getPublicKey();
const verifyToken = serverAuth.generateVerifyToken();
const offlineUUID = serverAuth.generateOfflineUUID('PlayerName');
const clientAuth = new ClientAuthHandler({
accessToken: 'token',
selectedProfile: { id: 'uuid', name: 'Name' }
});
`
$3
`javascript
import { BungeeCordForwarding, UUID } from 'packet-events-js';
const uuid = UUID.randomUUID();
const handshakeAddress = BungeeCordForwarding.create(
'play.example.com',
'192.168.1.100',
uuid,
[{ name: 'textures', value: '...' }]
);
const result = BungeeCordForwarding.parse(handshakeAddress);
if (result.success) {
console.log(Client IP: ${result.clientIP});
console.log(UUID: ${result.uuid.toString()});
}
`
$3
`javascript
import { VelocityForwarding, AuthHandler, AuthMode, UUID } from 'packet-events-js';
const auth = new AuthHandler({
mode: AuthMode.VELOCITY,
velocitySecret: 'your-secret-key'
});
const result = auth.handleVelocityForwarding(forwardingData);
if (result.success) {
console.log(Player: ${result.username});
console.log(UUID: ${result.uuid.toString()});
console.log(IP: ${result.clientIP});
}
const uuid = UUID.randomUUID();
const data = VelocityForwarding.create(
'your-secret-key',
'10.0.0.1',
uuid,
'PlayerName',
[{ name: 'textures', value: '...', signature: '...' }]
);
`
$3
`javascript
import { EventPriority } from 'packet-events-js';
client.packetManager.on('packetSend', (event) => {
if (event.packet.packetName === 'SetPlayerPosition') {
console.log(Moving to: ${event.packet.x}, ${event.packet.y}, ${event.packet.z});
if (event.packet.y < 0) {
event.cancel();
}
}
}, { priority: EventPriority.HIGH });
`
$3
`javascript
import {
Packet,
defaultRegistry,
ConnectionState,
PacketDirection
} from 'packet-events-js';
class MyCustomPacket extends Packet {
static get packetId() { return 0x50; }
static get packetName() { return 'MyPacket'; }
constructor() {
super();
this.myField = 0;
}
read(buffer, context) {
this.myField = buffer.readVarInt();
}
write(buffer, context) {
buffer.writeVarInt(this.myField);
}
}
defaultRegistry.register({
packetClass: MyCustomPacket,
state: ConnectionState.PLAY,
direction: PacketDirection.CLIENTBOUND,
packetId: 0x50
});
`
Advanced Features
$3
Record, export, import, and replay complete packet streams:
`javascript
import { PacketRecorder, PacketReplayer, PacketRecord } from 'packet-events-js';
const recorder = new PacketRecorder({
includeRaw: true,
maxRecords: 10000,
filter: (packet) => true
});
recorder.start();
client.packetManager.on('packetReceive', (event) => {
recorder.record(event.packet, 'CLIENTBOUND', 'PLAY', event.rawData);
});
const stats = recorder.getStats();
console.log(Recorded: ${stats.totalPackets} packets, ${stats.totalBytes} bytes);
console.log(Duration: ${stats.duration}ms);
console.log(Packets by type:, stats.packetsByType);
const exported = recorder.export();
const json = JSON.stringify(exported, null, 2);
const imported = recorder.import(JSON.parse(json));
const replayer = new PacketReplayer(recorder.records, {
speed: 1.0,
loop: false,
onPacket: (record) => {
console.log(Replaying: ${record.packetName});
}
});
await replayer.start();
replayer.pause();
replayer.resume();
replayer.stop();
`
$3
Deep protocol analysis with metrics and traffic visualization:
`javascript
import { ProtocolAnalyzer, ProtocolMetrics, PacketInspector } from 'packet-events-js';
const analyzer = new ProtocolAnalyzer({
trackHistory: true,
historySize: 1000,
alertThresholds: {
latency: 500,
packetLoss: 0.1,
throughputMin: 1000
}
});
analyzer.on('alert', (alert) => {
console.log(Alert: ${alert.type} - ${alert.message});
});
analyzer.start();
client.packetManager.on('packetReceive', (event) => {
analyzer.analyzePacket(event.packet, 'CLIENTBOUND', 'PLAY', event.rawData);
});
analyzer.recordLatency(50);
const report = analyzer.getReport();
console.log(Packets: ${report.packets.total});
console.log(Bytes: ${report.bytes.total});
console.log(Avg Latency: ${report.latency.average}ms);
const graph = analyzer.getTrafficGraph();
console.log(graph);
const metrics = new ProtocolMetrics();
metrics.recordLatency(100);
metrics.recordPacketLoss(1, 100);
console.log(Avg Latency: ${metrics.getAverageLatency()}ms);
console.log(Packet Loss: ${metrics.getPacketLoss() * 100}%);
const inspector = new PacketInspector();
const hexDump = inspector.hexDump(packetBuffer);
console.log(hexDump);
const structure = inspector.analyzeStructure(packet);
console.log(structure);
`
$3
Plugin-based packet processing pipeline with built-in middleware:
`javascript
import {
MiddlewarePipeline,
LoggingMiddleware,
RateLimitMiddleware,
ValidationMiddleware,
TransformMiddleware,
CacheMiddleware,
MetricsMiddleware
} from 'packet-events-js';
const pipeline = new MiddlewarePipeline();
pipeline.use(new LoggingMiddleware({
logLevel: 'debug',
includePayload: true,
filter: (ctx) => ctx.packet.constructor.packetName !== 'KeepAlive'
}));
pipeline.use(new RateLimitMiddleware({
maxPackets: 100,
windowMs: 1000,
onLimit: (ctx) => console.log('Rate limited!')
}));
pipeline.use(new ValidationMiddleware({
rules: {
'ChatMessage': (packet) => packet.message.length <= 256,
'SetPlayerPosition': (packet) => Math.abs(packet.y) < 320
},
onInvalid: (ctx, rule) => console.log(Invalid: ${rule})
}));
pipeline.use(new TransformMiddleware({
transforms: {
'ChatMessage': (packet) => {
packet.message = packet.message.trim();
return packet;
}
}
}));
const metricsMiddleware = new MetricsMiddleware();
pipeline.use(metricsMiddleware);
pipeline.use(async (ctx, next) => {
console.log(Before: ${ctx.packet.constructor.packetName});
await next();
console.log(After: processing time ${ctx.processingTime}ms);
});
client.packetManager.on('packetReceive', async (event) => {
const ctx = await pipeline.process({
packet: event.packet,
direction: 'CLIENTBOUND',
state: 'PLAY'
});
if (ctx.cancelled) {
event.cancel();
}
});
const metrics = metricsMiddleware.getMetrics();
console.log(Processed: ${metrics.processed} packets);
console.log(Blocked: ${metrics.blocked} packets);
`
$3
Advanced connection management with auto-reconnect, health monitoring, and connection pooling:
`javascript
import {
AutoReconnect,
ReconnectStrategy,
HealthMonitor,
HealthStatus,
ConnectionPool,
CircuitBreaker
} from 'packet-events-js';
const reconnect = new AutoReconnect({
strategy: ReconnectStrategy.EXPONENTIAL,
baseDelay: 1000,
maxDelay: 30000,
maxAttempts: 10,
jitter: true,
onReconnect: (attempt) => console.log(Reconnecting... attempt ${attempt}),
onMaxAttempts: () => console.log('Max reconnect attempts reached'),
onSuccess: () => console.log('Reconnected!')
});
client.on('disconnect', async () => {
await reconnect.attempt(async () => {
await client.connect();
await client.login();
});
});
const healthMonitor = new HealthMonitor({
latencyThreshold: 200,
packetLossThreshold: 0.05,
checkInterval: 5000
});
healthMonitor.on('statusChange', (status, previousStatus) => {
console.log(Health: ${previousStatus} -> ${status});
});
healthMonitor.on('alert', (alert) => {
console.log(${alert.type}: ${alert.message});
});
client.packetManager.on('packetReceive', (event) => {
if (event.packet.constructor.packetName === 'KeepAliveClientbound') {
healthMonitor.recordLatency(Date.now() - event.timestamp);
}
});
const pool = new ConnectionPool({
minConnections: 2,
maxConnections: 10,
strategy: 'least-loaded',
healthCheck: async (conn) => conn.isConnected,
healthCheckInterval: 30000
});
await pool.add('lobby', createClient('lobby.server.com'));
await pool.add('game1', createClient('game1.server.com'));
await pool.add('game2', createClient('game2.server.com'));
const { id, connection } = pool.get();
await connection.sendPacket(packet);
pool.release(id);
const breaker = new CircuitBreaker({
failureThreshold: 5,
successThreshold: 3,
timeout: 30000,
onOpen: () => console.log('Circuit OPEN - requests blocked'),
onClose: () => console.log('Circuit CLOSED - requests allowed'),
onHalfOpen: () => console.log('Circuit HALF-OPEN - testing')
});
try {
await breaker.execute(async () => {
await client.sendPacket(packet);
});
} catch (error) {
if (breaker.isOpen) {
console.log('Circuit is open, request blocked');
}
}
`
Project Structure
`
PacketEvents-JS/
├── src/
│ ├── index.js
│ ├── auth/
│ │ ├── AuthHandler.js
│ │ └── MojangAPI.js
│ ├── client/
│ │ └── MinecraftClient.js
│ ├── crypto/
│ │ └── Encryption.js
│ ├── events/
│ │ ├── EventEmitter.js
│ │ └── PacketEvent.js
│ ├── manager/
│ │ └── PacketManager.js
│ ├── protocol/
│ │ ├── ConnectionState.js
│ │ ├── PacketDirection.js
│ │ ├── ProtocolVersion.js
│ │ ├── types/
│ │ │ ├── VarInt.js
│ │ │ ├── UUID.js
│ │ │ ├── Position.js
│ │ │ ├── NBT.js
│ │ │ └── TextComponent.js
│ │ └── packets/
│ │ ├── Packet.js
│ │ ├── PacketRegistry.js
│ │ ├── handshake/
│ │ ├── status/
│ │ ├── login/
│ │ └── play/
│ ├── advanced/
│ │ ├── PacketRecorder.js
│ │ ├── ProtocolAnalyzer.js
│ │ ├── MiddlewareSystem.js
│ │ └── ConnectionManager.js
│ └── utils/
│ ├── PacketBuffer.js
│ └── Logger.js
└── examples/
├── authentication.js
├── basic-client.js
├── connection-flows.js
├── custom-packets.js
├── data-types.js
├── encryption.js
├── event-system.js
├── packet-buffer.js
├── packet-interception.js
├── packet-types.js
├── protocol-versions.js
└── server-ping.js
`
Main API
$3
`javascript
const client = new MinecraftClient({
host: string,
port: number,
version: ProtocolVersion,
username: string,
offline: boolean,
accessToken: string,
selectedProfile: object,
registry: PacketRegistry
});
await client.connect();
await client.ping();
await client.login();
await client.sendPacket(packet);
await client.disconnect();
client.isConnected;
client.isReady;
client.uuid;
client.playerName;
`
$3
`javascript
import { PacketBuffer } from 'packet-events-js';
const buffer = PacketBuffer.writer();
buffer.writeBoolean(true);
buffer.writeByte(42);
buffer.writeShort(1000);
buffer.writeInt(100000);
buffer.writeLong(9999999999n);
buffer.writeFloat(3.14);
buffer.writeDouble(3.14159265);
buffer.writeVarInt(12345);
buffer.writeString("Hello Minecraft");
buffer.writeUUID(uuid);
buffer.writePosition(position);
buffer.writeNBT(nbtCompound);
const data = buffer.getBuffer();
const reader = PacketBuffer.reader(data);
const bool = reader.readBoolean();
const num = reader.readVarInt();
const str = reader.readString();
`
$3
`javascript
import { MinecraftEncryption, EncryptedConnection } from 'packet-events-js';
const keyPair = MinecraftEncryption.generateKeyPair();
const verifyToken = MinecraftEncryption.generateVerifyToken();
const sharedSecret = MinecraftEncryption.generateSharedSecret();
MinecraftEncryption.encryptRSA(publicKey, data);
MinecraftEncryption.decryptRSA(privateKey, data);
MinecraftEncryption.encryptAES(secret, data);
MinecraftEncryption.decryptAES(secret, data);
MinecraftEncryption.computeServerIdHash(serverId, sharedSecret, publicKey);
const conn = new EncryptedConnection(sharedSecret);
conn.enable();
const encrypted = conn.encrypt(data);
const decrypted = conn.decrypt(data);
`
$3
`javascript
import { AuthHandler, ClientAuthHandler, AuthMode, BungeeCordForwarding, VelocityForwarding } from 'packet-events-js';
AuthMode.ONLINE;
AuthMode.OFFLINE;
AuthMode.BUNGEECORD;
AuthMode.VELOCITY;
const handler = new AuthHandler({ mode: AuthMode.ONLINE });
handler.initialize();
handler.getPublicKey();
handler.generateVerifyToken();
handler.generateOfflineUUID(username);
const bungeAuth = new AuthHandler({ mode: AuthMode.BUNGEECORD });
const result = bungeAuth.handleBungeeCordForwarding(serverAddress);
const velocityAuth = new AuthHandler({
mode: AuthMode.VELOCITY,
velocitySecret: 'your-secret'
});
const result2 = velocityAuth.handleVelocityForwarding(loginPluginData);
`
$3
`javascript
import { EventPriority } from 'packet-events-js';
EventPriority.LOWEST;
EventPriority.LOW;
EventPriority.NORMAL;
EventPriority.HIGH;
EventPriority.HIGHEST;
EventPriority.MONITOR;
emitter.on('event', callback, { priority: EventPriority.HIGH });
emitter.on('packet', (event) => {
event.cancel();
});
await emitter.emitAsync('event', data);
`
$3
`javascript
import { TextComponent, ChatColor } from 'packet-events-js';
const message = TextComponent.text('Hello!')
.color(ChatColor.GREEN)
.bold()
.append(
TextComponent.text(' World')
.color(ChatColor.YELLOW)
.italic()
)
.clickEvent('run_command', '/help')
.showText(TextComponent.text('Click for help'));
const json = message.toString();
`
Supported Versions
66 versions supported from 1.7.2 to 1.21.11:
| Range | Versions |
|-------|----------|
| 1.21.x | 1.21.11, 1.21.10, 1.21.9, 1.21.8, 1.21.7, 1.21.6, 1.21.5, 1.21.4, 1.21.3, 1.21.2, 1.21.1, 1.21 |
| 1.20.x | 1.20.6, 1.20.5, 1.20.4, 1.20.3, 1.20.2, 1.20.1, 1.20 |
| 1.19.x | 1.19.4, 1.19.3, 1.19.2, 1.19.1, 1.19 |
| 1.18.x | 1.18.2, 1.18.1, 1.18 |
| 1.17.x | 1.17.1, 1.17 |
| 1.16.x | 1.16.5, 1.16.4, 1.16.3, 1.16.2, 1.16.1, 1.16 |
| 1.15.x | 1.15.2, 1.15.1, 1.15 |
| 1.14.x | 1.14.4, 1.14.3, 1.14.2, 1.14.1, 1.14 |
| 1.13.x | 1.13.2, 1.13.1, 1.13 |
| 1.12.x | 1.12.2, 1.12.1, 1.12 |
| 1.11.x | 1.11.2, 1.11.1, 1.11 |
| 1.10.x | 1.10.2, 1.10.1, 1.10 |
| 1.9.x | 1.9.4, 1.9.3, 1.9.2, 1.9.1, 1.9 |
| 1.8.x | 1.8.9, 1.8.8, 1.8.7, 1.8.6, 1.8.5, 1.8.4, 1.8.3, 1.8.2, 1.8.1, 1.8 |
| 1.7.x | 1.7.10, 1.7.9, 1.7.6, 1.7.5, 1.7.4, 1.7.2 |
Examples
See the examples folder for complete usage examples:
- basic-client.js - Basic client connection
- server-ping.js - Server list ping
- packet-types.js - All packet types demonstration
- encryption.js - Encryption usage
- authentication.js - Authentication modes
- event-system.js - Event system usage
- packet-buffer.js - PacketBuffer operations
- data-types.js - Protocol data types
- protocol-versions.js - Protocol version utilities
- connection-flows.js - Connection flow examples
- custom-packets.js - Custom packet creation
- packet-interception.js` - Packet interception