File size: 5,235 Bytes
248d96b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | /* global THREE performance */
const { Vec3 } = require('vec3')
function getViewDirection (pitch, yaw) {
const csPitch = Math.cos(pitch)
const snPitch = Math.sin(pitch)
const csYaw = Math.cos(yaw)
const snYaw = Math.sin(yaw)
return new Vec3(-snYaw * csPitch, snPitch, -csYaw * csPitch)
}
class Cursor {
constructor (viewer, renderer, bot) {
// Init state
this.buttons = [false, false, false]
this.lastButtons = [false, false, false]
this.breakStartTime = 0
this.cursorBlock = null
// Setup graphics
const blockGeometry = new THREE.BoxGeometry(1.001, 1.001, 1.001)
this.cursorMesh = new THREE.LineSegments(new THREE.EdgesGeometry(blockGeometry), new THREE.LineBasicMaterial({ color: 0 }))
this.cursorMesh.visible = false
viewer.scene.add(this.cursorMesh)
const loader = new THREE.TextureLoader()
this.breakTextures = []
for (let i = 0; i < 10; i++) {
const texture = loader.load('textures/' + viewer.version + '/blocks/destroy_stage_' + i + '.png')
texture.magFilter = THREE.NearestFilter
texture.minFilter = THREE.NearestFilter
this.breakTextures.push(texture)
}
const breakMaterial = new THREE.MeshBasicMaterial({
transparent: true,
blending: THREE.MultiplyBlending
})
this.blockBreakMesh = new THREE.Mesh(blockGeometry, breakMaterial)
this.blockBreakMesh.visible = false
this.blockBreakMesh.renderOrder = 999
viewer.scene.add(this.blockBreakMesh)
// Setup events
document.addEventListener('mouseup', (e) => {
this.buttons[e.button] = false
})
document.addEventListener('mousedown', (e) => {
if (document.pointerLockElement !== renderer.domElement) return
this.buttons[e.button] = true
const entity = bot.nearestEntity((e) => {
if (e.position.distanceTo(bot.entity.position) <= (bot.player.gamemode === 1 ? 5 : 3)) {
const dir = getViewDirection(bot.entity.pitch, bot.entity.yaw)
const { width, height } = e
const { x: eX, y: eY, z: eZ } = e.position
const { x: bX, y: bY, z: bZ } = bot.entity.position
const box = new THREE.Box3(
new THREE.Vector3(eX - width / 2, eY, eZ - width / 2),
new THREE.Vector3(eX + width / 2, eY + height, eZ + width / 2)
)
const r = new THREE.Raycaster(
new THREE.Vector3(bX, bY + 1.52, bZ),
new THREE.Vector3(dir.x, dir.y, dir.z)
)
const int = r.ray.intersectBox(box, new THREE.Vector3(eX, eY, eZ))
return int !== null
}
return false
})
if (entity) {
bot.attack(entity)
}
})
this.lastPlaced = 4 // ticks since last placed
bot.on('physicsTick', () => { if (this.lastPlaced < 4) this.lastPlaced++ })
}
update (bot) {
let cursorBlock = bot.blockAtCursor(6)
if (!bot.canDigBlock(cursorBlock)) cursorBlock = null
let cursorChanged = !cursorBlock !== !this.cursorBlock
if (cursorBlock && this.cursorBlock) {
cursorChanged = !cursorBlock.position.equals(this.cursorBlock.position)
}
// Place
if (cursorBlock && this.buttons[2] && (!this.lastButtons[2] || cursorChanged) && this.lastPlaced >= 4) {
const vecArray = [new Vec3(0, -1, 0), new Vec3(0, 1, 0), new Vec3(0, 0, -1), new Vec3(0, 0, 1), new Vec3(-1, 0, 0), new Vec3(1, 0, 0)]
const delta = cursorBlock.intersect.minus(cursorBlock.position)
bot._placeBlockWithOptions(cursorBlock, vecArray[cursorBlock.face], { delta, forceLook: 'ignore' })
bot.lastPlaced = 0
}
// Start break
if (cursorBlock && this.buttons[0] && (!this.lastButtons[0] || cursorChanged)) {
this.breakStartTime = performance.now()
try {
bot.dig(cursorBlock, 'ignore')
} catch (e) {} // we don't care if its aborted
}
// Stop break
if (!this.buttons[0] && this.lastButtons[0]) {
try {
bot.stopDigging() // this shouldnt throw anything...
} catch (e) {} // to be reworked in mineflayer, then remove the try here
}
// Show break animation
if (cursorBlock && this.buttons[0]) {
const elapsed = performance.now() - this.breakStartTime
const time = bot.digTime(cursorBlock)
const state = Math.floor((elapsed / time) * 10)
this.blockBreakMesh.position.set(cursorBlock.position.x + 0.5, cursorBlock.position.y + 0.5, cursorBlock.position.z + 0.5)
this.blockBreakMesh.material.map = this.breakTextures[state]
this.blockBreakMesh.visible = true
} else {
this.blockBreakMesh.visible = false
}
// Show cursor
if (!cursorBlock) {
this.cursorMesh.visible = false
} else {
this.cursorMesh.visible = true
this.cursorMesh.position.set(cursorBlock.position.x + 0.5, cursorBlock.position.y + 0.5, cursorBlock.position.z + 0.5)
}
// Update state
this.cursorBlock = cursorBlock
this.lastButtons[0] = this.buttons[0]
this.lastButtons[1] = this.buttons[1]
this.lastButtons[2] = this.buttons[2]
}
}
module.exports = Cursor
|