Turn Damage Source/Damage Event into Death Message


#1

Hi!

I’m trying to generate a vanilla death message from a damage source.

My use case is that I’m trying to implement a quick respawn method. So what I’m doing is essentially this:

  @Listener(order = Order.LAST)
  public void onDamageChallenger(DamageEntityEvent event) {
    if (!event.willCauseDeath() || !(event.getEntity() instanceof Player)) return;

    event.setCancelled(true);
    respawnPlayer((Player) event.getEntity());
  }

This works all fine, however the only thing I’m missing is the death message. Has anyone any idea how I can broadcast the death message? It’s important that it uses the vanilla messages with translation keys and all. I’d love to avoid having to use NMS for this, but if there’s no other way I’m ok with it. (And know how to set it up)


#2

Vanilla translatable messages can be gotten like so:

Translation translation = Sponge.getRegistry().getTranslationById("death.attack.flyIntoWall").get();
Sponge.getServer().getBroadcastChannel().send(Text.of(translation, player.getName()));

All that’s left is to enumerate over every possible cause and damage source to find the correct message.


#3

Oh boy…

Do you at least know where I can find the vanilla code for this determination?


#4

You’ll find Sponge’s implementation of getting death messages here


#5

So I ended up compiling against SpongeCommon and NMS and used this code:

import net.minecraft.entity.EntityLivingBase;
import net.minecraft.util.DamageSource;
import org.spongepowered.api.entity.Entity;
import org.spongepowered.api.entity.living.player.Player;
import org.spongepowered.api.event.Listener;
import org.spongepowered.api.event.Order;
import org.spongepowered.api.event.entity.DamageEntityEvent;
import org.spongepowered.common.event.SpongeCommonEventFactory;

// ...

  @Listener(order = Order.LAST)
  public void onDamageChallenger(DamageEntityEvent event) {
    final Entity entity = event.getEntity();

    if (!event.willCauseDeath() || !(entity instanceof Player)) return;

    event.setCancelled(true);

    SpongeCommonEventFactory.callDestructEntityEventDeath(
        (EntityLivingBase) entity, event.getCause().first(DamageSource.class).get());
    respawnPlayer((Player) entity);
  }

Note that SpongeCommonEventFactory#callDestructEntityEventDeath will only create the event and not call it, while still sending the death message. Pretty handy.