Add next death text

This commit is contained in:
2026-04-10 09:41:43 +03:00
parent fb0f7fe358
commit 3660c4dac7
6 changed files with 33 additions and 5 deletions

View File

@@ -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;
}
}

View File

@@ -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<CooldownSyncPayload> 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

View File

@@ -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);
}
}

View File

@@ -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));
}
}

View File

@@ -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.",

View File

@@ -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 пропущено.",