@ -1,39 +1,104 @@
let cfg
let bot
let mcData
let quiet
// 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 ( ) )
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 ( ) )
if ( ! block ) {
cfg . quiet || bot . chat ( "empty block" )
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 ( ) ) )
cfg . quiet || bot . chat ( info . join ( ": " ) )
quiet || bot . chat ( info . join ( ": " ) )
}
function item (
slot ,
entity = bot . entity
entity = b ot. entity ,
slot = entity . heldItem
) {
const item = slot ?
bot . inventory . slots [ parseInt ( slot ) + bot . QUICK _BAR _START ] :
entity . heldItem
console . log ( item )
const item = typeof slot === "number" ?
bot . inventory . slots [ slot + bot . QUICK _BAR _START ] :
slot
console . log ( "info item:" , item )
if ( ! item ) {
cfg . quiet || bot . chat ( "no item" )
quiet || bot . chat ( "no item" )
return item
}
let info = [ item . type , item . name ]
let info = [ item . type , item . name , item . count ]
if ( item . metadata ) info . push ( "meta: " + item . metadata . length )
if ( item . nbt ) {
info . push ( compound _value ( item . nbt ) )
}
cfg . quiet || bot . chat ( info . join ( "; " ) )
quiet || bot . chat ( info . join ( "; " ) )
function compound _value ( obj ) {
if ( typeof obj . value == "object" ) {
return compound _value ( obj . value )
@ -51,27 +116,110 @@ function item(
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 )
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 )
if ( ! entity ) {
cfg . quiet || bot . chat ( "no entity" )
quiet || bot . chat ( "no entity" )
return entity
}
let info = [ entity . type , entity . username || entity . name ]
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 )
// 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 )
cfg . quiet || bot . chat ( info . join ( "; " ) )
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 ) {
@ -79,11 +227,15 @@ 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 ( player . position || player ? . entity . position || null )
block ( )
}
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 ( )
@ -92,10 +244,20 @@ function command(message_parts, player) {
case "entity" :
entity ( )
break
case "me" :
block ( player )
break
case "b" :
case "block" :
default :
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]`" )
}
break ;
}
@ -105,7 +267,43 @@ function command(message_parts, player) {
switch ( message _parts [ 0 ] ) {
case "i" :
case "item" :
item ( message _parts [ 1 ] )
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 ] )
}
break
case "e" :
case "entity" :
@ -120,7 +318,7 @@ function command(message_parts, player) {
case "b" :
case "block" :
default :
block ( message _parts . slice ( 1 ) )
block ( undefined , message _parts . slice ( 1 ) )
break ;
}
@ -133,12 +331,9 @@ 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 ) )
}