Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

entityHurt event doesn't work #3184

Open
1 task done
shanodis opened this issue Sep 2, 2023 · 8 comments
Open
1 task done

entityHurt event doesn't work #3184

shanodis opened this issue Sep 2, 2023 · 8 comments
Labels
possible bug Stage1 just created by someone new to the project, we don't know yet if it deserves an implementation / a f

Comments

@shanodis
Copy link

shanodis commented Sep 2, 2023

  • The FAQ doesn't contain a resolution to my issue

Versions

  • mineflayer: 4.13.0
  • server: vanilla/spigot/paper 1.20.1
  • node: 18.15.0

Detailed description of a problem

The entityHurt event is not called when attacking mobs.

What did you try yet?

I tried to:

  1. updating packages
  2. reinstalling node_modules
  3. updating/reinstalling paper server

Your current code

const bot = createBot({
  host: 'localhost',
  username: 'George',
});

bot.on('entityHurt', (entity) => {
  console.log('test')
});

Expected behavior

The entityHurt event should be called when attacking enemies or when player hurts himself.

@shanodis shanodis added possible bug Stage1 just created by someone new to the project, we don't know yet if it deserves an implementation / a f labels Sep 2, 2023
@rom1504
Copy link
Member

rom1504 commented Sep 2, 2023 via email

@shanodis
Copy link
Author

shanodis commented Sep 2, 2023

the paper server

@WhoTho
Copy link
Contributor

WhoTho commented Sep 10, 2023

bot._client.on("hurt_animation", (packet) => {
  const entity = this.bot.entities[packet.entityId]
  if (!entity) return
  console.log(entity.name, "hurt")
})

or

bot._client.on("damage_event", (packet) => {
  console.log(packet.entityId, packet.sourceTypeId, packet.sourceCauseId, packet.sourceDirectId, packet.sourcePosition)
})

honestly cba to make a pr

@shanodis
Copy link
Author

@WhoTho both examples don't work

@carloslfu
Copy link

Same on Vanilla 1.20.

@AkagawaTsurunaki
Copy link

bot._client.on("hurt_animation", (packet) => {
  const entity = this.bot.entities[packet.entityId]
  if (!entity) return
  console.log(entity.name, "hurt")
})

or

bot._client.on("damage_event", (packet) => {
  console.log(packet.entityId, packet.sourceTypeId, packet.sourceCauseId, packet.sourceDirectId, packet.sourcePosition)
})

honestly cba to make a pr

It works on Vanilla 1.20.4.

I use mineflayer of Python version to get the packet from the protected member bot._client.

@On(bot._client, 'damage_event')
def handle2(this, packet, *args):
    print(packet)

And there are the outputs:

{'entityId': 3595, 'sourceTypeId': 31, 'sourceCauseId': 124, 'sourceDirectId': 124}

However, entityHurt event is not emitted.

@wgaylord
Copy link
Contributor

wgaylord commented Mar 15, 2024

the entities plugin seems to not know about the damage_event packet and the older packets used to catch an entity being hurt are no longer called in the newer version (with the right arguments to cause a entityHurt even to be emitted)

Looks like a simple fix, just someone needs to do it.

@AkagawaTsurunaki
Copy link

I have reimplemented the flow of handling damageEvent, which should help fix the issue where entityHurt isn't firing correctly.

Note: I didn't make any changes to the source code of mineflayer, just implemented an enhanced version of the damageEvent to override the semantically unfriendly raw damage_event and the non-working entityHurt event.

Re-implement Damage Event

First, the interface ExtendedBotEvents for extending BotEvents is defined.

export interface ExtendedBotEvents extends BotEvents {
    damageEvent: (entity: Entity,
                  sourceType: DamageType,
                  sourceCause: Entity | null,
                  sourceDirect: Entity | null)
        => Promise<void> | void
}

Then create a function that starts the damageEvent listener.

/**
 * See: https://wiki.vg/Protocol#Damage_Event
 */
export function startDamageEvent() {
    bot._client.on('damage_event', async (packet) => {
        // The ID of the entity taking damage.
        const entityId = packet.entityId;
        // The entity taking damage.
        const entity = bot.entities[entityId];

        // The type of damage in the minecraft:damage_type registry, defined by the Registry Data packet.
        const sourceTypeId = packet.sourceTypeId;
        const sourceType = damageTypeMap.get(sourceTypeId);
        assert(sourceType, `Server should not send this damage type id: ${sourceTypeId}`)

        // The ID + 1 of the entity responsible for the damage, if present. If not present, the value is 0
        const sourceCauseId = packet.sourceCauseId;
        const sourceCause = sourceCauseId === 0 ? null : bot.entities[sourceCauseId - 1];

        // The ID + 1 of the entity that directly dealt the damage, if present. If not present, the value is 0.
        // If this field is present:
        // - and damage was dealt indirectly, such as by the use of a projectile, this field will contain the ID of such projectile;
        // - and damage was dealt directly, such as by manually attacking, this field will contain the same value as Source Cause ID.
        const sourceDirectId = packet.sourceDirectId;
        const sourceDirect = bot.entities[sourceDirectId - 1];

        // Enhance the raw damage_event event emitter.
        myEmitter.emit("damageEvent", entity, sourceType, sourceCause, sourceDirect)

        // Replace the original entityHurt event emitter.
        myEmitter.emit("entityHurt", entity)
    })
}

Finally, login the game and test the bot.

myEmitter.on("damageEvent", (entity: Entity,
                             sourceType: DamageType,
                             sourceCause: Entity | null,
                             sourceDirect: Entity | null) => {
    if (entity.type === "player" && entity.username === bot.username) {
        console.log(`${entity.username} got ${sourceType.name} damage by ${sourceDirect?.name} from ${sourceCause?.name}.`)
        if (sourceType.name === "arrow") {
            bot.chat("Ouch... Take care of your bow and arrows!!!")
        }
    }
})

I'm just showing the most important part here, if you need the full code, I've put it in a zip package re-implement-damage-event.zip and you can run it with node --import YOUR_LOADER_CJS_PATH index.ts

It's worth noting that the registry_data.json is for version 1.20.1, and I haven't tested it on other versions because damage types may have different id and name in different versions.

Version Information

  • Minecraft: 1.20.1
  • Fabric: 0.16.5
  • mineflayer: 4.20.1
  • minecraft-data: 3.69.0
  • prismarine-registry: 1.7.0

Relative Links

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
possible bug Stage1 just created by someone new to the project, we don't know yet if it deserves an implementation / a f
Projects
None yet
Development

No branches or pull requests

6 participants