From 18cca8808bc8ede3be02df246308c8fd4adfcc59 Mon Sep 17 00:00:00 2001 From: koka Date: Sat, 29 Aug 2026 11:08:47 +0200 Subject: [PATCH] =?UTF-8?q?fix(sanctuary):=20s=C3=A9parer=20les=20statuts?= =?UTF-8?q?=20du=20Shop?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sanctuary/build.gradle | 10 +++++++++- .../sanctuary/client/SanctuaryShopScreen.java | 8 +++++--- .../sanctuary/client/ShopDailyHeaderLayout.java | 17 +++++++++++++++++ .../client/ShopDailyHeaderLayoutSmoke.java | 16 ++++++++++++++++ 4 files changed, 47 insertions(+), 4 deletions(-) create mode 100644 sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/client/ShopDailyHeaderLayout.java create mode 100644 sanctuary/src/test/java/fr/koka99cab/sanctuary26/sanctuary/client/ShopDailyHeaderLayoutSmoke.java diff --git a/sanctuary/build.gradle b/sanctuary/build.gradle index dc29c49..dcc71a1 100644 --- a/sanctuary/build.gradle +++ b/sanctuary/build.gradle @@ -62,6 +62,14 @@ tasks.register("questRequestModelSmoke", JavaExec) { mainClass = "fr.koka99cab.sanctuary26.sanctuary.shop.QuestRequestModelSmoke" } +tasks.register("shopHeaderLayoutSmoke", JavaExec) { + group = "verification" + description = "Checks that the daily Shop timer and unlocked-offer status cannot overlap." + dependsOn tasks.named("testClasses") + classpath = sourceSets.test.runtimeClasspath + mainClass = "fr.koka99cab.sanctuary26.sanctuary.client.ShopDailyHeaderLayoutSmoke" +} + tasks.register("verifyBlackMarket") { group = "verification" description = "Checks the physical sign market, flash Shop, escrow ledger and mailbox delivery." @@ -212,7 +220,7 @@ tasks.register("verifySanctuary") { inputs.files(fileTree("tools")) dependsOn tasks.named("progressionModelSmoke"), tasks.named("serverIdentityModelSmoke"), tasks.named("shopDeliveryTimingSmoke"), tasks.named("blackMarketModelSmoke"), - tasks.named("questBoardModelSmoke"), + tasks.named("questBoardModelSmoke"), tasks.named("shopHeaderLayoutSmoke"), tasks.named("verifyBlackMarket") doLast { diff --git a/sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/client/SanctuaryShopScreen.java b/sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/client/SanctuaryShopScreen.java index 8b04a9c..cdca491 100644 --- a/sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/client/SanctuaryShopScreen.java +++ b/sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/client/SanctuaryShopScreen.java @@ -171,11 +171,13 @@ public final class SanctuaryShopScreen extends Screen { } else { if (!operatorPage) { if (!catalogPage) graphics.text(font, Component.translatable("screen.sanctuary.shop.flash_timer", - flashTimeRemaining(rendered.flashEndsAtEpochMillis())), layout.left(), 53, 0xFFFFD45C); + flashTimeRemaining(rendered.flashEndsAtEpochMillis())), layout.left(), + ShopDailyHeaderLayout.TIMER_Y, 0xFFFFD45C); drawBalance(graphics); if (!catalogPage && rendered.nextSlotLevelCost() < 0) graphics.centeredText(font, Component.translatable("screen.sanctuary.shop.slots_maximum", rendered.visibleOfferSlots(), PAGE_SIZE), - layout.left() + Math.min(240, layout.width() / 2) / 2, 53, 0xFF80E09A); + layout.left() + Math.min(240, layout.width() / 2) / 2, + ShopDailyHeaderLayout.PROGRESS_Y, 0xFF80E09A); } if (!operatorPage && !rendered.hasDeliveryBox()) graphics.centeredText(font, Component.translatable("screen.sanctuary.shop.no_box"), width / 2, 58, 0xFFFF7070); @@ -293,7 +295,7 @@ public final class SanctuaryShopScreen extends Screen { private GridLayout gridLayout() { int panelWidth = Math.max(240, Math.min(720, width - 12)); int left = width / 2 - panelWidth / 2; - int top = 70; + int top = ShopDailyHeaderLayout.GRID_TOP; int availableHeight = Math.max(174, height - top - 36); return new GridLayout(left, top, panelWidth, availableHeight); } diff --git a/sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/client/ShopDailyHeaderLayout.java b/sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/client/ShopDailyHeaderLayout.java new file mode 100644 index 0000000..6a1d883 --- /dev/null +++ b/sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/client/ShopDailyHeaderLayout.java @@ -0,0 +1,17 @@ +package fr.koka99cab.sanctuary26.sanctuary.client; + +/** Vertical layout reserved for the daily Shop status lines above the offer grid. */ +final class ShopDailyHeaderLayout { + static final int TIMER_Y = 53; + static final int PROGRESS_Y = 63; + static final int GRID_TOP = 74; + + private ShopDailyHeaderLayout() { + } + + static boolean hasSeparatedLines(int fontLineHeight) { + return fontLineHeight > 0 + && TIMER_Y + fontLineHeight <= PROGRESS_Y + && PROGRESS_Y + fontLineHeight <= GRID_TOP; + } +} diff --git a/sanctuary/src/test/java/fr/koka99cab/sanctuary26/sanctuary/client/ShopDailyHeaderLayoutSmoke.java b/sanctuary/src/test/java/fr/koka99cab/sanctuary26/sanctuary/client/ShopDailyHeaderLayoutSmoke.java new file mode 100644 index 0000000..08817f8 --- /dev/null +++ b/sanctuary/src/test/java/fr/koka99cab/sanctuary26/sanctuary/client/ShopDailyHeaderLayoutSmoke.java @@ -0,0 +1,16 @@ +package fr.koka99cab.sanctuary26.sanctuary.client; + +/** Executable smoke coverage for the two-line daily Shop header. */ +public final class ShopDailyHeaderLayoutSmoke { + private ShopDailyHeaderLayoutSmoke() { + } + + public static void main(String[] args) { + if (!ShopDailyHeaderLayout.hasSeparatedLines(9)) { + throw new AssertionError("Shop timer and unlocked-offer status must occupy separate lines"); + } + if (ShopDailyHeaderLayout.hasSeparatedLines(11)) { + throw new AssertionError("Layout check must reject text that would overlap the offer grid"); + } + } +} -- 2.54.0