diff --git a/src/main/java/me/sashegdev/blackknife/BlackKnifePlugin.java b/src/main/java/me/sashegdev/blackknife/BlackKnifePlugin.java index 9c7cee6..ae04d01 100644 --- a/src/main/java/me/sashegdev/blackknife/BlackKnifePlugin.java +++ b/src/main/java/me/sashegdev/blackknife/BlackKnifePlugin.java @@ -49,6 +49,7 @@ public class BlackKnifePlugin extends JavaPlugin { getServer().getPluginManager().registerEvents(new MoleHoleCoords(this), this); getServer().getPluginManager().registerEvents(new VoidWorld(), this); getServer().getPluginManager().registerEvents(new VoidExit(), this); + getServer().getPluginManager().registerEvents(new VoidDeath(), this); BlackKnife.init(this); // Имя измерения сервер выбирает сам, поэтому угадывать его в коде нельзя. // Находим и печатаем: по этой строке видно, какой мир считается пустотой. diff --git a/src/main/java/me/sashegdev/blackknife/VoidDeath.java b/src/main/java/me/sashegdev/blackknife/VoidDeath.java new file mode 100644 index 0000000..07d3abe --- /dev/null +++ b/src/main/java/me/sashegdev/blackknife/VoidDeath.java @@ -0,0 +1,71 @@ +package me.sashegdev.blackknife; + +import net.kyori.adventure.text.Component; +import org.bukkit.Location; +import org.bukkit.Sound; +import org.bukkit.SoundCategory; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.PlayerDeathEvent; + +/** + * Глухая смерть в пустоте. + * + *
По условию: в пустоте сообщение о смерти не уходит в общий чат, а достаёт + * только тех, кто рядом — в радиусе 100 блоков. Вместо сообщения слышен крик + * визера: громкость 0.2 от обычной, дальность 150 блоков. Убийство кого-то + * трактуется так же, как собственная смерть. + * + *
Убийство отдельным обработчиком ловить не нужно: сообщение «X убит Y» + * это то же самое событие {@link PlayerDeathEvent}, что и «X умер». Один + * обработчик покрывает оба случая, а различаются они только текстом сообщения, + * который мы и так передаём как есть. + * + *
Про «дальность 150» и «громкость 0.2» стоит понимать честно: 150 — это + * радиус доставки пакета на сервере, то есть кто его вообще получит. Громкость + * 0.2 — громкость самого пакета. Клиент дальше применяет своё позиционное + * затухание, поэтому вблизи источника звук слышен, а в сотне метров — уже + * почти нет. Сделать его одинаково громким на все 150 блоков можно было бы + * только громкостью от 9.4, и тогда заглушало бы всех, кто стоит рядом. + */ +public final class VoidDeath implements Listener { + + public VoidDeath() { + } + + /** Радиус, в котором сообщение о смерти ещё слышно. */ + public static final double MESSAGE_RADIUS = 100.0D; + /** Дальность доставки звука, блоков. */ + public static final float SOUND_RANGE = 150.0F; + /** Громкость крика визера. */ + public static final float SOUND_VOLUME = 0.2F; + + @EventHandler(priority = EventPriority.HIGHEST) + public void onDeath(PlayerDeathEvent e) { + final Player victim = e.getEntity(); + if (!VoidWorld.inVoid(victim)) { + return; + } + + // Забираем сообщение из общего чата. null означает «не показывать». + final Component message = e.deathMessage(); + e.deathMessage(null); + + final Location at = victim.getLocation(); + final double r2 = MESSAGE_RADIUS * MESSAGE_RADIUS; + + // Локально — только тем, кто рядом с местом смерти. + for (Player p : victim.getWorld().getPlayers()) { + if (p.getLocation().distanceSquared(at) <= r2 && message != null) { + p.sendMessage(message); + } + } + + // Крик визера. Отдельного ENTITY_WITHER_SCREAM в enum нет: визer's + // крик в ванилле называется entity.wither.spawn. + victim.getWorld().playSound(at, Sound.ENTITY_WITHER_SPAWN, + SoundCategory.HOSTILE, SOUND_VOLUME, 1.0F, SOUND_RANGE); + } +}