Center sculptures on aimed block middle without half-voxel offsets (beta.119)
Build Sanctuary / build (push) Canceled after 0s
Build Sanctuary / build (push) Canceled after 0s
This commit is contained in:
@@ -20,12 +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
|
L’économie, les claims et les dimensions décrits dans la vision restent
|
||||||
à implémenter.
|
à implémenter.
|
||||||
|
|
||||||
La version **beta.118** ajoute les seize murets en briques colorées, avec
|
La version **beta.119** permet de centrer une sculpture en visant le milieu
|
||||||
leurs textures existantes, les raccords natifs et leurs recettes. Ils forment
|
du bloc, ou de la caler contre un bord en visant autour. La grille de 1/16
|
||||||
une série de seize après les dalles dans l'onglet des blocs colorés.
|
reste respectée, même pour les modèles de taille impaire.
|
||||||
Le [ticket de livraison](docs/colored-brick-walls-beta118.md) conserve les
|
Le [ticket de livraison](docs/sculpture-center-beta119.md) conserve les contrôles
|
||||||
contrôles et le suivi de distribution. La release est publiée et l'instance
|
et le suivi de distribution. Les tests natifs, le build et les deux packs sont vérifiés localement.
|
||||||
**Sanctuary Beta** est synchronisée, sauvegardes et réglages conservés.
|
|
||||||
La [livraison précédente](docs/clay-workshop-integration-beta110.md) réunit déjà
|
La [livraison précédente](docs/clay-workshop-integration-beta110.md) réunit déjà
|
||||||
l’atelier, les œufs et la neige saisonnière dans l’instance **Sanctuary Beta**.
|
l’atelier, les œufs et la neige saisonnière dans l’instance **Sanctuary Beta**.
|
||||||
Les [synchronisations antérieures](docs/git-sync-beta092.md) restent documentées.
|
Les [synchronisations antérieures](docs/git-sync-beta092.md) restent documentées.
|
||||||
@@ -36,6 +35,11 @@ La [carte native beta.005](docs/atlas-beta005.md) prend le relais après
|
|||||||
l’étude de Xaero et des alternatives libres.
|
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
|
## beta.118 — Murets en briques colorées
|
||||||
|
|
||||||
Seize couleurs, fabrication et tailleur de pierre, eau, raccords et collisions
|
Seize couleurs, fabrication et tailleur de pierre, eau, raccords et collisions
|
||||||
|
|||||||
@@ -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.
|
||||||
+2
-2
@@ -9,8 +9,8 @@ loom_version=1.17.20
|
|||||||
fabric_api_version=0.160.5+26.3
|
fabric_api_version=0.160.5+26.3
|
||||||
|
|
||||||
# Release counter: beta.001, .002, .003, ... (see docs/versioning.md).
|
# Release counter: beta.001, .002, .003, ... (see docs/versioning.md).
|
||||||
mod_version=beta.118
|
mod_version=beta.119
|
||||||
pack_version=beta.118
|
pack_version=beta.119
|
||||||
resource_pack_version=beta.090
|
resource_pack_version=beta.090
|
||||||
maven_group=fr.koka.sanctuary
|
maven_group=fr.koka.sanctuary
|
||||||
jei_version=30.32.0-sanctuary.3
|
jei_version=30.32.0-sanctuary.3
|
||||||
|
|||||||
+13
@@ -18,7 +18,20 @@ import net.minecraft.world.phys.*;
|
|||||||
final class Sculpture113ClientChecks {
|
final class Sculpture113ClientChecks {
|
||||||
static void placementContexts(ServerPlayer player){
|
static void placementContexts(ServerPlayer player){
|
||||||
for(var pos:List.of(new BlockPos(2,0,-2),new BlockPos(-2,0,2))){
|
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(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 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 context=new BlockPlaceContext(player,InteractionHand.MAIN_HAND,new ItemStack(Statuary.ITEM),new BlockHitResult(top,Direction.UP,pos,false));
|
||||||
var state=Statuary.BLOCK.getStateForPlacement(context);
|
var state=Statuary.BLOCK.getStateForPlacement(context);
|
||||||
|
|||||||
+11
-2
@@ -119,7 +119,14 @@ public final class Statuary106ClientChecks implements FabricClientGameTest {
|
|||||||
for(var direction:Direction.Plane.HORIZONTAL){
|
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;
|
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();});
|
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.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);
|
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");
|
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"));
|
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(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");
|
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("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("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("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");
|
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){}}
|
}catch(IOException e){throw new AssertionError(e);}finally{try{Files.deleteIfExists(file);}catch(IOException ignored){}}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import net.minecraft.world.item.context.BlockPlaceContext;
|
|||||||
import net.minecraft.world.level.block.Mirror;
|
import net.minecraft.world.level.block.Mirror;
|
||||||
import net.minecraft.world.level.block.Rotation;
|
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 {
|
public enum SculptureAnchor implements StringRepresentable {
|
||||||
CENTER(null), NORTH(Direction.NORTH), SOUTH(Direction.SOUTH), EAST(Direction.EAST), WEST(Direction.WEST);
|
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){
|
public static SculptureAnchor placement(BlockPlaceContext context){
|
||||||
var pos=context.getClickedPos();var hit=context.getClickLocation();
|
var pos=context.getClickedPos();var hit=context.getClickLocation();
|
||||||
double x=hit.x-pos.getX()-.5,z=hit.z-pos.getZ()-.5;
|
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;
|
if(Math.abs(x)>Math.abs(z))return x<0?WEST:EAST;
|
||||||
return z<0?NORTH:SOUTH;
|
return z<0?NORTH:SOUTH;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2162,7 +2162,7 @@
|
|||||||
"sanctuary.statuary.folder": "Shared folder",
|
"sanctuary.statuary.folder": "Shared folder",
|
||||||
"sanctuary.statuary.refresh": "Refresh",
|
"sanctuary.statuary.refresh": "Refresh",
|
||||||
"sanctuary.statuary.models": "GLB models",
|
"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.rotate": "Rotate",
|
||||||
"sanctuary.statuary.working": "Voxelizing to 16 × 16 × 16…",
|
"sanctuary.statuary.working": "Voxelizing to 16 × 16 × 16…",
|
||||||
"sanctuary.statuary.ready": "1 block = 1 sculpture. Shades come from your material’s texture.",
|
"sanctuary.statuary.ready": "1 block = 1 sculpture. Shades come from your material’s texture.",
|
||||||
|
|||||||
@@ -2162,7 +2162,7 @@
|
|||||||
"sanctuary.statuary.folder": "Dossier commun",
|
"sanctuary.statuary.folder": "Dossier commun",
|
||||||
"sanctuary.statuary.refresh": "Actualiser",
|
"sanctuary.statuary.refresh": "Actualiser",
|
||||||
"sanctuary.statuary.models": "Modèles GLB",
|
"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 l’y 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.rotate": "Tourner",
|
||||||
"sanctuary.statuary.working": "Voxelisation en 16 × 16 × 16…",
|
"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.",
|
"sanctuary.statuary.ready": "1 bloc = 1 sculpture. Les nuances viennent de la texture de votre matière.",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
name = "Sanctuary"
|
name = "Sanctuary"
|
||||||
author = "KOKA99CAB"
|
author = "KOKA99CAB"
|
||||||
version = "beta.118"
|
version = "beta.119"
|
||||||
pack-format = "packwiz:1.1.0"
|
pack-format = "packwiz:1.1.0"
|
||||||
|
|
||||||
[index]
|
[index]
|
||||||
|
|||||||
Reference in New Issue
Block a user