Compare commits

...
4 Commits
Author SHA1 Message Date
koka 3fd64e1f2a Center sculptures on aimed block middle without half-voxel offsets (beta.119)
Build Sanctuary / build (push) Canceled after 0s
2026-09-17 13:14:54 +02:00
koka 8af406a028 Record verified beta.118 publication and Prism update
Build Sanctuary / build (push) Canceled after 0s
2026-09-17 13:05:40 +02:00
koka 0a81b3c147 Add sixteen native colored brick walls (beta.118)
Build Sanctuary / build (push) Canceled after 0s
2026-09-17 13:03:18 +02:00
koka 68fd97d287 Record verified beta.117 publication and Prism update
Build Sanctuary / build (push) Canceled after 0s
2026-09-17 12:19:54 +02:00
197 changed files with 4211 additions and 42 deletions
+20 -8
View File
@@ -20,13 +20,11 @@ La [vision complète](docs/vision.md) conserve les intentions ; le
L’économie, les claims et les dimensions décrits dans la vision restent
à implémenter.
La version **beta.117** répartit les couleurs exactes des textures de blocs
sur les sculptures, y compris les modèles unis, avec un calcul Java borné
et conservé. Elle corrige aussi les sculptures devenues invisibles après
équipement en chapeau.
Le [ticket de livraison](docs/sculpture-texture-grain-beta117.md) conserve les
contrôles et le suivi de distribution. La livraison est en préparation ;
l'instance **Sanctuary Beta** publiée reste beta.116 jusqu'à sa synchronisation.
La version **beta.119** permet de centrer une sculpture en visant le milieu
du bloc, ou de la caler contre un bord en visant autour. La grille de 1/16
reste respectée, même pour les modèles de taille impaire.
Le [ticket de livraison](docs/sculpture-center-beta119.md) conserve les contrôles
et le suivi de distribution. Les tests natifs, le build et les deux packs sont vérifiés localement.
La [livraison précédente](docs/clay-workshop-integration-beta110.md) réunit déjà
latelier, les œufs et la neige saisonnière dans linstance **Sanctuary Beta**.
Les [synchronisations antérieures](docs/git-sync-beta092.md) restent documentées.
@@ -37,11 +35,25 @@ La [carte native beta.005](docs/atlas-beta005.md) prend le relais après
l’étude de Xaero et des alternatives libres.
## beta.119 — Sculptures au centre ou au bord
Pose selon le point visé, centrage sur la grille entière et ancrage conservé
en sauvegarde. [Contrat et vérifications](docs/sculpture-center-beta119.md).
## beta.118 — Murets en briques colorées
Seize couleurs, fabrication et tailleur de pierre, eau, raccords et collisions
natifs. [Contrat et vérifications](docs/colored-brick-walls-beta118.md) ·
[Pack normal](https://git.botsu.net/koka/sanctuary-beta/releases/download/beta.118/Sanctuary-beta.118.mrpack) ·
[Pack de test](https://git.botsu.net/koka/sanctuary-beta/releases/download/beta.118/Sanctuary-Test-beta.118.mrpack).
## beta.117 — Grain des textures et sculptures en chapeau
Les petits cubes d'une sculpture reprennent plusieurs nuances des textures
de la matière. Le modèle reste intact dans le slot chapeau et au retrait.
[Contrat et vérifications](docs/sculpture-texture-grain-beta117.md).
[Contrat et vérifications](docs/sculpture-texture-grain-beta117.md) ·
[Pack normal](https://git.botsu.net/koka/sanctuary-beta/releases/download/beta.117/Sanctuary-beta.117.mrpack) ·
[Pack de test](https://git.botsu.net/koka/sanctuary-beta/releases/download/beta.117/Sanctuary-Test-beta.117.mrpack).
## beta.116 — Matières de sculpture et Fourneau
+83
View File
@@ -0,0 +1,83 @@
# beta.118 — Murets en briques de couleur
Ticket sur `codex/colored-brick-walls-beta118`, Minecraft 26.3.
Les seize familles de briques reçoivent un muret natif `WallBlock`, sous
l'identifiant `sanctuary:<couleur>_brick_wall`. Chaque muret réutilise la texture
de briques fournie de sa couleur, sans nouvelle image ni recoloration.
Les murets forment une série de seize dans **Blocs colorés**, après les dalles
et avant les argiles, dans l'ordre des couleurs vanilla retenu en beta.103.
Les libellés sont traduits FR/EN.
Recettes : six briques de même couleur, en deux rangées de trois, donnent six
murets ; le tailleur de pierre donne un muret par bloc de briques. Les deux
recettes par couleur rejoignent la collection Argile et briques et leurs
déblocages. Totaux des ajouts colorés : 80 blocs, 112 objets dont ces blocs,
224 recettes. Les recettes et identifiants préexistants sont conservés.
Piliers, raccords entre couleurs et aux murets vanilla, côtés hauts/bas,
collisions et immersion dans l'eau viennent du jeu. Tags natifs `walls`
pour blocs et objets, pioche et butin de la bonne couleur. États, modèles
multipart et butins sont repris des ressources exactes Minecraft 26.3.
La génération reste reproductible dans `tools/generate-colored-bricks.py` ;
elle conserve les ajouts externes à ses briques, notamment la recette du
Clay Workshop et les membres Sculpture/Atelier. Le compilateur des collections
reste leur seul générateur. Aucun ajout au
terrain, changement de format ou migration de sauvegarde. Les dépendances
et le pack de textures intégré beta.090 restent inchangés.
## Vérifications et livraison
Le scénario natif `Bricks102ClientChecks`, complété par `Walls118Checks`,
passe en **38 secondes** sur un nouveau monde plat de graine 102 avec serveur
intégré Minecraft 26.3 :
- Seize murets réellement posés, dont une seconde série dans l'eau.
- Recette de six murets et tailleur de pierre pour chaque couleur ; les
anciennes recettes de briques, dalles, escaliers et argiles passent aussi.
- Raccords entre couleurs et au muret vanilla, retrait des piliers intermédiaires,
côtés relevés sous un bloc plein, collisions identiques au muret vanilla.
- Eau conservée, pioche, butin de la bonne couleur, collection et recettes
découvertes, recette du Clay Workshop toujours découverte, série créative
de seize dans l'ordre natif.
- États et modèles de tous les blocs de la famille vérifiés, sans texture
manquante ; sauvegarde et reconnexion conservent les murets et leur eau.
Log : `build/walls118-client.log`, marqueur `WALLS118_PASS`. Capture de la
galerie relue dans `build/walls118-evidence/`. Aucun essai Windows ou LAN ;
GameTest dédié exclu selon le refus antérieur de son EULA. Aucun monde personnel
ouvert. La régénération finale conserve à l'identique 2 024 fichiers de
ressources et métadonnées.
`check build assemblePack assembleTestPack -x :sanctuary:runGameTest` réussit
en **2 min 5 s**, 125 tâches dont 101 exécutées. Sources et JAR concordants,
intégrité ZIP, versions, modèles natifs, recettes et empreintes vérifiés.
La comparaison avec beta.117 limite les changements de classes à
`ColoredBricks` et ses classes internes ; les sculptures et chapeaux restent
identiques. Les textures existantes sont toutes conservées octet pour octet.
- `Sanctuary-beta.118.mrpack` : 10216437 octets, SHA-256
`75bb04aad981644888690aaeda9a293a94c5d32f6439ca24613365a41aba1b6b`.
- `Sanctuary-Test-beta.118.mrpack` : 10235359 octets, SHA-256
`f7f0a177b8472f0e8c34ad99a1ccef5d61396014017d260e934e910c4e6eb00f`.
- JAR Sanctuary :
`fc6edf4046a8ace357d561ed942213a22c7a27164fa160cdb4316f72ec302575`.
Reçu : `build/walls118-artifact.json`.
## Publication et instance
La [release beta.118](https://git.botsu.net/koka/sanctuary-beta/releases/tag/beta.118)
est publiée : JAR, MRpack normal/Test et amorçage Prism, téléchargements publics
et empreintes vérifiés. Le tag immuable désigne
`0a81b3c1471c43d705eec4e31a8f6f1820049ca8`. Le canal packwiz avance au commit
`e6bab433bea9528f67d39af0d6c7bcb6443e4817`.
Deux synchronisations isolées puis deux dans l'unique instance **Sanctuary
Beta** réussissent, la seconde passe laissant les fichiers gérés identiques.
Un seul JAR Sanctuary beta.118 est actif. Les 923 fichiers personnels et
réglages suivis sont inchangés ; aucun monde personnel n'a été ouvert.
Copie préalable des fichiers remplacés dans `sanctuary-backups/before-beta.118/`.
Reçus : `build/walls118-isolated.json`, `build/walls118-prism.json`.
+23
View File
@@ -14,6 +14,29 @@ JAR Sanctuary sont des pièces jointes de releases Gitea. Aucun JAR de mod ou
dépendance téléchargée n'entre dans l'historique Git. Le canal Beta est distinct
de l'ancien pack 26.2.
## beta.118 — murets en briques colorées
Seize murets natifs, recettes, tailleur, eau et série créative par couleurs.
[Contrat et vérifications](colored-brick-walls-beta118.md).
[Release beta.118](https://git.botsu.net/koka/sanctuary-beta/releases/tag/beta.118)
publiée ; canal `e6bab433bea9528f67d39af0d6c7bcb6443e4817`. Deux
synchronisations isolées puis deux dans la même instance **Sanctuary Beta**
réussies. Les 923 fichiers personnels et réglages suivis sont inchangés ;
sauvegardes restées fermées. Copie préalable des fichiers remplacés dans
`sanctuary-backups/before-beta.118/`.
## beta.117 — grain des textures et sculptures en chapeau
Échantillonnage des pixels de plusieurs textures, grain stable même sur un
modèle uni et conservation des données du chapeau.
[Contrat et vérifications](sculpture-texture-grain-beta117.md).
[Release beta.117](https://git.botsu.net/koka/sanctuary-beta/releases/tag/beta.117)
publiée ; canal `a5b75a70f86e42afb8e06ba4daa9880d61c6373e`. Deux
synchronisations isolées puis deux dans la même instance **Sanctuary Beta**
réussies. Les 923 fichiers personnels et réglages suivis sont inchangés ;
sauvegardes restées fermées. Copie préalable des fichiers remplacés dans
`sanctuary-backups/before-beta.117/`.
## beta.116 — palettes de sculpture et Fourneau
Le Clay Workshop utilise les nuances des textures de blocs ; le Fourneau
+71
View File
@@ -0,0 +1,71 @@
# STAT-07 — Pose centrée des sculptures — beta.119
Contrat du 17 septembre 2026, branche `codex/sculpture-center-beta119`.
Viser le carré central de 8 × 8 pixels de la face supérieure ou inférieure
du bloc place la sculpture au centre. Les limites de cette zone sont incluses.
Autour, le bord horizontal le plus proche reste choisi ; une pose latérale
continue à s'appuyer contre le bloc support. L'orientation suit le regard.
L'aide du Clay Workshop explique les deux possibilités en français et anglais.
Le centrage utilise l'emprise réelle des voxels après rotation, en ignorant les
marges transparentes. Tous les sommets restent sur la grille de 1/16 de bloc.
Une dimension impaire ne peut pas être parfaitement symétrique dans un bloc de
16 pixels sans décaler ses voxels : elle prend donc le centrage entier le plus
proche, avec un pixel de différence entre les deux marges. Aucune position à
un demi-voxel n'est introduite.
## Compatibilité
La pose réutilise `anchor=center`, déjà présent depuis beta.113. Aucun nouvel
état, identifiant, composant ou format de sauvegarde. Les sculptures existantes
gardent leur ancrage ; casser et reposer choisit l'emplacement visé. Le rendu,
les couleurs, les chapeaux et les collisions restent inchangés. Aucun parcours
de monde existant, aucune régénération. Client et serveur doivent utiliser
ensemble la nouvelle version pour le choix de pose.
## Vérifications et livraison
Le parcours natif `Statuary106ClientChecks`, avec `Sculpture113ClientChecks`,
passe en **54 s** sur Minecraft 26.3/macOS :
- Vrais clics de pose centrée dans quatre orientations, sur client et serveur,
puis pose contre les quatre bords sans modifier les couleurs du modèle.
- Limites incluses et points immédiatement de part et d'autre de la zone,
faces supérieure/inférieure et positions positives/négatives ; faces
latérales toujours calées contre le support.
- 5 120 combinaisons de largeur/profondeur, orientation et ancrage : géométrie
effectivement rendue sur la grille exacte, emprise sans dépassement,
centrage pair/impair et marges transparentes.
- Sauvegarde/reconnexion des sculptures centrées et aux bords, sans fichier
source ; rotations/miroirs, anciens états, fabrication et hotbar vérifiés.
```sh
./gradlew :sanctuary:runClientGameTest \
-PsanctuaryClientTests=true -PsanctuaryStatuary106ClientTests=true \
-PsanctuaryClientNoVsync=true -PsanctuaryQuickTests=true
```
Marqueurs `SCULPTURE119_PASS`, `STATUARY113_PASS` et
`SCULPTURE113_GEOMETRY_PASS` dans `build/sculpture119-client.log`.
Captures conservées dans `build/sculpture119-evidence/`, vue centrée relue.
Monde plat jetable de graine 106 ; aucun monde personnel ouvert. Pas de
validation Windows ni de test depuis deux ordinateurs.
Le GameTest dédié reste exclu conformément au refus antérieur de son EULA ;
le parcours natif utilise le serveur intégré.
`./gradlew check build assemblePack assembleTestPack -x :sanctuary:runGameTest`
passe en **2 min 24 s**, 125 tâches. Les sources JAR correspondent aux sources
du dépôt ; seuls `SculptureAnchor.class` et le texte d'aide FR/EN diffèrent
parmi les classes et ressources de production de beta.118. Les deux packs
contiennent le même JAR, sans monde ni fixture de test.
- Sanctuary-beta.119.mrpack : 10216447 octets, SHA-256
`ce29702eaaac7301c77fb6af63a76c6bc1c0c704313ce1b8243c95b5fe59d893`.
- Sanctuary-Test-beta.119.mrpack : 10235369 octets, SHA-256
`a1a2845f9678b1144d7d9eab4867970cc1776fe0ad5d51722c8110b7c1d4c682`.
- JAR Sanctuary : SHA-256
`d353bd89b16c53ee1ee48836fa2ff4b311249b280992300c28bf03048d805bff`.
Reçu local : `build/sculpture119-artifact.json`. Publication et synchronisation
Prism à consigner après leur réussite.
+16 -2
View File
@@ -92,5 +92,19 @@ Les modèles de test et classes de GameTest sont absents de la livraison.
- JAR Sanctuary :
`1ce63f97f17c6098f3c86c6753f9b912bce39d88e05ba240423c38bdc97307ee`.
Reçu : `build/sculpture117-artifact.json`. Publication et synchronisation
finales en cours.
Reçu : `build/sculpture117-artifact.json`.
## Publication et instance
La [release beta.117](https://git.botsu.net/koka/sanctuary-beta/releases/tag/beta.117)
est publiée : JAR, MRpack normal/Test et amorçage Prism, téléchargements publics
et empreintes vérifiés. Le tag immuable désigne
`0f1efdec830342e25d3316b356330ad937d0d942`. Le canal packwiz avance au commit
`a5b75a70f86e42afb8e06ba4daa9880d61c6373e`.
Deux synchronisations isolées puis deux dans l'unique instance **Sanctuary
Beta** réussissent, la seconde passe laissant les fichiers gérés identiques.
Un seul JAR Sanctuary beta.117 est actif. Les 923 fichiers personnels et
réglages suivis sont inchangés ; aucun monde personnel n'a été ouvert.
Copie préalable des fichiers remplacés dans `sanctuary-backups/before-beta.117/`.
Reçus : `build/sculpture117-isolated.json`, `build/sculpture117-prism.json`.
+2 -2
View File
@@ -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.117
pack_version=beta.117
mod_version=beta.119
pack_version=beta.119
resource_pack_version=beta.090
maven_group=fr.koka.sanctuary
jei_version=30.32.0-sanctuary.3
@@ -37,10 +37,10 @@ public final class Bricks102ClientChecks implements FabricClientGameTest {
c.waitFor(m->ProgressionClient.active()&&m.player!=null&&m.gui.screen()==null&&!IntroSpawnFlash.active(),1200);
world.getServer().runOnServer(s->{
var p=s.getPlayerList().getPlayers().getFirst();var level=p.level();var pos=new BlockPos(0,3,0);
check(ColoredBricks.families().size()==16,"All colors registered");int index=0;
check(ColoredBricks.families().size()==16,"All colors registered");Walls118Checks.server(s);int index=0;
for(var f:ColoredBricks.families()){
String color=f.color().getName();
for(var block:List.of(f.bricks(),f.slab(),f.stairs(),f.clay()))check(block.asItem()!=Items.AIR,"Block item exists "+block);
for(var block:List.of(f.bricks(),f.slab(),f.stairs(),f.wall(),f.clay()))check(block.asItem()!=Items.AIR,"Block item exists "+block);
check(f.bricks().defaultBlockState().is(BlockTags.MINEABLE_WITH_PICKAXE),"Pickaxe tag "+color);
check(f.clay().defaultBlockState().is(BlockTags.MINEABLE_WITH_SHOVEL),"Shovel tag "+color);
var shovel=new ItemStack(Items.DIAMOND_SHOVEL);var silk=shovel.copy();silk.enchant(level.registryAccess().lookupOrThrow(Registries.ENCHANTMENT).getOrThrow(Enchantments.SILK_TOUCH),1);
@@ -52,7 +52,7 @@ public final class Bricks102ClientChecks implements FabricClientGameTest {
drop(Block.getDrops(f.stairs().defaultBlockState(),level,pos,null),f.stairs().asItem(),1);
check(f.slab().defaultBlockState().setValue(SlabBlock.WATERLOGGED,true).getFluidState().isSource(),"Slab water "+color);
check(f.stairs().defaultBlockState().setValue(StairBlock.WATERLOGGED,true).getFluidState().isSource(),"Stair water "+color);
for(String suffix:List.of("clay_ball_from_dye","clay_from_dye","brick_from_dye","bricks_from_dye","clay","bricks","brick_slab","brick_stairs","brick_slab_from_stonecutting","brick_stairs_from_stonecutting","clay_ball_smelting","clay_smelting"))check(s.getRecipeManager().byKey(ResourceKey.create(Registries.RECIPE,SanctuaryMod.id(color+"_"+suffix))).isPresent(),"Recipe loaded "+color+"_"+suffix);
for(String suffix:List.of("clay_ball_from_dye","clay_from_dye","brick_from_dye","bricks_from_dye","clay","bricks","brick_slab","brick_stairs","brick_slab_from_stonecutting","brick_stairs_from_stonecutting","brick_wall","brick_wall_from_stonecutting","clay_ball_smelting","clay_smelting"))check(s.getRecipeManager().byKey(ResourceKey.create(Registries.RECIPE,SanctuaryMod.id(color+"_"+suffix))).isPresent(),"Recipe loaded "+color+"_"+suffix);
craft(s,level,2,2,List.of(f.brick(),f.brick(),f.brick(),f.brick()),f.bricks().asItem(),1);
craft(s,level,2,2,List.of(f.clayBall(),f.clayBall(),f.clayBall(),f.clayBall()),f.clay().asItem(),1);
craft(s,level,3,1,List.of(f.bricks().asItem(),f.bricks().asItem(),f.bricks().asItem()),f.slab().asItem(),6);
@@ -62,39 +62,40 @@ public final class Bricks102ClientChecks implements FabricClientGameTest {
var input=new SingleRecipeInput(new ItemStack(f.clayBall()));var cooked=s.getRecipeManager().getRecipeFor(RecipeType.SMELTING,input,level).orElseThrow().value().assemble(input);check(cooked.is(f.brick()),"Smelt brick "+color);
input=new SingleRecipeInput(new ItemStack(f.clay()));cooked=s.getRecipeManager().getRecipeFor(RecipeType.SMELTING,input,level).orElseThrow().value().assemble(input);check(cooked.is(BuiltInRegistries.ITEM.getValue(net.minecraft.resources.Identifier.withDefaultNamespace(color+"_terracotta"))),"Smelt terracotta "+color);
var stoneInput=new SingleRecipeInput(new ItemStack(f.bricks()));
for(var variant:List.of(new Object[]{"brick_slab",f.slab().asItem(),2},new Object[]{"brick_stairs",f.stairs().asItem(),1})){
for(var variant:List.of(new Object[]{"brick_slab",f.slab().asItem(),2},new Object[]{"brick_stairs",f.stairs().asItem(),1},new Object[]{"brick_wall",f.wall().asItem(),1})){
var recipe=(StonecutterRecipe)s.getRecipeManager().byKey(ResourceKey.create(Registries.RECIPE,SanctuaryMod.id(color+"_"+variant[0]+"_from_stonecutting"))).orElseThrow().value();check(recipe.matches(stoneInput,level),"Stonecutting accepts input");var cut=recipe.assemble(stoneInput);check(cut.is((Item)variant[1])&&cut.getCount()==(int)variant[2],"Stonecutting result");
}
int x=(index%8)*3,z=(index/8)*5;level.setBlockAndUpdate(new BlockPos(x,1,z),f.bricks().defaultBlockState());level.setBlockAndUpdate(new BlockPos(x,2,z),f.slab().defaultBlockState().setValue(SlabBlock.TYPE,SlabType.TOP));level.setBlockAndUpdate(new BlockPos(x+1,1,z),f.stairs().defaultBlockState().setValue(StairBlock.FACING,Direction.SOUTH));level.setBlockAndUpdate(new BlockPos(x,1,z+1),f.clay().defaultBlockState());index++;
}
fr.koka.sanctuary.recipes.RecipeService.discover(p,Items.CLAY_BALL);fr.koka.sanctuary.recipes.RecipeService.refresh(p);
var known=fr.koka.sanctuary.recipes.RecipeService.knowledge(p);
for(var f:ColoredBricks.families())check(known.recipes.contains("sanctuary:"+f.color().getName()+"_brick_stairs_from_stonecutting"),"Collection unlock "+f.color());
check(known.recipes.contains("sanctuary:clay_workshop"),"Existing workshop recipe remains discoverable");
for(var f:ColoredBricks.families())check(known.recipes.contains("sanctuary:"+f.color().getName()+"_brick_stairs_from_stonecutting")&&known.recipes.contains("sanctuary:"+f.color().getName()+"_brick_wall")&&known.recipes.contains("sanctuary:"+f.color().getName()+"_brick_wall_from_stonecutting"),"Collection unlock "+f.color());
s.getCommands().performPrefixedCommand(s.createCommandSourceStack(),"sanctuary time vanilla");s.getCommands().performPrefixedCommand(s.createCommandSourceStack(),"time set noon");
p.teleportTo(11,8,19);p.setYRot(180);p.setXRot(26);p.getAbilities().flying=true;p.onUpdateAbilities();
});
c.runOnClient(m->{
CreativeModeTabs.tryRebuildTabContents(m.level.enabledFeatures(),true,m.level.registryAccess());
var blocks=BuiltInRegistries.CREATIVE_MODE_TAB.getOrThrow(CreativeModeTabs.COLORED_BLOCKS).value().getDisplayItems();
var ingredients=BuiltInRegistries.CREATIVE_MODE_TAB.getOrThrow(CreativeModeTabs.INGREDIENTS).value().getDisplayItems();
var ingredients=BuiltInRegistries.CREATIVE_MODE_TAB.getOrThrow(CreativeModeTabs.INGREDIENTS).value().getDisplayItems();Walls118Checks.creative(new ArrayList<>(blocks));
for(var f:ColoredBricks.families()){
for(var b:List.of(f.bricks(),f.slab(),f.stairs(),f.clay())){
for(var b:List.of(f.bricks(),f.slab(),f.stairs(),f.wall(),f.clay())){
check(blocks.stream().anyMatch(i->i.is(b.asItem())),"Creative color tab "+b);
for(var state:b.getStateDefinition().getPossibleStates()){
var parts=new ArrayList<net.minecraft.client.renderer.block.dispatch.BlockStateModelPart>();m.getModelManager().getBlockStateModelSet().get(state).collectParts(net.minecraft.util.RandomSource.create(0),parts);check(!parts.isEmpty(),"Baked model "+state);
var parts=new ArrayList<net.minecraft.client.renderer.block.dispatch.BlockStateModelPart>();m.getModelManager().getBlockStateModelSet().get(state).collectParts(net.minecraft.util.RandomSource.create(0),parts);check(b instanceof WallBlock||!parts.isEmpty(),"Baked model "+state);
for(var part:parts)for(var direction:new Direction[]{Direction.UP,Direction.DOWN,Direction.NORTH,Direction.SOUTH,Direction.EAST,Direction.WEST,null})for(var quad:part.getQuads(direction))check(!quad.materialInfo().sprite().contents().name().toString().contains("missingno"),"No missing texture "+state);
}
}
for(var item:List.of(f.clayBall(),f.brick()))check(ingredients.stream().anyMatch(i->i.is(item)),"Creative ingredients "+item);
}
});
c.waitTicks(20);c.runOnClient(m->{m.player.setYRot(180);m.player.setXRot(26);});c.waitTicks(4);c.takeScreenshot("bricks102-gallery");saved=world.getWorldSave();System.out.println("BRICKS102_NATIVE_PASS colors=16 recipes=192 blocks=64 items=96");
c.waitTicks(20);c.runOnClient(m->{m.player.setYRot(180);m.player.setXRot(26);});c.waitTicks(4);c.takeScreenshot("bricks102-gallery");saved=world.getWorldSave();System.out.println("BRICKS102_NATIVE_PASS colors=16 recipes=224 blocks=80 items=112");
}
try(var world=saved.open()){
c.waitFor(m->m.player!=null&&m.gui.screen()==null,1200);
world.getServer().runOnServer(s->{var level=s.getPlayerList().getPlayers().getFirst().level();int i=0;for(var f:ColoredBricks.families()){var pos=new BlockPos((i%8)*3,1,(i/8)*5);check(level.getBlockState(pos).is(f.bricks()),"Saved bricks "+f.color());check(level.getBlockState(pos.above()).getValue(SlabBlock.TYPE)==SlabType.TOP,"Saved slab state");i++;}});
world.getServer().runOnServer(s->{var level=s.getPlayerList().getPlayers().getFirst().level();Walls118Checks.saved(level);int i=0;for(var f:ColoredBricks.families()){var pos=new BlockPos((i%8)*3,1,(i/8)*5);check(level.getBlockState(pos).is(f.bricks()),"Saved bricks "+f.color());check(level.getBlockState(pos.above()).getValue(SlabBlock.TYPE)==SlabType.TOP,"Saved slab state");i++;}});
}
System.out.println("BRICKS102_PASS");
System.out.println("BRICKS102_PASS");System.out.println("WALLS118_PASS native placement, mixed connections, tall sides, waterlogging, collision, crafting, stonecutting, loot, collection, creative order, baked models and reconnect");
}
private static void craft(net.minecraft.server.MinecraftServer s,net.minecraft.server.level.ServerLevel level,int w,int h,List<Item> items,Item result,int count){var input=CraftingInput.of(w,h,items.stream().map(ItemStack::new).toList());var stack=s.getRecipeManager().getRecipeFor(RecipeType.CRAFTING,input,level).orElseThrow().value().assemble(input);check(stack.is(result)&&stack.getCount()==count,"Craft "+result);}
private static void drop(List<ItemStack> drops,Item item,int count){check(drops.size()==1&&drops.getFirst().is(item)&&drops.getFirst().getCount()==count,"Loot "+item+" expected "+count+" got "+drops);}
@@ -18,7 +18,20 @@ import net.minecraft.world.phys.*;
final class Sculpture113ClientChecks {
static void placementContexts(ServerPlayer player){
for(var pos:List.of(new BlockPos(2,0,-2),new BlockPos(-2,0,2))){
for(var face:List.of(Direction.UP,Direction.DOWN)){
for(double x:new double[]{.25,.5,.75})for(double z:new double[]{.25,.5,.75}){
var hit=new Vec3(pos.getX()+x,pos.getY()+(face==Direction.UP?1:0),pos.getZ()+z);
var context=new BlockPlaceContext(player,InteractionHand.MAIN_HAND,new ItemStack(Statuary.ITEM),new BlockHitResult(hit,face,pos,false));
check(Statuary.BLOCK.getStateForPlacement(context).getValue(Statuary.ANCHOR)==SculptureAnchor.CENTER,"Middle square including boundaries selects center on top/bottom faces");
}
}
for(var edge:Direction.Plane.HORIZONTAL){
for(double offset:new double[]{.25-1e-6,.25+1e-6}){
var hit=new Vec3(pos.getX()+.5+edge.getStepX()*offset,pos.getY()+1,pos.getZ()+.5+edge.getStepZ()*offset);
var context=new BlockPlaceContext(player,InteractionHand.MAIN_HAND,new ItemStack(Statuary.ITEM),new BlockHitResult(hit,Direction.UP,pos,false));
var expected=offset<.25?SculptureAnchor.CENTER:SculptureAnchor.of(edge);
check(Statuary.BLOCK.getStateForPlacement(context).getValue(Statuary.ANCHOR)==expected,"Center boundary switches to the aimed edge");
}
var top=new Vec3(pos.getX()+.5+edge.getStepX()*.4,pos.getY()+1,pos.getZ()+.5+edge.getStepZ()*.4);
var context=new BlockPlaceContext(player,InteractionHand.MAIN_HAND,new ItemStack(Statuary.ITEM),new BlockHitResult(top,Direction.UP,pos,false));
var state=Statuary.BLOCK.getStateForPlacement(context);
@@ -119,7 +119,14 @@ public final class Statuary106ClientChecks implements FabricClientGameTest {
for(var direction:Direction.Plane.HORIZONTAL){
var pos=DIRECTIONS.get(direction);double px=pos.getX()+.5-direction.getStepX()*2,pz=pos.getZ()+.5-direction.getStepZ()*2;
server.runOnServer(s->{var p=player(s);p.teleportTo(px,1,pz);p.getInventory().setItem(p.getInventory().getSelectedSlot(),StatuaryEntity.item(source));p.inventoryMenu.broadcastFullState();});
c.waitFor(m->m.player.distanceToSqr(px,1,pz)<.05&&m.player.getMainHandItem().is(Statuary.ITEM),150);place(c,pos,direction.getOpposite());
c.waitFor(m->m.player.distanceToSqr(px,1,pz)<.05&&m.player.getMainHandItem().is(Statuary.ITEM),150);place(c,pos);
server.waitFor(s->player(s).level().getBlockState(pos).is(Statuary.BLOCK),100);
server.runOnServer(s->{var state=player(s).level().getBlockState(pos);check(state.getValue(Statuary.FACING)==direction&&state.getValue(Statuary.ANCHOR)==SculptureAnchor.CENTER,"Native center placement follows gaze on server");});
c.waitFor(m->m.level.getBlockEntity(pos) instanceof StatuaryEntity e&&source.equals(e.sculpture())&&e.getBlockState().getValue(Statuary.ANCHOR)==SculptureAnchor.CENTER,100);
c.runOnClient(m->Sculpture113ClientChecks.rendered((StatuaryEntity)m.level.getBlockEntity(pos)));
c.takeScreenshot("sculpture119-center-"+direction.getSerializedName());
server.runOnServer(s->{var p=player(s);p.level().removeBlock(pos,false);p.getInventory().setItem(p.getInventory().getSelectedSlot(),StatuaryEntity.item(source));p.inventoryMenu.broadcastFullState();});
c.waitFor(m->m.level.getBlockState(pos).isAir()&&m.player.getMainHandItem().is(Statuary.ITEM),100);place(c,pos,direction.getOpposite());
server.waitFor(s->player(s).level().getBlockState(pos).is(Statuary.BLOCK),100);
server.runOnServer(s->{var state=player(s).level().getBlockState(pos);check(state.getValue(Statuary.FACING)==direction,"Native placement faces gaze: "+direction);
check(state.getValue(Statuary.ANCHOR)==SculptureAnchor.of(direction.getOpposite()),"Aimed edge stored on server");
@@ -189,12 +196,14 @@ public final class Statuary106ClientChecks implements FabricClientGameTest {
server.runOnServer(s->check(player(s).level().getBlockState(pos).getValue(Statuary.ANCHOR)==SculptureAnchor.of(direction.getOpposite()),"Anchor survives server save/reload"));
c.waitFor(m->m.level.getBlockEntity(pos) instanceof StatuaryEntity e&&ORIGINAL.get().equals(e.sculpture())&&e.getBlockState().getValue(Statuary.FACING)==direction,150);
}
c.waitFor(m->m.level.getBlockEntity(SCULPTURE) instanceof StatuaryEntity e&&e.sculpture()!=null,150);c.runOnClient(m->check(((StatuaryEntity)m.level.getBlockEntity(SCULPTURE)).sculpture().equals(ORIGINAL.get()),"Fresh client receives server model without file"));
server.runOnServer(s->check(player(s).level().getBlockState(SCULPTURE).getValue(Statuary.ANCHOR)==SculptureAnchor.CENTER,"Centered placement survives server save/reload"));
c.waitFor(m->m.level.getBlockEntity(SCULPTURE) instanceof StatuaryEntity e&&e.sculpture()!=null,150);c.runOnClient(m->{check(((StatuaryEntity)m.level.getBlockEntity(SCULPTURE)).sculpture().equals(ORIGINAL.get()),"Fresh client receives server model without file");check(m.level.getBlockState(SCULPTURE).getValue(Statuary.ANCHOR)==SculptureAnchor.CENTER,"Fresh client receives centered anchor");});
c.getInput().lookAt(SCULPTURE);c.takeScreenshot("statuary106-reload-no-source");
}
System.out.println("STATUARY106_PASS GLB textured scene, bounded import, shared folder filters, native paid crafting, 16 clay colors, model ID, shift-click, place/drop/re-place, Metabli plan, cancellation, server save/reconnect without source");
System.out.println("STATUARY111_PASS nine-slice GUI FR/EN scales 2/3, four native gaze placements, renderer directions, structure rotation/mirror, legacy state default, drop/re-place and persisted orientation");
System.out.println("STATUARY113_PASS clay sculpture FR/EN, native aimed edges, voxel grid across every footprint/orientation/anchor, side placement, legacy states, rotated/mirrored anchor, save/reconnect");
System.out.println("SCULPTURE119_PASS native centered placements in four directions, center/edge boundaries, odd/even voxel grid, side anchoring and center save/reconnect");
System.out.println("STATUARY112_PASS fixed compact hotbar-only menu, native input transfer, hidden slots/offhand rejected, full hotbar no consumption, partial merge exact cost, closing restitution");
}catch(IOException e){throw new AssertionError(e);}finally{try{Files.deleteIfExists(file);}catch(IOException ignored){}}
}
@@ -0,0 +1,73 @@
package fr.koka.sanctuary.client;
import fr.koka.sanctuary.building.ColoredBricks;
import java.util.*;
import net.minecraft.core.*;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.tags.*;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.item.*;
import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.item.crafting.*;
import net.minecraft.world.level.block.*;
import net.minecraft.world.level.block.state.properties.WallSide;
import net.minecraft.world.phys.*;
/** Gameplay regressions using native placement, neighbor updates and recipe matching. */
final class Walls118Checks {
static void server(MinecraftServer server){
var player=server.getPlayerList().getPlayers().getFirst();var level=player.level();
for(int x=-1;x<=17;x++)for(int z=9;z<=13;z++)level.setBlockAndUpdate(new BlockPos(x,0,z),Blocks.STONE.defaultBlockState());
int index=0;
for(var family:ColoredBricks.families()){
var wall=family.wall();var state=wall.defaultBlockState();
check(wall instanceof WallBlock&&state.is(BlockTags.WALLS)&&state.is(BlockTags.MINEABLE_WITH_PICKAXE),"Native wall type, connection and mining tags");
check(new ItemStack(wall).is(ItemTags.WALLS),"Native wall item tag");
var input=CraftingInput.of(3,2,Collections.nCopies(6,new ItemStack(family.bricks())));
var recipe=server.getRecipeManager().getRecipeFor(RecipeType.CRAFTING,input,level).orElseThrow().value();var result=recipe.assemble(input);
check(result.is(wall.asItem())&&result.getCount()==6,"Six matching bricks craft six walls");
var drops=Block.getDrops(state,level,new BlockPos(0,2,0),null,player,new ItemStack(Items.DIAMOND_PICKAXE));
check(drops.size()==1&&drops.getFirst().is(wall.asItem())&&drops.getFirst().getCount()==1,"Wall drops its own color");
for(int z:new int[]{10,12}){
var pos=new BlockPos(index,1,z);
player.teleportTo(index+.5,1,z+2.5);
if(z==12)level.setBlockAndUpdate(pos,Blocks.WATER.defaultBlockState());
player.setItemInHand(InteractionHand.MAIN_HAND,new ItemStack(wall));
var hit=new BlockHitResult(Vec3.atBottomCenterOf(pos),Direction.UP,pos.below(),false);
var placed=player.getMainHandItem().useOn(new UseOnContext(player,InteractionHand.MAIN_HAND,hit));
check(placed.consumesAction(),"Native wall item placement: "+family.color()+" at "+pos+" = "+placed+", existing "+level.getBlockState(pos));
check(level.getBlockState(pos).is(wall),"Placed wall keeps its color");
check(level.getBlockState(pos).getValue(WallBlock.WATERLOGGED)==(z==12),"Native waterlogging on placement");
}
index++;
}
for(int i=1;i<15;i++){
var pos=new BlockPos(i,1,10);var state=level.getBlockState(pos);
check(state.getValue(WallBlock.EAST)==WallSide.LOW&&state.getValue(WallBlock.WEST)==WallSide.LOW&&!state.getValue(WallBlock.UP),"Mixed-color straight wall removes middle post");
level.setBlockAndUpdate(pos.above(),Blocks.STONE.defaultBlockState());
state=level.getBlockState(pos);check(state.getValue(WallBlock.EAST)==WallSide.TALL&&state.getValue(WallBlock.WEST)==WallSide.TALL,"Full block above raises connected sides");
var vanilla=Blocks.BRICK_WALL.withPropertiesOf(state);
check(state.getCollisionShape(level,pos).toAabbs().equals(vanilla.getCollisionShape(level,pos).toAabbs()),"Collision equals native brick wall");
level.removeBlock(pos.above(),false);
}
var end=new BlockPos(16,1,10);level.setBlockAndUpdate(end,Blocks.BRICK_WALL.defaultBlockState());
check(level.getBlockState(end.west()).getValue(WallBlock.EAST)==WallSide.LOW,"Connects to vanilla brick wall");
saved(level);
}
static void creative(List<ItemStack> display){
var colors=List.of(DyeColor.WHITE,DyeColor.LIGHT_GRAY,DyeColor.GRAY,DyeColor.BLACK,DyeColor.BROWN,DyeColor.RED,DyeColor.ORANGE,DyeColor.YELLOW,DyeColor.LIME,DyeColor.GREEN,DyeColor.CYAN,DyeColor.LIGHT_BLUE,DyeColor.BLUE,DyeColor.PURPLE,DyeColor.MAGENTA,DyeColor.PINK);
var families=ColoredBricks.families().stream().sorted(Comparator.comparingInt(f->colors.indexOf(f.color()))).toList();
int start=-1;for(int i=0;i<display.size();i++)if(display.get(i).is(families.getFirst().wall().asItem())){start=i;break;}
check(start>0,"Wall series is visible in Colored Blocks");
for(int i=0;i<16;i++)check(display.get(start+i).is(families.get(i).wall().asItem()),"Contiguous series of sixteen in native color order");
check(display.get(start-1).is(families.getLast().slab().asItem())&&display.get(start+16).is(families.getFirst().clay().asItem()),"Wall series follows slabs and precedes clay");
}
static void saved(ServerLevel level){
int i=0;for(var family:ColoredBricks.families()){
check(level.getBlockState(new BlockPos(i,1,10)).is(family.wall()),"Persisted wall color");
var wet=level.getBlockState(new BlockPos(i++,1,12));check(wet.is(family.wall())&&wet.getValue(WallBlock.WATERLOGGED)&&wet.getFluidState().isSource(),"Persisted waterlogged wall");
}
}
private static void check(boolean ok,String message){if(!ok)throw new AssertionError(message);}
}
@@ -12,7 +12,7 @@ import net.minecraft.world.level.block.state.BlockBehaviour;
/** Native building blocks; no world-generation, ticking entities or custom inventory. */
public final class ColoredBricks {
public record Family(DyeColor color,Block bricks,Block slab,Block stairs,Block clay,Item clayBall,Item brick){}
public record Family(DyeColor color,Block bricks,Block slab,Block stairs,Block wall,Block clay,Item clayBall,Item brick){}
private static final List<Family> FAMILIES=new ArrayList<>();
// The order used by the native 26.3 Colored Blocks tab, rather than dye numeric IDs.
private static final List<DyeColor> CREATIVE_COLORS=List.of(
@@ -27,15 +27,17 @@ public final class ColoredBricks {
var bricks=block(name+"_bricks",new Block(properties(name+"_bricks",Blocks.BRICKS,color)));
var slab=block(name+"_brick_slab",new SlabBlock(properties(name+"_brick_slab",Blocks.BRICK_SLAB,color)));
var stairs=block(name+"_brick_stairs",new Stairs(bricks,properties(name+"_brick_stairs",Blocks.BRICK_STAIRS,color)));
var wall=block(name+"_brick_wall",new WallBlock(properties(name+"_brick_wall",Blocks.BRICK_WALL,color)));
var clay=block(name+"_clay",new Block(properties(name+"_clay",Blocks.CLAY,color)));
var clayBall=item(name+"_clay_ball");var brick=item(name+"_brick");
FAMILIES.add(new Family(color,bricks,slab,stairs,clay,clayBall,brick));
FAMILIES.add(new Family(color,bricks,slab,stairs,wall,clay,clayBall,brick));
}
var display=FAMILIES.stream().sorted(Comparator.comparingInt(f->CREATIVE_COLORS.indexOf(f.color()))).toList();
CreativeModeTabEvents.modifyOutputEvent(CreativeModeTabs.COLORED_BLOCKS).register(out->{
for(var f:display)out.accept(f.bricks);
for(var f:display)out.accept(f.stairs);
for(var f:display)out.accept(f.slab);
for(var f:display)out.accept(f.wall);
for(var f:display)out.accept(f.clay);
});
CreativeModeTabEvents.modifyOutputEvent(CreativeModeTabs.INGREDIENTS).register(out->{
@@ -7,7 +7,7 @@ import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.block.Mirror;
import net.minecraft.world.level.block.Rotation;
/** World-space edge of the occupied block; CENTER is the legacy placement. */
/** World-space anchor of the occupied block, always on the whole-voxel grid. */
public enum SculptureAnchor implements StringRepresentable {
CENTER(null), NORTH(Direction.NORTH), SOUTH(Direction.SOUTH), EAST(Direction.EAST), WEST(Direction.WEST);
@@ -23,7 +23,8 @@ public enum SculptureAnchor implements StringRepresentable {
public static SculptureAnchor placement(BlockPlaceContext context){
var pos=context.getClickedPos();var hit=context.getClickLocation();
double x=hit.x-pos.getX()-.5,z=hit.z-pos.getZ()-.5;
if(Math.abs(x)<1e-7&&Math.abs(z)<1e-7)return of(context.getHorizontalDirection().getOpposite());
// The middle 8 x 8 pixels select the existing grid-aligned center.
if(Math.abs(x)<=.25&&Math.abs(z)<=.25)return CENTER;
if(Math.abs(x)>Math.abs(z))return x<0?WEST:EAST;
return z<0?NORTH:SOUTH;
}
@@ -0,0 +1,90 @@
{
"multipart": [
{
"apply": {
"model": "sanctuary:block/black_brick_wall_post"
},
"when": {
"up": "true"
}
},
{
"apply": {
"model": "sanctuary:block/black_brick_wall_side",
"uvlock": true
},
"when": {
"north": "low"
}
},
{
"apply": {
"model": "sanctuary:block/black_brick_wall_side",
"uvlock": true,
"y": 90
},
"when": {
"east": "low"
}
},
{
"apply": {
"model": "sanctuary:block/black_brick_wall_side",
"uvlock": true,
"y": 180
},
"when": {
"south": "low"
}
},
{
"apply": {
"model": "sanctuary:block/black_brick_wall_side",
"uvlock": true,
"y": 270
},
"when": {
"west": "low"
}
},
{
"apply": {
"model": "sanctuary:block/black_brick_wall_side_tall",
"uvlock": true
},
"when": {
"north": "tall"
}
},
{
"apply": {
"model": "sanctuary:block/black_brick_wall_side_tall",
"uvlock": true,
"y": 90
},
"when": {
"east": "tall"
}
},
{
"apply": {
"model": "sanctuary:block/black_brick_wall_side_tall",
"uvlock": true,
"y": 180
},
"when": {
"south": "tall"
}
},
{
"apply": {
"model": "sanctuary:block/black_brick_wall_side_tall",
"uvlock": true,
"y": 270
},
"when": {
"west": "tall"
}
}
]
}
@@ -0,0 +1,90 @@
{
"multipart": [
{
"apply": {
"model": "sanctuary:block/blue_brick_wall_post"
},
"when": {
"up": "true"
}
},
{
"apply": {
"model": "sanctuary:block/blue_brick_wall_side",
"uvlock": true
},
"when": {
"north": "low"
}
},
{
"apply": {
"model": "sanctuary:block/blue_brick_wall_side",
"uvlock": true,
"y": 90
},
"when": {
"east": "low"
}
},
{
"apply": {
"model": "sanctuary:block/blue_brick_wall_side",
"uvlock": true,
"y": 180
},
"when": {
"south": "low"
}
},
{
"apply": {
"model": "sanctuary:block/blue_brick_wall_side",
"uvlock": true,
"y": 270
},
"when": {
"west": "low"
}
},
{
"apply": {
"model": "sanctuary:block/blue_brick_wall_side_tall",
"uvlock": true
},
"when": {
"north": "tall"
}
},
{
"apply": {
"model": "sanctuary:block/blue_brick_wall_side_tall",
"uvlock": true,
"y": 90
},
"when": {
"east": "tall"
}
},
{
"apply": {
"model": "sanctuary:block/blue_brick_wall_side_tall",
"uvlock": true,
"y": 180
},
"when": {
"south": "tall"
}
},
{
"apply": {
"model": "sanctuary:block/blue_brick_wall_side_tall",
"uvlock": true,
"y": 270
},
"when": {
"west": "tall"
}
}
]
}
@@ -0,0 +1,90 @@
{
"multipart": [
{
"apply": {
"model": "sanctuary:block/brown_brick_wall_post"
},
"when": {
"up": "true"
}
},
{
"apply": {
"model": "sanctuary:block/brown_brick_wall_side",
"uvlock": true
},
"when": {
"north": "low"
}
},
{
"apply": {
"model": "sanctuary:block/brown_brick_wall_side",
"uvlock": true,
"y": 90
},
"when": {
"east": "low"
}
},
{
"apply": {
"model": "sanctuary:block/brown_brick_wall_side",
"uvlock": true,
"y": 180
},
"when": {
"south": "low"
}
},
{
"apply": {
"model": "sanctuary:block/brown_brick_wall_side",
"uvlock": true,
"y": 270
},
"when": {
"west": "low"
}
},
{
"apply": {
"model": "sanctuary:block/brown_brick_wall_side_tall",
"uvlock": true
},
"when": {
"north": "tall"
}
},
{
"apply": {
"model": "sanctuary:block/brown_brick_wall_side_tall",
"uvlock": true,
"y": 90
},
"when": {
"east": "tall"
}
},
{
"apply": {
"model": "sanctuary:block/brown_brick_wall_side_tall",
"uvlock": true,
"y": 180
},
"when": {
"south": "tall"
}
},
{
"apply": {
"model": "sanctuary:block/brown_brick_wall_side_tall",
"uvlock": true,
"y": 270
},
"when": {
"west": "tall"
}
}
]
}
@@ -0,0 +1,90 @@
{
"multipart": [
{
"apply": {
"model": "sanctuary:block/cyan_brick_wall_post"
},
"when": {
"up": "true"
}
},
{
"apply": {
"model": "sanctuary:block/cyan_brick_wall_side",
"uvlock": true
},
"when": {
"north": "low"
}
},
{
"apply": {
"model": "sanctuary:block/cyan_brick_wall_side",
"uvlock": true,
"y": 90
},
"when": {
"east": "low"
}
},
{
"apply": {
"model": "sanctuary:block/cyan_brick_wall_side",
"uvlock": true,
"y": 180
},
"when": {
"south": "low"
}
},
{
"apply": {
"model": "sanctuary:block/cyan_brick_wall_side",
"uvlock": true,
"y": 270
},
"when": {
"west": "low"
}
},
{
"apply": {
"model": "sanctuary:block/cyan_brick_wall_side_tall",
"uvlock": true
},
"when": {
"north": "tall"
}
},
{
"apply": {
"model": "sanctuary:block/cyan_brick_wall_side_tall",
"uvlock": true,
"y": 90
},
"when": {
"east": "tall"
}
},
{
"apply": {
"model": "sanctuary:block/cyan_brick_wall_side_tall",
"uvlock": true,
"y": 180
},
"when": {
"south": "tall"
}
},
{
"apply": {
"model": "sanctuary:block/cyan_brick_wall_side_tall",
"uvlock": true,
"y": 270
},
"when": {
"west": "tall"
}
}
]
}
@@ -0,0 +1,90 @@
{
"multipart": [
{
"apply": {
"model": "sanctuary:block/gray_brick_wall_post"
},
"when": {
"up": "true"
}
},
{
"apply": {
"model": "sanctuary:block/gray_brick_wall_side",
"uvlock": true
},
"when": {
"north": "low"
}
},
{
"apply": {
"model": "sanctuary:block/gray_brick_wall_side",
"uvlock": true,
"y": 90
},
"when": {
"east": "low"
}
},
{
"apply": {
"model": "sanctuary:block/gray_brick_wall_side",
"uvlock": true,
"y": 180
},
"when": {
"south": "low"
}
},
{
"apply": {
"model": "sanctuary:block/gray_brick_wall_side",
"uvlock": true,
"y": 270
},
"when": {
"west": "low"
}
},
{
"apply": {
"model": "sanctuary:block/gray_brick_wall_side_tall",
"uvlock": true
},
"when": {
"north": "tall"
}
},
{
"apply": {
"model": "sanctuary:block/gray_brick_wall_side_tall",
"uvlock": true,
"y": 90
},
"when": {
"east": "tall"
}
},
{
"apply": {
"model": "sanctuary:block/gray_brick_wall_side_tall",
"uvlock": true,
"y": 180
},
"when": {
"south": "tall"
}
},
{
"apply": {
"model": "sanctuary:block/gray_brick_wall_side_tall",
"uvlock": true,
"y": 270
},
"when": {
"west": "tall"
}
}
]
}
@@ -0,0 +1,90 @@
{
"multipart": [
{
"apply": {
"model": "sanctuary:block/green_brick_wall_post"
},
"when": {
"up": "true"
}
},
{
"apply": {
"model": "sanctuary:block/green_brick_wall_side",
"uvlock": true
},
"when": {
"north": "low"
}
},
{
"apply": {
"model": "sanctuary:block/green_brick_wall_side",
"uvlock": true,
"y": 90
},
"when": {
"east": "low"
}
},
{
"apply": {
"model": "sanctuary:block/green_brick_wall_side",
"uvlock": true,
"y": 180
},
"when": {
"south": "low"
}
},
{
"apply": {
"model": "sanctuary:block/green_brick_wall_side",
"uvlock": true,
"y": 270
},
"when": {
"west": "low"
}
},
{
"apply": {
"model": "sanctuary:block/green_brick_wall_side_tall",
"uvlock": true
},
"when": {
"north": "tall"
}
},
{
"apply": {
"model": "sanctuary:block/green_brick_wall_side_tall",
"uvlock": true,
"y": 90
},
"when": {
"east": "tall"
}
},
{
"apply": {
"model": "sanctuary:block/green_brick_wall_side_tall",
"uvlock": true,
"y": 180
},
"when": {
"south": "tall"
}
},
{
"apply": {
"model": "sanctuary:block/green_brick_wall_side_tall",
"uvlock": true,
"y": 270
},
"when": {
"west": "tall"
}
}
]
}
@@ -0,0 +1,90 @@
{
"multipart": [
{
"apply": {
"model": "sanctuary:block/light_blue_brick_wall_post"
},
"when": {
"up": "true"
}
},
{
"apply": {
"model": "sanctuary:block/light_blue_brick_wall_side",
"uvlock": true
},
"when": {
"north": "low"
}
},
{
"apply": {
"model": "sanctuary:block/light_blue_brick_wall_side",
"uvlock": true,
"y": 90
},
"when": {
"east": "low"
}
},
{
"apply": {
"model": "sanctuary:block/light_blue_brick_wall_side",
"uvlock": true,
"y": 180
},
"when": {
"south": "low"
}
},
{
"apply": {
"model": "sanctuary:block/light_blue_brick_wall_side",
"uvlock": true,
"y": 270
},
"when": {
"west": "low"
}
},
{
"apply": {
"model": "sanctuary:block/light_blue_brick_wall_side_tall",
"uvlock": true
},
"when": {
"north": "tall"
}
},
{
"apply": {
"model": "sanctuary:block/light_blue_brick_wall_side_tall",
"uvlock": true,
"y": 90
},
"when": {
"east": "tall"
}
},
{
"apply": {
"model": "sanctuary:block/light_blue_brick_wall_side_tall",
"uvlock": true,
"y": 180
},
"when": {
"south": "tall"
}
},
{
"apply": {
"model": "sanctuary:block/light_blue_brick_wall_side_tall",
"uvlock": true,
"y": 270
},
"when": {
"west": "tall"
}
}
]
}
@@ -0,0 +1,90 @@
{
"multipart": [
{
"apply": {
"model": "sanctuary:block/light_gray_brick_wall_post"
},
"when": {
"up": "true"
}
},
{
"apply": {
"model": "sanctuary:block/light_gray_brick_wall_side",
"uvlock": true
},
"when": {
"north": "low"
}
},
{
"apply": {
"model": "sanctuary:block/light_gray_brick_wall_side",
"uvlock": true,
"y": 90
},
"when": {
"east": "low"
}
},
{
"apply": {
"model": "sanctuary:block/light_gray_brick_wall_side",
"uvlock": true,
"y": 180
},
"when": {
"south": "low"
}
},
{
"apply": {
"model": "sanctuary:block/light_gray_brick_wall_side",
"uvlock": true,
"y": 270
},
"when": {
"west": "low"
}
},
{
"apply": {
"model": "sanctuary:block/light_gray_brick_wall_side_tall",
"uvlock": true
},
"when": {
"north": "tall"
}
},
{
"apply": {
"model": "sanctuary:block/light_gray_brick_wall_side_tall",
"uvlock": true,
"y": 90
},
"when": {
"east": "tall"
}
},
{
"apply": {
"model": "sanctuary:block/light_gray_brick_wall_side_tall",
"uvlock": true,
"y": 180
},
"when": {
"south": "tall"
}
},
{
"apply": {
"model": "sanctuary:block/light_gray_brick_wall_side_tall",
"uvlock": true,
"y": 270
},
"when": {
"west": "tall"
}
}
]
}
@@ -0,0 +1,90 @@
{
"multipart": [
{
"apply": {
"model": "sanctuary:block/lime_brick_wall_post"
},
"when": {
"up": "true"
}
},
{
"apply": {
"model": "sanctuary:block/lime_brick_wall_side",
"uvlock": true
},
"when": {
"north": "low"
}
},
{
"apply": {
"model": "sanctuary:block/lime_brick_wall_side",
"uvlock": true,
"y": 90
},
"when": {
"east": "low"
}
},
{
"apply": {
"model": "sanctuary:block/lime_brick_wall_side",
"uvlock": true,
"y": 180
},
"when": {
"south": "low"
}
},
{
"apply": {
"model": "sanctuary:block/lime_brick_wall_side",
"uvlock": true,
"y": 270
},
"when": {
"west": "low"
}
},
{
"apply": {
"model": "sanctuary:block/lime_brick_wall_side_tall",
"uvlock": true
},
"when": {
"north": "tall"
}
},
{
"apply": {
"model": "sanctuary:block/lime_brick_wall_side_tall",
"uvlock": true,
"y": 90
},
"when": {
"east": "tall"
}
},
{
"apply": {
"model": "sanctuary:block/lime_brick_wall_side_tall",
"uvlock": true,
"y": 180
},
"when": {
"south": "tall"
}
},
{
"apply": {
"model": "sanctuary:block/lime_brick_wall_side_tall",
"uvlock": true,
"y": 270
},
"when": {
"west": "tall"
}
}
]
}
@@ -0,0 +1,90 @@
{
"multipart": [
{
"apply": {
"model": "sanctuary:block/magenta_brick_wall_post"
},
"when": {
"up": "true"
}
},
{
"apply": {
"model": "sanctuary:block/magenta_brick_wall_side",
"uvlock": true
},
"when": {
"north": "low"
}
},
{
"apply": {
"model": "sanctuary:block/magenta_brick_wall_side",
"uvlock": true,
"y": 90
},
"when": {
"east": "low"
}
},
{
"apply": {
"model": "sanctuary:block/magenta_brick_wall_side",
"uvlock": true,
"y": 180
},
"when": {
"south": "low"
}
},
{
"apply": {
"model": "sanctuary:block/magenta_brick_wall_side",
"uvlock": true,
"y": 270
},
"when": {
"west": "low"
}
},
{
"apply": {
"model": "sanctuary:block/magenta_brick_wall_side_tall",
"uvlock": true
},
"when": {
"north": "tall"
}
},
{
"apply": {
"model": "sanctuary:block/magenta_brick_wall_side_tall",
"uvlock": true,
"y": 90
},
"when": {
"east": "tall"
}
},
{
"apply": {
"model": "sanctuary:block/magenta_brick_wall_side_tall",
"uvlock": true,
"y": 180
},
"when": {
"south": "tall"
}
},
{
"apply": {
"model": "sanctuary:block/magenta_brick_wall_side_tall",
"uvlock": true,
"y": 270
},
"when": {
"west": "tall"
}
}
]
}
@@ -0,0 +1,90 @@
{
"multipart": [
{
"apply": {
"model": "sanctuary:block/orange_brick_wall_post"
},
"when": {
"up": "true"
}
},
{
"apply": {
"model": "sanctuary:block/orange_brick_wall_side",
"uvlock": true
},
"when": {
"north": "low"
}
},
{
"apply": {
"model": "sanctuary:block/orange_brick_wall_side",
"uvlock": true,
"y": 90
},
"when": {
"east": "low"
}
},
{
"apply": {
"model": "sanctuary:block/orange_brick_wall_side",
"uvlock": true,
"y": 180
},
"when": {
"south": "low"
}
},
{
"apply": {
"model": "sanctuary:block/orange_brick_wall_side",
"uvlock": true,
"y": 270
},
"when": {
"west": "low"
}
},
{
"apply": {
"model": "sanctuary:block/orange_brick_wall_side_tall",
"uvlock": true
},
"when": {
"north": "tall"
}
},
{
"apply": {
"model": "sanctuary:block/orange_brick_wall_side_tall",
"uvlock": true,
"y": 90
},
"when": {
"east": "tall"
}
},
{
"apply": {
"model": "sanctuary:block/orange_brick_wall_side_tall",
"uvlock": true,
"y": 180
},
"when": {
"south": "tall"
}
},
{
"apply": {
"model": "sanctuary:block/orange_brick_wall_side_tall",
"uvlock": true,
"y": 270
},
"when": {
"west": "tall"
}
}
]
}
@@ -0,0 +1,90 @@
{
"multipart": [
{
"apply": {
"model": "sanctuary:block/pink_brick_wall_post"
},
"when": {
"up": "true"
}
},
{
"apply": {
"model": "sanctuary:block/pink_brick_wall_side",
"uvlock": true
},
"when": {
"north": "low"
}
},
{
"apply": {
"model": "sanctuary:block/pink_brick_wall_side",
"uvlock": true,
"y": 90
},
"when": {
"east": "low"
}
},
{
"apply": {
"model": "sanctuary:block/pink_brick_wall_side",
"uvlock": true,
"y": 180
},
"when": {
"south": "low"
}
},
{
"apply": {
"model": "sanctuary:block/pink_brick_wall_side",
"uvlock": true,
"y": 270
},
"when": {
"west": "low"
}
},
{
"apply": {
"model": "sanctuary:block/pink_brick_wall_side_tall",
"uvlock": true
},
"when": {
"north": "tall"
}
},
{
"apply": {
"model": "sanctuary:block/pink_brick_wall_side_tall",
"uvlock": true,
"y": 90
},
"when": {
"east": "tall"
}
},
{
"apply": {
"model": "sanctuary:block/pink_brick_wall_side_tall",
"uvlock": true,
"y": 180
},
"when": {
"south": "tall"
}
},
{
"apply": {
"model": "sanctuary:block/pink_brick_wall_side_tall",
"uvlock": true,
"y": 270
},
"when": {
"west": "tall"
}
}
]
}
@@ -0,0 +1,90 @@
{
"multipart": [
{
"apply": {
"model": "sanctuary:block/purple_brick_wall_post"
},
"when": {
"up": "true"
}
},
{
"apply": {
"model": "sanctuary:block/purple_brick_wall_side",
"uvlock": true
},
"when": {
"north": "low"
}
},
{
"apply": {
"model": "sanctuary:block/purple_brick_wall_side",
"uvlock": true,
"y": 90
},
"when": {
"east": "low"
}
},
{
"apply": {
"model": "sanctuary:block/purple_brick_wall_side",
"uvlock": true,
"y": 180
},
"when": {
"south": "low"
}
},
{
"apply": {
"model": "sanctuary:block/purple_brick_wall_side",
"uvlock": true,
"y": 270
},
"when": {
"west": "low"
}
},
{
"apply": {
"model": "sanctuary:block/purple_brick_wall_side_tall",
"uvlock": true
},
"when": {
"north": "tall"
}
},
{
"apply": {
"model": "sanctuary:block/purple_brick_wall_side_tall",
"uvlock": true,
"y": 90
},
"when": {
"east": "tall"
}
},
{
"apply": {
"model": "sanctuary:block/purple_brick_wall_side_tall",
"uvlock": true,
"y": 180
},
"when": {
"south": "tall"
}
},
{
"apply": {
"model": "sanctuary:block/purple_brick_wall_side_tall",
"uvlock": true,
"y": 270
},
"when": {
"west": "tall"
}
}
]
}
@@ -0,0 +1,90 @@
{
"multipart": [
{
"apply": {
"model": "sanctuary:block/red_brick_wall_post"
},
"when": {
"up": "true"
}
},
{
"apply": {
"model": "sanctuary:block/red_brick_wall_side",
"uvlock": true
},
"when": {
"north": "low"
}
},
{
"apply": {
"model": "sanctuary:block/red_brick_wall_side",
"uvlock": true,
"y": 90
},
"when": {
"east": "low"
}
},
{
"apply": {
"model": "sanctuary:block/red_brick_wall_side",
"uvlock": true,
"y": 180
},
"when": {
"south": "low"
}
},
{
"apply": {
"model": "sanctuary:block/red_brick_wall_side",
"uvlock": true,
"y": 270
},
"when": {
"west": "low"
}
},
{
"apply": {
"model": "sanctuary:block/red_brick_wall_side_tall",
"uvlock": true
},
"when": {
"north": "tall"
}
},
{
"apply": {
"model": "sanctuary:block/red_brick_wall_side_tall",
"uvlock": true,
"y": 90
},
"when": {
"east": "tall"
}
},
{
"apply": {
"model": "sanctuary:block/red_brick_wall_side_tall",
"uvlock": true,
"y": 180
},
"when": {
"south": "tall"
}
},
{
"apply": {
"model": "sanctuary:block/red_brick_wall_side_tall",
"uvlock": true,
"y": 270
},
"when": {
"west": "tall"
}
}
]
}
@@ -0,0 +1,90 @@
{
"multipart": [
{
"apply": {
"model": "sanctuary:block/white_brick_wall_post"
},
"when": {
"up": "true"
}
},
{
"apply": {
"model": "sanctuary:block/white_brick_wall_side",
"uvlock": true
},
"when": {
"north": "low"
}
},
{
"apply": {
"model": "sanctuary:block/white_brick_wall_side",
"uvlock": true,
"y": 90
},
"when": {
"east": "low"
}
},
{
"apply": {
"model": "sanctuary:block/white_brick_wall_side",
"uvlock": true,
"y": 180
},
"when": {
"south": "low"
}
},
{
"apply": {
"model": "sanctuary:block/white_brick_wall_side",
"uvlock": true,
"y": 270
},
"when": {
"west": "low"
}
},
{
"apply": {
"model": "sanctuary:block/white_brick_wall_side_tall",
"uvlock": true
},
"when": {
"north": "tall"
}
},
{
"apply": {
"model": "sanctuary:block/white_brick_wall_side_tall",
"uvlock": true,
"y": 90
},
"when": {
"east": "tall"
}
},
{
"apply": {
"model": "sanctuary:block/white_brick_wall_side_tall",
"uvlock": true,
"y": 180
},
"when": {
"south": "tall"
}
},
{
"apply": {
"model": "sanctuary:block/white_brick_wall_side_tall",
"uvlock": true,
"y": 270
},
"when": {
"west": "tall"
}
}
]
}
@@ -0,0 +1,90 @@
{
"multipart": [
{
"apply": {
"model": "sanctuary:block/yellow_brick_wall_post"
},
"when": {
"up": "true"
}
},
{
"apply": {
"model": "sanctuary:block/yellow_brick_wall_side",
"uvlock": true
},
"when": {
"north": "low"
}
},
{
"apply": {
"model": "sanctuary:block/yellow_brick_wall_side",
"uvlock": true,
"y": 90
},
"when": {
"east": "low"
}
},
{
"apply": {
"model": "sanctuary:block/yellow_brick_wall_side",
"uvlock": true,
"y": 180
},
"when": {
"south": "low"
}
},
{
"apply": {
"model": "sanctuary:block/yellow_brick_wall_side",
"uvlock": true,
"y": 270
},
"when": {
"west": "low"
}
},
{
"apply": {
"model": "sanctuary:block/yellow_brick_wall_side_tall",
"uvlock": true
},
"when": {
"north": "tall"
}
},
{
"apply": {
"model": "sanctuary:block/yellow_brick_wall_side_tall",
"uvlock": true,
"y": 90
},
"when": {
"east": "tall"
}
},
{
"apply": {
"model": "sanctuary:block/yellow_brick_wall_side_tall",
"uvlock": true,
"y": 180
},
"when": {
"south": "tall"
}
},
{
"apply": {
"model": "sanctuary:block/yellow_brick_wall_side_tall",
"uvlock": true,
"y": 270
},
"when": {
"west": "tall"
}
}
]
}
@@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "sanctuary:block/black_brick_wall_inventory"
}
}
@@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "sanctuary:block/blue_brick_wall_inventory"
}
}
@@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "sanctuary:block/brown_brick_wall_inventory"
}
}
@@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "sanctuary:block/cyan_brick_wall_inventory"
}
}
@@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "sanctuary:block/gray_brick_wall_inventory"
}
}
@@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "sanctuary:block/green_brick_wall_inventory"
}
}
@@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "sanctuary:block/light_blue_brick_wall_inventory"
}
}
@@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "sanctuary:block/light_gray_brick_wall_inventory"
}
}
@@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "sanctuary:block/lime_brick_wall_inventory"
}
}
@@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "sanctuary:block/magenta_brick_wall_inventory"
}
}
@@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "sanctuary:block/orange_brick_wall_inventory"
}
}
@@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "sanctuary:block/pink_brick_wall_inventory"
}
}
@@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "sanctuary:block/purple_brick_wall_inventory"
}
}
@@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "sanctuary:block/red_brick_wall_inventory"
}
}
@@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "sanctuary:block/white_brick_wall_inventory"
}
}
@@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "sanctuary:block/yellow_brick_wall_inventory"
}
}
@@ -2162,7 +2162,7 @@
"sanctuary.statuary.folder": "Shared folder",
"sanctuary.statuary.refresh": "Refresh",
"sanctuary.statuary.models": "GLB models",
"sanctuary.statuary.placement": "The sculpture faces your gaze and snaps to the aimed block edge, on the pixel grid. Rotate adjusts the model before crafting.",
"sanctuary.statuary.placement": "Aim at the middle of the block to center the sculpture, or at an edge to snap to it. It faces your gaze and stays on the pixel grid. Rotate adjusts the model before crafting.",
"sanctuary.statuary.rotate": "Rotate",
"sanctuary.statuary.working": "Voxelizing to 16 × 16 × 16…",
"sanctuary.statuary.ready": "1 block = 1 sculpture. Shades come from your materials texture.",
@@ -2205,5 +2205,21 @@
"sanctuary.multiblock.state.blocked": "Empty the matching slot in Results.",
"sanctuary.multiblock.state.no_recipe": "This item has no furnace recipe.",
"sanctuary.statuary.choose_material": "Add a block to apply its palette to the model. Containers must be empty.",
"sanctuary.statuary.material_ready": "1 block = 1 sculpture. Palette: %s."
"sanctuary.statuary.material_ready": "1 block = 1 sculpture. Palette: %s.",
"block.sanctuary.white_brick_wall": "White Brick Wall",
"block.sanctuary.orange_brick_wall": "Orange Brick Wall",
"block.sanctuary.magenta_brick_wall": "Magenta Brick Wall",
"block.sanctuary.light_blue_brick_wall": "Light Blue Brick Wall",
"block.sanctuary.yellow_brick_wall": "Yellow Brick Wall",
"block.sanctuary.lime_brick_wall": "Lime Brick Wall",
"block.sanctuary.pink_brick_wall": "Pink Brick Wall",
"block.sanctuary.gray_brick_wall": "Gray Brick Wall",
"block.sanctuary.light_gray_brick_wall": "Light Gray Brick Wall",
"block.sanctuary.cyan_brick_wall": "Cyan Brick Wall",
"block.sanctuary.purple_brick_wall": "Purple Brick Wall",
"block.sanctuary.blue_brick_wall": "Blue Brick Wall",
"block.sanctuary.brown_brick_wall": "Brown Brick Wall",
"block.sanctuary.green_brick_wall": "Green Brick Wall",
"block.sanctuary.red_brick_wall": "Red Brick Wall",
"block.sanctuary.black_brick_wall": "Black Brick Wall"
}
@@ -2162,7 +2162,7 @@
"sanctuary.statuary.folder": "Dossier commun",
"sanctuary.statuary.refresh": "Actualiser",
"sanctuary.statuary.models": "Modèles GLB",
"sanctuary.statuary.placement": "La sculpture suit votre regard et se cale contre le bord visé du bloc, sur la grille de pixels. Tourner ajuste le modèle avant fabrication.",
"sanctuary.statuary.placement": "Visez le milieu du bloc pour centrer la sculpture, ou un bord pour ly caler. Elle suit votre regard et reste sur la grille de pixels. Tourner ajuste le modèle avant fabrication.",
"sanctuary.statuary.rotate": "Tourner",
"sanctuary.statuary.working": "Voxelisation en 16 × 16 × 16…",
"sanctuary.statuary.ready": "1 bloc = 1 sculpture. Les nuances viennent de la texture de votre matière.",
@@ -2205,5 +2205,21 @@
"sanctuary.multiblock.state.blocked": "Vider la case correspondante dans Résultats.",
"sanctuary.multiblock.state.no_recipe": "Cet objet ne possède pas de recette au four.",
"sanctuary.statuary.choose_material": "Ajoutez un bloc pour appliquer sa palette au modèle. Les conteneurs doivent être vides.",
"sanctuary.statuary.material_ready": "1 bloc = 1 sculpture. Palette : %s."
"sanctuary.statuary.material_ready": "1 bloc = 1 sculpture. Palette : %s.",
"block.sanctuary.white_brick_wall": "Muret de briques blanches",
"block.sanctuary.orange_brick_wall": "Muret de briques orange",
"block.sanctuary.magenta_brick_wall": "Muret de briques magenta",
"block.sanctuary.light_blue_brick_wall": "Muret de briques bleu clair",
"block.sanctuary.yellow_brick_wall": "Muret de briques jaunes",
"block.sanctuary.lime_brick_wall": "Muret de briques vert clair",
"block.sanctuary.pink_brick_wall": "Muret de briques roses",
"block.sanctuary.gray_brick_wall": "Muret de briques grises",
"block.sanctuary.light_gray_brick_wall": "Muret de briques gris clair",
"block.sanctuary.cyan_brick_wall": "Muret de briques cyan",
"block.sanctuary.purple_brick_wall": "Muret de briques violettes",
"block.sanctuary.blue_brick_wall": "Muret de briques bleues",
"block.sanctuary.brown_brick_wall": "Muret de briques marron",
"block.sanctuary.green_brick_wall": "Muret de briques vertes",
"block.sanctuary.red_brick_wall": "Muret de briques rouges",
"block.sanctuary.black_brick_wall": "Muret de briques noires"
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/wall_inventory",
"textures": {
"wall": "sanctuary:block/black_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/template_wall_post",
"textures": {
"wall": "sanctuary:block/black_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/template_wall_side",
"textures": {
"wall": "sanctuary:block/black_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/template_wall_side_tall",
"textures": {
"wall": "sanctuary:block/black_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/wall_inventory",
"textures": {
"wall": "sanctuary:block/blue_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/template_wall_post",
"textures": {
"wall": "sanctuary:block/blue_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/template_wall_side",
"textures": {
"wall": "sanctuary:block/blue_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/template_wall_side_tall",
"textures": {
"wall": "sanctuary:block/blue_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/wall_inventory",
"textures": {
"wall": "sanctuary:block/brown_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/template_wall_post",
"textures": {
"wall": "sanctuary:block/brown_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/template_wall_side",
"textures": {
"wall": "sanctuary:block/brown_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/template_wall_side_tall",
"textures": {
"wall": "sanctuary:block/brown_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/wall_inventory",
"textures": {
"wall": "sanctuary:block/cyan_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/template_wall_post",
"textures": {
"wall": "sanctuary:block/cyan_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/template_wall_side",
"textures": {
"wall": "sanctuary:block/cyan_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/template_wall_side_tall",
"textures": {
"wall": "sanctuary:block/cyan_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/wall_inventory",
"textures": {
"wall": "sanctuary:block/gray_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/template_wall_post",
"textures": {
"wall": "sanctuary:block/gray_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/template_wall_side",
"textures": {
"wall": "sanctuary:block/gray_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/template_wall_side_tall",
"textures": {
"wall": "sanctuary:block/gray_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/wall_inventory",
"textures": {
"wall": "sanctuary:block/green_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/template_wall_post",
"textures": {
"wall": "sanctuary:block/green_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/template_wall_side",
"textures": {
"wall": "sanctuary:block/green_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/template_wall_side_tall",
"textures": {
"wall": "sanctuary:block/green_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/wall_inventory",
"textures": {
"wall": "sanctuary:block/light_blue_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/template_wall_post",
"textures": {
"wall": "sanctuary:block/light_blue_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/template_wall_side",
"textures": {
"wall": "sanctuary:block/light_blue_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/template_wall_side_tall",
"textures": {
"wall": "sanctuary:block/light_blue_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/wall_inventory",
"textures": {
"wall": "sanctuary:block/light_gray_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/template_wall_post",
"textures": {
"wall": "sanctuary:block/light_gray_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/template_wall_side",
"textures": {
"wall": "sanctuary:block/light_gray_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/template_wall_side_tall",
"textures": {
"wall": "sanctuary:block/light_gray_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/wall_inventory",
"textures": {
"wall": "sanctuary:block/lime_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/template_wall_post",
"textures": {
"wall": "sanctuary:block/lime_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/template_wall_side",
"textures": {
"wall": "sanctuary:block/lime_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/template_wall_side_tall",
"textures": {
"wall": "sanctuary:block/lime_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/wall_inventory",
"textures": {
"wall": "sanctuary:block/magenta_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/template_wall_post",
"textures": {
"wall": "sanctuary:block/magenta_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/template_wall_side",
"textures": {
"wall": "sanctuary:block/magenta_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/template_wall_side_tall",
"textures": {
"wall": "sanctuary:block/magenta_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/wall_inventory",
"textures": {
"wall": "sanctuary:block/orange_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/template_wall_post",
"textures": {
"wall": "sanctuary:block/orange_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/template_wall_side",
"textures": {
"wall": "sanctuary:block/orange_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/template_wall_side_tall",
"textures": {
"wall": "sanctuary:block/orange_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/wall_inventory",
"textures": {
"wall": "sanctuary:block/pink_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/template_wall_post",
"textures": {
"wall": "sanctuary:block/pink_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/template_wall_side",
"textures": {
"wall": "sanctuary:block/pink_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/template_wall_side_tall",
"textures": {
"wall": "sanctuary:block/pink_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/wall_inventory",
"textures": {
"wall": "sanctuary:block/purple_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/template_wall_post",
"textures": {
"wall": "sanctuary:block/purple_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/template_wall_side",
"textures": {
"wall": "sanctuary:block/purple_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/template_wall_side_tall",
"textures": {
"wall": "sanctuary:block/purple_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/wall_inventory",
"textures": {
"wall": "sanctuary:block/red_bricks"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/template_wall_post",
"textures": {
"wall": "sanctuary:block/red_bricks"
}
}

Some files were not shown because too many files have changed in this diff Show More