114 lines
4.0 KiB
JavaScript
114 lines
4.0 KiB
JavaScript
|
const { Vec3 } = require('vec3')
|
||
|
|
||
|
module.exports = inject
|
||
|
|
||
|
const CARDINALS = {
|
||
|
north: new Vec3(0, 0, -1),
|
||
|
south: new Vec3(0, 0, 1),
|
||
|
west: new Vec3(-1, 0, 0),
|
||
|
east: new Vec3(1, 0, 0)
|
||
|
}
|
||
|
|
||
|
const FACING_MAP = {
|
||
|
north: { west: 'right', east: 'left' },
|
||
|
south: { west: 'left', east: 'right' },
|
||
|
west: { north: 'left', south: 'right' },
|
||
|
east: { north: 'right', south: 'left' }
|
||
|
}
|
||
|
|
||
|
function inject (bot) {
|
||
|
const { instruments, blocks } = bot.registry
|
||
|
|
||
|
// Stores how many players have currently open a container at a certain position
|
||
|
const openCountByPos = {}
|
||
|
|
||
|
function parseChestMetadata (chestBlock) {
|
||
|
const chestTypes = ['single', 'right', 'left']
|
||
|
|
||
|
return bot.supportFeature('doesntHaveChestType')
|
||
|
? { facing: Object.keys(CARDINALS)[chestBlock.metadata - 2] }
|
||
|
: {
|
||
|
waterlogged: !(chestBlock.metadata & 1),
|
||
|
type: chestTypes[(chestBlock.metadata >> 1) % 3],
|
||
|
facing: Object.keys(CARDINALS)[Math.floor(chestBlock.metadata / 6)]
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function getChestType (chestBlock) { // Returns 'single', 'right' or 'left'
|
||
|
if (bot.supportFeature('doesntHaveChestType')) {
|
||
|
const facing = parseChestMetadata(chestBlock).facing
|
||
|
|
||
|
if (!facing) return 'single'
|
||
|
|
||
|
// We have to check if the adjacent blocks in the perpendicular cardinals are the same type
|
||
|
const perpendicularCardinals = Object.keys(FACING_MAP[facing])
|
||
|
for (const cardinal of perpendicularCardinals) {
|
||
|
const cardinalOffset = CARDINALS[cardinal]
|
||
|
if (bot.blockAt(chestBlock.position.plus(cardinalOffset))?.type === chestBlock.type) {
|
||
|
return FACING_MAP[cardinal][facing]
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return 'single'
|
||
|
} else {
|
||
|
return parseChestMetadata(chestBlock).type
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bot._client.on('block_action', (packet) => {
|
||
|
const pt = new Vec3(packet.location.x, packet.location.y, packet.location.z)
|
||
|
const block = bot.blockAt(pt)
|
||
|
|
||
|
// Ignore on non-vanilla blocks
|
||
|
if (block === null || !blocks[packet.blockId]) { return }
|
||
|
|
||
|
const blockName = blocks[packet.blockId].name
|
||
|
|
||
|
if (blockName === 'noteblock') { // Pre 1.13
|
||
|
bot.emit('noteHeard', block, instruments[packet.byte1], packet.byte2)
|
||
|
} else if (blockName === 'note_block') { // 1.13 onward
|
||
|
bot.emit('noteHeard', block, instruments[Math.floor(block.metadata / 50)], Math.floor((block.metadata % 50) / 2))
|
||
|
} else if (blockName === 'sticky_piston' || blockName === 'piston') {
|
||
|
bot.emit('pistonMove', block, packet.byte1, packet.byte2)
|
||
|
} else {
|
||
|
let block2 = null
|
||
|
|
||
|
if (blockName === 'chest' || blockName === 'trapped_chest') {
|
||
|
const chestType = getChestType(block)
|
||
|
if (chestType === 'right') {
|
||
|
const index = Object.values(FACING_MAP[parseChestMetadata(block).facing]).indexOf('left')
|
||
|
const cardinalBlock2 = Object.keys(FACING_MAP[parseChestMetadata(block).facing])[index]
|
||
|
const block2Position = block.position.plus(CARDINALS[cardinalBlock2])
|
||
|
block2 = bot.blockAt(block2Position)
|
||
|
} else if (chestType === 'left') return // Omit left part of the chest so 'chestLidMove' doesn't emit twice when it's a double chest
|
||
|
}
|
||
|
|
||
|
// Emit 'chestLidMove' only if the number of players with the lid open changes
|
||
|
if (openCountByPos[block.position] !== packet.byte2) {
|
||
|
bot.emit('chestLidMove', block, packet.byte2, block2)
|
||
|
|
||
|
if (packet.byte2 > 0) {
|
||
|
openCountByPos[block.position] = packet.byte2
|
||
|
} else {
|
||
|
delete openCountByPos[block.position]
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
})
|
||
|
|
||
|
bot._client.on('block_break_animation', (packet) => {
|
||
|
const destroyStage = packet.destroyStage
|
||
|
const pt = new Vec3(packet.location.x, packet.location.y, packet.location.z)
|
||
|
const block = bot.blockAt(pt)
|
||
|
const entity = bot.entities[packet.entityId]
|
||
|
|
||
|
if (destroyStage < 0 || destroyStage > 9) {
|
||
|
// http://wiki.vg/Protocol#Block_Break_Progress
|
||
|
// "0-9 to set it, any other value to remove it"
|
||
|
bot.emit('blockBreakProgressEnd', block, entity)
|
||
|
} else {
|
||
|
bot.emit('blockBreakProgressObserved', block, destroyStage, entity)
|
||
|
}
|
||
|
})
|
||
|
}
|