A high-level, general purpose and modular minecraft bot using hot re-loadable (without restarting the bot!) plugins. Batteries included, launch to run!
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

147 lines
4.0 KiB

let cfg
let bot
let mcData
// import v from 'vec3'
const v = require('vec3')
function block(pos) {
const block = pos ? bot.blockAt(v(pos)) : bot.blockAtCursor()
console.log(block, block && block.getProperties())
if (!block) {
cfg.quiet || bot.chat("empty block")
return block
}
let info = [block.type, block.name]
if (block.metadata) info.push(Object.entries(block.getProperties()))
cfg.quiet || bot.chat(info.join(": "))
}
function item(
slot,
entity = bot.entity
) {
const item = slot ?
bot.inventory.slots[parseInt(slot) + bot.QUICK_BAR_START] :
entity.heldItem
console.log(item)
if (!item) {
cfg.quiet || bot.chat("no item")
return item
}
let info = [item.type, item.name]
if (item.metadata) info.push("meta: " + item.metadata.length)
if (item.nbt) {
info.push(compound_value(item.nbt))
}
cfg.quiet || bot.chat(info.join("; "))
function compound_value(obj) {
if (typeof obj.value == "object") {
return compound_value(obj.value)
} else if (obj.value) {
return obj.value
} else if (typeof obj == "object") {
const keys = Object.keys(obj)
return keys.map(key => {
return `${key}: ${compound_value(obj[key])}`
});
} else {
return obj
}
}
return item
}
function entity(name) {
const entity = typeof name === "string" ? bot.nearestEntity((entity) => {
const ename = entity.name || entity.username
return name && ename ? ename == name : true
}) : entity
console.log(entity)
if (!entity) {
cfg.quiet || bot.chat("no entity")
return entity
}
let info = [entity.type, entity.username || entity.name]
// TODO various info depending on the type of entity; player, villager, etc
if (entity.metadata) info.push("len: " + entity.metadata.length)
cfg.quiet || bot.chat(info.join("; "))
return entity
}
function command(message_parts, player) {
if (message_parts.length > 0) {
cfg.info.recentCommand = message_parts
}
switch (message_parts.length) {
case 0:
if (cfg.info.recentCommand) {
command(cfg.info.recentCommand, player)
} else {
// TODO dispatch on instance of entity, block, etc..
// TODO have the logic inside the function or with a utility function
block(player.position || player?.entity.position || null)
}
break;
case 1:
switch (message_parts[0]) {
case "i":
case "item":
item()
break
case "e":
case "entity":
entity()
break
case "b":
case "block":
default:
block()
break;
}
break;
case 2:
switch (message_parts[0]) {
case "i":
case "item":
item(message_parts[1])
break
case "e":
case "entity":
default:
entity(message_parts[1])
break;
}
break
case 4:
switch (message_parts[0]) {
case "b":
case "block":
default:
block(message_parts.slice(1))
break;
}
break;
default:
cfg.quiet || bot.chat("info: unknown command")
break;
}
}
const load = (config) => {
cfg = config
bot = cfg.bot
cfg.info = {
quiet: cfg.quiet,
recentCommand: null,
}
mcData = bot.mcData || (bot.mcData = require('minecraft-data')(bot.version))
}
const unload = () => {}
module.exports = { load, unload, command, block, item, entity }