Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
00d175cb98 | ||
|
|
a7bdfe6998 |
@@ -6,6 +6,18 @@ Créer un monde **Sanctuary** en Petit, Moyen ou Grand, puis activer les ancres
|
||||
correspondantes. Le module Sanctuary Test n’est pas requis.
|
||||
[Intégration et vérification du pack beta.224](docs/four-islands-base224.md).
|
||||
|
||||
## beta.235 — Essai réversible du menu Pause
|
||||
|
||||
[Disposition adaptative](docs/pause-columns-beta235.md) : avant Atlas, Aventure
|
||||
à gauche et Communauté à droite, avec Partie / Game juste dessous. Avec Atlas,
|
||||
une colonne étroite à gauche, Communauté → Aventure → Game, carte au centre.
|
||||
Bloc centré verticalement, libellés de navigation entiers et ordre clavier
|
||||
adapté. Parcours Pause et Story Vulkan FR/EN GUI 2/3/4, `check build assemblePack`
|
||||
et quatre GameTests ciblés réussis.
|
||||
Le commit de disposition `a7bdfe6` peut être annulé indépendamment de la
|
||||
livraison. [MRpack local beta.235](build/Sanctuary-beta.235.mrpack) vérifié,
|
||||
sans publication ni mise à jour personnelle. Le rendu reste à apprécier.
|
||||
|
||||
## beta.234 — Story, recherche et filtres
|
||||
|
||||
[Premier menu Story](docs/story-beta234.md), sous Progression dans Aventure :
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
# Backlog Sanctuary
|
||||
|
||||
## PAUSE-235 — groupes côte à côte avant Atlas — essai livré localement
|
||||
|
||||
Branche `codex/pause-columns-beta235`, base beta.234. Avant Atlas : Aventure à
|
||||
gauche, Communauté à droite et Game juste dessous, bloc centré. Avec Atlas :
|
||||
une colonne étroite à gauche dans l'ordre Communauté → Aventure → Game,
|
||||
carte centrale et fils à droite. [Contrat et vérifications](pause-columns-beta235.md),
|
||||
parcours Vulkan Pause et Story FR/EN GUI 2/3/4, build, quatre GameTests ciblés
|
||||
et MRpack local vérifiés ; rendu à apprécier.
|
||||
Commit de disposition `a7bdfe6` séparé des métadonnées pour permettre son retour.
|
||||
|
||||
## STORY-234 — recueil personnel avec recherche — livré localement
|
||||
|
||||
Branche `codex/story-beta234`, base beta.233. Story sous Progression dans
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
# PAUSE-235 — Aventure et Communauté côte à côte
|
||||
|
||||
Branche d'essai `codex/pause-columns-beta235`, base beta.234, commit `f9c2ce8`,
|
||||
Minecraft 26.3. Le rendu reste à apprécier par le créateur.
|
||||
|
||||
## Disposition et réversibilité
|
||||
|
||||
Avant Atlas, Aventure et Communauté occupent deux colonnes au même niveau :
|
||||
Discovery, Progression et Story à gauche ; Habitant, Faction et Battle à droite.
|
||||
Partie / Game suit juste dessous avec Options, World Options et la sortie
|
||||
native. L'ensemble est centré verticalement dans le corps de Pause, avec de
|
||||
l'espace sous Game ; Reprendre la partie reste dans le pied de page.
|
||||
|
||||
Sans Atlas, ce bloc est centré entre Gazette à gauche et Notice Board à droite.
|
||||
Avec Atlas, une seule colonne étroite est serrée à gauche : Communauté, puis
|
||||
Aventure, puis Partie / Game, selon l'ordre confirmé par le créateur. La carte
|
||||
garde la région centrale et les deux fils communautaires restent à droite.
|
||||
Le bloc complet reste centré verticalement. La largeur minimale des boutons
|
||||
de navigation tient compte des libellés localisés et de leur marge native.
|
||||
Aux petites hauteurs, boutons et espacements se compactent. Tab suit l'ordre
|
||||
visuel : par rangée de gauche à droite avant Atlas, puis de haut en bas avec
|
||||
Atlas. Les libellés FR/EN existants sont réutilisés.
|
||||
|
||||
Le changement de disposition et les assertions correspondantes sont isolés
|
||||
dans le commit `a7bdfe6`, séparé de la livraison et de ses métadonnées. La branche
|
||||
`codex/story-beta234` conserve la disposition précédente. Un retour s'effectue
|
||||
avec `git revert a7bdfe6` ; une éventuelle nouvelle
|
||||
livraison doit prendre le numéro beta suivant, sans diminuer le compteur.
|
||||
L'application inverse du patch a été vérifiée avec `git apply --reverse --check`,
|
||||
sans modifier les fichiers de travail.
|
||||
|
||||
Ce ticket ne change ni génération, sauvegarde, données communautaires, protocole,
|
||||
conditions de progression ou contenus Story. Aucune installation personnelle
|
||||
ou publication n'est demandée.
|
||||
|
||||
## Vérifications
|
||||
|
||||
```sh
|
||||
./gradlew :sanctuary:runClientGameTest -PsanctuaryClientTests=true -PsanctuaryPause233ClientTests=true -PsanctuaryClientGraphicsBackend=vulkan
|
||||
./gradlew :sanctuary:runClientGameTest -PsanctuaryClientTests=true -PsanctuaryStory234ClientTests=true -PsanctuaryClientGraphicsBackend=vulkan
|
||||
./gradlew check build assemblePack -PsanctuaryFocusedTests=menus -PsanctuaryAtlasOnly=true
|
||||
```
|
||||
|
||||
Le parcours Pause final réussit en 1 min 22 s (`PAUSE233_PASS`), dans un monde
|
||||
plat neuf de développement, Survie sans commandes. FR/EN, GUI 2/3/4, fenêtre
|
||||
1280 × 960, avant et après Atlas : six actions Sanctuary, alignement et absence
|
||||
de chevauchement, largeur des libellés avec la marge native, ordre de Tab et
|
||||
Game sous les groupes, avec de l'espace avant le pied. Le test attend désormais
|
||||
un créneau de requête communautaire pour son amorçage et envoie le code de
|
||||
raccourci natif de Tab, requis par Minecraft 26.3.
|
||||
|
||||
Le parcours communautaire existant passe également : publication et photo,
|
||||
retours des sélecteurs, brouillons, édition d'une ancienne catégorie, inventaire
|
||||
réel conservé et aucun changement du fichier communautaire pendant les lectures.
|
||||
La configuration temporaire est restaurée à la fin du banc.
|
||||
Log : `build/pause235-client-vulkan-final.log`. 38 captures finales copiées dans
|
||||
`build/pause235-screenshots/`. Captures inspectées : sans Atlas FR/4, avec Atlas
|
||||
FR/2 et EN/4. Vulkan confirmé : MoltenVK 1.4.2 sur Apple M1.
|
||||
|
||||
Le parcours Story final réussit en 29 s (`STORY234_PASS`), avec les mêmes
|
||||
langues, GUI et états Atlas. Accès depuis les deux dispositions de Pause,
|
||||
100 entrées désactivées, recherche/filtres, saisie continue et focus, molette,
|
||||
redimensionnement à 1344 × 1008 et retours Échap / Terminé vérifiés. Le record
|
||||
de progression serveur ne change pas. Log :
|
||||
`build/pause235-story-client-vulkan-final.log` ; 21 captures copiées dans
|
||||
`build/pause235-story-screenshots/`.
|
||||
|
||||
Aux GUI étroits, les longs libellés natifs des options/sortie et les titres des
|
||||
fils gardent leur défilement ou découpage existant ; les boutons de navigation
|
||||
Sanctuary montrent leur libellé entier. Les infobulles des actions Game sont
|
||||
conservées. Aucun essai OpenGL, Windows ou monde personnel n'est revendiqué.
|
||||
|
||||
Le contrôle `check build assemblePack` réussit en 3 min 1 s : quatre GameTests
|
||||
requis et contrôles purs du dépôt, dont les quatre contrôles communautaires
|
||||
fichier/photos/demandes/recherche. Log : `build/pause235-check-build-pack.log`.
|
||||
Le banc menus conserve sa sélection Atlas existante ; le conflit de générateur
|
||||
sur le chemin natif par défaut, documenté en beta.232, reste hors de ce ticket.
|
||||
|
||||
## Livraison locale
|
||||
|
||||
`mod_version`, `pack_version` et `packwiz/pack.toml` sont alignés sur beta.235.
|
||||
Le commit de livraison conserve ces métadonnées et cette documentation séparées
|
||||
du commit de disposition.
|
||||
|
||||
Export [Sanctuary-beta.235.mrpack](../build/Sanctuary-beta.235.mrpack),
|
||||
12 776 222 octets : intégrité ZIP, Minecraft 26.3 et Fabric Loader 0.19.5,
|
||||
un seul JAR Sanctuary embarqué, identique au JAR construit, sans monde ni module
|
||||
de test. Les 3 303 fichiers d'assets, données et resourcepacks sont identiques
|
||||
à beta.234, traductions incluses. Story reste dans le JAR de production et les
|
||||
classes des bancs client en sont absentes. Reçu :
|
||||
`build/pause235-mrpack-receipt.json`.
|
||||
|
||||
- JAR : `aad94732c749161d775ee634bdd85de70de511ef875c6c00fa167d230d0d600b`.
|
||||
- MRpack : `5f1bd18aa8a4145b7e708da0abfff22068365847dddbc95ae2b490b88bbb305e`.
|
||||
|
||||
Aucune publication distante, modification du canal packwiz, synchronisation
|
||||
Prism ou ouverture d'un monde personnel effectuée.
|
||||
+2
-2
@@ -9,8 +9,8 @@ loom_version=1.17.20
|
||||
fabric_api_version=0.160.5+26.3
|
||||
|
||||
# Release counter: beta.001, .002, .003, ... (see docs/versioning.md).
|
||||
mod_version=beta.234
|
||||
pack_version=beta.234
|
||||
mod_version=beta.235
|
||||
pack_version=beta.235
|
||||
resource_pack_version=beta.121
|
||||
maven_group=fr.koka.sanctuary
|
||||
jei_version=30.32.0-sanctuary.3
|
||||
|
||||
+36
-12
@@ -1,6 +1,7 @@
|
||||
package fr.koka.sanctuary.client;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.mojang.blaze3d.platform.InputConstants;
|
||||
import fr.koka.sanctuary.community.*;
|
||||
import fr.koka.sanctuary.gametest.Starter039TestSupport;
|
||||
import fr.koka.sanctuary.progression.*;
|
||||
@@ -15,6 +16,7 @@ import net.minecraft.client.gui.components.*;
|
||||
import net.minecraft.client.gui.screens.*;
|
||||
import net.minecraft.client.gui.screens.worldselection.WorldCreationUiState;
|
||||
import net.minecraft.network.chat.contents.TranslatableContents;
|
||||
import net.minecraft.client.input.KeyEvent;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.item.*;
|
||||
import static fr.koka.sanctuary.client.Community154ClientChecks.*;
|
||||
@@ -46,7 +48,8 @@ public final class Pause233ClientChecks implements FabricClientGameTest {
|
||||
var server=world.getServer();
|
||||
server.runOnServer(s->{var p=s.getPlayerList().getPlayers().getFirst();p.getAbilities().invulnerable=true;p.getInventory().setItem(6,new ItemStack(Items.OAK_LOG,17));p.getInventory().setItem(7,new ItemStack(Items.DIAMOND,3));});
|
||||
String legacy=UUID.randomUUID().toString();
|
||||
c.runOnClient(m->check(CommunityClient.request(null,"create",legacy,"","notice","event","Ancienne annonce","Texte historique",0,0,r->check(!r.has("error"),"Legacy-compatible notice seeded through the server")),"Seed request dispatched"));
|
||||
// Wait and dispatch together so the periodic following request cannot take the slot between them.
|
||||
c.waitFor(m->CommunityClient.request(null,"create",legacy,"","notice","event","Ancienne annonce","Texte historique",0,0,r->check(!r.has("error"),"Legacy-compatible notice seeded through the server")),200);
|
||||
c.waitFor(m->!CommunityClient.pending(),200);c.waitTicks(24);
|
||||
|
||||
c.runOnClient(m->{m.getWindow().setWindowed(1280,960);m.options.guiScale().set(2);m.resizeGui();CommunityClient.open(new PauseScreen(true),"notice","",true);edit(m.gui.screen()).setValue("Du bois pour le pont");body(m.gui.screen()).setValue("Une annonce commune, avec une demande facultative.");composer(m.gui.screen(),"notice");press(m.gui.screen(),"sanctuary.community.task_configure");press(m.gui.screen(),"sanctuary.community.location_current");press(m.gui.screen(),"sanctuary.community.materials");edit(m.gui.screen()).setValue("minecraft:oak_log");});
|
||||
@@ -86,7 +89,7 @@ public final class Pause233ClientChecks implements FabricClientGameTest {
|
||||
}
|
||||
}
|
||||
server.runOnServer(s->checked(()->{check(Arrays.equals(saved,Files.readAllBytes(s.getWorldPath(net.minecraft.world.level.storage.LevelResource.ROOT).resolve("data/sanctuary-community.json"))),"Reading/resizing old and new posts never rewrites stored categories");return null;}));
|
||||
System.out.println("PAUSE233_PASS: FR/EN GUI 2/3/4, identity/faction/battle at top, discovery/progression centered, options below, unified notice composer, descriptive task and photo publication, legacy category preservation");
|
||||
System.out.println("PAUSE233_PASS: FR/EN GUI 2/3/4, parallel Adventure/Community before Atlas, narrow Community/Adventure stack beside Atlas, Game directly below, centered navigation block, visual Tab order, unified notice composer, descriptive task and photo publication, legacy category preservation");
|
||||
}finally {intro.set(false);checked(()->{if(previous==null)Files.deleteIfExists(config);else Files.write(config,previous);Files.deleteIfExists(fixture);return null;});}
|
||||
}
|
||||
private FileCommunityStore store(net.minecraft.server.MinecraftServer s)throws Exception{return new FileCommunityStore(s.getWorldPath(net.minecraft.world.level.storage.LevelResource.ROOT).resolve("data/sanctuary-community.json"),serverId);}
|
||||
@@ -105,19 +108,40 @@ public final class Pause233ClientChecks implements FabricClientGameTest {
|
||||
check((((PauseAtlasAccess)s).sanctuary$pauseMap()!=null)==unlocked,"Pause map appears only after Atlas purchase");
|
||||
var keys=Set.of("sanctuary.progression.blocks","sanctuary.progression.progress","sanctuary.story.title","sanctuary.progression.identity","sanctuary.cycle.faction","sanctuary.arena.title");
|
||||
var nav=s.children().stream().filter(Button.class::isInstance).map(Button.class::cast).filter(b->keys.contains(key(b))).toList();check(nav.size()==6,"Six Sanctuary navigation actions");
|
||||
int top=nav.stream().mapToInt(AbstractWidget::getY).min().orElseThrow(),bottom=nav.stream().mapToInt(AbstractWidget::getBottom).max().orElseThrow();
|
||||
int options=s.children().stream().filter(Button.class::isInstance).map(Button.class::cast).filter(b->key(b).equals("menu.options")).findFirst().orElseThrow().getY();
|
||||
check(bottom+8<=options,"Navigation stays separated from Options/World Options/Quit");
|
||||
var options=s.children().stream().filter(Button.class::isInstance).map(Button.class::cast).filter(b->key(b).equals("menu.options")).findFirst().orElseThrow();
|
||||
var worldOptions=s.children().stream().filter(Button.class::isInstance).map(Button.class::cast).filter(b->key(b).equals("options.worldOptions.button")).findFirst().orElseThrow();
|
||||
var quit=s.children().stream().filter(Button.class::isInstance).map(Button.class::cast).filter(b->Set.of("menu.returnToMenu","menu.disconnect").contains(key(b))).findFirst().orElseThrow();
|
||||
var community=widget(s,"pause_group_community");var adventure=widget(s,"pause_group_adventure");var game=widget(s,"pause_group_game");
|
||||
check(community.getY()==(s.height<280?46:50)&&community.getBottom()<nav.get(0).getY()&&adventure.getBottom()<nav.get(3).getY()&&game.getBottom()<options,"All three headings precede their buttons");
|
||||
check(nav.stream().map(CommunityPausePanels::key).toList().equals(List.of("sanctuary.progression.identity","sanctuary.cycle.faction","sanctuary.arena.title","sanctuary.progression.blocks","sanctuary.progression.progress","sanctuary.story.title")),"Same visual and keyboard order with or without the map");
|
||||
check(nav.get(0).getBottom()<nav.get(1).getY()&&nav.get(1).getBottom()<nav.get(2).getY()&&nav.get(2).getBottom()<adventure.getY()&&nav.get(3).getBottom()<nav.get(4).getY()&&nav.get(4).getBottom()<nav.get(5).getY()&&nav.get(5).getBottom()<game.getY(),"Three distinct titled groups without overlap");
|
||||
double center=(nav.get(3).getY()+nav.get(5).getBottom())/2.;check(Math.abs(center-s.height/2.)<=.5,"Discovery/progression/story are vertically centered");
|
||||
check(nav.stream().map(CommunityPausePanels::key).toList().equals(unlocked
|
||||
?List.of("sanctuary.progression.identity","sanctuary.cycle.faction","sanctuary.arena.title","sanctuary.progression.blocks","sanctuary.progression.progress","sanctuary.story.title")
|
||||
:List.of("sanctuary.progression.blocks","sanctuary.progression.identity","sanctuary.progression.progress","sanctuary.cycle.faction","sanctuary.story.title","sanctuary.arena.title")),"Navigation follows visual order in both layouts");
|
||||
for(var button:nav)check(s.getFont().width(button.getMessage())+8<=button.getWidth(),"Navigation labels fit with native button padding");
|
||||
check(nav.stream().allMatch(b->b.getBottom()<game.getY())&&game.getBottom()<options.getY()&&options.getBottom()<worldOptions.getY()&&worldOptions.getBottom()<quit.getY(),"Game follows below Sanctuary navigation");
|
||||
check(options.getX()==nav.get(0).getX()&&worldOptions.getX()==options.getX()&&quit.getX()==options.getX()&&worldOptions.getWidth()==options.getWidth()&&quit.getWidth()==options.getWidth(),"Native Game actions share the navigation block width");
|
||||
int bodyTop=s.height<280?46:50,bodyBottom=s.height-39;
|
||||
check(Math.abs((Math.min(adventure.getY(),community.getY())+quit.getBottom())/2.-(bodyTop+bodyBottom)/2.)<=.5&&quit.getBottom()+8<=bodyBottom,"Complete block centered with clear space below Game");
|
||||
// KeyEvent carries the physical key and the SDL shortcut key separately.
|
||||
s.setFocused(nav.get(0));s.keyPressed(new KeyEvent(InputConstants.KEY_TAB,'\t',0));check(s.getFocused()==nav.get(1),"Tab follows the second visible action");
|
||||
s.keyPressed(new KeyEvent(InputConstants.KEY_TAB,'\t',0));check(s.getFocused()==nav.get(2),"Tab follows the third visible action");
|
||||
if(!unlocked){
|
||||
for(var b:nav)check(Math.abs(b.getX()+b.getWidth()/2.-s.width/2.)<=.5,"Navigation centered horizontally");
|
||||
check(widget(s,"article").getX()==8&&widget(s,"notice").getX()>nav.getFirst().getRight(),"Gazette remains left and Notice Board right");
|
||||
check(adventure.getY()==community.getY()&&adventure.getX()==nav.get(0).getX()&&community.getX()==nav.get(1).getX()&&adventure.getBottom()<nav.get(0).getY(),"Both headings align above their columns");
|
||||
for(int row=0;row<3;row++) {
|
||||
var left=nav.get(2*row);var right=nav.get(2*row+1);
|
||||
check(left.getY()==right.getY()&&left.getHeight()==right.getHeight()&&left.getRight()<right.getX(),"Two parallel columns without overlap");
|
||||
if(row>0)check(nav.get(2*row-2).getBottom()<left.getY(),"Rows remain separated");
|
||||
}
|
||||
check(options.getRight()==nav.get(1).getRight(),"Game spans both columns before Atlas");
|
||||
check(Math.abs((nav.get(0).getX()+nav.get(1).getRight())/2.-s.width/2.)<=.5,"Two-column block centered horizontally");
|
||||
check(widget(s,"article").getX()==8&&widget(s,"article").getRight()<nav.get(0).getX()&&widget(s,"notice").getX()>nav.get(1).getRight(),"Gazette remains left and Notice Board right");
|
||||
}
|
||||
else {
|
||||
check(community.getBottom()<nav.get(0).getY()&&nav.get(2).getBottom()<adventure.getY()&&adventure.getBottom()<nav.get(3).getY(),"Community then Adventure stacked above Game with Atlas");
|
||||
for(int i=0;i<nav.size();i++) {
|
||||
var button=nav.get(i);check(button.getX()==8&&button.getWidth()==options.getWidth()&&button.getWidth()<=132,"All actions use one narrow left column");
|
||||
if(i>0)check(nav.get(i-1).getBottom()<button.getY(),"Stacked buttons remain separated");
|
||||
}
|
||||
var map=((PauseAtlasAccess)s).sanctuary$pauseMap();check(nav.get(0).getRight()<map.getX()&&map.getRight()<widget(s,"article").getX()&&widget(s,"article").getX()==widget(s,"notice").getX(),"Narrow navigation left, map center and community feeds right");
|
||||
}
|
||||
else check(nav.getFirst().getX()==8&&widget(s,"article").getX()==widget(s,"notice").getX(),"Unlocked map retains left navigation and community feeds on the right");
|
||||
}
|
||||
private void shot(ClientGameTestContext c,String name){var path=c.takeScreenshot("pause233-"+name);checked(()->{var dir=game.resolve("../../../../../build/pause233-screenshots").normalize();Files.createDirectories(dir);Files.copy(path,dir.resolve(name+".png"),StandardCopyOption.REPLACE_EXISTING);return null;});}
|
||||
private interface Checked<T>{T run()throws Exception;}
|
||||
|
||||
+2
-1
@@ -54,7 +54,8 @@ public final class Solo232ClientChecks implements FabricClientGameTest {
|
||||
var article=heading(screen,"sanctuary.community.article");var notice=heading(screen,"sanctuary.community.notice");
|
||||
if(!unlocked){check(article.getX()==8&&article.getY()==(screen.height<280?46:50)&¬ice.getY()==article.getY(),"Locked map uses full-height Gazette on the left and Notice Board on the right");for(var button:buttons)check(article.getRight()<button.getX()&¬ice.getX()>button.getRight(),"Community columns do not overlap centered navigation");}
|
||||
else check(article.getX()==notice.getX()&&article.getY()<notice.getY(),"Unlocked map retains both community feeds stacked on the right");
|
||||
for(var button:buttons){check(button.getY()>=50&&button.getBottom()<=screen.height-33,"Button stays in pause body");if(!unlocked)check(Math.abs(button.getX()+button.getWidth()/2.-screen.width/2.)<=.5,"Locked-map navigation is horizontally centered");else check(button.getX()==8,"Unlocked layout retains original left column");}
|
||||
for(var button:buttons)check(button.getY()>=50&&button.getBottom()<=screen.height-33,"Button stays in pause body");
|
||||
Pause233ClientChecks.pause(screen,unlocked);
|
||||
});
|
||||
String shot="solo232-pause-"+(unlocked?"unlocked-":"locked-")+language+"-"+scale;
|
||||
var image=c.takeScreenshot(shot);checked(()->{var dir=net.fabricmc.loader.api.FabricLoader.getInstance().getGameDir().resolve("../../../../../build/solo232-screenshots").normalize();java.nio.file.Files.createDirectories(dir);java.nio.file.Files.copy(image,dir.resolve(shot+".png"),java.nio.file.StandardCopyOption.REPLACE_EXISTING);});
|
||||
|
||||
@@ -24,35 +24,44 @@ public final class CommunityPausePanels implements AutoCloseable {
|
||||
public CommunityPausePanels(Screen screen,Consumer<AbstractWidget> add,List<Button> nativeButtons) {
|
||||
this.screen=screen;
|
||||
boolean compact=screen.height<280;
|
||||
int margin=8,gap=10,top=compact?46:50,bottom=screen.height-39;
|
||||
int left=Math.min(132,Math.max(76,screen.width/5)),right=Math.min(244,Math.max(104,screen.width*31/100));
|
||||
int centerX=margin+left+gap,rightX=screen.width-margin-right,centerWidth=rightX-gap-centerX;
|
||||
boolean unlocked=ProgressionClient.progress.atlas();
|
||||
int menuWidth=unlocked?left:Math.max(left,Math.min(200,2*(rightX-gap)-screen.width));
|
||||
int margin=8,gap=10,top=compact?46:50,bottom=screen.height-39;
|
||||
String[] sections={"blocks","identity","progress","faction","story","battle"};
|
||||
int columnGap=compact?4:8;
|
||||
int minimumWidth=Arrays.stream(sections).map(CommunityPausePanels::sectionLabel).mapToInt(Minecraft.getInstance().font::width).max().orElse(0)+8;
|
||||
int columnWidth=Math.max(minimumWidth,(Math.min(264,screen.width/3)-columnGap)/2);
|
||||
int menuWidth=unlocked?Math.max(minimumWidth,Math.min(132,Math.max(76,screen.width/5))):2*columnWidth+columnGap;
|
||||
int right=unlocked?Math.min(244,Math.max(104,screen.width*31/100))
|
||||
:Math.min(244,(screen.width-2*margin-menuWidth-2*gap)/2);
|
||||
int centerX=margin+menuWidth+gap,rightX=screen.width-margin-right,centerWidth=rightX-gap-centerX;
|
||||
int menuX=unlocked?margin:(screen.width-menuWidth)/2;
|
||||
int optionHeight=compact?14:20,navGap=compact?1:4,groupGap=compact?2:12,titleHeight=compact?10:12;
|
||||
int optionsTop=bottom-(3*optionHeight+8);
|
||||
int navHeight=Math.min(20,Math.max(11,(optionsTop-top-3*titleHeight-4*navGap-2*groupGap)/6));
|
||||
// Leave room for Community and its heading above the centered Adventure group.
|
||||
navHeight=Math.min(navHeight,Math.max(11,(screen.height-2*top-4*titleHeight-6*navGap-2*groupGap)/9));
|
||||
int communityX=unlocked?menuX:menuX+columnWidth+columnGap;
|
||||
int navGap=compact?(unlocked?1:2):4,groupGap=compact?(unlocked?2:8):12,titleHeight=compact&&unlocked?10:12;
|
||||
int groupCount=unlocked?3:2;
|
||||
int navHeight=Math.min(compact?14:20,Math.max(11,(bottom-top-16-groupCount*titleHeight-(groupCount-1)*groupGap-2*groupCount*navGap)/(3*groupCount)));
|
||||
int step=navHeight+navGap;
|
||||
int upperTop=top+titleHeight;
|
||||
int adventureSize=3*navHeight+2*navGap;
|
||||
int adventureTop=Math.max(upperTop+2*step+navHeight+groupGap+titleHeight,Math.min((screen.height-adventureSize)/2,optionsTop-titleHeight-adventureSize-groupGap));
|
||||
int sectionHeight=titleHeight+3*navHeight+2*navGap;
|
||||
int menuHeight=groupCount*sectionHeight+(groupCount-1)*groupGap;
|
||||
// Use a narrow stack beside the map, or parallel groups before Atlas.
|
||||
int menuTop=top+Math.max(0,(bottom-top-menuHeight)/2);
|
||||
int adventureTop=unlocked?menuTop+sectionHeight+groupGap:menuTop;
|
||||
int communityTop=menuTop;
|
||||
int gameTop=menuTop+(groupCount-1)*(sectionHeight+groupGap);
|
||||
int optionsTop=gameTop+titleHeight;
|
||||
add.accept(new Frame(screen.width,screen.height));
|
||||
date=new Calendar(margin,3,left);
|
||||
date=new Calendar(margin,3,Math.min(132,Math.max(76,screen.width/5)));
|
||||
add.accept(date);
|
||||
bulletin=new PauseTextButton(centerX,3,screen.width-margin-centerX,38,text("bulletin"),()->open(screen,"bulletin",items("bulletins").isEmpty()?"":str(items("bulletins").get(0).getAsJsonObject(),"id"),false));
|
||||
add.accept(bulletin);
|
||||
add.accept(new StringWidget(menuX,top,menuWidth,9,text("pause_group_community").withStyle(net.minecraft.ChatFormatting.GRAY),Minecraft.getInstance().font));
|
||||
add.accept(new StringWidget(menuX,adventureTop-titleHeight,menuWidth,9,text("pause_group_adventure").withStyle(net.minecraft.ChatFormatting.GRAY),Minecraft.getInstance().font));
|
||||
add.accept(new StringWidget(menuX,optionsTop-titleHeight,menuWidth,9,text("pause_group_game").withStyle(net.minecraft.ChatFormatting.GRAY),Minecraft.getInstance().font));
|
||||
String[] sections={"identity","faction","battle","blocks","progress","story"};
|
||||
add.accept(new StringWidget(menuX,adventureTop,unlocked?menuWidth:columnWidth,9,text("pause_group_adventure").withStyle(net.minecraft.ChatFormatting.GRAY),Minecraft.getInstance().font));
|
||||
add.accept(new StringWidget(communityX,communityTop,unlocked?menuWidth:columnWidth,9,text("pause_group_community").withStyle(net.minecraft.ChatFormatting.GRAY),Minecraft.getInstance().font));
|
||||
add.accept(new StringWidget(menuX,gameTop,menuWidth,9,text("pause_group_game").withStyle(net.minecraft.ChatFormatting.GRAY),Minecraft.getInstance().font));
|
||||
if(unlocked)sections=new String[]{"identity","faction","battle","blocks","progress","story"};
|
||||
for(String target:sections) {
|
||||
int y=switch(target){case "blocks"->adventureTop;case "progress"->adventureTop+step;case "story"->adventureTop+2*step;case "identity"->upperTop;case "faction"->upperTop+step;default->upperTop+2*step;};
|
||||
Component label=switch(target){case "story"->StoryScreen.label("title");case "faction"->fr.koka.sanctuary.cycle.CycleService.label("faction");case "battle"->fr.koka.sanctuary.arena.Arenas.text("title");default->fr.koka.sanctuary.progression.ProgressionService.label(target);};
|
||||
add.accept(Button.builder(label,b->{switch(target){case "faction"->CycleClient.open(screen,"faction");case "battle"->ArenaClient.open(screen);default->ProgressionClient.open(screen,target);}})
|
||||
.bounds(menuX,y,menuWidth,navHeight).build());
|
||||
boolean adventure=target.equals("blocks")||target.equals("progress")||target.equals("story");
|
||||
int y=(adventure?adventureTop:communityTop)+titleHeight+step*switch(target){case "blocks","identity"->0;case "progress","faction"->1;default->2;};
|
||||
add.accept(Button.builder(sectionLabel(target),b->{switch(target){case "faction"->CycleClient.open(screen,"faction");case "battle"->ArenaClient.open(screen);default->ProgressionClient.open(screen,target);}})
|
||||
.bounds(adventure?menuX:communityX,y,unlocked?menuWidth:columnWidth,navHeight).build());
|
||||
}
|
||||
map=unlocked?new PauseAtlasWidget(screen,centerX,top,centerWidth,Math.max(30,bottom-top)):null;
|
||||
if(map!=null)add.accept(map);
|
||||
@@ -61,13 +70,16 @@ public final class CommunityPausePanels implements AutoCloseable {
|
||||
int feedHeight=(bottom-top-gap)/2;
|
||||
articles=new PauseCommunityFeed(screen,add,unlocked?rightX:margin,top,right,unlocked?feedHeight:bottom-top,"article");
|
||||
notices=new PauseCommunityFeed(screen,add,rightX,unlocked?top+feedHeight+gap:top,right,unlocked?bottom-top-feedHeight-gap:bottom-top,"notice");
|
||||
place(nativeButtons,add,"menu.options",menuX,optionsTop,menuWidth,optionHeight);
|
||||
place(nativeButtons,add,"options.worldOptions.button",menuX,optionsTop+optionHeight+4,menuWidth,optionHeight);
|
||||
place(nativeButtons,add,"menu.options",menuX,optionsTop,menuWidth,navHeight);
|
||||
place(nativeButtons,add,"options.worldOptions.button",menuX,optionsTop+step,menuWidth,navHeight);
|
||||
for(var button:nativeButtons) if(key(button).equals("menu.returnToMenu") || key(button).equals("menu.disconnect")) {
|
||||
button.setRectangle(menuWidth,optionHeight,menuX,optionsTop+2*(optionHeight+4));button.setTooltip(Tooltip.create(button.getMessage()));add.accept(button);
|
||||
button.setRectangle(menuWidth,navHeight,menuX,optionsTop+2*step);button.setTooltip(Tooltip.create(button.getMessage()));add.accept(button);
|
||||
}
|
||||
updateHeader();
|
||||
}
|
||||
private static Component sectionLabel(String target) {
|
||||
return switch(target){case "story"->StoryScreen.label("title");case "faction"->fr.koka.sanctuary.cycle.CycleService.label("faction");case "battle"->fr.koka.sanctuary.arena.Arenas.text("title");default->fr.koka.sanctuary.progression.ProgressionService.label(target);};
|
||||
}
|
||||
public static String key(Button button) { return button.getMessage().getContents() instanceof TranslatableContents t?t.getKey():""; }
|
||||
private static void place(List<Button> buttons,Consumer<AbstractWidget> add,String key,int x,int y,int width) {
|
||||
place(buttons,add,key,x,y,width,20);
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
name = "Sanctuary"
|
||||
author = "KOKA99CAB"
|
||||
version = "beta.234"
|
||||
version = "beta.235"
|
||||
pack-format = "packwiz:1.1.0"
|
||||
|
||||
[index]
|
||||
|
||||
Reference in New Issue
Block a user