feat: add native Blocodex and material census for alpha23
This commit is contained in:
@@ -0,0 +1,255 @@
|
||||
# Blocodex natif — connaissances, matière et stocks
|
||||
|
||||
Ticket META-01, branche `codex/blocodex-natif`, cible Minecraft **26.3-pre-2**.
|
||||
Le Blocodex appartient au mod Sanctuary. Il est disponible sans appareil,
|
||||
recette ni déblocage. La mémoire personnelle, le recensement du terrain et
|
||||
celui des stocks forment un socle commun aux futures palettes de structures,
|
||||
règles d’expansion et règles du shop. Les relevés datés ajoutent la temporalité
|
||||
nécessaire à une future lecture de l’histoire économique du serveur.
|
||||
|
||||
## Contrat des informations
|
||||
|
||||
La mémoire est personnelle : une identité de joueur (UUID), dans une sauvegarde
|
||||
de serveur, partagée entre ses dimensions. Les indicateurs sont indépendants.
|
||||
|
||||
| Information | Sens |
|
||||
| --- | --- |
|
||||
| Inconnu | Aucune observation, possession, pose ni statistique de minage ou de jet. C'est un état calculé, pas une étape enregistrée. |
|
||||
| Vu | Le premier bloc rencontré par le regard du joueur, à au plus 32 blocs, observé côté serveur tous les 5 ticks. Les obstacles arrêtent le rayon ; les chunks absents ne sont pas chargés. Ce relevé ne couvre pas chaque pixel du champ de vision. |
|
||||
| Miné | Compteur vanilla `mined` du bloc. Ses règles sont conservées : notamment pas de minage créatif, ni de minage sans l'outil requis. |
|
||||
| Déjà possédé | Le bloc, sous forme d'item, a été présent dans l'inventaire personnel ou sur le curseur d'un menu. Les statistiques vanilla de ramassage et de jet prouvent aussi une possession passée. |
|
||||
| Jeté | Compteur vanilla `dropped` de l'item du bloc. Il compte les unités volontairement jetées, pas les objets éjectés à la mort ni le butin produit par le bloc cassé. |
|
||||
| Posé | Nombre de placements réussis par le joueur avec un item de bloc, y compris en créatif. Une tentative refusée, une interaction ou un placement par commande ne compte pas. |
|
||||
| En inventaire | Quantité actuellement dans l'inventaire personnel, équipement et curseur compris. Les coffres ouverts, ender chests et contenus imbriqués des boîtes ne sont pas inclus. |
|
||||
|
||||
Les blocs sont identifiés par leur identifiant de registre ; les propriétés
|
||||
d'état (orientation, humidité, etc.) ne créent pas une nouvelle fiche. Deux
|
||||
identifiants restent distincts : une torche murale peut être vue et posée tandis
|
||||
que l'item possédé correspond à la torche debout. Les noms des blocs inconnus
|
||||
restent consultables, comme un catalogue ; cette version ne décide pas d'une
|
||||
politique de secrets ou de verrouillage des recettes.
|
||||
|
||||
L'inventaire est observé chaque tick serveur, après les transactions de menus
|
||||
et avant la consommation d'un item placé. Les statistiques de ramassage/jet
|
||||
complètent ce relevé. Une mutation d'inventaire entièrement réalisée entre ces
|
||||
points par un autre mod ne peut pas être reconstruite après coup.
|
||||
Les spectateurs ne découvrent pas de blocs par le regard.
|
||||
|
||||
## Persistance et arrivée dans une sauvegarde antérieure
|
||||
|
||||
Contrat additif v1 : fichiers `data/sanctuary-blocodex/<uuid>.json`, enveloppe
|
||||
avec `schema: 1` et UUID, puis observations, possessions et poses par identifiant.
|
||||
Les statistiques vanilla restent dans leurs propres fichiers et sont seulement
|
||||
lues. Aucune conversion du terrain, des paramètres de génération, des chunks,
|
||||
du journal d'expansion ou des statistiques existantes n'est effectuée.
|
||||
|
||||
Sans fichier Blocodex, les observations et poses commencent vides. Le minage,
|
||||
le jet et les preuves de possession sont disponibles depuis les statistiques
|
||||
vanilla déjà présentes. On n'invente pas les observations ni les poses passées
|
||||
à partir de `used`, qui compte aussi d'autres usages.
|
||||
|
||||
Les changements sont sauvegardés tous les 600 ticks, lors de la sauvegarde du
|
||||
serveur, à la déconnexion et à l'arrêt. Un crash peut perdre les dernières
|
||||
observations ou poses non sauvegardées. Un fichier invalide ou d'une version
|
||||
inconnue désactive la mémoire concernée et n'est jamais remplacé silencieusement.
|
||||
Les identifiants de mods absents sont conservés sur disque. Les anciennes
|
||||
versions de Sanctuary ignorent ce répertoire additionnel ; les poses réalisées
|
||||
pendant un retour à une ancienne version ne peuvent pas être récupérées.
|
||||
|
||||
## Réutilisation
|
||||
|
||||
`BlockKnowledgeService.knowledge(player, block)` et `snapshot(player)` renvoient
|
||||
des valeurs immuables calculées côté serveur. Le service expose aussi sa santé ;
|
||||
un consommateur doit refuser une condition de progression si la mémoire est
|
||||
indisponible, plutôt que d'interpréter une panne comme une découverte vierge.
|
||||
`BlockKnowledgeEvents.CHANGED` permet de réagir aux observations, possessions,
|
||||
poses et changements de statistiques. Les écouteurs s'exécutent sur le thread
|
||||
serveur ; ils ne constituent pas un journal transactionnel de récompenses.
|
||||
|
||||
Cette livraison ne verrouille aucune recette et n'accorde aucune récompense.
|
||||
Palettes disponibles, recherches, progression et structures pourront ensuite
|
||||
définir leurs propres conditions en utilisant cette API commune.
|
||||
|
||||
### Palettes de structures
|
||||
|
||||
`BlockKnowledgeService.palette(player, condition, tag)` croise les connaissances
|
||||
du joueur avec une famille de matériaux. Les critères `BlockKnowledgeFacet`
|
||||
sont combinables avec `and` et `or` : vus **ou** déjà possédés, minés **et**
|
||||
actuellement portés, etc. Le résultat immuable garde les identifiants triés et
|
||||
les quantités réellement portées.
|
||||
|
||||
```java
|
||||
var candidates = BlockKnowledgeService.palette(player,
|
||||
BlockKnowledgeFacet.SEEN.or(BlockKnowledgeFacet.POSSESSED),
|
||||
BlockKnowledgeService.NATURAL_STRUCTURE_MATERIALS);
|
||||
```
|
||||
|
||||
Le tag `sanctuary:structure_palette/natural` fournit une première famille de
|
||||
pierres, terres, bois, feuilles et autres matériaux naturels, modifiable par
|
||||
datapack. D'autres tags pourront définir des palettes minérales, végétales ou
|
||||
propres à un biome. Le choix des couleurs, les contraintes physiques des blocs,
|
||||
les quantités nécessaires et la construction de la structure appartiendront au
|
||||
moteur de structures : une sélection de palette ne réserve aucun stock et ne
|
||||
place aucun bloc.
|
||||
|
||||
## Recensement du terrain chargé
|
||||
|
||||
`TerrainCensus.snapshot(server)` expose une distribution des blocs par dimension ;
|
||||
`TerrainCensus.chunkSnapshot(level, pos)` fournit le détail d’un chunk déjà
|
||||
chargé. Ces lectures se font sur le thread serveur et renvoient des valeurs
|
||||
immuables. Elles parcourent les chunks `FULL` déjà accessibles, sans charger
|
||||
de chunk absent ni attendre la fin d’une génération.
|
||||
|
||||
Le comptage utilise les palettes des sections de 16 × 16 × 16 blocs. Il regroupe
|
||||
les orientations et autres propriétés sous l’identifiant du bloc. Les blocs
|
||||
d’air sont exclus ; l’eau et la lave conservent leurs identifiants de blocs.
|
||||
Le budget est de **16 sections non vides par tick serveur**, partagé entre les
|
||||
dimensions et les demandes du même tick. Une section entièrement vide est
|
||||
reconnue par ses métadonnées, sans parcourir sa palette.
|
||||
|
||||
Le relevé est progressif. Une section modifiée est retirée des totaux dès que
|
||||
sa révision change, puis remise dans la file de comptage. Les sections et
|
||||
chunks déchargés sortent du relevé. Un consommateur dispose, par dimension ou
|
||||
chunk, du nombre de sections chargées et comptées, du tick de capture, du tick
|
||||
du dernier comptage effectué et de l’âge de la plus ancienne attente.
|
||||
`complete()` et `coverage()` décrivent la couverture **des zones chargées**.
|
||||
Une couverture de 100 % ne signifie jamais que toute la sauvegarde a été lue.
|
||||
|
||||
Pendant un rattrapage, zéro bloc compté ne prouve donc pas l’absence de ce bloc.
|
||||
Les futures règles d’expansion devront fixer leur couverture minimale et leur
|
||||
zone d’étude avant de prendre une décision. Les résultats en mémoire sont
|
||||
reconstruits après redémarrage ; ce service n’écrit pas dans les chunks et ne
|
||||
modifie pas leur génération.
|
||||
|
||||
## Recensement des stocks présents
|
||||
|
||||
`StockCensus.snapshot(server)` photographie les objets accessibles au tick de
|
||||
la demande, sur le thread serveur. Le parcours des slots et des entités chargées
|
||||
est effectué à la demande ; aucun abonnement ne le relance à chaque tick.
|
||||
Les quantités sont des unités d’items, tous
|
||||
types confondus : un lingot, un outil ou une graine sont comptés même s’ils ne
|
||||
correspondent pas à un bloc. Les composants, l’usure et les enchantements ne
|
||||
créent pas de nouveaux identifiants de stock dans cette version.
|
||||
|
||||
| Catégorie | Couverture |
|
||||
| --- | --- |
|
||||
| `playerItems` | Joueurs connectés : inventaire personnel, équipement et curseur du menu. Le contenu du menu ouvert n’est pas additionné. |
|
||||
| `blockContainerItems` | Entités de blocs déjà instanciées dans les chunks chargés, qui exposent l’interface `Container` : coffres, hoppers, fours, pots décorés, etc. Chaque moitié d’un double coffre est comptée une fois. |
|
||||
| `entityContainerItems` | Entités chargées qui exposent `Container`, notamment les wagonnets et bateaux à coffre. |
|
||||
| `groundItems` | Quantités des `ItemEntity` chargées et encore présentes au sol. |
|
||||
|
||||
Le relevé ne déballe **aucune table de butin**. Tout conteneur dont la table
|
||||
reste à résoudre est ignoré avant la lecture de ses slots ; son existence
|
||||
augmente `pendingLootContainers`. Les entités de blocs encore stockées sous
|
||||
forme de NBT et non instanciées sont également laissées intactes, avec leur
|
||||
nombre dans `pendingBlockEntities`. Leur contenu n’est pas remplacé par une
|
||||
estimation.
|
||||
|
||||
La couverture exclut les joueurs hors ligne, les chunks et entités déchargés,
|
||||
les ender chests, le contenu imbriqué des shulker boxes et bundles, les grilles
|
||||
de fabrication en cours dans l’inventaire ou l’établi (`menuInputsIncluded()`
|
||||
est faux), les inventaires et équipements des créatures. Le résultat de
|
||||
fabrication affiché avant validation ne constitue pas un stock supplémentaire.
|
||||
Elle exclut aussi les objets internes
|
||||
des entités de blocs qui n’exposent pas `Container`, comme les aliments d’un feu
|
||||
de camp ou le livre d’un pupitre. Une shulker box portée compte comme un item ;
|
||||
une shulker box posée et chargée expose son conteneur. Les exclusions figurent
|
||||
dans le contrat de couverture ; `partial()` reste vrai.
|
||||
|
||||
Ce relevé indique où se trouvent les unités observées. Il ne les réserve pas,
|
||||
ne les transfère pas et n’évalue pas leur prix. Ajouter le terrain aux stocks
|
||||
ne donne pas une quantité immédiatement vendable : une roche dans un chunk
|
||||
reste différente d’un item dans un coffre.
|
||||
|
||||
## Consultation et futurs consommateurs communs
|
||||
|
||||
`WorldCensusService.capture(server)` rassemble les deux relevés pour une même
|
||||
lecture côté serveur. Le consommateur réutilise cet instantané pendant son
|
||||
calcul et conserve ses informations de couverture. Le shop et les expansions
|
||||
pourront ainsi consulter la même base, avec leurs propres règles de fraîcheur,
|
||||
de portée géographique, de prix, de consommation et de réservation.
|
||||
|
||||
Les diagnostics suivants sont réservés aux opérateurs :
|
||||
|
||||
```text
|
||||
/sanctuary census
|
||||
/sanctuary census block minecraft:stone
|
||||
/sanctuary census item minecraft:gold_ingot
|
||||
```
|
||||
|
||||
Le résumé présente la couverture du terrain par dimension, les quatre catégories
|
||||
de stocks et les conteneurs au butin encore indéterminé. Le Blocodex personnel
|
||||
accessible par **B** conserve les données du joueur ; ces diagnostics ne diffusent
|
||||
pas les inventaires agrégés aux autres joueurs.
|
||||
|
||||
## Relevés datés — portée de l’alpha.23
|
||||
|
||||
La collecte regroupe les activités observées par **jour civil UTC**, pour
|
||||
l’ensemble du serveur, sans attribution à un UUID ou à une dimension :
|
||||
|
||||
| Action | Registre et unité |
|
||||
| --- | --- |
|
||||
| `mined` | `block` : nombre de blocs minés, selon les règles des statistiques vanilla. |
|
||||
| `placed` | `block` : placements réussis par le joueur, créatif inclus et spectateurs exclus. |
|
||||
| `picked_up` | `item` : unités ramassées observées par les statistiques vanilla. |
|
||||
| `dropped` | `item` : unités volontairement jetées observées par les statistiques vanilla. |
|
||||
| `crafted` | `item` : unités fabriquées créditées au joueur par les statistiques vanilla. |
|
||||
|
||||
Chaque combinaison conserve son action, son registre, son identifiant et une
|
||||
quantité entière sur 64 bits, saturée à la valeur maximale en cas de dépassement.
|
||||
Un compteur de minage n’est pas transformé en nombre d’items produits. Les actions
|
||||
antérieures à l’installation ne sont pas réparties artificiellement entre des
|
||||
dates à partir des statistiques cumulées de Minecraft.
|
||||
|
||||
`MaterialActivityHistory.snapshot(server, day)` expose un instantané immuable
|
||||
avec le jour, les compteurs, `recorded` et `unsaved`. Un jour sans données
|
||||
enregistrées demeure inconnu ; il ne constitue pas un historique d’activité nulle.
|
||||
Les opérateurs peuvent consulter `/sanctuary history` ou préciser une date avec
|
||||
`/sanctuary history 2026-09-10`. La commande affiche au plus les 16 lignes aux
|
||||
quantités les plus élevées et indique combien ont été omises ; l’API conserve
|
||||
l’ensemble des compteurs du jour.
|
||||
|
||||
La persistance additionnelle utilise `data/sanctuary-activity/YYYY-MM-DD.json`,
|
||||
avec un schéma 1 et des dates UTC. Elle est séparée de la mémoire personnelle
|
||||
et des chunks. Les écritures ont lieu tous les **600 ticks**, à la sauvegarde
|
||||
et à l’arrêt du serveur, ainsi qu’au changement de jour observé par le service.
|
||||
Un crash peut perdre les derniers relevés non sauvegardés, soit normalement
|
||||
jusqu’à 30 secondes de jeu à 20 ticks par seconde. Le fichier conserve les
|
||||
identifiants de mods absents ; il refuse les schémas inconnus, doublons,
|
||||
compteurs invalides et changements externes. Une erreur arrête la collecte et
|
||||
rend le service indisponible jusqu’à réparation puis redémarrage, en conservant
|
||||
le fichier en cause. Les limites sont de 100 000 tuples et 16 Mio par jour.
|
||||
|
||||
Ces relevés permettent de distinguer des périodes d’activité. Ils ne conservent
|
||||
pas d’historique des instantanés de stocks, ne couvrent pas la fabrication automatique des
|
||||
machines et n’établissent ni consommation, ni perte, ni destination des objets.
|
||||
Ils ne retracent pas chaque transfert entre coffres ou chaque changement de propriétaire, et
|
||||
ne constituent pas un journal transactionnel d’achats, de récompenses ou de
|
||||
réservations. Le **ballast**, ses unités, ses conversions et sa traduction en
|
||||
géologie restent à concevoir dans le [cahier de cosmologie](cosmologie.md).
|
||||
Aucun objet n’est consommé et aucune Backroom n’est générée par ces mesures.
|
||||
|
||||
## Référence WSMC retrouvée
|
||||
|
||||
La recherche locale a retrouvé une partie du travail précédent dans
|
||||
`/Users/koka/Documents/sanctuary/Gameplay/blocodex` :
|
||||
`ClientVoxelProjectBuilder` convertit des apparences de blocs et d’items en
|
||||
volumes/couches de blocs ; `BlocodexStudioPalettes` sélectionne des matériaux
|
||||
opaques appris. Le projet conserve aussi un instantané WSMC de 1 881 entrées
|
||||
(1 168 blocs, 490 items, 223 mobs), issu de Minecraft 1.21.11.
|
||||
|
||||
Cette référence reste historique. La nouvelle API fournit la connaissance et
|
||||
les candidats de palette ; la traduction de modèles d’entités en structures
|
||||
(visage de creeper, squelette géant, etc.) reste un chantier distinct. Aucun
|
||||
générateur d’entités ni import de ce snapshot ancien n’est ajouté au registre
|
||||
de Minecraft 26.3 par le socle méta.
|
||||
|
||||
## Validation
|
||||
|
||||
Validation locale du 10 septembre 2026 : `./gradlew check build assemblePack`
|
||||
passe, avec **24 GameTests natifs réussis**. Le client graphique vérifie les
|
||||
widgets et les messages réels dans un nouveau monde intégré, avec B sans droit
|
||||
opérateur, observation serveur et possession conservée après retrait du stock.
|
||||
Les tests de stockage passent. Les [preuves et limites](testing-alpha23.md)
|
||||
détaillent le protocole, l’artefact et son empreinte. Alpha.23 assemblée localement ;
|
||||
publication du MRpack et mise à jour du canal demandées, en préparation.
|
||||
Reference in New Issue
Block a user