@@ -358,6 +358,70 @@ function inject (bot) {
358358 }
359359 } )
360360
361+ bot . fireworkRocketDuration = 0
362+ function setElytraFlyingState ( entity , elytraFlying ) {
363+ let startedFlying = false
364+ if ( elytraFlying ) {
365+ startedFlying = ! entity . elytraFlying
366+ entity . elytraFlying = true
367+ } else if ( entity . elytraFlying ) {
368+ entity . elytraFlying = false
369+ }
370+ if ( bot . fireworkRocketDuration !== 0 && entity . id === bot . entity ?. id && ! elytraFlying ) {
371+ bot . fireworkRocketDuration = 0
372+ knownFireworks . splice ( 0 , knownFireworks . length )
373+ }
374+
375+ if ( startedFlying ) {
376+ bot . emit ( 'entityElytraFlew' , entity )
377+ }
378+ }
379+
380+ const knownFireworks = [ ]
381+ function handleBotUsedFireworkRocket ( fireworkEntityId , fireworkInfo ) {
382+ if ( knownFireworks . includes ( fireworkEntityId ) ) return
383+ knownFireworks . push ( fireworkEntityId )
384+ let flightDur = 1
385+ if ( fireworkInfo ?. nbtData != null ) {
386+ let nbt = fireworkInfo . nbtData
387+ if ( nbt . type === 'compound' && nbt . value . Fireworks != null ) {
388+ nbt = nbt . value . Fireworks
389+ if ( nbt . type === 'compound' && nbt . value . Flight != null ) {
390+ nbt = nbt . value . Flight
391+ if ( nbt . type === 'int' ) {
392+ flightDur += nbt . value
393+ }
394+ }
395+ }
396+ }
397+ const baseDuration = 10 * flightDur
398+ const randomDuration = Math . floor ( Math . random ( ) * 6 ) + Math . floor ( Math . random ( ) * 7 )
399+ bot . fireworkRocketDuration = baseDuration + randomDuration
400+
401+ bot . emit ( 'usedFirework' )
402+ }
403+
404+ let fireworkEntityName
405+ if ( bot . supportFeature ( 'fireworkNamePlural' ) ) {
406+ fireworkEntityName = 'fireworks_rocket'
407+ } else if ( bot . supportFeature ( 'fireworkNameSingular' ) ) {
408+ fireworkEntityName = 'firework_rocket'
409+ }
410+
411+ let fireworkMetadataIdx
412+ let fireworkMetadataIsOpt
413+ if ( bot . supportFeature ( 'fireworkMetadataVarInt7' ) ) {
414+ fireworkMetadataIdx = 7
415+ fireworkMetadataIsOpt = false
416+ } else if ( bot . supportFeature ( 'fireworkMetadataOptVarInt8' ) ) {
417+ fireworkMetadataIdx = 8
418+ fireworkMetadataIsOpt = true
419+ } else if ( bot . supportFeature ( 'fireworkMetadataOptVarInt9' ) ) {
420+ fireworkMetadataIdx = 9
421+ fireworkMetadataIsOpt = true
422+ }
423+ const hasFireworkSupport = fireworkEntityName !== undefined && fireworkMetadataIdx !== undefined && fireworkMetadataIsOpt !== undefined
424+
361425 bot . _client . on ( 'entity_metadata' , ( packet ) => {
362426 // entity metadata
363427 const entity = fetchEntity ( packet . entityId )
@@ -374,7 +438,25 @@ function inject (bot) {
374438 if ( metas . sleeping_pos || metas . pose === 2 ) {
375439 bot . emit ( 'entitySleep' , entity )
376440 }
441+
442+ if ( hasFireworkSupport && fireworkEntityName === entity . name && metas . attached_to_target !== undefined ) {
443+ // fireworkMetadataOptVarInt9 and later is implied by
444+ // mcDataHasEntityMetadata, so no need to check metadata index and type
445+ // (eg fireworkMetadataOptVarInt8)
446+ if ( metas . attached_to_target !== 0 ) {
447+ const entityId = metas . attached_to_target - 1
448+ if ( entityId === bot . entity ?. id ) {
449+ handleBotUsedFireworkRocket ( entity . id , metas . fireworks_item )
450+ }
451+ }
452+ }
453+
377454 if ( metas . shared_flags != null ) {
455+ if ( bot . supportFeature ( 'hasElytraFlying' ) ) {
456+ const elytraFlying = metas . shared_flags & 0x80
457+ setElytraFlyingState ( entity , Boolean ( elytraFlying ) )
458+ }
459+
378460 if ( metas . shared_flags & 2 ) {
379461 entity . crouching = true
380462 bot . emit ( 'entityCrouch' , entity )
@@ -396,16 +478,38 @@ function inject (bot) {
396478 bot . emit ( 'entitySleep' , entity )
397479 }
398480
399- const bitField = packet . metadata . find ( p => p . key === 0 )
400- if ( bitField === undefined ) {
401- return
481+ if ( hasFireworkSupport && fireworkEntityName === entity . name ) {
482+ const attachedToTarget = packet . metadata . find ( e => e . key === fireworkMetadataIdx )
483+ if ( attachedToTarget !== undefined ) {
484+ let entityId
485+ if ( fireworkMetadataIsOpt ) {
486+ if ( attachedToTarget . value !== 0 ) {
487+ entityId = attachedToTarget . value - 1
488+ } // else, not attached to an entity
489+ } else {
490+ entityId = attachedToTarget . value
491+ }
492+ if ( entityId !== undefined && entityId === bot . entity ?. id ) {
493+ const fireworksItem = packet . metadata . find ( e => e . key === ( fireworkMetadataIdx - 1 ) )
494+ handleBotUsedFireworkRocket ( entity . id , fireworksItem ?. value )
495+ }
496+ }
402497 }
403- if ( ( bitField . value & 2 ) !== 0 ) {
404- entity . crouching = true
405- bot . emit ( 'entityCrouch' , entity )
406- } else if ( entity . crouching ) { // prevent the initial entity_metadata packet from firing off an uncrouch event
407- entity . crouching = false
408- bot . emit ( 'entityUncrouch' , entity )
498+
499+ const bitField = packet . metadata . find ( p => p . key === 0 )
500+ if ( bitField !== undefined ) {
501+ if ( bot . supportFeature ( 'hasElytraFlying' ) ) {
502+ const elytraFlying = bitField . value & 0x80
503+ setElytraFlyingState ( entity , Boolean ( elytraFlying ) )
504+ }
505+
506+ if ( ( bitField . value & 2 ) !== 0 ) {
507+ entity . crouching = true
508+ bot . emit ( 'entityCrouch' , entity )
509+ } else if ( entity . crouching ) { // prevent the initial entity_metadata packet from firing off an uncrouch event
510+ entity . crouching = false
511+ bot . emit ( 'entityUncrouch' , entity )
512+ }
409513 }
410514 }
411515 } )
0 commit comments