|
|
|
@ -1,104 +1,39 @@ |
|
|
|
|
let cfg |
|
|
|
|
let bot |
|
|
|
|
let mcData |
|
|
|
|
let quiet |
|
|
|
|
// import v from 'vec3'
|
|
|
|
|
const v = require('vec3') |
|
|
|
|
|
|
|
|
|
let cfg = { |
|
|
|
|
info: { |
|
|
|
|
quiet: quiet, |
|
|
|
|
recentCommand: null, |
|
|
|
|
}, |
|
|
|
|
// to satisfy typescript
|
|
|
|
|
quiet: null, |
|
|
|
|
bot: bot |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var RelativePosEnum |
|
|
|
|
(function (RelativePosEnum) { |
|
|
|
|
RelativePosEnum[RelativePosEnum["feet"] = 0] = "feet" |
|
|
|
|
RelativePosEnum[RelativePosEnum["standing"] = 1] = "standing" |
|
|
|
|
RelativePosEnum[RelativePosEnum["head"] = 2] = "head" |
|
|
|
|
RelativePosEnum[RelativePosEnum["looking"] = 3] = "looking" |
|
|
|
|
RelativePosEnum[RelativePosEnum["infront"] = 4] = "infront" |
|
|
|
|
RelativePosEnum[RelativePosEnum["behind"] = 5] = "behind" |
|
|
|
|
})(RelativePosEnum || (RelativePosEnum = {})) |
|
|
|
|
|
|
|
|
|
function relPosToBlock(entity, relPos) { |
|
|
|
|
let pos |
|
|
|
|
if (!(relPos in RelativePosEnum)) return console.warn("info: not a relative position:", relPos) |
|
|
|
|
relPos = typeof relPos === "number" ? RelativePosEnum[relPos] : relPos |
|
|
|
|
switch (relPos) { |
|
|
|
|
case "feet": |
|
|
|
|
pos = entity.position; |
|
|
|
|
break |
|
|
|
|
case "standing": |
|
|
|
|
pos = entity.position.offset(0, -1, 0) |
|
|
|
|
break |
|
|
|
|
// todo use CARDINAL directions api from pathfinder
|
|
|
|
|
// case "behind":
|
|
|
|
|
// entity.yaw
|
|
|
|
|
// pos = entity.position
|
|
|
|
|
// break
|
|
|
|
|
// case "front":
|
|
|
|
|
// case "infront":
|
|
|
|
|
// pos = entity.position
|
|
|
|
|
// break
|
|
|
|
|
case "head": |
|
|
|
|
pos = entity.position.offset(0, 1.85, 0) |
|
|
|
|
break |
|
|
|
|
case "looking": |
|
|
|
|
if (entity === bot.entity) { |
|
|
|
|
return bot.blockAtCursor() |
|
|
|
|
// return bot.blockInSight(128, 128)
|
|
|
|
|
} |
|
|
|
|
default: |
|
|
|
|
quiet || bot.chat(`info: pos '${relPos}' not implemented`) |
|
|
|
|
break |
|
|
|
|
} |
|
|
|
|
if (pos) { |
|
|
|
|
// nearest block
|
|
|
|
|
return bot.blockAt(pos) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function isVec3(vec) { |
|
|
|
|
return vec?.length === 3 || vec.x && vec.y && vec.z |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function block(entity = bot.entity, pos = entity?.position?.offset(0, -1, 0)) { |
|
|
|
|
console.assert(pos || entity) |
|
|
|
|
const block = isVec3(pos) ? bot.blockAt(v(pos)) |
|
|
|
|
: typeof pos === "string" ? relPosToBlock(entity, RelativePosEnum[pos]) : pos |
|
|
|
|
console.log(block, block?.getProperties && block.getProperties()) |
|
|
|
|
function block(pos) { |
|
|
|
|
const block = pos ? bot.blockAt(v(pos)) : bot.blockAtCursor() |
|
|
|
|
console.log(block, block && block.getProperties()) |
|
|
|
|
if (!block) { |
|
|
|
|
quiet || bot.chat("empty block") |
|
|
|
|
cfg.quiet || bot.chat("empty block") |
|
|
|
|
return block |
|
|
|
|
} |
|
|
|
|
bot.lookAt(block?.position) |
|
|
|
|
let info = [block.type, block.name] |
|
|
|
|
if (block.metadata) info.push(Object.entries(block.getProperties())) |
|
|
|
|
quiet || bot.chat(info.join(": ")) |
|
|
|
|
cfg.quiet || bot.chat(info.join(": ")) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function item( |
|
|
|
|
entity = bot.entity, |
|
|
|
|
slot = entity.heldItem |
|
|
|
|
slot, |
|
|
|
|
entity = bot.entity |
|
|
|
|
) { |
|
|
|
|
const item = typeof slot === "number" ? |
|
|
|
|
bot.inventory.slots[slot + bot.QUICK_BAR_START] : |
|
|
|
|
slot |
|
|
|
|
console.log("info item:", item) |
|
|
|
|
const item = slot ? |
|
|
|
|
bot.inventory.slots[parseInt(slot) + bot.QUICK_BAR_START] : |
|
|
|
|
entity.heldItem |
|
|
|
|
console.log(item) |
|
|
|
|
if (!item) { |
|
|
|
|
quiet || bot.chat("no item") |
|
|
|
|
cfg.quiet || bot.chat("no item") |
|
|
|
|
return item |
|
|
|
|
} |
|
|
|
|
let info = [item.type, item.name, item.count] |
|
|
|
|
let info = [item.type, item.name] |
|
|
|
|
if (item.metadata) info.push("meta: " + item.metadata.length) |
|
|
|
|
if (item.nbt) { |
|
|
|
|
info.push(compound_value(item.nbt)) |
|
|
|
|
} |
|
|
|
|
quiet || bot.chat(info.join("; ")) |
|
|
|
|
cfg.quiet || bot.chat(info.join("; ")) |
|
|
|
|
function compound_value(obj) { |
|
|
|
|
if (typeof obj.value == "object") { |
|
|
|
|
return compound_value(obj.value) |
|
|
|
@ -116,110 +51,27 @@ function item( |
|
|
|
|
return item |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var VillagerProfession |
|
|
|
|
(function (VillagerProfession) { |
|
|
|
|
VillagerProfession[VillagerProfession["Unemployed"] = 0] = "Unemployed" |
|
|
|
|
VillagerProfession[VillagerProfession["Armourer"] = 1] = "Armourer" |
|
|
|
|
VillagerProfession[VillagerProfession["Butcher"] = 2] = "Butcher" |
|
|
|
|
VillagerProfession[VillagerProfession["Cartographer"] = 3] = "Cartographer" |
|
|
|
|
VillagerProfession[VillagerProfession["Cleric"] = 4] = "Cleric" |
|
|
|
|
VillagerProfession[VillagerProfession["Farmer"] = 5] = "Farmer" |
|
|
|
|
VillagerProfession[VillagerProfession["Fisherman"] = 6] = "Fisherman" |
|
|
|
|
VillagerProfession[VillagerProfession["Fletcher"] = 7] = "Fletcher" |
|
|
|
|
VillagerProfession[VillagerProfession["Leatherworker"] = 8] = "Leatherworker" |
|
|
|
|
VillagerProfession[VillagerProfession["Librarian"] = 9] = "Librarian" |
|
|
|
|
VillagerProfession[VillagerProfession["Mason"] = 10] = "Mason" |
|
|
|
|
VillagerProfession[VillagerProfession["Nitwit"] = 11] = "Nitwit" |
|
|
|
|
VillagerProfession[VillagerProfession["Shepherd"] = 12] = "Shepherd" |
|
|
|
|
VillagerProfession[VillagerProfession["Toolsmith"] = 13] = "Toolsmith" |
|
|
|
|
VillagerProfession[VillagerProfession["Weaponsmith"] = 14] = "Weaponsmith" |
|
|
|
|
})(VillagerProfession || (VillagerProfession = {})) |
|
|
|
|
|
|
|
|
|
function entity(name = bot.nearestEntity()) { |
|
|
|
|
const entity = typeof name === "string" ? (name = name.toLowerCase()) && bot.nearestEntity((entity) => { |
|
|
|
|
const enames = [entity.username?.toLowerCase(), entity.name, entity.displayName?.toLowerCase()] |
|
|
|
|
return enames.includes(name) |
|
|
|
|
}) : name |
|
|
|
|
console.log("info entity:", entity) |
|
|
|
|
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) { |
|
|
|
|
quiet || bot.chat("no entity") |
|
|
|
|
cfg.quiet || bot.chat("no entity") |
|
|
|
|
return entity |
|
|
|
|
} |
|
|
|
|
entity?.position && bot.lookAt(entity.position) |
|
|
|
|
let info = [(entity.entityType && entity.entityType + ":" || "") + (entity.type === "object" ? entity.kind : entity.type)] |
|
|
|
|
info.push(entity.username || entity.name) |
|
|
|
|
let info = [entity.type, entity.username || entity.name] |
|
|
|
|
// TODO various info depending on the type of entity; player, villager, etc
|
|
|
|
|
// TODO refactor and combine with compound_value()
|
|
|
|
|
switch (entity.type) { |
|
|
|
|
case "object": |
|
|
|
|
switch (entity.kind) { |
|
|
|
|
case "Drops": |
|
|
|
|
const item = entity.metadata[7]; |
|
|
|
|
entity.metadata; |
|
|
|
|
if (item.present) { |
|
|
|
|
info.push("item: " + item.itemId + ": " |
|
|
|
|
+ mcData.items[item.itemId].name |
|
|
|
|
+ `x${item.itemCount}`); |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
console.warn("info entity: metadata expected item, got:", entity.metadata[7]); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case "mob": |
|
|
|
|
switch (name) { |
|
|
|
|
case 'villager': |
|
|
|
|
const { villagerProfession, ...otherProps } = entity.metadata[17] |
|
|
|
|
info.push(VillagerProfession[villagerProfession]) |
|
|
|
|
info.push(Object.entries(otherProps).toString()) |
|
|
|
|
break |
|
|
|
|
default: |
|
|
|
|
break |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
entity.metadata[8] && info.push("health:" + entity.metadata[8]) |
|
|
|
|
entity.metadata[15] && info.push("baby") |
|
|
|
|
if (entity.heldItem) { |
|
|
|
|
info.push("holding") |
|
|
|
|
item(entity) |
|
|
|
|
} |
|
|
|
|
case "global": |
|
|
|
|
case "orb": |
|
|
|
|
case "player": |
|
|
|
|
break; |
|
|
|
|
case "other": |
|
|
|
|
info.push("kind:" + entity.kind) |
|
|
|
|
default: |
|
|
|
|
} |
|
|
|
|
if (entity.metadata) info.push("len: " + entity.metadata.length) |
|
|
|
|
quiet || bot.chat(info.join("; ")) |
|
|
|
|
cfg.quiet || bot.chat(info.join("; ")) |
|
|
|
|
return entity |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function blockOrItemFromId(num, quiet = cfg.info.quiet) { |
|
|
|
|
const block = mcData?.blocks[num] |
|
|
|
|
const item = mcData?.items[num] |
|
|
|
|
// const entity = mcData?.entities[num]
|
|
|
|
|
if (block || item) { |
|
|
|
|
quiet || bot.chat( |
|
|
|
|
(block && `block: ${block.name}, ` || "") |
|
|
|
|
+ (item && `item: ${item.name}, ` || "") |
|
|
|
|
// + (entity && `entity: ${entity.name}, ` || "")
|
|
|
|
|
) |
|
|
|
|
} else { |
|
|
|
|
quiet || bot.chat("info: nonexistent block or item") |
|
|
|
|
} |
|
|
|
|
return { block, item } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function command(message_parts, player) { |
|
|
|
|
if (message_parts.length > 0) { |
|
|
|
|
cfg.info.recentCommand = message_parts |
|
|
|
|
} |
|
|
|
|
if (player === null) |
|
|
|
|
player = void 0 |
|
|
|
|
switch (message_parts.length) { |
|
|
|
|
case 0: |
|
|
|
|
if (cfg.info.recentCommand) { |
|
|
|
@ -227,15 +79,11 @@ function command(message_parts, player) { |
|
|
|
|
} else { |
|
|
|
|
// TODO dispatch on instance of entity, block, etc..
|
|
|
|
|
// TODO have the logic inside the function or with a utility function
|
|
|
|
|
block() |
|
|
|
|
block(player.position || player?.entity.position || null) |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case 1: |
|
|
|
|
switch (message_parts[0]) { |
|
|
|
|
case "quiet": |
|
|
|
|
cfg.info.quiet = quiet = !quiet; |
|
|
|
|
quiet || bot.chat(`info: ${quiet ? "" : "not "}being quiet`); |
|
|
|
|
break; |
|
|
|
|
case "i": |
|
|
|
|
case "item": |
|
|
|
|
item() |
|
|
|
@ -244,20 +92,10 @@ function command(message_parts, player) { |
|
|
|
|
case "entity": |
|
|
|
|
entity() |
|
|
|
|
break |
|
|
|
|
case "me": |
|
|
|
|
block(player) |
|
|
|
|
break |
|
|
|
|
case "b": |
|
|
|
|
case "block": |
|
|
|
|
block() |
|
|
|
|
break |
|
|
|
|
default: |
|
|
|
|
const num = parseInt(message_parts[0]) |
|
|
|
|
if (isFinite(num)) { |
|
|
|
|
blockOrItemFromId(num) |
|
|
|
|
} else { |
|
|
|
|
quiet || bot.chat("info usage: `!info [me|i|e|b|<num>|quiet]`") |
|
|
|
|
} |
|
|
|
|
block() |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -267,43 +105,7 @@ function command(message_parts, player) { |
|
|
|
|
switch (message_parts[0]) { |
|
|
|
|
case "i": |
|
|
|
|
case "item": |
|
|
|
|
switch (message_parts[1]) { |
|
|
|
|
case "me": |
|
|
|
|
item(player) |
|
|
|
|
break |
|
|
|
|
default: |
|
|
|
|
const slot = parseInt(message_parts[1]) |
|
|
|
|
slot && item(undefined, slot) |
|
|
|
|
break |
|
|
|
|
} |
|
|
|
|
break |
|
|
|
|
case "b": |
|
|
|
|
case "block": |
|
|
|
|
switch (message_parts[1]) { |
|
|
|
|
case "me": |
|
|
|
|
block(player) |
|
|
|
|
break |
|
|
|
|
default: |
|
|
|
|
const aPlayer = bot.players[message_parts[1]] |
|
|
|
|
if (message_parts[1] in RelativePosEnum) { |
|
|
|
|
block(undefined, message_parts[1]) |
|
|
|
|
} else if (aPlayer) { |
|
|
|
|
if (aPlayer.entity) { |
|
|
|
|
block(aPlayer.entity) |
|
|
|
|
} else { |
|
|
|
|
quiet || bot.chat(`info: player ${aPlayer.username} too far!`) |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
// or entity(message_parts[1]).position
|
|
|
|
|
console.log(bot.players[message_parts[1]]) |
|
|
|
|
quiet || bot.chat("info: not yet implemented") |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
break |
|
|
|
|
case "me": |
|
|
|
|
if (message_parts[1] in RelativePosEnum) { |
|
|
|
|
block(player, message_parts[1]) |
|
|
|
|
} |
|
|
|
|
item(message_parts[1]) |
|
|
|
|
break |
|
|
|
|
case "e": |
|
|
|
|
case "entity": |
|
|
|
@ -318,7 +120,7 @@ function command(message_parts, player) { |
|
|
|
|
case "b": |
|
|
|
|
case "block": |
|
|
|
|
default: |
|
|
|
|
block(undefined, message_parts.slice(1)) |
|
|
|
|
block(message_parts.slice(1)) |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -331,9 +133,12 @@ function command(message_parts, player) { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const load = (config) => { |
|
|
|
|
config.info = cfg.info |
|
|
|
|
cfg = config |
|
|
|
|
bot = cfg.bot |
|
|
|
|
cfg.info = { |
|
|
|
|
quiet: cfg.quiet, |
|
|
|
|
recentCommand: null, |
|
|
|
|
} |
|
|
|
|
mcData = bot.mcData || (bot.mcData = require('minecraft-data')(bot.version)) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|