From 31d77534719c3bdfbf6162545df88710f934db29 Mon Sep 17 00:00:00 2001 From: SashegDev Date: Mon, 19 Oct 2026 20:49:27 +0000 Subject: [PATCH] feat(voiddeath): muffled death in the void, local message only MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Одиннадцатый этап, последний из задуманных. Сообщение о смерти в пустоте не уходит в общий чат: забирается через deathMessage(null) и отправляется только тем, кто в радиусе 100 блоков от места смерти. Текст сообщения при этом тот же самый, что и обычно. Убийство кого-то отдельным обработчиком ловить не пришлось: «X убит Y» — это то же самое событие PlayerDeathEvent, что и «X умер». Различаются они только текстом, который и так передаётся как есть. Крик визера: громкость 0.2, дальность доставки 150 блоков. Отдельного ENTITY_WITHER_SCREAM в enum нет — визer's крик в ванилле называется entity.wither.spawn, то есть ENTITY_WITHER_SPAWN. Про «дальность 150» честно: это радиус доставки пакета на сервере, то есть кто его вообще получил. Громкость 0.2 — громкость пакета, а клиент дальше применяет своё позиционное затухание: у источника слышно, в сотне метров почти нет. Чтобы звук был одинаково громким на всех 150 блоках, громкость пришлось бы поднять до 9.4, и тогда заглушало бы всех рядом с источником. Именно для такой задачи в Delta есть раздельная дальность звука, и флаг decoupled-sound-range-enabled на проде включён: без него World#playSound с радиусом молча уходит в стоковое поведение, где радиус выводится из громкости, то есть 0.2 даёт 3.2 блока. Проверено: плагин грузится без ошибок, флаг виден в /delta как true. Сама смерть в пустоте не проверялась — нужен игрок. --- .../blackknife/BlackKnifePlugin.java | 1 + .../me/sashegdev/blackknife/VoidDeath.java | 71 +++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 src/main/java/me/sashegdev/blackknife/VoidDeath.java 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); + } +}