Reset at MSK timezone
This commit is contained in:
@@ -6,7 +6,7 @@ minecraft_version=1.21.1
|
|||||||
loader_version=0.18.5
|
loader_version=0.18.5
|
||||||
loom_version=1.15-SNAPSHOT
|
loom_version=1.15-SNAPSHOT
|
||||||
|
|
||||||
mod_version=1.0.0
|
mod_version=1.0.1
|
||||||
maven_group=net.respawnbackoff
|
maven_group=net.respawnbackoff
|
||||||
|
|
||||||
fabric_api_version=0.116.10+1.21.1
|
fabric_api_version=0.116.10+1.21.1
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents;
|
|||||||
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
|
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.gui.GuiGraphics;
|
import net.minecraft.client.gui.GuiGraphics;
|
||||||
|
import net.minecraft.client.renderer.MultiBufferSource;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.respawnbackoff.CooldownSyncPayload;
|
import net.respawnbackoff.CooldownSyncPayload;
|
||||||
|
|
||||||
@@ -27,8 +28,28 @@ public class RespawnBackoffClient implements ClientModInitializer {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Invoked from a mixin at the end of {@link net.minecraft.client.gui.Gui#render} (HUD + chat). Pause UI and toasts draw later. */
|
/**
|
||||||
public static void renderPenaltyOverlay(GuiGraphics graphics) {
|
* Invoked from a mixin at the end of {@link net.minecraft.client.renderer.GameRenderer#render} so chat,
|
||||||
|
* Jade, and other late overlays sit underneath the blackout. Skipped while any screen is open.
|
||||||
|
*/
|
||||||
|
public static void renderPenaltyOverlayEndOfFrame() {
|
||||||
|
if (!overlayActive) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Minecraft client = Minecraft.getInstance();
|
||||||
|
if (client.player == null || client.screen != null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
MultiBufferSource.BufferSource bufferSource = client.renderBuffers().bufferSource();
|
||||||
|
GuiGraphics graphics = new GuiGraphics(client, bufferSource);
|
||||||
|
try {
|
||||||
|
renderPenaltyOverlay(graphics);
|
||||||
|
} finally {
|
||||||
|
graphics.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void renderPenaltyOverlay(GuiGraphics graphics) {
|
||||||
if (!overlayActive) {
|
if (!overlayActive) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package net.respawnbackoff.mixin;
|
||||||
|
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
import net.minecraft.client.DeltaTracker;
|
||||||
|
import net.minecraft.client.renderer.GameRenderer;
|
||||||
|
import net.respawnbackoff.client.RespawnBackoffClient;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw the penalty blackout after the full frame (vanilla HUD, chat, and typical mod overlays like
|
||||||
|
* Jade). Skip while a {@link net.minecraft.client.gui.screens.Screen} is open so pause menus stay unobstructed.
|
||||||
|
*/
|
||||||
|
@Mixin(GameRenderer.class)
|
||||||
|
public class GameRendererMixin {
|
||||||
|
@Inject(method = "render", at = @At("RETURN"))
|
||||||
|
private void respawn_backoff$penaltyOverlayLastInFrame(DeltaTracker deltaTracker, boolean tick, CallbackInfo ci) {
|
||||||
|
RespawnBackoffClient.renderPenaltyOverlayEndOfFrame();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
package net.respawnbackoff.mixin;
|
|
||||||
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|
||||||
|
|
||||||
import net.minecraft.client.DeltaTracker;
|
|
||||||
import net.minecraft.client.gui.Gui;
|
|
||||||
import net.minecraft.client.gui.GuiGraphics;
|
|
||||||
import net.respawnbackoff.client.RespawnBackoffClient;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Draw the penalty screen after the in-game HUD (including chat). Vanilla then draws the pause
|
|
||||||
* menu and toasts on top, so we no longer paint over {@link net.minecraft.client.gui.screens.PauseScreen} widgets.
|
|
||||||
*/
|
|
||||||
@Mixin(Gui.class)
|
|
||||||
public class GuiMixin {
|
|
||||||
@Inject(method = "render", at = @At("RETURN"))
|
|
||||||
private void respawn_backoff$afterInGameHud(GuiGraphics graphics, DeltaTracker deltaTracker, CallbackInfo ci) {
|
|
||||||
RespawnBackoffClient.renderPenaltyOverlay(graphics);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package net.respawnbackoff;
|
package net.respawnbackoff;
|
||||||
|
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.ZoneOffset;
|
import java.time.ZoneId;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@@ -25,6 +25,9 @@ import net.minecraft.world.level.GameType;
|
|||||||
public class RespawnBackoffMod implements ModInitializer {
|
public class RespawnBackoffMod implements ModInitializer {
|
||||||
public static final String MOD_ID = "respawn_backoff";
|
public static final String MOD_ID = "respawn_backoff";
|
||||||
|
|
||||||
|
/** Calendar day for resetting the death-chain exponent: midnight MSK (UTC+3). */
|
||||||
|
private static final ZoneId DAILY_RESET_ZONE = ZoneId.of("Europe/Moscow");
|
||||||
|
|
||||||
public static final AttachmentType<RespawnBackoffData> RESPAWN_BACKOFF = AttachmentRegistry.create(
|
public static final AttachmentType<RespawnBackoffData> RESPAWN_BACKOFF = AttachmentRegistry.create(
|
||||||
ResourceLocation.fromNamespaceAndPath(MOD_ID, "state"),
|
ResourceLocation.fromNamespaceAndPath(MOD_ID, "state"),
|
||||||
builder -> builder
|
builder -> builder
|
||||||
@@ -78,12 +81,12 @@ public class RespawnBackoffMod implements ModInitializer {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static long currentUtcEpochDay() {
|
private static long currentResetEpochDay() {
|
||||||
return LocalDate.now(ZoneOffset.UTC).toEpochDay();
|
return LocalDate.now(DAILY_RESET_ZONE).toEpochDay();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void onPlayerDeath(ServerPlayer player) {
|
static void onPlayerDeath(ServerPlayer player) {
|
||||||
long today = currentUtcEpochDay();
|
long today = currentResetEpochDay();
|
||||||
RespawnBackoffData data = player.getAttachedOrElse(RESPAWN_BACKOFF, RespawnBackoffData.DEFAULT);
|
RespawnBackoffData data = player.getAttachedOrElse(RESPAWN_BACKOFF, RespawnBackoffData.DEFAULT);
|
||||||
|
|
||||||
int exponent = data.exponent();
|
int exponent = data.exponent();
|
||||||
@@ -166,11 +169,11 @@ public class RespawnBackoffMod implements ModInitializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Next death uses the minimum wait (1 minute): exponent 0 and today's UTC day recorded.
|
* Next death uses the minimum wait (1 minute): exponent 0 and today's calendar day (MSK) recorded.
|
||||||
* Does not end an active on-screen countdown; use {@link #skipCooldown} for that.
|
* Does not end an active on-screen countdown; use {@link #skipCooldown} for that.
|
||||||
*/
|
*/
|
||||||
public static void resetBackoffChain(ServerPlayer player) {
|
public static void resetBackoffChain(ServerPlayer player) {
|
||||||
long today = currentUtcEpochDay();
|
long today = currentResetEpochDay();
|
||||||
RespawnBackoffData data = player.getAttachedOrElse(RESPAWN_BACKOFF, RespawnBackoffData.DEFAULT);
|
RespawnBackoffData data = player.getAttachedOrElse(RESPAWN_BACKOFF, RespawnBackoffData.DEFAULT);
|
||||||
RespawnBackoffData next = new RespawnBackoffData(
|
RespawnBackoffData next = new RespawnBackoffData(
|
||||||
0,
|
0,
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
"ServerPlayerGameModeMixin"
|
"ServerPlayerGameModeMixin"
|
||||||
],
|
],
|
||||||
"client": [
|
"client": [
|
||||||
"GuiMixin"
|
"GameRendererMixin"
|
||||||
],
|
],
|
||||||
"injectors": {
|
"injectors": {
|
||||||
"defaultRequire": 1
|
"defaultRequire": 1
|
||||||
|
|||||||
Reference in New Issue
Block a user