mcraft-fun-mineflayer
Version:
Mineflayer viewer (connector) for mcraft.fun project and vanilla Minecraft client! Both TCP and WebSockets servers are supported.
155 lines (154 loc) • 5.69 kB
JavaScript
"use strict";
// todo split more code
Object.defineProperty(exports, "__esModule", { value: true });
exports.entityReplicator = void 0;
const versionToNumber = (version) => {
const [major, minor, patch] = version.split('.').map(Number);
return (major ?? 0) * 10000 + (minor ?? 0) * 100 + (patch ?? 0);
};
const entityReplicator = (bot) => {
class EntitySpawnState {
packetType;
packet;
constructor(packetType, packet) {
this.packetType = packetType;
this.packet = packet;
}
updatePosition(packet) {
if ('x' in packet)
this.packet.x = packet.x;
if ('y' in packet)
this.packet.y = packet.y;
if ('z' in packet)
this.packet.z = packet.z;
}
updateRelativePosition(packet) {
// if (versionToNumber(bot.version) < versionToNumber('1.8')) {
this.packet.x += packet.dX;
this.packet.y += packet.dY;
this.packet.z += packet.dZ;
// } else {
// // 1.8+ uses fixed-point numbers
// this.packet.x += packet.dX / 32;
// this.packet.y += packet.dY / 32;
// this.packet.z += packet.dZ / 32;
// }
// 1.8+ has onGround
if ('onGround' in packet) {
this.packet.onGround = packet.onGround;
}
}
updateRotation(packet) {
if ('yaw' in packet)
this.packet.yaw = packet.yaw;
if ('pitch' in packet)
this.packet.pitch = packet.pitch;
}
updateVelocity(packet) {
if ('velocityX' in this.packet) {
this.packet.velocityX = packet.velocityX;
this.packet.velocityY = packet.velocityY;
this.packet.velocityZ = packet.velocityZ;
}
}
handleUpdatePacket(packetType, packet) {
switch (packetType) {
case 'rel_entity_move':
this.updateRelativePosition(packet);
break;
case 'entity_look':
this.updateRotation(packet);
if ('onGround' in packet)
this.packet.onGround = packet.onGround;
break;
case 'entity_move_look':
this.updateRelativePosition(packet);
this.updateRotation(packet);
break;
case 'entity_teleport':
this.updatePosition(packet);
this.updateRotation(packet);
break;
case 'sync_entity_position':
this.updatePosition(packet);
this.updateRotation(packet);
this.updateVelocity(packet);
break;
case 'entity_velocity':
this.updateVelocity(packet);
break;
}
}
}
class EntityAdditionalState {
entityId;
lastPackets;
constructor(entityId, lastPackets = new Map()) {
this.entityId = entityId;
this.lastPackets = lastPackets;
}
handleAdditionalPacket(packetType, packet) {
this.lastPackets.set(packetType, packet);
}
getLastPacket(packetType) {
return this.lastPackets.get(packetType);
}
}
const entities = new Map();
function handleEntityPacket(packetType, packet) {
const entityId = packet.entityId;
// Handle spawn packets
if (packetType.startsWith('spawn_') || packetType === 'named_entity_spawn') {
entities.set(`${entityId}`, {
spawnState: new EntitySpawnState(packetType, packet),
additional: new EntityAdditionalState(entityId)
});
return;
}
const entity = entities.get(`${entityId}`);
if (!entity)
return;
// Check if it's a spawn-modifying packet
if (['rel_entity_move', 'entity_look', 'entity_move_look',
'entity_teleport', 'sync_entity_position', 'entity_velocity'].includes(packetType)) {
entity.spawnState.handleUpdatePacket(packetType, packet);
}
else {
// It's an additional state packet
entity.additional.handleAdditionalPacket(packetType, packet);
}
}
function getAllEntityPackets(entityId) {
const entity = entities.get(entityId);
if (!entity)
return [];
const packets = [[entity.spawnState.packetType, entity.spawnState.packet]]; // Spawn packet is always up to date
// Add all additional state packets
for (const [packetType, packet] of entity.additional.lastPackets) {
packets.push([packetType, packet]);
}
return packets;
}
bot._client.on('packet', (data, packetMeta, buffer, fullBuffer) => {
if (!data)
return;
handleEntityPacket(packetMeta.name, data);
});
bot.on('entityGone', ({ id }) => {
entities.delete(String(id));
});
bot.on('respawn', () => {
entities.clear();
});
return {
onClientJoin(client) {
for (const [id, entity] of Object.entries(bot.entities)) {
const entityPackets = getAllEntityPackets(id);
for (const [packetType, packet] of entityPackets) {
client.write(packetType, packet);
}
}
}
};
};
exports.entityReplicator = entityReplicator;