From 3660c4dac74723d9e207cb68b1f42b347d98b274 Mon Sep 17 00:00:00 2001 From: Anatoly Kopyl Date: Fri, 10 Apr 2026 09:41:43 +0300 Subject: [PATCH] Add next death text --- .../client/RespawnBackoffClient.java | 16 ++++++++++++++-- .../net/respawnbackoff/CooldownSyncPayload.java | 5 +++-- .../net/respawnbackoff/RespawnBackoffData.java | 8 ++++++++ .../respawnbackoff/RespawnBackoffNetworking.java | 7 ++++++- .../assets/respawn_backoff/lang/en_us.json | 1 + .../assets/respawn_backoff/lang/ru_ru.json | 1 + 6 files changed, 33 insertions(+), 5 deletions(-) diff --git a/src/client/java/net/respawnbackoff/client/RespawnBackoffClient.java b/src/client/java/net/respawnbackoff/client/RespawnBackoffClient.java index 7f746a0..c8191cf 100644 --- a/src/client/java/net/respawnbackoff/client/RespawnBackoffClient.java +++ b/src/client/java/net/respawnbackoff/client/RespawnBackoffClient.java @@ -11,6 +11,7 @@ import net.respawnbackoff.CooldownSyncPayload; public class RespawnBackoffClient implements ClientModInitializer { private static volatile boolean overlayActive; private static volatile long cooldownEndEpochMs; + private static volatile long nextDeathWaitMinutes; @Override public void onInitializeClient() { @@ -20,6 +21,7 @@ public class RespawnBackoffClient implements ClientModInitializer { context.client().execute(() -> { overlayActive = payload.active(); cooldownEndEpochMs = payload.cooldownEndEpochMs(); + nextDeathWaitMinutes = payload.nextDeathWaitMinutes(); }); }); @@ -44,13 +46,23 @@ public class RespawnBackoffClient implements ClientModInitializer { int seconds = totalSeconds % 60; String time = String.format("%02d:%02d", minutes, seconds); Component line = Component.translatable("respawn_backoff.hud.countdown", time); - + int lineHeight = client.font.lineHeight; + int centerY = h / 2; + int mainY = centerY - lineHeight - 2; int textWidth = client.font.width(line); - graphics.drawString(client.font, line, (w - textWidth) / 2, h / 2, 0xFFFFFF, false); + graphics.drawString(client.font, line, (w - textWidth) / 2, mainY, 0xFFFFFF, false); + + long nextMin = nextDeathWaitMinutes; + if (nextMin > 0L) { + Component sub = Component.translatable("respawn_backoff.hud.next_death", nextMin); + int subW = client.font.width(sub); + graphics.drawString(client.font, sub, (w - subW) / 2, centerY + 4, 0xA0A0A0, false); + } } public static void clearForDisconnect() { overlayActive = false; cooldownEndEpochMs = 0L; + nextDeathWaitMinutes = 0L; } } diff --git a/src/main/java/net/respawnbackoff/CooldownSyncPayload.java b/src/main/java/net/respawnbackoff/CooldownSyncPayload.java index 37edc78..88e6a8a 100644 --- a/src/main/java/net/respawnbackoff/CooldownSyncPayload.java +++ b/src/main/java/net/respawnbackoff/CooldownSyncPayload.java @@ -5,7 +5,7 @@ import net.minecraft.network.codec.StreamCodec; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; -public record CooldownSyncPayload(boolean active, long cooldownEndEpochMs) implements CustomPacketPayload { +public record CooldownSyncPayload(boolean active, long cooldownEndEpochMs, long nextDeathWaitMinutes) implements CustomPacketPayload { public static final CustomPacketPayload.Type TYPE = new CustomPacketPayload.Type<>( ResourceLocation.fromNamespaceAndPath(RespawnBackoffMod.MOD_ID, "cooldown_sync") ); @@ -14,8 +14,9 @@ public record CooldownSyncPayload(boolean active, long cooldownEndEpochMs) imple (RegistryFriendlyByteBuf buf, CooldownSyncPayload payload) -> { buf.writeBoolean(payload.active()); buf.writeLong(payload.cooldownEndEpochMs()); + buf.writeLong(payload.nextDeathWaitMinutes()); }, - buf -> new CooldownSyncPayload(buf.readBoolean(), buf.readLong()) + buf -> new CooldownSyncPayload(buf.readBoolean(), buf.readLong(), buf.readLong()) ); @Override diff --git a/src/main/java/net/respawnbackoff/RespawnBackoffData.java b/src/main/java/net/respawnbackoff/RespawnBackoffData.java index 987c2d8..b14eeab 100644 --- a/src/main/java/net/respawnbackoff/RespawnBackoffData.java +++ b/src/main/java/net/respawnbackoff/RespawnBackoffData.java @@ -30,4 +30,12 @@ public record RespawnBackoffData( public boolean isCooldownFinished(long nowMs) { return cooldownEndEpochMs > 0L && nowMs >= cooldownEndEpochMs; } + + /** + * Spectator wait length in whole minutes if the player dies again now (same formula as the next death). + */ + public long nextDeathWaitMinutes() { + int cappedExp = Math.min(exponent, 6); + return Math.min(1L << cappedExp, 64L); + } } diff --git a/src/main/java/net/respawnbackoff/RespawnBackoffNetworking.java b/src/main/java/net/respawnbackoff/RespawnBackoffNetworking.java index d7a8adc..dcbfbc6 100644 --- a/src/main/java/net/respawnbackoff/RespawnBackoffNetworking.java +++ b/src/main/java/net/respawnbackoff/RespawnBackoffNetworking.java @@ -8,6 +8,11 @@ public final class RespawnBackoffNetworking { } public static void sendCooldown(ServerPlayer player, boolean active, long cooldownEndEpochMs) { - ServerPlayNetworking.send(player, new CooldownSyncPayload(active, cooldownEndEpochMs)); + long nextMinutes = 0L; + if (active) { + RespawnBackoffData data = player.getAttachedOrElse(RespawnBackoffMod.RESPAWN_BACKOFF, RespawnBackoffData.DEFAULT); + nextMinutes = data.nextDeathWaitMinutes(); + } + ServerPlayNetworking.send(player, new CooldownSyncPayload(active, cooldownEndEpochMs, nextMinutes)); } } diff --git a/src/main/resources/assets/respawn_backoff/lang/en_us.json b/src/main/resources/assets/respawn_backoff/lang/en_us.json index 75cb865..e472340 100644 --- a/src/main/resources/assets/respawn_backoff/lang/en_us.json +++ b/src/main/resources/assets/respawn_backoff/lang/en_us.json @@ -1,5 +1,6 @@ { "respawn_backoff.hud.countdown": "Respawn in %s", + "respawn_backoff.hud.next_death": "If you die again: %s min", "respawn_backoff.command.reset.single": "Reset respawn backoff for %s to the minimum (next death: 1 minute).", "respawn_backoff.command.reset.multiple": "Reset respawn backoff to the minimum for %s players.", "respawn_backoff.command.skip.single": "Skipped respawn wait for %s.", diff --git a/src/main/resources/assets/respawn_backoff/lang/ru_ru.json b/src/main/resources/assets/respawn_backoff/lang/ru_ru.json index 4a32ad1..e8659a5 100644 --- a/src/main/resources/assets/respawn_backoff/lang/ru_ru.json +++ b/src/main/resources/assets/respawn_backoff/lang/ru_ru.json @@ -1,5 +1,6 @@ { "respawn_backoff.hud.countdown": "Возрождение через %s", + "respawn_backoff.hud.next_death": "Если умрёте снова: %s мин.", "respawn_backoff.command.reset.single": "Откат респавна для %s сброшен к минимуму (после следующей смерти: 1 минута).", "respawn_backoff.command.reset.multiple": "Откат респавна сброшен к минимуму для %s игроков.", "respawn_backoff.command.skip.single": "Ожидание респавна для %s пропущено.",