diff --git a/README.md b/README.md index 1853494..ea52140 100644 --- a/README.md +++ b/README.md @@ -20,13 +20,13 @@ 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.125** étend les sculptures au centre, aux bords et aux coins, -en bas, au milieu ou en haut du bloc. Les éclats reprennent la couleur des voxels -et le Clay Workshop propose les animaux déjà découverts, en plus des imports GLB. -Le [ticket de livraison](docs/sculpture-placement-beta125.md) décrit le placement, -la compatibilité des anciennes sculptures et les vérifications. La release est -publiée et l’instance **Sanctuary Beta** synchronisée, sauvegardes et réglages -conservés. Packs normal/Test et template sont aussi dans le dossier `build/`. +La version **beta.126** ajoute le rubis et le saphir, leurs minerais et leurs +blocs, rangés après l'émeraude. Leur génération est configurable et limitée +aux nouveaux chunks de Sanctuary. L'argile classique du Clay Workshop conserve +les couleurs originales des modèles. La commande `/sanctuary discovery` +enrichit les découvertes communes, globalement ou précisément, et actualise +les recettes et catalogues liés. Le [ticket de livraison](docs/gems-beta126.md) +décrit les règles, la compatibilité et les vérifications. 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**. Les [synchronisations antérieures](docs/git-sync-beta092.md) restent documentées. @@ -37,6 +37,14 @@ La [carte native beta.005](docs/atlas-beta005.md) prend le relais après l’étude de Xaero et des alternatives libres. +## beta.126 — Gemmes, argile et découvertes + +Rubis et saphir avec filons configurables, couleurs originales avec l'argile, +commandes de découverte globales ou ciblées. +[Contrat et vérifications](docs/gems-beta126.md) · +[Pack normal](https://git.botsu.net/koka/sanctuary-beta/releases/download/beta.126/Sanctuary-beta.126.mrpack) · +[Pack de test](https://git.botsu.net/koka/sanctuary-beta/releases/download/beta.126/Sanctuary-Test-beta.126.mrpack). + ## beta.125 — Sculptures : placement, éclats et animaux Coins et trois hauteurs sur la grille 1/16 ; particules issues des voxels ; diff --git a/docs/gems-beta126.md b/docs/gems-beta126.md new file mode 100644 index 0000000..d7774f0 --- /dev/null +++ b/docs/gems-beta126.md @@ -0,0 +1,136 @@ +# GEM-01 — Gemmes, argile et découvertes — beta.126 + +Contrat du 17 septembre 2026, branche `codex/gems-beta126`, Minecraft 26.3. + +Deux gemmes natives complètent l'émeraude : `sanctuary:ruby` et +`sanctuary:sapphire`. Chaque famille comprend un bloc de stockage, un minerai +ordinaire et un minerai des abîmes. Les huit PNG du créateur sont copiés à +l'identique ; leurs empreintes figurent dans `tools/gems-textures-beta126.json`. +Les noms des fichiers français `saphir` sont associés aux identifiants anglais +stables `sapphire`, sans modifier les pixels. Les deux items utilisent les fichiers de remplacement +`Desktop/ruby.png` et `Desktop/saphir.png` fournis en fin de livraison. + +L'ordre créatif est émeraude, rubis, saphir : ingrédients, blocs de stockage, +minerais ordinaires et minerais des abîmes dans leurs onglets natifs respectifs. +Minage à la pioche de fer ou mieux, résistance et expérience comme l'émeraude, +Fortune, Toucher de soie, cuisson/four à fusion et conversion 9 gemmes ↔ 1 bloc. +Les blocs peuvent former un socle de balise et les gemmes servir de paiement. +Les recettes rejoignent la collection actuelle de l'émeraude, sans ajouter de +transactions de villageois. Libellés français et anglais, tags communs `c:`. + +## Génération procédurale et contrat de compatibilité + +Profil initial **gemmes 1 / beta.126** : quatre tentatives par chunk et par +gemme, filons natifs de taille 3, hauteur uniforme Y0–256, probabilité de rejet +au contact de l'air de 0,25. Ces nombres sont un réglage initial à équilibrer +lors de la future refonte ; aucun quota de gemmes par chunk n'est garanti. +Les variantes ordinaires remplacent les roches du tag vanilla +`stone_ore_replaceables`, les variantes des abîmes celles de +`deepslate_ore_replaceables`. + +Les fichiers `worldgen/feature/ore_.json`, +`worldgen/placed_feature/ore_.json` et les tags de biomes +`has_ore/` séparent les cibles, la forme, la fréquence, la hauteur et +les régions. Un datapack peut les remplacer sans recompiler le mod. Le code +réutilise `OreFeature` et le hasard natif issu de la graine ; il limite ces +filons aux mondes utilisant `SanctuaryChunkGenerator`. Les biomes vanilla +partagés avec Sanctuary restent compatibles sans ajouter les gemmes aux +mondes vanilla, au Nether ou à l'End. + +Cette évolution additive est autorisée pour les **nouveaux chunks uniquement**. +Aucun remplissage rétrospectif, aucune régénération, aucun remplacement de chunk +sauvegardé ni activation d'expansion. Les codecs du relief, les dimensions et +le format des sauvegardes restent inchangés. Les filons suivent les protections +existantes de la décoration native. Les anciens profils expérimentaux précédant +le générateur Sanctuary unifié ne sont pas étendus. + +## Argile spéciale dans le Clay Workshop + +Le bloc d'argile vanilla conserve les couleurs échantillonnées sur le modèle +original, animal découvert ou import GLB. Les argiles colorées et les autres +blocs continuent à transférer leur palette de texture. Une même règle est +appliquée à l'aperçu client et au résultat serveur. Le changement de matériau +invalide le résultat même si les deux palettes sont identiques. Le texte de +l'atelier explique l'exception en français et en anglais. + +Une sculpture coûte toujours un bloc ; aucune recette, découverte, donnée de +sculpture déjà fabriquée ni règle de placement n'est modifiée. + +## Commande de découverte commune + +`/sanctuary discovery all` découvre tous les blocs, objets et espèces enregistrés. +Les variantes `blocks all`, `items all` et `mobs all` ciblent une catégorie ; +`block `, `item ` et `mob ` ciblent une +entrée avec la complétion native. Un sélecteur de joueurs en fin de commande +est facultatif ; sans cible, elle s'applique au joueur qui l'exécute. + +Exemples : + +```mcfunction +/sanctuary discovery all +/sanctuary discovery mobs all +/sanctuary discovery block minecraft:stone +/sanctuary discovery item minecraft:diamond +/sanctuary discovery mob minecraft:cow +/sanctuary discovery all @a +``` + +La permission suit « Autoriser les commandes » en solo et les droits opérateur +sur serveur. La console doit préciser la cible. Les identifiants invalides, +l'air et les types d'entités sans espèce découvrable sont refusés. + +Les blocs passent par le registre de découvertes et son événement existant ; +les objets passent par `RecipeService.discover`. Les collections et recettes +sont ensuite recalculées normalement. Les espèces rejoignent `seen_mobs`, +la même donnée que l'observation naturelle, consommée par les familiers, +le Métabli et le Clay Workshop. Il n'existe aucun drapeau de déblocage parallèle. +Les catalogues déjà ouverts sont à rouvrir après la commande. + +La commande conserve les quantités possédées et les compteurs de combat, +minage, pose et fabrication. Elle ne donne pas d'objets, n'achète pas les skills +et n'attribue pas d'advancements. Les recettes réservées aux opérateurs gardent +leurs règles. Les historiques personnels sont enrichis sans changer leur +schéma ; la commande refuse les données illisibles plutôt que les remplacer. + +## Vérifications + +Client natif Minecraft 26.3 / Java 25, `Gems126ClientChecks`, réussi en +1 min 08 s. Les mondes sont jetables, sans sauvegarde personnelle ouverte : + +- Les huit items et six blocs sont présents, avec les huit textures exactes. + Quatre groupes créatifs respectent émeraude → rubis → saphir, sans doublons. +- Douze recettes natives, découverte du bloc de stockage, outil fer minimum, + Fortune III, Toucher de soie et balises passent les contrôles serveur. +- Graine **126**, profil gemmes 1, 81 chunks autour de l'origine : 7 rubis dans + la pierre et 8 dans la roche des abîmes ; 15 saphirs dans la pierre et 10 dans + la roche des abîmes. La génération est refusée dans le monde plat vanilla. + Les minerais persistent à la reconnexion, et un minerai retiré ne réapparaît pas. +- L'argile conserve exactement les couleurs des voxels d'une vache et d'un GLB + texturé. Bois et argile colorée transfèrent toujours leur palette. Le retour + à l'argile, l'égalité aperçu/résultat et le coût d'un bloc en survie sont vérifiés. +- La commande native respecte « Autoriser les commandes », accepte une cible + et la console, refuse les identifiants invalides et permet une espèce, un + bloc, un objet, toutes les espèces ou tout le contenu. Les recettes liées + sont recalculées. La répétition est idempotente et les découvertes survivent + à la reconnexion sans inventer de compteurs de combat ou de possession. + +Logs et captures dans `build/gems126-client.log` et +`mods/sanctuary/build/run/clientGameTest/screenshots/`. Le GameTest dédié +reste exclu conformément au refus antérieur de son EULA. Le build complet et +les archives sont vérifiés séparément avant publication. + + +Build final `./gradlew check build assemblePack assembleTestPack +-x :sanctuary:runGameTest` réussi en **2 min 10 s**, 126 tâches. Les contrôles +natifs de gameplay précèdent uniquement le remplacement final des deux PNG +d'items ; les huit fichiers livrés sont vérifiés à l'octet près contre les +sources, tous en 16 × 16. Les JAR de sources correspondent aux sources courantes. +L'audit entre les binaires beta.125 et beta.126 ne trouve que les 112 entrées +de production prévues. Les archives normal/Test contiennent le même mod et +le template reproduit exactement ses ressources exportables. + +| Artefact | SHA-256 | +| --- | --- | +| `Sanctuary-beta.126.mrpack` | `716221ce24549781ab91f5437ad2310497b198a4b61c43c40c67a27984365ae5` | +| `Sanctuary-Test-beta.126.mrpack` | `bbf22d7dd72e6746538b4ec28686f699225d4a59372304e5db42140a80e88bd1` | +| `sanctuary-beta.126.jar` | `85dbe1b41d98751029bb62e87d259522f8609758896c797b1e02fa7656ec0342` | diff --git a/gradle.properties b/gradle.properties index 4525f4c..864022f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -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.125 -pack_version=beta.125 +mod_version=beta.126 +pack_version=beta.126 resource_pack_version=beta.121 maven_group=fr.koka.sanctuary jei_version=30.32.0-sanctuary.3 diff --git a/mods/sanctuary/build.gradle b/mods/sanctuary/build.gradle index c0ee4bd..be6d2ca 100644 --- a/mods/sanctuary/build.gradle +++ b/mods/sanctuary/build.gradle @@ -93,6 +93,10 @@ tasks.named('runGameTest') { } tasks.named('processGametestResources') { + def gems126Client = providers.gradleProperty('sanctuaryGems126ClientTests').map { it.toBoolean() }.getOrElse(false) + inputs.property('sanctuaryGems126ClientTests', gems126Client) + if (gems126Client) filter { line -> line.replace('fr.koka.sanctuary.gametest.SanctuaryClientRenderTests', 'fr.koka.sanctuary.client.Gems126ClientChecks') } + def sculpture125Client = providers.gradleProperty('sanctuarySculpture125ClientTests').map { it.toBoolean() }.getOrElse(false) inputs.property('sanctuarySculpture125ClientTests', sculpture125Client) if (sculpture125Client) filter { line -> line.replace('fr.koka.sanctuary.gametest.SanctuaryClientRenderTests', 'fr.koka.sanctuary.client.Sculpture125ClientChecks') } diff --git a/mods/sanctuary/src/clientGametest/java/fr/koka/sanctuary/client/Clay126Checks.java b/mods/sanctuary/src/clientGametest/java/fr/koka/sanctuary/client/Clay126Checks.java new file mode 100644 index 0000000..5c96a6b --- /dev/null +++ b/mods/sanctuary/src/clientGametest/java/fr/koka/sanctuary/client/Clay126Checks.java @@ -0,0 +1,42 @@ +package fr.koka.sanctuary.client; + +import fr.koka.sanctuary.companion.CompanionService; +import fr.koka.sanctuary.plans.*; +import java.nio.file.*; +import java.util.*; +import net.fabricmc.fabric.api.client.gametest.v1.context.*; +import net.minecraft.core.BlockPos; +import net.minecraft.world.entity.EntityTypes; +import net.minecraft.world.inventory.ContainerInput; +import net.minecraft.world.item.*; +import net.minecraft.world.level.GameType; + +/** Native preview, server result and survival payment for the special plain-clay material. */ +final class Clay126Checks { + static void exercise(ClientGameTestContext c,TestServerContext server){ + var pos=new BlockPos(4,1,4); + server.runOnServer(s->{var p=s.getPlayerList().getPlayers().getFirst();p.teleportTo(3,1,3);p.setGameMode(GameType.SURVIVAL);p.getAbilities().invulnerable=true;p.onUpdateAbilities();p.level().setBlockAndUpdate(pos,Statuary.WORKSHOP.defaultBlockState());CompanionService.save(p,CompanionService.record(p).note("seen_mobs","cow"));Statuary.open(p,pos);p.containerMenu.getSlot(0).set(new ItemStack(Items.CLAY,2));p.containerMenu.broadcastChanges();}); + c.waitForScreen(ClayWorkshopScreen.class);c.runOnClient(m->{m.options.guiScale().set(2);m.getWindow().setWindowed(1280,800);m.resizeGui();((ClayWorkshopScreen)m.gui.screen()).load(EntityTypes.COW);}); + c.waitFor(m->{var screen=(ClayWorkshopScreen)m.gui.screen();return !screen.busy()&&screen.selected()!=null&&screen.selected().equals(StatuaryEntity.sculpture(m.player.containerMenu.getSlot(1).getItem()));},250); + var cow=c.computeOnClient(m->((ClayWorkshopScreen)m.gui.screen()).selected());check(cow.cells().stream().map(VoxelSculpture.Cell::color).distinct().count()>3,"Cow source retains texture colors"); + for(var material:List.of(Items.OAK_PLANKS,fr.koka.sanctuary.building.ColoredBricks.families().getFirst().clay().asItem(),Items.CLAY)){ + server.runOnServer(s->{var menu=s.getPlayerList().getPlayers().getFirst().containerMenu;menu.getSlot(0).set(new ItemStack(material,2));menu.broadcastChanges();}); + var expected=c.computeOnClient(m->ClayWorkshopMenu.appearance(cow,material,SculptureMaterialSampler.sample(new ItemStack(material)))); + check(material==Items.CLAY?expected.equals(cow):!expected.equals(cow),"Only plain clay retains original colors"); + c.waitFor(m->expected.equals(StatuaryEntity.sculpture(m.player.containerMenu.getSlot(1).getItem())),180); + c.runOnClient(m->check(ItemStack.matches(((ClayWorkshopScreen)m.gui.screen()).preview(),m.player.containerMenu.getSlot(1).getItem()),"Preview matches authoritative material switch")); + } + c.takeScreenshot("clay126-original-cow"); + c.runOnClient(m->m.gameMode.handleContainerInput(m.player.containerMenu.containerId,1,0,ContainerInput.PICKUP,m.player)); + server.waitFor(s->{var menu=s.getPlayerList().getPlayers().getFirst().containerMenu;return cow.equals(StatuaryEntity.sculpture(menu.getCarried()))&&menu.getSlot(0).getItem().getCount()==1;},100); + c.waitFor(m->cow.equals(StatuaryEntity.sculpture(m.player.containerMenu.getCarried()))&&m.player.containerMenu.getSlot(0).getItem().getCount()==1,100); + Path file=PlanClient.directory().resolve("clay126-"+UUID.randomUUID()+".glb"); + try{Files.createDirectories(file.getParent());Files.write(file,Statuary106ClientChecks.fixture());var id=GlbModel.load(file).id();c.runOnClient(m->((ClayWorkshopScreen)m.gui.screen()).load(file)); + c.waitFor(m->{var screen=(ClayWorkshopScreen)m.gui.screen();return !screen.busy()&&screen.selected()!=null&&screen.selected().modelId().equals(id)&&screen.selected().equals(StatuaryEntity.sculpture(m.player.containerMenu.getSlot(1).getItem()));},250); + c.runOnClient(m->{var screen=(ClayWorkshopScreen)m.gui.screen();check(screen.selected().cells().stream().map(VoxelSculpture.Cell::color).distinct().count()>1,"Imported textured GLB retains its original colors");check(ItemStack.matches(screen.preview(),m.player.containerMenu.getSlot(1).getItem()),"Imported preview equals native result");}); + }catch(Exception e){throw new AssertionError(e);}finally{try{Files.deleteIfExists(file);}catch(Exception ignored){}} + server.runOnServer(s->{var p=s.getPlayerList().getPlayers().getFirst();p.closeContainer();p.setGameMode(GameType.CREATIVE);p.getAbilities().flying=true;p.onUpdateAbilities();});c.waitFor(m->m.gui.screen()==null,100); + System.out.println("CLAY126_PASS original animal and GLB colors, oak and colored clay palette transfer, switch back, matching previews and one clay paid in survival"); + } + private static void check(boolean ok,String message){if(!ok)throw new AssertionError(message);} +} diff --git a/mods/sanctuary/src/clientGametest/java/fr/koka/sanctuary/client/Discovery126Checks.java b/mods/sanctuary/src/clientGametest/java/fr/koka/sanctuary/client/Discovery126Checks.java new file mode 100644 index 0000000..34bf1a8 --- /dev/null +++ b/mods/sanctuary/src/clientGametest/java/fr/koka/sanctuary/client/Discovery126Checks.java @@ -0,0 +1,47 @@ +package fr.koka.sanctuary.client; + +import fr.koka.sanctuary.companion.*; +import fr.koka.sanctuary.knowledge.*; +import fr.koka.sanctuary.plans.*; +import fr.koka.sanctuary.recipes.*; +import java.util.*; +import net.fabricmc.fabric.api.client.gametest.v1.context.*; +import net.minecraft.core.BlockPos; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.stats.Stats; +import net.minecraft.world.entity.EntityTypes; +import net.minecraft.world.item.*; +import net.minecraft.world.level.block.Blocks; + +final class Discovery126Checks { + static void exercise(ClientGameTestContext c,TestServerContext server){ + server.runOnServer(s->{var p=s.getPlayerList().getPlayers().getFirst();var dispatcher=s.getCommands().getDispatcher(); + var source=p.createCommandSourceStack();var root=dispatcher.getRoot().getChild("sanctuary").getChild("discovery"); + s.getWorldData().setAllowCommands(false);check(!root.canUse(source),"Discovery commands respect native Allow Commands"); + try{dispatcher.execute("sanctuary discovery all",source);throw new AssertionError("Denied command executed");}catch(com.mojang.brigadier.exceptions.CommandSyntaxException expected){} + s.getWorldData().setAllowCommands(true); + var before=CompanionService.record(p);var items=new TreeSet<>(RecipeService.knowledge(p).items);int kills=p.getStats().getValue(Stats.ENTITY_KILLED,EntityTypes.WITHER); + command(p,"mob minecraft:wither");check(StatueDiscoveries.known(p).contains("minecraft:wither"),"Precise species unlocks sculpture catalogue");check(CompanionService.record(p).notes().get("seen_mobs").contains("wither"),"Same actual seen_mobs record");check(RecipeService.knowledge(p).items.equals(items),"Mob discovery invents no unrelated item discovery");check(p.getStats().getValue(Stats.ENTITY_KILLED,EntityTypes.WITHER)==kills,"No fake kill stat"); + command(p,"block minecraft:pink_glazed_terracotta");var block=BlockKnowledgeService.knowledge(p,Blocks.GLAZED_TERRACOTTA.pick(DyeColor.PINK));check(block.seen()&&!block.possessed()&&block.mined()==0&&block.placed()==0,"Precise block is seen without fabricated possession or stats");check(RecipeService.knowledge(p).items.contains("minecraft:pink_glazed_terracotta")&&RecipeService.knowledge(p).collections.contains("sanctuary:terracotta"),"Block event unlocks its normal recipe collection"); + command(p,"item minecraft:amethyst_shard");check(RecipeService.knowledge(p).items.contains("minecraft:amethyst_shard")&&RecipeService.knowledge(p).recipes.contains("minecraft:spyglass"),"Precise item unlocks linked recipes"); + String old=CompanionService.record(p).json();check(run(p,"mob minecraft:item")==0,"Nonmob type refused");check(CompanionService.record(p).json().equals(old),"Rejected request does not change discoveries"); + try{dispatcher.execute("sanctuary discovery item sanctuary:missing_item",source);throw new AssertionError("Missing ID accepted");}catch(com.mojang.brigadier.exceptions.CommandSyntaxException expected){} + command(p,"mobs all");allSpecies(p);var pos=new BlockPos(4,1,4);Statuary.open(p,pos);check(((ClayWorkshopMenu)p.containerMenu).view.statues().equals(StatueDiscoveries.known(p)),"Workshop sees the shared full catalogue");p.closeContainer(); + command(p,"all");all(p);String species=CompanionService.record(p).json(),recipes=RecipeService.knowledge(p).json();var blocks=BlockKnowledgeService.snapshot(p);command(p,"all @s");check(species.equals(CompanionService.record(p).json())&&recipes.equals(RecipeService.knowledge(p).json())&&blocks.equals(BlockKnowledgeService.snapshot(p)),"Repeated all with target selector is idempotent"); + check(CompanionService.record(p).paid()==before.paid()&&CompanionService.record(p).unlocked()==before.unlocked(),"Discoveries do not fabricate paid skills"); + try{check(dispatcher.execute("sanctuary discovery mob minecraft:cow "+p.getGameProfile().name(),s.createCommandSourceStack())==1,"Console can address an online player");}catch(Exception e){throw new AssertionError(e);} + System.out.println("DISCOVERY126_PASS native permissions, precise block/item/species, linked recipes, shared catalogue, all three categories, all, selector, console, idempotence and unchanged combat/ownership counters"); + }); + c.waitFor(m->m.gui.screen()==null,100); + } + static void all(ServerPlayer p){ + allSpecies(p);check(BlockKnowledgeService.snapshot(p).stream().allMatch(BlockKnowledge::known),"All block discoveries"); + var knowledge=RecipeService.knowledge(p);for(var item:BuiltInRegistries.ITEM)if(item!=Items.AIR)check(knowledge.items.contains(BuiltInRegistries.ITEM.getKey(item).toString()),"All registered items discovered"); + check(knowledge.recipes.contains("minecraft:spyglass")&&knowledge.recipes.contains("sanctuary:ruby_block"),"Vanilla and Sanctuary recipes are derived from discoveries"); + } + static void allSpecies(ServerPlayer p){check(StatueDiscoveries.known(p).size()==BuiltInRegistries.ENTITY_TYPE.stream().filter(t->SpawnEggItem.byId(t).isPresent()).count(),"All registered species discovered");} + static void command(ServerPlayer p,String args){check(run(p,args)==1,"Discovery command succeeds: "+args);} + private static int run(ServerPlayer p,String args){try{return p.level().getServer().getCommands().getDispatcher().execute("sanctuary discovery "+args,p.createCommandSourceStack());}catch(Exception e){throw new AssertionError(e);}} + private static void check(boolean ok,String message){if(!ok)throw new AssertionError(message);} +} diff --git a/mods/sanctuary/src/clientGametest/java/fr/koka/sanctuary/client/Gems126ClientChecks.java b/mods/sanctuary/src/clientGametest/java/fr/koka/sanctuary/client/Gems126ClientChecks.java new file mode 100644 index 0000000..30fb9ee --- /dev/null +++ b/mods/sanctuary/src/clientGametest/java/fr/koka/sanctuary/client/Gems126ClientChecks.java @@ -0,0 +1,88 @@ +package fr.koka.sanctuary.client; + +import com.mojang.blaze3d.platform.InputConstants; +import fr.koka.sanctuary.SanctuaryMod; +import fr.koka.sanctuary.gems.*; +import fr.koka.sanctuary.gametest.Starter039TestSupport; +import java.util.*; +import java.util.concurrent.atomic.AtomicBoolean; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; +import net.fabricmc.fabric.api.client.gametest.v1.FabricClientGameTest; +import net.fabricmc.fabric.api.client.gametest.v1.context.ClientGameTestContext; +import net.minecraft.client.gui.components.Button; +import net.minecraft.client.gui.screens.worldselection.WorldCreationUiState; +import net.minecraft.client.input.KeyEvent; +import net.minecraft.core.*; +import net.minecraft.core.registries.*; +import net.minecraft.network.chat.contents.TranslatableContents; +import net.minecraft.resources.ResourceKey; +import net.minecraft.tags.*; +import net.minecraft.util.RandomSource; +import net.minecraft.world.item.*; +import net.minecraft.world.item.crafting.*; +import net.minecraft.world.item.enchantment.Enchantments; +import net.minecraft.world.level.block.*; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.GenerationStep; + +/** Actual native registration, recipes, drops, tab order and naturally decorated Sanctuary chunks. */ +public final class Gems126ClientChecks implements FabricClientGameTest { + public void runTest(ClientGameTestContext c){ + var intro=new AtomicBoolean(true); + c.runOnClient(m->{m.options.renderDistance().set(5);m.options.simulationDistance().set(5);m.options.pauseOnLostFocus=false;IntroClient.setQuickTestIntro(true);}); + ClientTickEvents.END_CLIENT_TICK.register(m->{if(intro.get()&&m.gui.screen() instanceof HelloWorldScreen screen){ + IntroClient.setQuickTestIntro(true);Starter039TestSupport.selectFirst(screen);var enter=new KeyEvent(InputConstants.KEY_RETURN,0,0); + screen.children().stream().filter(Button.class::isInstance).map(Button.class::cast).filter(b->b.getClass().getSimpleName().equals("ColorButton")).findFirst().orElseThrow().onPress(enter); + screen.children().stream().filter(Button.class::isInstance).map(Button.class::cast).filter(b->b.getMessage().getContents() instanceof TranslatableContents t&&t.getKey().equals("sanctuary.progression.enter")).findFirst().orElseThrow().onPress(enter);intro.set(false); + }}); + try(var world=c.worldBuilder().adjustSettings(s->{s.setName("Gems126 registry "+UUID.randomUUID());s.setSeed("126");s.setAllowCommands(true);s.setGameMode(WorldCreationUiState.SelectedGameMode.CREATIVE);s.setWorldType(s.getNormalPresetList().stream().filter(e->e.preset()!=null&&e.preset().getRegisteredName().equals("sanctuary_test:flat")).findFirst().orElseThrow());}).create()){ + 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 l=p.level();var pos=new BlockPos(0,4,0);var iron=new ItemStack(Items.IRON_PICKAXE);var silk=iron.copy();silk.enchant(l.registryAccess().lookupOrThrow(Registries.ENCHANTMENT).getOrThrow(Enchantments.SILK_TOUCH),1);var fortune=iron.copy();fortune.enchant(l.registryAccess().lookupOrThrow(Registries.ENCHANTMENT).getOrThrow(Enchantments.FORTUNE),3); + for(var f:Gems.FAMILIES){ + for(var b:List.of(f.block(),f.ore(),f.deepslateOre())){var state=b.defaultBlockState();check(state.is(BlockTags.MINEABLE_WITH_PICKAXE)&&state.is(BlockTags.NEEDS_IRON_TOOL),"Native mining tags "+b);check(iron.isCorrectToolForDrops(state)&&!new ItemStack(Items.STONE_PICKAXE).isCorrectToolForDrops(state),"Iron tier enforced "+b);} + drop(Block.getDrops(f.block().defaultBlockState(),l,pos,null,p,iron),f.block().asItem(),1); + for(var ore:List.of(f.ore(),f.deepslateOre())){ + drop(Block.getDrops(ore.defaultBlockState(),l,pos,null,p,iron),f.gem(),1);drop(Block.getDrops(ore.defaultBlockState(),l,pos,null,p,silk),ore.asItem(),1); + int max=0;for(int i=0;i<48;i++){var drops=Block.getDrops(ore.defaultBlockState(),l,pos,null,p,fortune);check(drops.size()==1&&drops.getFirst().is(f.gem()),"Fortune gem type");int n=drops.getFirst().getCount();check(n>=1&&n<=4,"Native Fortune III range");max=Math.max(max,n);}check(max>1,"Fortune increases gem yield"); + var input=new SingleRecipeInput(new ItemStack(ore));for(var type:List.of(RecipeType.SMELTING,RecipeType.BLASTING)){var recipe=s.getRecipeManager().getRecipeFor(type,input,l).orElseThrow().value();check(recipe.assemble(input).is(f.gem()),"Native furnace recipe");} + } + var input=CraftingInput.of(3,3,Collections.nCopies(9,new ItemStack(f.gem())));drop(List.of(s.getRecipeManager().getRecipeFor(RecipeType.CRAFTING,input,l).orElseThrow().value().assemble(input)),f.block().asItem(),1); + input=CraftingInput.of(1,1,List.of(new ItemStack(f.block())));drop(List.of(s.getRecipeManager().getRecipeFor(RecipeType.CRAFTING,input,l).orElseThrow().value().assemble(input)),f.gem(),9); + check(f.block().defaultBlockState().is(BlockTags.BEACON_BASE_BLOCKS)&&new ItemStack(f.gem()).is(ItemTags.BEACON_PAYMENT_ITEMS),"Native beacon compatibility"); + var feature=l.registryAccess().lookupOrThrow(Registries.FEATURE).getOrThrow(ResourceKey.create(Registries.FEATURE,SanctuaryMod.id("ore_"+f.id()))).value();check(feature instanceof GemOreFeature,"Data feature decoded"); + check(!feature.place(l,l.getChunkSource().getGenerator(),RandomSource.create(126),pos),"Gem veins do not run in ordinary flat/vanilla worlds"); + fr.koka.sanctuary.recipes.RecipeService.discover(p,f.gem());fr.koka.sanctuary.recipes.RecipeService.refresh(p);check(fr.koka.sanctuary.recipes.RecipeService.knowledge(p).recipes.contains("sanctuary:"+f.id()+"_block"),"Native discovery unlocks storage recipe"); + } + int x=0;for(var block:List.of(Blocks.EMERALD_BLOCK,Gems.RUBY.block(),Gems.SAPPHIRE.block(),Blocks.EMERALD_ORE,Gems.RUBY.ore(),Gems.SAPPHIRE.ore(),Blocks.DEEPSLATE_EMERALD_ORE,Gems.RUBY.deepslateOre(),Gems.SAPPHIRE.deepslateOre())){l.setBlockAndUpdate(new BlockPos(x%3,1,x/3),block.defaultBlockState());x++;} + p.teleportTo(1.5,3,7);p.getAbilities().flying=true;p.onUpdateAbilities();p.getInventory().setItem(0,new ItemStack(Items.EMERALD));p.getInventory().setItem(1,new ItemStack(Gems.RUBY.gem()));p.getInventory().setItem(2,new ItemStack(Gems.SAPPHIRE.gem()));p.inventoryMenu.broadcastFullState(); + System.out.println("GEMS126_SERVER_PASS eight registered items, six blocks, native loot/Fortune/Silk Touch, twelve recipes, mining tiers, beacons, discoveries and vanilla generation exclusion"); + }); + c.runOnClient(m->{CreativeModeTabs.tryRebuildTabContents(m.level.enabledFeatures(),true,m.level.registryAccess());order(CreativeModeTabs.INGREDIENTS,Items.EMERALD,Gems.RUBY.gem(),Gems.SAPPHIRE.gem());order(CreativeModeTabs.BUILDING_BLOCKS,Items.EMERALD_BLOCK,Gems.RUBY.block().asItem(),Gems.SAPPHIRE.block().asItem());order(CreativeModeTabs.NATURAL_BLOCKS,Items.EMERALD_ORE,Gems.RUBY.ore().asItem(),Gems.SAPPHIRE.ore().asItem());order(CreativeModeTabs.NATURAL_BLOCKS,Items.DEEPSLATE_EMERALD_ORE,Gems.RUBY.deepslateOre().asItem(),Gems.SAPPHIRE.deepslateOre().asItem()); + for(var f:Gems.FAMILIES)for(var block:List.of(f.block(),f.ore(),f.deepslateOre())){var parts=new ArrayList();m.getModelManager().getBlockStateModelSet().get(block.defaultBlockState()).collectParts(RandomSource.create(0),parts);check(!parts.isEmpty(),"Baked gem block model");for(var part:parts)for(var face:Direction.values())for(var quad:part.getQuads(face))check(!quad.materialInfo().sprite().contents().name().toString().contains("missingno"),"Native texture atlas resolves supplied gem PNG");} + System.out.println("GEMS126_CREATIVE_PASS emerald, ruby, sapphire adjacency in four groups; all six baked block models"); + }); + c.waitTicks(10);c.runOnClient(m->m.player.lookAt(net.minecraft.commands.arguments.EntityAnchorArgument.Anchor.EYES,new net.minecraft.world.phys.Vec3(1.5,1.5,1.5)));c.waitTicks(4);c.takeScreenshot("gems126-gallery"); + Clay126Checks.exercise(c,world.getServer()); + Discovery126Checks.exercise(c,world.getServer()); + } + intro.set(true);net.fabricmc.fabric.api.client.gametest.v1.world.TestWorldSave saved;var found=new HashMap(); + try(var world=c.worldBuilder().adjustSettings(s->{s.setName("Gems126 natural "+UUID.randomUUID());s.setSeed("126");s.setAllowCommands(true);s.setGenerateStructures(false);s.setGameMode(WorldCreationUiState.SelectedGameMode.CREATIVE);s.setWorldType(s.getNormalPresetList().stream().filter(e->e.preset()!=null&&e.preset().getRegisteredName().equals("sanctuary:sanctuary")).findFirst().orElseThrow());}).create()){ + c.waitFor(m->m.player!=null&&m.gui.screen()==null&&ProgressionClient.active()&&!IntroSpawnFlash.active(),2400); + world.getServer().runOnServer(s->{var l=s.overworld();check(l.getChunkSource().getGenerator() instanceof fr.koka.sanctuary.worldgen.SanctuaryChunkGenerator,"Actual Sanctuary generator"); + for(int cx=-4;cx<=4;cx++)for(int cz=-4;cz<=4;cz++){var chunk=l.getChunk(cx,cz);var cursor=new BlockPos.MutableBlockPos();for(int x=0;x<16;x++)for(int z=0;z<16;z++)for(int y=0;y<=256;y++){cursor.set(cx*16+x,y,cz*16+z);var state=chunk.getBlockState(cursor);if(state.is(Gems.RUBY.ore())||state.is(Gems.RUBY.deepslateOre())||state.is(Gems.SAPPHIRE.ore())||state.is(Gems.SAPPHIRE.deepslateOre()))found.put(cursor.immutable(),state);}} + for(var f:Gems.FAMILIES){long ordinary=found.values().stream().filter(b->b.is(f.ore())).count(),deep=found.values().stream().filter(b->b.is(f.deepslateOre())).count();System.out.println("GEMS126_NATURAL "+f.id()+" stone="+ordinary+" deepslate="+deep+" seed=126 chunks=81");check(ordinary+deep>0,"Both gems generate naturally without structure placement: "+f.id());} + var biome=l.getBiome(found.keySet().iterator().next()).value();var features=biome.getGenerationSettings().features().get(GenerationStep.Decoration.UNDERGROUND_ORES.ordinal());for(var f:Gems.FAMILIES)check(features.stream().anyMatch(h->h.is(ResourceKey.create(Registries.PLACED_FEATURE,SanctuaryMod.id("ore_"+f.id())))),"Native biome includes configurable gem placement"); + Discovery126Checks.command(s.getPlayerList().getPlayers().getFirst(),"all"); + var mined=found.keySet().iterator().next();l.setBlockAndUpdate(mined,Blocks.AIR.defaultBlockState());found.put(mined,Blocks.AIR.defaultBlockState()); + });saved=world.getWorldSave(); + } + try(var world=saved.open()){ + c.waitFor(m->m.player!=null&&m.gui.screen()==null,2400);world.getServer().runOnServer(s->{Discovery126Checks.all(s.getPlayerList().getPlayers().getFirst());for(var e:found.entrySet())check(s.overworld().getBlockState(e.getKey())==e.getValue(),"Generated ores persist on reload without repopulation");}); + } + System.out.println("GEMS126_PASS registry, recipes, drops, creative order, native models, natural Sanctuary generation seed 126 and save/reconnect"); + } + private static void order(ResourceKey tab,Item anchor,Item ruby,Item sapphire){var items=new ArrayList<>(BuiltInRegistries.CREATIVE_MODE_TAB.getOrThrow(tab).value().getDisplayItems());int i=0;while(iv.is(ruby)||v.is(sapphire)).count()==2,"No duplicate creative entries");} + private static void drop(List drops,Item item,int n){check(drops.size()==1&&drops.getFirst().is(item)&&drops.getFirst().getCount()==n,"Native loot/craft expected "+n+" "+item+", got "+drops);} + private static void check(boolean ok,String message){if(!ok)throw new AssertionError(message);} +} diff --git a/mods/sanctuary/src/clientGametest/java/fr/koka/sanctuary/client/Sculpture116ClientChecks.java b/mods/sanctuary/src/clientGametest/java/fr/koka/sanctuary/client/Sculpture116ClientChecks.java index 0bd7c5e..d380125 100644 --- a/mods/sanctuary/src/clientGametest/java/fr/koka/sanctuary/client/Sculpture116ClientChecks.java +++ b/mods/sanctuary/src/clientGametest/java/fr/koka/sanctuary/client/Sculpture116ClientChecks.java @@ -48,7 +48,7 @@ public final class Sculpture116ClientChecks implements FabricClientGameTest { var rendered=new HashSet(); for(var item:List.of(Items.STONE,Items.OAK_PLANKS,Items.GOLD_BLOCK,Items.WOOL.pick(DyeColor.RED),Items.GLASS,Items.OAK_LEAVES,Items.CLAY,Items.DEEPSLATE)){ server.runOnServer(s->{var p=s.getPlayerList().getPlayers().getFirst();p.getInventory().clearContent();var menu=(ClayWorkshopMenu)p.containerMenu;menu.getSlot(0).set(new ItemStack(item,2));check(menu.getSlot(1).getItem().isEmpty(),"Previous material result invalidates immediately");menu.broadcastChanges();}); - var expected=c.computeOnClient(m->SculptureMaterialSampler.sample(new ItemStack(item)).apply(source));rendered.add(expected); + var expected=c.computeOnClient(m->ClayWorkshopMenu.appearance(source,item,SculptureMaterialSampler.sample(new ItemStack(item))));rendered.add(expected); c.waitFor(m->expected.equals(StatuaryEntity.sculpture(m.player.containerMenu.getSlot(1).getItem())),180); c.runOnClient(m->check(ItemStack.matches(((ClayWorkshopScreen)m.gui.screen()).preview(),m.player.containerMenu.getSlot(1).getItem()),"Preview equals server-owned result")); check(StatuaryEntity.decode(StatuaryEntity.encode(expected)).equals(expected),"Palette colors persist in unchanged schema 1"); diff --git a/mods/sanctuary/src/clientGametest/java/fr/koka/sanctuary/client/Statuary106ClientChecks.java b/mods/sanctuary/src/clientGametest/java/fr/koka/sanctuary/client/Statuary106ClientChecks.java index 47d3cdc..537e3fb 100644 --- a/mods/sanctuary/src/clientGametest/java/fr/koka/sanctuary/client/Statuary106ClientChecks.java +++ b/mods/sanctuary/src/clientGametest/java/fr/koka/sanctuary/client/Statuary106ClientChecks.java @@ -62,7 +62,7 @@ public final class Statuary106ClientChecks implements FabricClientGameTest { try(var world=c.worldBuilder().adjustSettings(s->{s.setName("Statuary106 "+UUID.randomUUID());s.setSeed("106");s.setAllowCommands(true);s.setGameMode(WorldCreationUiState.SelectedGameMode.CREATIVE); s.setWorldType(s.getNormalPresetList().stream().filter(e->e.preset()!=null&&e.preset().getRegisteredName().equals("sanctuary_test:flat")).findFirst().orElseThrow());}).create()){ saved=world.getWorldSave();c.waitFor(m->ProgressionClient.active()&&m.player!=null&&m.gui.screen()==null&&!IntroSpawnFlash.active(),1200); - var source=c.computeOnClient(m->SculptureMaterialSampler.sample(new ItemStack(Items.CLAY)).apply(originalSource)); + var source=originalSource; var server=world.getServer(); server.runOnServer(s->{var p=player(s);p.teleportTo(.5,1,.5);p.getInventory().clearContent();p.setGameMode(GameType.SURVIVAL);for(int x=-7;x<=9;x++)for(int z=-5;z<=9;z++)p.level().setBlockAndUpdate(new BlockPos(x,0,z),Blocks.STONE.defaultBlockState());p.level().setBlockAndUpdate(WORKSHOP,Statuary.WORKSHOP.defaultBlockState()); var legacy=net.minecraft.nbt.NbtUtils.writeBlockState(Statuary.BLOCK.defaultBlockState());legacy.remove("properties"); diff --git a/mods/sanctuary/src/main/java/fr/koka/sanctuary/SanctuaryMod.java b/mods/sanctuary/src/main/java/fr/koka/sanctuary/SanctuaryMod.java index 02adc72..b44f498 100644 --- a/mods/sanctuary/src/main/java/fr/koka/sanctuary/SanctuaryMod.java +++ b/mods/sanctuary/src/main/java/fr/koka/sanctuary/SanctuaryMod.java @@ -44,6 +44,7 @@ public final class SanctuaryMod implements ModInitializer { @Override public void onInitialize() { fr.koka.sanctuary.building.ColoredBricks.register(); + fr.koka.sanctuary.gems.Gems.register(); fr.koka.sanctuary.sky.VortexClouds.register(); fr.koka.sanctuary.loading.PreloadProgress.register(); fr.koka.sanctuary.progression.SanctuaryGameplay.register(); diff --git a/mods/sanctuary/src/main/java/fr/koka/sanctuary/client/ClayWorkshopScreen.java b/mods/sanctuary/src/main/java/fr/koka/sanctuary/client/ClayWorkshopScreen.java index 24213aa..cb63e9a 100644 --- a/mods/sanctuary/src/main/java/fr/koka/sanctuary/client/ClayWorkshopScreen.java +++ b/mods/sanctuary/src/main/java/fr/koka/sanctuary/client/ClayWorkshopScreen.java @@ -14,6 +14,7 @@ import net.minecraft.network.chat.Component; import net.minecraft.resources.Identifier; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; /** File selection is local; the two ordinary inventory slots and every crafted item are server-owned. */ public final class ClayWorkshopScreen extends AbstractContainerScreen { @@ -91,9 +92,9 @@ public final class ClayWorkshopScreen extends AbstractContainerScreen(Arrays.asList(record.notes().getOrDefault("seen_mobs","").split(",")));seen.remove(""); - if(seen.add(id))record=record.note("seen_mobs",String.join(",",seen)); + record=discoverSpecies(record,List.of(id)); if(entity instanceof net.minecraft.world.entity.animal.fish.TropicalFish fish){ var variants=fishVariants(record);variants.set(fishVariant(fish));record=record.note("seen_fish_v1",Base64.getEncoder().encodeToString(variants.toByteArray())); } if(!record.equals(CompanionService.record(p)))CompanionService.save(p,record); } + /** The same encounter record is used by natural observation and administrative discoveries. */ + public static CompanionRecord discoverSpecies(CompanionRecord record,Collection ids){ + var seen=new TreeSet<>(Arrays.asList(record.notes().getOrDefault("seen_mobs","").split(",")));seen.remove(""); + return seen.addAll(ids)?record.note("seen_mobs",String.join(",",seen)):record; + } private static int fishVariant(net.minecraft.world.entity.animal.fish.TropicalFish fish){ int packed=fish.getPattern().getPackedId();return ((packed>>>8)*2+(packed&1))*256+fish.getBaseColor().getId()*16+fish.getPatternColor().getId(); } diff --git a/mods/sanctuary/src/main/java/fr/koka/sanctuary/gems/GemOreFeature.java b/mods/sanctuary/src/main/java/fr/koka/sanctuary/gems/GemOreFeature.java new file mode 100644 index 0000000..c769c09 --- /dev/null +++ b/mods/sanctuary/src/main/java/fr/koka/sanctuary/gems/GemOreFeature.java @@ -0,0 +1,19 @@ +package fr.koka.sanctuary.gems; + +import com.mojang.serialization.MapCodec; +import fr.koka.sanctuary.worldgen.SanctuaryChunkGenerator; +import net.minecraft.core.BlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.chunk.ChunkGenerator; +import net.minecraft.world.level.levelgen.feature.*; + +/** Native seeded ore veins, scoped to Sanctuary even when its biomes are shared with vanilla. */ +public record GemOreFeature(OreFeature ore) implements Feature { + public static final MapCodec CODEC=OreFeature.CODEC.xmap(GemOreFeature::new,GemOreFeature::ore); + @Override public MapCodec codec(){return CODEC;} + @Override public boolean place(WorldGenLevel level,ChunkGenerator generator,RandomSource random,BlockPos origin){ + if(!(level.getLevel().getChunkSource().getGenerator() instanceof SanctuaryChunkGenerator))return false; + return ore.place(level,generator,random,origin); + } +} diff --git a/mods/sanctuary/src/main/java/fr/koka/sanctuary/gems/Gems.java b/mods/sanctuary/src/main/java/fr/koka/sanctuary/gems/Gems.java new file mode 100644 index 0000000..9ee0636 --- /dev/null +++ b/mods/sanctuary/src/main/java/fr/koka/sanctuary/gems/Gems.java @@ -0,0 +1,50 @@ +package fr.koka.sanctuary.gems; + +import fr.koka.sanctuary.SanctuaryMod; +import java.util.List; +import net.fabricmc.fabric.api.biome.v1.BiomeModifications; +import net.fabricmc.fabric.api.creativetab.v1.CreativeModeTabEvents; +import net.minecraft.core.Registry; +import net.minecraft.core.registries.*; +import net.minecraft.resources.ResourceKey; +import net.minecraft.tags.TagKey; +import net.minecraft.util.valueproviders.UniformInt; +import net.minecraft.world.item.*; +import net.minecraft.world.level.block.*; +import net.minecraft.world.level.block.state.BlockBehaviour; +import net.minecraft.world.level.levelgen.GenerationStep; + +/** Ordinary gem items and blocks; their distribution lives in data, not this registry. */ +public final class Gems { + public record Family(String id,Item gem,Block block,Block ore,Block deepslateOre){} + public static final Family RUBY=family("ruby",DyeColor.RED); + public static final Family SAPPHIRE=family("sapphire",DyeColor.BLUE); + public static final List FAMILIES=List.of(RUBY,SAPPHIRE); + public static void register(){ + Registry.register(BuiltInRegistries.FEATURE_TYPE,SanctuaryMod.id("gem_ore"),GemOreFeature.CODEC); + for(var f:FAMILIES){ + var biomes=TagKey.create(Registries.BIOME,SanctuaryMod.id("has_ore/"+f.id)); + BiomeModifications.addFeature(c->c.hasTag(biomes),GenerationStep.Decoration.UNDERGROUND_ORES, + ResourceKey.create(Registries.PLACED_FEATURE,SanctuaryMod.id("ore_"+f.id))); + } + CreativeModeTabEvents.modifyOutputEvent(CreativeModeTabs.INGREDIENTS).register(out->out.insertAfter(Items.EMERALD,RUBY.gem,SAPPHIRE.gem)); + CreativeModeTabEvents.modifyOutputEvent(CreativeModeTabs.BUILDING_BLOCKS).register(out->out.insertAfter(Blocks.EMERALD_BLOCK,RUBY.block,SAPPHIRE.block)); + CreativeModeTabEvents.modifyOutputEvent(CreativeModeTabs.NATURAL_BLOCKS).register(out->{ + out.insertAfter(Blocks.EMERALD_ORE,RUBY.ore,SAPPHIRE.ore); + out.insertAfter(Blocks.DEEPSLATE_EMERALD_ORE,RUBY.deepslateOre,SAPPHIRE.deepslateOre); + }); + } + private static Family family(String id,DyeColor color){ + var key=SanctuaryMod.id(id);var item=Registry.register(BuiltInRegistries.ITEM,key,new Item(new Item.Properties().setId(ResourceKey.create(Registries.ITEM,key)))); + var block=block(id+"_block",new Block(properties(id+"_block",Blocks.EMERALD_BLOCK).mapColor(color.getMapColor()))); + var ore=block(id+"_ore",new DropExperienceBlock(UniformInt.of(3,7),properties(id+"_ore",Blocks.EMERALD_ORE))); + var deep=block("deepslate_"+id+"_ore",new DropExperienceBlock(UniformInt.of(3,7),properties("deepslate_"+id+"_ore",Blocks.DEEPSLATE_EMERALD_ORE))); + return new Family(id,item,block,ore,deep); + } + private static BlockBehaviour.Properties properties(String id,Block source){return BlockBehaviour.Properties.ofFullCopy(source).setId(ResourceKey.create(Registries.BLOCK,SanctuaryMod.id(id)));} + private static Block block(String id,Block block){ + var key=SanctuaryMod.id(id);Registry.register(BuiltInRegistries.BLOCK,key,block); + Registry.register(BuiltInRegistries.ITEM,key,new BlockItem(block,new Item.Properties().setId(ResourceKey.create(Registries.ITEM,key)).useBlockDescriptionPrefix()));return block; + } + private Gems(){} +} diff --git a/mods/sanctuary/src/main/java/fr/koka/sanctuary/knowledge/BlockKnowledgeService.java b/mods/sanctuary/src/main/java/fr/koka/sanctuary/knowledge/BlockKnowledgeService.java index 47d5f5f..8aa878d 100644 --- a/mods/sanctuary/src/main/java/fr/koka/sanctuary/knowledge/BlockKnowledgeService.java +++ b/mods/sanctuary/src/main/java/fr/koka/sanctuary/knowledge/BlockKnowledgeService.java @@ -47,6 +47,7 @@ public final class BlockKnowledgeService { private BlockKnowledgeService() {} public static void register() { + DiscoveryCommands.register(); ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> observeInventory(handler.player)); // Fabric also reaches DISCONNECT through Netty's channelInactive callback. ServerPlayConnectionEvents.DISCONNECT.register((handler, server) -> server.execute(() -> { @@ -97,6 +98,12 @@ public final class BlockKnowledgeService { public static void recordSeen(ServerPlayer player, Block block) { if (block.defaultBlockState().isAir() || player.isSpectator()) return; + discover(player,block); + } + + /** Explicit discoveries use the same record and events, including for a spectator command target. */ + public static void discover(ServerPlayer player,Block block) { + if(block.defaultBlockState().isAir())return; Session session = session(player); if (session.failed || !session.memory.recordSeen(id(block))) return; session.dirty = true; diff --git a/mods/sanctuary/src/main/java/fr/koka/sanctuary/knowledge/DiscoveryCommands.java b/mods/sanctuary/src/main/java/fr/koka/sanctuary/knowledge/DiscoveryCommands.java new file mode 100644 index 0000000..1bf797c --- /dev/null +++ b/mods/sanctuary/src/main/java/fr/koka/sanctuary/knowledge/DiscoveryCommands.java @@ -0,0 +1,75 @@ +package fr.koka.sanctuary.knowledge; + +import com.mojang.brigadier.builder.ArgumentBuilder; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import fr.koka.sanctuary.companion.*; +import fr.koka.sanctuary.operator.OperatorService; +import fr.koka.sanctuary.progression.ProgressEffects; +import fr.koka.sanctuary.recipes.*; +import java.util.*; +import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; +import net.minecraft.commands.*; +import net.minecraft.commands.arguments.*; +import net.minecraft.core.registries.*; +import net.minecraft.network.chat.Component; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.item.*; +import net.minecraft.world.level.block.Block; + +/** One command routes through the existing discovery services and their dependent recipe/catalogue rules. */ +public final class DiscoveryCommands { + private record Selection(List blocks,List items,List> mobs){} + @FunctionalInterface private interface SelectionArgument {Selection get(CommandContext context)throws CommandSyntaxException;} + public static void register(){ + CommandRegistrationCallback.EVENT.register((dispatcher,registries,environment)->{ + var root=Commands.literal("discovery").requires(OperatorService::canCommand); + root.then(targets(Commands.literal("all"),c->all(true,true,true))); + root.then(Commands.literal("blocks").then(targets(Commands.literal("all"),c->all(true,false,false)))); + root.then(Commands.literal("items").then(targets(Commands.literal("all"),c->all(false,true,false)))); + root.then(Commands.literal("mobs").then(targets(Commands.literal("all"),c->all(false,false,true)))); + root.then(Commands.literal("block").then(targets(Commands.argument("block",ResourceArgument.resource(registries,Registries.BLOCK)),c->new Selection(List.of(ResourceArgument.getResource(c,"block",Registries.BLOCK).value()),List.of(),List.of())))); + root.then(Commands.literal("item").then(targets(Commands.argument("item",ResourceArgument.resource(registries,Registries.ITEM)),c->new Selection(List.of(),List.of(ResourceArgument.getResource(c,"item",Registries.ITEM).value()),List.of())))); + root.then(Commands.literal("mob").then(targets(Commands.argument("mob",ResourceArgument.resource(registries,Registries.ENTITY_TYPE)),c->new Selection(List.of(),List.of(),List.of(ResourceArgument.getResource(c,"mob",Registries.ENTITY_TYPE).value()))))); + dispatcher.register(Commands.literal("sanctuary").then(root)); + }); + } + private static > T targets(T node,SelectionArgument selection){ + return node.executes(c->discover(c,selection.get(c),List.of(c.getSource().getPlayerOrException()))) + .then(Commands.argument("players",EntityArgument.players()).executes(c->discover(c,selection.get(c),EntityArgument.getPlayers(c,"players")))); + } + private static Selection all(boolean blocks,boolean items,boolean mobs){ + return new Selection(blocks?BuiltInRegistries.BLOCK.stream().filter(b->!b.defaultBlockState().isAir()).toList():List.of(), + items?BuiltInRegistries.ITEM.stream().filter(i->i!=Items.AIR).toList():List.of(), + mobs?BuiltInRegistries.ENTITY_TYPE.stream().filter(t->SpawnEggItem.byId(t).isPresent()).toList():List.of()); + } + private static int discover(CommandContext context,Selection selection,Collection players){ + var source=context.getSource(); + if(selection.blocks.stream().anyMatch(b->b.defaultBlockState().isAir())||selection.items.contains(Items.AIR)||selection.mobs.stream().anyMatch(t->SpawnEggItem.byId(t).isEmpty())){ + source.sendFailure(Component.translatable("sanctuary.discovery.invalid"));return 0; + } + var species=selection.mobs.stream().map(BuiltInRegistries.ENTITY_TYPE::getKey).map(id->id.getNamespace().equals("minecraft")?id.getPath():id.toString()).toList(); + int changed=0; + for(var player:players){ + var record=CompanionService.record(player); + if(ProgressEffects.get(player)==null||record==null||!BlockKnowledgeService.healthy(player)||!RecipeService.healthy(player)){ + source.sendFailure(Component.translatable("sanctuary.discovery.unavailable",player.getDisplayName()));continue; + } + // Validate bounded records before any write; no new save schema or unlock flag. + CompanionRecord next; + var discoveredItems=new HashSet(RecipeService.knowledge(player).items); + for(var item:selection.items)discoveredItems.add(BuiltInRegistries.ITEM.getKey(item).toString()); + for(var block:selection.blocks)if(block.asItem()!=Items.AIR)discoveredItems.add(BuiltInRegistries.ITEM.getKey(block.asItem()).toString()); + try{next=CompanionQueries.discoverSpecies(record,species);if(discoveredItems.size()>RecipeKnowledge.MAX_IDS)throw new IllegalArgumentException("Discovery capacity");} + catch(IllegalArgumentException invalid){source.sendFailure(Component.translatable("sanctuary.discovery.unavailable",player.getDisplayName()));continue;} + CompanionService.save(player,next); + for(var block:selection.blocks)BlockKnowledgeService.discover(player,block); + for(var item:selection.items){if(item instanceof BlockItem b)BlockKnowledgeService.discover(player,b.getBlock());RecipeService.discover(player,item);} + RecipeService.refresh(player); + source.sendSuccess(()->Component.translatable("sanctuary.discovery.granted",player.getDisplayName(),selection.blocks.size(),selection.items.size(),selection.mobs.size()),true);changed++; + } + return changed; + } + private DiscoveryCommands(){} +} diff --git a/mods/sanctuary/src/main/java/fr/koka/sanctuary/plans/ClayWorkshopMenu.java b/mods/sanctuary/src/main/java/fr/koka/sanctuary/plans/ClayWorkshopMenu.java index 5567d57..6d646d7 100644 --- a/mods/sanctuary/src/main/java/fr/koka/sanctuary/plans/ClayWorkshopMenu.java +++ b/mods/sanctuary/src/main/java/fr/koka/sanctuary/plans/ClayWorkshopMenu.java @@ -71,14 +71,18 @@ public final class ClayWorkshopMenu extends AbstractContainerMenu { var contents=item.get(DataComponents.CONTAINER); return contents==null||!contents.nonEmptyItems().iterator().hasNext(); } + /** Plain clay retains the model's sampled colors; other blocks transfer their texture palette. */ + public static VoxelSculpture appearance(VoxelSculpture source,Item material,SculpturePalette palette){ + return material==Items.CLAY?source:palette.apply(source); + } public void select(ServerPlayer p,VoxelSculpture sculpture,Item material,SculpturePalette palette){ if(level==null||!stillValid(p)||level.getGameTime()-lastSelection<4)return; var hit=new BlockHitResult(Vec3.atCenterOf(view.pos),Direction.UP,view.pos,false); if(UseBlockCallback.EVENT.invoker().interact(p,level,InteractionHand.MAIN_HAND,hit)!=InteractionResult.PASS||!stillValid(p))return; lastSelection=level.getGameTime(); if(sculpture!=null&&(!StatueDiscoveries.allowedModel(sculpture.modelId(),view.statues())||!material(input.getItem(0))||!input.getItem(0).is(material)||palette==null))return; - if(!Objects.equals(selected,sculpture)||!Objects.equals(selectedPalette,palette)) - selectedResult=sculpture==null||palette==null?null:palette.apply(sculpture); + if(!Objects.equals(selected,sculpture)||selectedMaterial!=material||!Objects.equals(selectedPalette,palette)) + selectedResult=sculpture==null||palette==null?null:appearance(sculpture,material,palette); selected=sculpture;selectedMaterial=material;selectedPalette=palette;refresh();broadcastChanges(); } private void refresh(){ diff --git a/mods/sanctuary/src/main/java/fr/koka/sanctuary/recipes/RecipeService.java b/mods/sanctuary/src/main/java/fr/koka/sanctuary/recipes/RecipeService.java index 0789a55..02a1aea 100644 --- a/mods/sanctuary/src/main/java/fr/koka/sanctuary/recipes/RecipeService.java +++ b/mods/sanctuary/src/main/java/fr/koka/sanctuary/recipes/RecipeService.java @@ -35,6 +35,7 @@ public final class RecipeService { } private static Session session(ServerPlayer p){return SESSIONS.computeIfAbsent(p,Session::new);} public static RecipeKnowledge knowledge(ServerPlayer p){return session(p).data;} + public static boolean healthy(ServerPlayer p){return !session(p).invalid;} public static void discover(ServerPlayer p,Item item){ if(ProgressEffects.get(p)==null||item==Items.AIR)return;var s=session(p);if(s.invalid)return; s.dirty|=RecipeKnowledge.add(s.data.items,BuiltInRegistries.ITEM.getKey(item).toString()); diff --git a/mods/sanctuary/src/main/resources/assets/sanctuary/blockstates/deepslate_ruby_ore.json b/mods/sanctuary/src/main/resources/assets/sanctuary/blockstates/deepslate_ruby_ore.json new file mode 100644 index 0000000..a3601e6 --- /dev/null +++ b/mods/sanctuary/src/main/resources/assets/sanctuary/blockstates/deepslate_ruby_ore.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "sanctuary:block/deepslate_ruby_ore" + } + } +} diff --git a/mods/sanctuary/src/main/resources/assets/sanctuary/blockstates/deepslate_sapphire_ore.json b/mods/sanctuary/src/main/resources/assets/sanctuary/blockstates/deepslate_sapphire_ore.json new file mode 100644 index 0000000..6a8a60b --- /dev/null +++ b/mods/sanctuary/src/main/resources/assets/sanctuary/blockstates/deepslate_sapphire_ore.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "sanctuary:block/deepslate_sapphire_ore" + } + } +} diff --git a/mods/sanctuary/src/main/resources/assets/sanctuary/blockstates/ruby_block.json b/mods/sanctuary/src/main/resources/assets/sanctuary/blockstates/ruby_block.json new file mode 100644 index 0000000..e129eb5 --- /dev/null +++ b/mods/sanctuary/src/main/resources/assets/sanctuary/blockstates/ruby_block.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "sanctuary:block/ruby_block" + } + } +} diff --git a/mods/sanctuary/src/main/resources/assets/sanctuary/blockstates/ruby_ore.json b/mods/sanctuary/src/main/resources/assets/sanctuary/blockstates/ruby_ore.json new file mode 100644 index 0000000..d10f04a --- /dev/null +++ b/mods/sanctuary/src/main/resources/assets/sanctuary/blockstates/ruby_ore.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "sanctuary:block/ruby_ore" + } + } +} diff --git a/mods/sanctuary/src/main/resources/assets/sanctuary/blockstates/sapphire_block.json b/mods/sanctuary/src/main/resources/assets/sanctuary/blockstates/sapphire_block.json new file mode 100644 index 0000000..f2d918a --- /dev/null +++ b/mods/sanctuary/src/main/resources/assets/sanctuary/blockstates/sapphire_block.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "sanctuary:block/sapphire_block" + } + } +} diff --git a/mods/sanctuary/src/main/resources/assets/sanctuary/blockstates/sapphire_ore.json b/mods/sanctuary/src/main/resources/assets/sanctuary/blockstates/sapphire_ore.json new file mode 100644 index 0000000..9bfb39e --- /dev/null +++ b/mods/sanctuary/src/main/resources/assets/sanctuary/blockstates/sapphire_ore.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "sanctuary:block/sapphire_ore" + } + } +} diff --git a/mods/sanctuary/src/main/resources/assets/sanctuary/items/deepslate_ruby_ore.json b/mods/sanctuary/src/main/resources/assets/sanctuary/items/deepslate_ruby_ore.json new file mode 100644 index 0000000..c5ced12 --- /dev/null +++ b/mods/sanctuary/src/main/resources/assets/sanctuary/items/deepslate_ruby_ore.json @@ -0,0 +1,6 @@ +{ + "model": { + "type": "minecraft:model", + "model": "sanctuary:block/deepslate_ruby_ore" + } +} diff --git a/mods/sanctuary/src/main/resources/assets/sanctuary/items/deepslate_sapphire_ore.json b/mods/sanctuary/src/main/resources/assets/sanctuary/items/deepslate_sapphire_ore.json new file mode 100644 index 0000000..1f9b083 --- /dev/null +++ b/mods/sanctuary/src/main/resources/assets/sanctuary/items/deepslate_sapphire_ore.json @@ -0,0 +1,6 @@ +{ + "model": { + "type": "minecraft:model", + "model": "sanctuary:block/deepslate_sapphire_ore" + } +} diff --git a/mods/sanctuary/src/main/resources/assets/sanctuary/items/ruby.json b/mods/sanctuary/src/main/resources/assets/sanctuary/items/ruby.json new file mode 100644 index 0000000..fee3968 --- /dev/null +++ b/mods/sanctuary/src/main/resources/assets/sanctuary/items/ruby.json @@ -0,0 +1,6 @@ +{ + "model": { + "type": "minecraft:model", + "model": "sanctuary:item/ruby" + } +} diff --git a/mods/sanctuary/src/main/resources/assets/sanctuary/items/ruby_block.json b/mods/sanctuary/src/main/resources/assets/sanctuary/items/ruby_block.json new file mode 100644 index 0000000..d23129d --- /dev/null +++ b/mods/sanctuary/src/main/resources/assets/sanctuary/items/ruby_block.json @@ -0,0 +1,6 @@ +{ + "model": { + "type": "minecraft:model", + "model": "sanctuary:block/ruby_block" + } +} diff --git a/mods/sanctuary/src/main/resources/assets/sanctuary/items/ruby_ore.json b/mods/sanctuary/src/main/resources/assets/sanctuary/items/ruby_ore.json new file mode 100644 index 0000000..a4220c8 --- /dev/null +++ b/mods/sanctuary/src/main/resources/assets/sanctuary/items/ruby_ore.json @@ -0,0 +1,6 @@ +{ + "model": { + "type": "minecraft:model", + "model": "sanctuary:block/ruby_ore" + } +} diff --git a/mods/sanctuary/src/main/resources/assets/sanctuary/items/sapphire.json b/mods/sanctuary/src/main/resources/assets/sanctuary/items/sapphire.json new file mode 100644 index 0000000..4b2c1c8 --- /dev/null +++ b/mods/sanctuary/src/main/resources/assets/sanctuary/items/sapphire.json @@ -0,0 +1,6 @@ +{ + "model": { + "type": "minecraft:model", + "model": "sanctuary:item/sapphire" + } +} diff --git a/mods/sanctuary/src/main/resources/assets/sanctuary/items/sapphire_block.json b/mods/sanctuary/src/main/resources/assets/sanctuary/items/sapphire_block.json new file mode 100644 index 0000000..c5276c5 --- /dev/null +++ b/mods/sanctuary/src/main/resources/assets/sanctuary/items/sapphire_block.json @@ -0,0 +1,6 @@ +{ + "model": { + "type": "minecraft:model", + "model": "sanctuary:block/sapphire_block" + } +} diff --git a/mods/sanctuary/src/main/resources/assets/sanctuary/items/sapphire_ore.json b/mods/sanctuary/src/main/resources/assets/sanctuary/items/sapphire_ore.json new file mode 100644 index 0000000..4c1c7f4 --- /dev/null +++ b/mods/sanctuary/src/main/resources/assets/sanctuary/items/sapphire_ore.json @@ -0,0 +1,6 @@ +{ + "model": { + "type": "minecraft:model", + "model": "sanctuary:block/sapphire_ore" + } +} diff --git a/mods/sanctuary/src/main/resources/assets/sanctuary/lang/en_us.json b/mods/sanctuary/src/main/resources/assets/sanctuary/lang/en_us.json index 6121ea3..2f6615b 100644 --- a/mods/sanctuary/src/main/resources/assets/sanctuary/lang/en_us.json +++ b/mods/sanctuary/src/main/resources/assets/sanctuary/lang/en_us.json @@ -1,4 +1,5 @@ { + "sanctuary.statuary.clay_ready": "Clay: original model colors.", "sanctuary.weather.selected": "Real Time weather: %s for %s (%s). The daily forecast resumes at midnight.", "sanctuary.weather.overcast": "Overcast", "sanctuary.weather.fog": "Fog", @@ -1972,7 +1973,7 @@ "sanctuary.discovery.item_filter": "Show carried items or every item already discovered.", "sanctuary.discovery.catalogue_required": "The Catalogue ability lets you browse discovered items you no longer carry.", "sanctuary.discovery.loading": "Loading statistics…", - "sanctuary.discovery.unavailable": "Statistics unavailable. Refresh to try again.", + "sanctuary.discovery.unavailable": "Unable to update discoveries for %s; no changes made.", "sanctuary.discovery.mobs_hint": "Mobs you have killed or that have killed you. Sightings alone are not recorded yet.", "sanctuary.discovery.count": "%s entries", "sanctuary.discovery.empty": "No entries match this filter.", @@ -2245,5 +2246,15 @@ "sanctuary.statuary.animals": "Animals", "sanctuary.statuary.imports": "Imports", "sanctuary.statuary.no_animals": "Encounter creatures to unlock their sculptures.", - "sanctuary.statuary.animal_error": "This creature’s model could not be sculpted." + "sanctuary.statuary.animal_error": "This creature’s model could not be sculpted.", + "item.sanctuary.ruby": "Ruby", + "block.sanctuary.ruby_block": "Block of Ruby", + "block.sanctuary.ruby_ore": "Ruby Ore", + "block.sanctuary.deepslate_ruby_ore": "Deepslate Ruby Ore", + "item.sanctuary.sapphire": "Sapphire", + "block.sanctuary.sapphire_block": "Block of Sapphire", + "block.sanctuary.sapphire_ore": "Sapphire Ore", + "block.sanctuary.deepslate_sapphire_ore": "Deepslate Sapphire Ore", + "sanctuary.discovery.granted": "Discoveries added for %s: %s blocks, %s items, %s species. Linked recipes updated; reopen catalogues.", + "sanctuary.discovery.invalid": "Choose a discoverable block, item or species." } diff --git a/mods/sanctuary/src/main/resources/assets/sanctuary/lang/fr_fr.json b/mods/sanctuary/src/main/resources/assets/sanctuary/lang/fr_fr.json index 014a99c..98f00b3 100644 --- a/mods/sanctuary/src/main/resources/assets/sanctuary/lang/fr_fr.json +++ b/mods/sanctuary/src/main/resources/assets/sanctuary/lang/fr_fr.json @@ -1,4 +1,5 @@ { + "sanctuary.statuary.clay_ready": "Argile : couleurs originales du modèle.", "sanctuary.weather.selected": "Météo Real Time : %s pour la journée du %s (%s). Le tirage quotidien reprend à minuit.", "sanctuary.weather.overcast": "Ciel gris", "sanctuary.weather.fog": "Brouillard", @@ -1972,7 +1973,7 @@ "sanctuary.discovery.item_filter": "Afficher les objets portés ou tous les objets déjà découverts.", "sanctuary.discovery.catalogue_required": "L’aptitude Catalogue permet de consulter les objets découverts que tu ne portes plus.", "sanctuary.discovery.loading": "Chargement des statistiques…", - "sanctuary.discovery.unavailable": "Statistiques indisponibles. Actualise pour réessayer.", + "sanctuary.discovery.unavailable": "Impossible de mettre à jour les découvertes de %s ; aucune modification effectuée.", "sanctuary.discovery.mobs_hint": "Créatures déjà tuées ou responsables de ta mort. Les simples observations ne sont pas encore enregistrées.", "sanctuary.discovery.count": "%s entrées", "sanctuary.discovery.empty": "Aucune entrée pour ce filtre.", @@ -2245,5 +2246,15 @@ "sanctuary.statuary.animals": "Animaux", "sanctuary.statuary.imports": "Imports", "sanctuary.statuary.no_animals": "Rencontrez des créatures pour débloquer leurs sculptures.", - "sanctuary.statuary.animal_error": "Impossible de sculpter le modèle de cette créature." + "sanctuary.statuary.animal_error": "Impossible de sculpter le modèle de cette créature.", + "item.sanctuary.ruby": "Rubis", + "block.sanctuary.ruby_block": "Bloc de rubis", + "block.sanctuary.ruby_ore": "Minerai de rubis", + "block.sanctuary.deepslate_ruby_ore": "Minerai de rubis des abîmes", + "item.sanctuary.sapphire": "Saphir", + "block.sanctuary.sapphire_block": "Bloc de saphir", + "block.sanctuary.sapphire_ore": "Minerai de saphir", + "block.sanctuary.deepslate_sapphire_ore": "Minerai de saphir des abîmes", + "sanctuary.discovery.granted": "Découvertes ajoutées pour %s : %s blocs, %s objets, %s espèces. Recettes liées actualisées ; rouvre les catalogues.", + "sanctuary.discovery.invalid": "Choisis un bloc, un objet ou une espèce découvrable." } diff --git a/mods/sanctuary/src/main/resources/assets/sanctuary/models/block/deepslate_ruby_ore.json b/mods/sanctuary/src/main/resources/assets/sanctuary/models/block/deepslate_ruby_ore.json new file mode 100644 index 0000000..f2a4b79 --- /dev/null +++ b/mods/sanctuary/src/main/resources/assets/sanctuary/models/block/deepslate_ruby_ore.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "sanctuary:block/deepslate_ruby_ore" + } +} diff --git a/mods/sanctuary/src/main/resources/assets/sanctuary/models/block/deepslate_sapphire_ore.json b/mods/sanctuary/src/main/resources/assets/sanctuary/models/block/deepslate_sapphire_ore.json new file mode 100644 index 0000000..634413e --- /dev/null +++ b/mods/sanctuary/src/main/resources/assets/sanctuary/models/block/deepslate_sapphire_ore.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "sanctuary:block/deepslate_sapphire_ore" + } +} diff --git a/mods/sanctuary/src/main/resources/assets/sanctuary/models/block/ruby_block.json b/mods/sanctuary/src/main/resources/assets/sanctuary/models/block/ruby_block.json new file mode 100644 index 0000000..46b6310 --- /dev/null +++ b/mods/sanctuary/src/main/resources/assets/sanctuary/models/block/ruby_block.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "sanctuary:block/ruby_block" + } +} diff --git a/mods/sanctuary/src/main/resources/assets/sanctuary/models/block/ruby_ore.json b/mods/sanctuary/src/main/resources/assets/sanctuary/models/block/ruby_ore.json new file mode 100644 index 0000000..2743e13 --- /dev/null +++ b/mods/sanctuary/src/main/resources/assets/sanctuary/models/block/ruby_ore.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "sanctuary:block/ruby_ore" + } +} diff --git a/mods/sanctuary/src/main/resources/assets/sanctuary/models/block/sapphire_block.json b/mods/sanctuary/src/main/resources/assets/sanctuary/models/block/sapphire_block.json new file mode 100644 index 0000000..16459ac --- /dev/null +++ b/mods/sanctuary/src/main/resources/assets/sanctuary/models/block/sapphire_block.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "sanctuary:block/sapphire_block" + } +} diff --git a/mods/sanctuary/src/main/resources/assets/sanctuary/models/block/sapphire_ore.json b/mods/sanctuary/src/main/resources/assets/sanctuary/models/block/sapphire_ore.json new file mode 100644 index 0000000..5532714 --- /dev/null +++ b/mods/sanctuary/src/main/resources/assets/sanctuary/models/block/sapphire_ore.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "sanctuary:block/sapphire_ore" + } +} diff --git a/mods/sanctuary/src/main/resources/assets/sanctuary/models/item/ruby.json b/mods/sanctuary/src/main/resources/assets/sanctuary/models/item/ruby.json new file mode 100644 index 0000000..4ebfb90 --- /dev/null +++ b/mods/sanctuary/src/main/resources/assets/sanctuary/models/item/ruby.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "sanctuary:item/ruby" + } +} diff --git a/mods/sanctuary/src/main/resources/assets/sanctuary/models/item/sapphire.json b/mods/sanctuary/src/main/resources/assets/sanctuary/models/item/sapphire.json new file mode 100644 index 0000000..94938ee --- /dev/null +++ b/mods/sanctuary/src/main/resources/assets/sanctuary/models/item/sapphire.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "sanctuary:item/sapphire" + } +} diff --git a/mods/sanctuary/src/main/resources/assets/sanctuary/textures/block/deepslate_ruby_ore.png b/mods/sanctuary/src/main/resources/assets/sanctuary/textures/block/deepslate_ruby_ore.png new file mode 100644 index 0000000..eb52fd8 Binary files /dev/null and b/mods/sanctuary/src/main/resources/assets/sanctuary/textures/block/deepslate_ruby_ore.png differ diff --git a/mods/sanctuary/src/main/resources/assets/sanctuary/textures/block/deepslate_sapphire_ore.png b/mods/sanctuary/src/main/resources/assets/sanctuary/textures/block/deepslate_sapphire_ore.png new file mode 100644 index 0000000..63f4133 Binary files /dev/null and b/mods/sanctuary/src/main/resources/assets/sanctuary/textures/block/deepslate_sapphire_ore.png differ diff --git a/mods/sanctuary/src/main/resources/assets/sanctuary/textures/block/ruby_block.png b/mods/sanctuary/src/main/resources/assets/sanctuary/textures/block/ruby_block.png new file mode 100644 index 0000000..f10cbe2 Binary files /dev/null and b/mods/sanctuary/src/main/resources/assets/sanctuary/textures/block/ruby_block.png differ diff --git a/mods/sanctuary/src/main/resources/assets/sanctuary/textures/block/ruby_ore.png b/mods/sanctuary/src/main/resources/assets/sanctuary/textures/block/ruby_ore.png new file mode 100644 index 0000000..f2becf8 Binary files /dev/null and b/mods/sanctuary/src/main/resources/assets/sanctuary/textures/block/ruby_ore.png differ diff --git a/mods/sanctuary/src/main/resources/assets/sanctuary/textures/block/sapphire_block.png b/mods/sanctuary/src/main/resources/assets/sanctuary/textures/block/sapphire_block.png new file mode 100644 index 0000000..029623d Binary files /dev/null and b/mods/sanctuary/src/main/resources/assets/sanctuary/textures/block/sapphire_block.png differ diff --git a/mods/sanctuary/src/main/resources/assets/sanctuary/textures/block/sapphire_ore.png b/mods/sanctuary/src/main/resources/assets/sanctuary/textures/block/sapphire_ore.png new file mode 100644 index 0000000..b9376d1 Binary files /dev/null and b/mods/sanctuary/src/main/resources/assets/sanctuary/textures/block/sapphire_ore.png differ diff --git a/mods/sanctuary/src/main/resources/assets/sanctuary/textures/item/ruby.png b/mods/sanctuary/src/main/resources/assets/sanctuary/textures/item/ruby.png new file mode 100644 index 0000000..d840aff Binary files /dev/null and b/mods/sanctuary/src/main/resources/assets/sanctuary/textures/item/ruby.png differ diff --git a/mods/sanctuary/src/main/resources/assets/sanctuary/textures/item/sapphire.png b/mods/sanctuary/src/main/resources/assets/sanctuary/textures/item/sapphire.png new file mode 100644 index 0000000..6ab1480 Binary files /dev/null and b/mods/sanctuary/src/main/resources/assets/sanctuary/textures/item/sapphire.png differ diff --git a/mods/sanctuary/src/main/resources/data/c/tags/block/ores.json b/mods/sanctuary/src/main/resources/data/c/tags/block/ores.json new file mode 100644 index 0000000..373d8da --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/c/tags/block/ores.json @@ -0,0 +1,7 @@ +{ + "replace": false, + "values": [ + "#c:ores/ruby", + "#c:ores/sapphire" + ] +} diff --git a/mods/sanctuary/src/main/resources/data/c/tags/block/ores/ruby.json b/mods/sanctuary/src/main/resources/data/c/tags/block/ores/ruby.json new file mode 100644 index 0000000..24f0f3f --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/c/tags/block/ores/ruby.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "#sanctuary:ruby_ores" + ] +} diff --git a/mods/sanctuary/src/main/resources/data/c/tags/block/ores/sapphire.json b/mods/sanctuary/src/main/resources/data/c/tags/block/ores/sapphire.json new file mode 100644 index 0000000..1aa4d1f --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/c/tags/block/ores/sapphire.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "#sanctuary:sapphire_ores" + ] +} diff --git a/mods/sanctuary/src/main/resources/data/c/tags/block/ores_in_ground/deepslate.json b/mods/sanctuary/src/main/resources/data/c/tags/block/ores_in_ground/deepslate.json new file mode 100644 index 0000000..601d59e --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/c/tags/block/ores_in_ground/deepslate.json @@ -0,0 +1,7 @@ +{ + "replace": false, + "values": [ + "sanctuary:deepslate_ruby_ore", + "sanctuary:deepslate_sapphire_ore" + ] +} diff --git a/mods/sanctuary/src/main/resources/data/c/tags/block/ores_in_ground/stone.json b/mods/sanctuary/src/main/resources/data/c/tags/block/ores_in_ground/stone.json new file mode 100644 index 0000000..c5173d5 --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/c/tags/block/ores_in_ground/stone.json @@ -0,0 +1,7 @@ +{ + "replace": false, + "values": [ + "sanctuary:ruby_ore", + "sanctuary:sapphire_ore" + ] +} diff --git a/mods/sanctuary/src/main/resources/data/c/tags/block/storage_blocks.json b/mods/sanctuary/src/main/resources/data/c/tags/block/storage_blocks.json new file mode 100644 index 0000000..0f623cc --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/c/tags/block/storage_blocks.json @@ -0,0 +1,7 @@ +{ + "replace": false, + "values": [ + "#c:storage_blocks/ruby", + "#c:storage_blocks/sapphire" + ] +} diff --git a/mods/sanctuary/src/main/resources/data/c/tags/block/storage_blocks/ruby.json b/mods/sanctuary/src/main/resources/data/c/tags/block/storage_blocks/ruby.json new file mode 100644 index 0000000..237852b --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/c/tags/block/storage_blocks/ruby.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "sanctuary:ruby_block" + ] +} diff --git a/mods/sanctuary/src/main/resources/data/c/tags/block/storage_blocks/sapphire.json b/mods/sanctuary/src/main/resources/data/c/tags/block/storage_blocks/sapphire.json new file mode 100644 index 0000000..9391357 --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/c/tags/block/storage_blocks/sapphire.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "sanctuary:sapphire_block" + ] +} diff --git a/mods/sanctuary/src/main/resources/data/c/tags/item/gems.json b/mods/sanctuary/src/main/resources/data/c/tags/item/gems.json new file mode 100644 index 0000000..b1ce65c --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/c/tags/item/gems.json @@ -0,0 +1,7 @@ +{ + "replace": false, + "values": [ + "#c:gems/ruby", + "#c:gems/sapphire" + ] +} diff --git a/mods/sanctuary/src/main/resources/data/c/tags/item/gems/ruby.json b/mods/sanctuary/src/main/resources/data/c/tags/item/gems/ruby.json new file mode 100644 index 0000000..43f558c --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/c/tags/item/gems/ruby.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "sanctuary:ruby" + ] +} diff --git a/mods/sanctuary/src/main/resources/data/c/tags/item/gems/sapphire.json b/mods/sanctuary/src/main/resources/data/c/tags/item/gems/sapphire.json new file mode 100644 index 0000000..623956b --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/c/tags/item/gems/sapphire.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "sanctuary:sapphire" + ] +} diff --git a/mods/sanctuary/src/main/resources/data/c/tags/item/ores.json b/mods/sanctuary/src/main/resources/data/c/tags/item/ores.json new file mode 100644 index 0000000..373d8da --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/c/tags/item/ores.json @@ -0,0 +1,7 @@ +{ + "replace": false, + "values": [ + "#c:ores/ruby", + "#c:ores/sapphire" + ] +} diff --git a/mods/sanctuary/src/main/resources/data/c/tags/item/ores/ruby.json b/mods/sanctuary/src/main/resources/data/c/tags/item/ores/ruby.json new file mode 100644 index 0000000..24f0f3f --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/c/tags/item/ores/ruby.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "#sanctuary:ruby_ores" + ] +} diff --git a/mods/sanctuary/src/main/resources/data/c/tags/item/ores/sapphire.json b/mods/sanctuary/src/main/resources/data/c/tags/item/ores/sapphire.json new file mode 100644 index 0000000..1aa4d1f --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/c/tags/item/ores/sapphire.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "#sanctuary:sapphire_ores" + ] +} diff --git a/mods/sanctuary/src/main/resources/data/c/tags/item/ores_in_ground/deepslate.json b/mods/sanctuary/src/main/resources/data/c/tags/item/ores_in_ground/deepslate.json new file mode 100644 index 0000000..601d59e --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/c/tags/item/ores_in_ground/deepslate.json @@ -0,0 +1,7 @@ +{ + "replace": false, + "values": [ + "sanctuary:deepslate_ruby_ore", + "sanctuary:deepslate_sapphire_ore" + ] +} diff --git a/mods/sanctuary/src/main/resources/data/c/tags/item/ores_in_ground/stone.json b/mods/sanctuary/src/main/resources/data/c/tags/item/ores_in_ground/stone.json new file mode 100644 index 0000000..c5173d5 --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/c/tags/item/ores_in_ground/stone.json @@ -0,0 +1,7 @@ +{ + "replace": false, + "values": [ + "sanctuary:ruby_ore", + "sanctuary:sapphire_ore" + ] +} diff --git a/mods/sanctuary/src/main/resources/data/c/tags/item/storage_blocks.json b/mods/sanctuary/src/main/resources/data/c/tags/item/storage_blocks.json new file mode 100644 index 0000000..0f623cc --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/c/tags/item/storage_blocks.json @@ -0,0 +1,7 @@ +{ + "replace": false, + "values": [ + "#c:storage_blocks/ruby", + "#c:storage_blocks/sapphire" + ] +} diff --git a/mods/sanctuary/src/main/resources/data/c/tags/item/storage_blocks/ruby.json b/mods/sanctuary/src/main/resources/data/c/tags/item/storage_blocks/ruby.json new file mode 100644 index 0000000..237852b --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/c/tags/item/storage_blocks/ruby.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "sanctuary:ruby_block" + ] +} diff --git a/mods/sanctuary/src/main/resources/data/c/tags/item/storage_blocks/sapphire.json b/mods/sanctuary/src/main/resources/data/c/tags/item/storage_blocks/sapphire.json new file mode 100644 index 0000000..9391357 --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/c/tags/item/storage_blocks/sapphire.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "sanctuary:sapphire_block" + ] +} diff --git a/mods/sanctuary/src/main/resources/data/minecraft/tags/block/beacon_base_blocks.json b/mods/sanctuary/src/main/resources/data/minecraft/tags/block/beacon_base_blocks.json new file mode 100644 index 0000000..0dd9ac6 --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/minecraft/tags/block/beacon_base_blocks.json @@ -0,0 +1,7 @@ +{ + "replace": false, + "values": [ + "sanctuary:ruby_block", + "sanctuary:sapphire_block" + ] +} diff --git a/mods/sanctuary/src/main/resources/data/minecraft/tags/block/mineable/pickaxe.json b/mods/sanctuary/src/main/resources/data/minecraft/tags/block/mineable/pickaxe.json index 2688da0..9b3d272 100644 --- a/mods/sanctuary/src/main/resources/data/minecraft/tags/block/mineable/pickaxe.json +++ b/mods/sanctuary/src/main/resources/data/minecraft/tags/block/mineable/pickaxe.json @@ -64,6 +64,12 @@ "sanctuary:brown_brick_wall", "sanctuary:green_brick_wall", "sanctuary:red_brick_wall", - "sanctuary:black_brick_wall" + "sanctuary:black_brick_wall", + "sanctuary:ruby_block", + "sanctuary:ruby_ore", + "sanctuary:deepslate_ruby_ore", + "sanctuary:sapphire_block", + "sanctuary:sapphire_ore", + "sanctuary:deepslate_sapphire_ore" ] } diff --git a/mods/sanctuary/src/main/resources/data/minecraft/tags/block/needs_iron_tool.json b/mods/sanctuary/src/main/resources/data/minecraft/tags/block/needs_iron_tool.json new file mode 100644 index 0000000..190c8b8 --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/minecraft/tags/block/needs_iron_tool.json @@ -0,0 +1,11 @@ +{ + "replace": false, + "values": [ + "sanctuary:ruby_block", + "sanctuary:ruby_ore", + "sanctuary:deepslate_ruby_ore", + "sanctuary:sapphire_block", + "sanctuary:sapphire_ore", + "sanctuary:deepslate_sapphire_ore" + ] +} diff --git a/mods/sanctuary/src/main/resources/data/minecraft/tags/item/beacon_payment_items.json b/mods/sanctuary/src/main/resources/data/minecraft/tags/item/beacon_payment_items.json new file mode 100644 index 0000000..a213208 --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/minecraft/tags/item/beacon_payment_items.json @@ -0,0 +1,7 @@ +{ + "replace": false, + "values": [ + "sanctuary:ruby", + "sanctuary:sapphire" + ] +} diff --git a/mods/sanctuary/src/main/resources/data/sanctuary/advancement/recipes/building_blocks/ruby_block.json b/mods/sanctuary/src/main/resources/data/sanctuary/advancement/recipes/building_blocks/ruby_block.json new file mode 100644 index 0000000..c94023c --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/sanctuary/advancement/recipes/building_blocks/ruby_block.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_emerald": { + "conditions": { + "items": [ + { + "items": "sanctuary:ruby" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipes": "sanctuary:ruby_block" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_emerald" + ] + ], + "rewards": { + "recipes": [ + "sanctuary:ruby_block" + ] + } +} diff --git a/mods/sanctuary/src/main/resources/data/sanctuary/advancement/recipes/building_blocks/sapphire_block.json b/mods/sanctuary/src/main/resources/data/sanctuary/advancement/recipes/building_blocks/sapphire_block.json new file mode 100644 index 0000000..c17cb38 --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/sanctuary/advancement/recipes/building_blocks/sapphire_block.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_emerald": { + "conditions": { + "items": [ + { + "items": "sanctuary:sapphire" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipes": "sanctuary:sapphire_block" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_emerald" + ] + ], + "rewards": { + "recipes": [ + "sanctuary:sapphire_block" + ] + } +} diff --git a/mods/sanctuary/src/main/resources/data/sanctuary/advancement/recipes/misc/ruby.json b/mods/sanctuary/src/main/resources/data/sanctuary/advancement/recipes/misc/ruby.json new file mode 100644 index 0000000..d1d2656 --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/sanctuary/advancement/recipes/misc/ruby.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_emerald_block": { + "conditions": { + "items": [ + { + "items": "sanctuary:ruby_block" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipes": "sanctuary:ruby" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_emerald_block" + ] + ], + "rewards": { + "recipes": [ + "sanctuary:ruby" + ] + } +} diff --git a/mods/sanctuary/src/main/resources/data/sanctuary/advancement/recipes/misc/ruby_from_blasting_deepslate_ruby_ore.json b/mods/sanctuary/src/main/resources/data/sanctuary/advancement/recipes/misc/ruby_from_blasting_deepslate_ruby_ore.json new file mode 100644 index 0000000..8f1c96e --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/sanctuary/advancement/recipes/misc/ruby_from_blasting_deepslate_ruby_ore.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_deepslate_ruby_ore": { + "conditions": { + "items": [ + { + "items": "sanctuary:deepslate_ruby_ore" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipes": "sanctuary:ruby_from_blasting_deepslate_ruby_ore" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_deepslate_ruby_ore" + ] + ], + "rewards": { + "recipes": [ + "sanctuary:ruby_from_blasting_deepslate_ruby_ore" + ] + } +} diff --git a/mods/sanctuary/src/main/resources/data/sanctuary/advancement/recipes/misc/ruby_from_blasting_ruby_ore.json b/mods/sanctuary/src/main/resources/data/sanctuary/advancement/recipes/misc/ruby_from_blasting_ruby_ore.json new file mode 100644 index 0000000..8aa9943 --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/sanctuary/advancement/recipes/misc/ruby_from_blasting_ruby_ore.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_ruby_ore": { + "conditions": { + "items": [ + { + "items": "sanctuary:ruby_ore" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipes": "sanctuary:ruby_from_blasting_ruby_ore" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_ruby_ore" + ] + ], + "rewards": { + "recipes": [ + "sanctuary:ruby_from_blasting_ruby_ore" + ] + } +} diff --git a/mods/sanctuary/src/main/resources/data/sanctuary/advancement/recipes/misc/ruby_from_smelting_deepslate_ruby_ore.json b/mods/sanctuary/src/main/resources/data/sanctuary/advancement/recipes/misc/ruby_from_smelting_deepslate_ruby_ore.json new file mode 100644 index 0000000..48c4921 --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/sanctuary/advancement/recipes/misc/ruby_from_smelting_deepslate_ruby_ore.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_deepslate_ruby_ore": { + "conditions": { + "items": [ + { + "items": "sanctuary:deepslate_ruby_ore" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipes": "sanctuary:ruby_from_smelting_deepslate_ruby_ore" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_deepslate_ruby_ore" + ] + ], + "rewards": { + "recipes": [ + "sanctuary:ruby_from_smelting_deepslate_ruby_ore" + ] + } +} diff --git a/mods/sanctuary/src/main/resources/data/sanctuary/advancement/recipes/misc/ruby_from_smelting_ruby_ore.json b/mods/sanctuary/src/main/resources/data/sanctuary/advancement/recipes/misc/ruby_from_smelting_ruby_ore.json new file mode 100644 index 0000000..0d3fed4 --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/sanctuary/advancement/recipes/misc/ruby_from_smelting_ruby_ore.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_ruby_ore": { + "conditions": { + "items": [ + { + "items": "sanctuary:ruby_ore" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipes": "sanctuary:ruby_from_smelting_ruby_ore" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_ruby_ore" + ] + ], + "rewards": { + "recipes": [ + "sanctuary:ruby_from_smelting_ruby_ore" + ] + } +} diff --git a/mods/sanctuary/src/main/resources/data/sanctuary/advancement/recipes/misc/sapphire.json b/mods/sanctuary/src/main/resources/data/sanctuary/advancement/recipes/misc/sapphire.json new file mode 100644 index 0000000..2f97d3c --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/sanctuary/advancement/recipes/misc/sapphire.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_emerald_block": { + "conditions": { + "items": [ + { + "items": "sanctuary:sapphire_block" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipes": "sanctuary:sapphire" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_emerald_block" + ] + ], + "rewards": { + "recipes": [ + "sanctuary:sapphire" + ] + } +} diff --git a/mods/sanctuary/src/main/resources/data/sanctuary/advancement/recipes/misc/sapphire_from_blasting_deepslate_sapphire_ore.json b/mods/sanctuary/src/main/resources/data/sanctuary/advancement/recipes/misc/sapphire_from_blasting_deepslate_sapphire_ore.json new file mode 100644 index 0000000..4850946 --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/sanctuary/advancement/recipes/misc/sapphire_from_blasting_deepslate_sapphire_ore.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_deepslate_sapphire_ore": { + "conditions": { + "items": [ + { + "items": "sanctuary:deepslate_sapphire_ore" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipes": "sanctuary:sapphire_from_blasting_deepslate_sapphire_ore" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_deepslate_sapphire_ore" + ] + ], + "rewards": { + "recipes": [ + "sanctuary:sapphire_from_blasting_deepslate_sapphire_ore" + ] + } +} diff --git a/mods/sanctuary/src/main/resources/data/sanctuary/advancement/recipes/misc/sapphire_from_blasting_sapphire_ore.json b/mods/sanctuary/src/main/resources/data/sanctuary/advancement/recipes/misc/sapphire_from_blasting_sapphire_ore.json new file mode 100644 index 0000000..a6c25f6 --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/sanctuary/advancement/recipes/misc/sapphire_from_blasting_sapphire_ore.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_sapphire_ore": { + "conditions": { + "items": [ + { + "items": "sanctuary:sapphire_ore" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipes": "sanctuary:sapphire_from_blasting_sapphire_ore" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_sapphire_ore" + ] + ], + "rewards": { + "recipes": [ + "sanctuary:sapphire_from_blasting_sapphire_ore" + ] + } +} diff --git a/mods/sanctuary/src/main/resources/data/sanctuary/advancement/recipes/misc/sapphire_from_smelting_deepslate_sapphire_ore.json b/mods/sanctuary/src/main/resources/data/sanctuary/advancement/recipes/misc/sapphire_from_smelting_deepslate_sapphire_ore.json new file mode 100644 index 0000000..dd7d80f --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/sanctuary/advancement/recipes/misc/sapphire_from_smelting_deepslate_sapphire_ore.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_deepslate_sapphire_ore": { + "conditions": { + "items": [ + { + "items": "sanctuary:deepslate_sapphire_ore" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipes": "sanctuary:sapphire_from_smelting_deepslate_sapphire_ore" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_deepslate_sapphire_ore" + ] + ], + "rewards": { + "recipes": [ + "sanctuary:sapphire_from_smelting_deepslate_sapphire_ore" + ] + } +} diff --git a/mods/sanctuary/src/main/resources/data/sanctuary/advancement/recipes/misc/sapphire_from_smelting_sapphire_ore.json b/mods/sanctuary/src/main/resources/data/sanctuary/advancement/recipes/misc/sapphire_from_smelting_sapphire_ore.json new file mode 100644 index 0000000..4188fba --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/sanctuary/advancement/recipes/misc/sapphire_from_smelting_sapphire_ore.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_sapphire_ore": { + "conditions": { + "items": [ + { + "items": "sanctuary:sapphire_ore" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipes": "sanctuary:sapphire_from_smelting_sapphire_ore" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_sapphire_ore" + ] + ], + "rewards": { + "recipes": [ + "sanctuary:sapphire_from_smelting_sapphire_ore" + ] + } +} diff --git a/mods/sanctuary/src/main/resources/data/sanctuary/loot_table/blocks/deepslate_ruby_ore.json b/mods/sanctuary/src/main/resources/data/sanctuary/loot_table/blocks/deepslate_ruby_ore.json new file mode 100644 index 0000000..cb54b63 --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/sanctuary/loot_table/blocks/deepslate_ruby_ore.json @@ -0,0 +1,35 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "entries": [ + { + "type": "minecraft:alternatives", + "children": [ + { + "type": "minecraft:item", + "condition": "minecraft:tool/can_silk_touch", + "name": "sanctuary:deepslate_ruby_ore" + }, + { + "type": "minecraft:item", + "modifier": [ + { + "type": "minecraft:apply_bonus", + "enchantment": "minecraft:fortune", + "formula": "minecraft:ore_drops" + }, + { + "type": "minecraft:explosion_decay" + } + ], + "name": "sanctuary:ruby" + } + ] + } + ], + "rolls": 1 + } + ], + "random_sequence": "sanctuary:blocks/deepslate_ruby_ore" +} diff --git a/mods/sanctuary/src/main/resources/data/sanctuary/loot_table/blocks/deepslate_sapphire_ore.json b/mods/sanctuary/src/main/resources/data/sanctuary/loot_table/blocks/deepslate_sapphire_ore.json new file mode 100644 index 0000000..6aa432e --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/sanctuary/loot_table/blocks/deepslate_sapphire_ore.json @@ -0,0 +1,35 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "entries": [ + { + "type": "minecraft:alternatives", + "children": [ + { + "type": "minecraft:item", + "condition": "minecraft:tool/can_silk_touch", + "name": "sanctuary:deepslate_sapphire_ore" + }, + { + "type": "minecraft:item", + "modifier": [ + { + "type": "minecraft:apply_bonus", + "enchantment": "minecraft:fortune", + "formula": "minecraft:ore_drops" + }, + { + "type": "minecraft:explosion_decay" + } + ], + "name": "sanctuary:sapphire" + } + ] + } + ], + "rolls": 1 + } + ], + "random_sequence": "sanctuary:blocks/deepslate_sapphire_ore" +} diff --git a/mods/sanctuary/src/main/resources/data/sanctuary/loot_table/blocks/ruby_block.json b/mods/sanctuary/src/main/resources/data/sanctuary/loot_table/blocks/ruby_block.json new file mode 100644 index 0000000..60a7212 --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/sanctuary/loot_table/blocks/ruby_block.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "condition": { + "type": "minecraft:survives_explosion" + }, + "entries": [ + { + "type": "minecraft:item", + "name": "sanctuary:ruby_block" + } + ], + "rolls": 1 + } + ], + "random_sequence": "sanctuary:blocks/ruby_block" +} diff --git a/mods/sanctuary/src/main/resources/data/sanctuary/loot_table/blocks/ruby_ore.json b/mods/sanctuary/src/main/resources/data/sanctuary/loot_table/blocks/ruby_ore.json new file mode 100644 index 0000000..858bac0 --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/sanctuary/loot_table/blocks/ruby_ore.json @@ -0,0 +1,35 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "entries": [ + { + "type": "minecraft:alternatives", + "children": [ + { + "type": "minecraft:item", + "condition": "minecraft:tool/can_silk_touch", + "name": "sanctuary:ruby_ore" + }, + { + "type": "minecraft:item", + "modifier": [ + { + "type": "minecraft:apply_bonus", + "enchantment": "minecraft:fortune", + "formula": "minecraft:ore_drops" + }, + { + "type": "minecraft:explosion_decay" + } + ], + "name": "sanctuary:ruby" + } + ] + } + ], + "rolls": 1 + } + ], + "random_sequence": "sanctuary:blocks/ruby_ore" +} diff --git a/mods/sanctuary/src/main/resources/data/sanctuary/loot_table/blocks/sapphire_block.json b/mods/sanctuary/src/main/resources/data/sanctuary/loot_table/blocks/sapphire_block.json new file mode 100644 index 0000000..7fb64f3 --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/sanctuary/loot_table/blocks/sapphire_block.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "condition": { + "type": "minecraft:survives_explosion" + }, + "entries": [ + { + "type": "minecraft:item", + "name": "sanctuary:sapphire_block" + } + ], + "rolls": 1 + } + ], + "random_sequence": "sanctuary:blocks/sapphire_block" +} diff --git a/mods/sanctuary/src/main/resources/data/sanctuary/loot_table/blocks/sapphire_ore.json b/mods/sanctuary/src/main/resources/data/sanctuary/loot_table/blocks/sapphire_ore.json new file mode 100644 index 0000000..2c1504b --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/sanctuary/loot_table/blocks/sapphire_ore.json @@ -0,0 +1,35 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "entries": [ + { + "type": "minecraft:alternatives", + "children": [ + { + "type": "minecraft:item", + "condition": "minecraft:tool/can_silk_touch", + "name": "sanctuary:sapphire_ore" + }, + { + "type": "minecraft:item", + "modifier": [ + { + "type": "minecraft:apply_bonus", + "enchantment": "minecraft:fortune", + "formula": "minecraft:ore_drops" + }, + { + "type": "minecraft:explosion_decay" + } + ], + "name": "sanctuary:sapphire" + } + ] + } + ], + "rolls": 1 + } + ], + "random_sequence": "sanctuary:blocks/sapphire_ore" +} diff --git a/mods/sanctuary/src/main/resources/data/sanctuary/recipe/ruby.json b/mods/sanctuary/src/main/resources/data/sanctuary/recipe/ruby.json new file mode 100644 index 0000000..fade174 --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/sanctuary/recipe/ruby.json @@ -0,0 +1,10 @@ +{ + "type": "minecraft:crafting_shapeless", + "ingredients": [ + "sanctuary:ruby_block" + ], + "result": { + "count": 9, + "id": "sanctuary:ruby" + } +} diff --git a/mods/sanctuary/src/main/resources/data/sanctuary/recipe/ruby_block.json b/mods/sanctuary/src/main/resources/data/sanctuary/recipe/ruby_block.json new file mode 100644 index 0000000..792253e --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/sanctuary/recipe/ruby_block.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "building", + "key": { + "#": "sanctuary:ruby" + }, + "pattern": [ + "###", + "###", + "###" + ], + "result": { + "id": "sanctuary:ruby_block" + } +} diff --git a/mods/sanctuary/src/main/resources/data/sanctuary/recipe/ruby_from_blasting_deepslate_ruby_ore.json b/mods/sanctuary/src/main/resources/data/sanctuary/recipe/ruby_from_blasting_deepslate_ruby_ore.json new file mode 100644 index 0000000..3d2fa33 --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/sanctuary/recipe/ruby_from_blasting_deepslate_ruby_ore.json @@ -0,0 +1,10 @@ +{ + "type": "minecraft:blasting", + "cookingtime": 200, + "experience": 1.0, + "group": "ruby", + "ingredient": "sanctuary:deepslate_ruby_ore", + "result": { + "id": "sanctuary:ruby" + } +} diff --git a/mods/sanctuary/src/main/resources/data/sanctuary/recipe/ruby_from_blasting_ruby_ore.json b/mods/sanctuary/src/main/resources/data/sanctuary/recipe/ruby_from_blasting_ruby_ore.json new file mode 100644 index 0000000..2ab864f --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/sanctuary/recipe/ruby_from_blasting_ruby_ore.json @@ -0,0 +1,10 @@ +{ + "type": "minecraft:blasting", + "cookingtime": 200, + "experience": 1.0, + "group": "ruby", + "ingredient": "sanctuary:ruby_ore", + "result": { + "id": "sanctuary:ruby" + } +} diff --git a/mods/sanctuary/src/main/resources/data/sanctuary/recipe/ruby_from_smelting_deepslate_ruby_ore.json b/mods/sanctuary/src/main/resources/data/sanctuary/recipe/ruby_from_smelting_deepslate_ruby_ore.json new file mode 100644 index 0000000..a77659e --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/sanctuary/recipe/ruby_from_smelting_deepslate_ruby_ore.json @@ -0,0 +1,10 @@ +{ + "type": "minecraft:smelting", + "cookingtime": 200, + "experience": 1.0, + "group": "ruby", + "ingredient": "sanctuary:deepslate_ruby_ore", + "result": { + "id": "sanctuary:ruby" + } +} diff --git a/mods/sanctuary/src/main/resources/data/sanctuary/recipe/ruby_from_smelting_ruby_ore.json b/mods/sanctuary/src/main/resources/data/sanctuary/recipe/ruby_from_smelting_ruby_ore.json new file mode 100644 index 0000000..20fe86f --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/sanctuary/recipe/ruby_from_smelting_ruby_ore.json @@ -0,0 +1,10 @@ +{ + "type": "minecraft:smelting", + "cookingtime": 200, + "experience": 1.0, + "group": "ruby", + "ingredient": "sanctuary:ruby_ore", + "result": { + "id": "sanctuary:ruby" + } +} diff --git a/mods/sanctuary/src/main/resources/data/sanctuary/recipe/sapphire.json b/mods/sanctuary/src/main/resources/data/sanctuary/recipe/sapphire.json new file mode 100644 index 0000000..1cd5667 --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/sanctuary/recipe/sapphire.json @@ -0,0 +1,10 @@ +{ + "type": "minecraft:crafting_shapeless", + "ingredients": [ + "sanctuary:sapphire_block" + ], + "result": { + "count": 9, + "id": "sanctuary:sapphire" + } +} diff --git a/mods/sanctuary/src/main/resources/data/sanctuary/recipe/sapphire_block.json b/mods/sanctuary/src/main/resources/data/sanctuary/recipe/sapphire_block.json new file mode 100644 index 0000000..df5a786 --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/sanctuary/recipe/sapphire_block.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "building", + "key": { + "#": "sanctuary:sapphire" + }, + "pattern": [ + "###", + "###", + "###" + ], + "result": { + "id": "sanctuary:sapphire_block" + } +} diff --git a/mods/sanctuary/src/main/resources/data/sanctuary/recipe/sapphire_from_blasting_deepslate_sapphire_ore.json b/mods/sanctuary/src/main/resources/data/sanctuary/recipe/sapphire_from_blasting_deepslate_sapphire_ore.json new file mode 100644 index 0000000..e152b8d --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/sanctuary/recipe/sapphire_from_blasting_deepslate_sapphire_ore.json @@ -0,0 +1,10 @@ +{ + "type": "minecraft:blasting", + "cookingtime": 200, + "experience": 1.0, + "group": "sapphire", + "ingredient": "sanctuary:deepslate_sapphire_ore", + "result": { + "id": "sanctuary:sapphire" + } +} diff --git a/mods/sanctuary/src/main/resources/data/sanctuary/recipe/sapphire_from_blasting_sapphire_ore.json b/mods/sanctuary/src/main/resources/data/sanctuary/recipe/sapphire_from_blasting_sapphire_ore.json new file mode 100644 index 0000000..4b388e3 --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/sanctuary/recipe/sapphire_from_blasting_sapphire_ore.json @@ -0,0 +1,10 @@ +{ + "type": "minecraft:blasting", + "cookingtime": 200, + "experience": 1.0, + "group": "sapphire", + "ingredient": "sanctuary:sapphire_ore", + "result": { + "id": "sanctuary:sapphire" + } +} diff --git a/mods/sanctuary/src/main/resources/data/sanctuary/recipe/sapphire_from_smelting_deepslate_sapphire_ore.json b/mods/sanctuary/src/main/resources/data/sanctuary/recipe/sapphire_from_smelting_deepslate_sapphire_ore.json new file mode 100644 index 0000000..07b42ba --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/sanctuary/recipe/sapphire_from_smelting_deepslate_sapphire_ore.json @@ -0,0 +1,10 @@ +{ + "type": "minecraft:smelting", + "cookingtime": 200, + "experience": 1.0, + "group": "sapphire", + "ingredient": "sanctuary:deepslate_sapphire_ore", + "result": { + "id": "sanctuary:sapphire" + } +} diff --git a/mods/sanctuary/src/main/resources/data/sanctuary/recipe/sapphire_from_smelting_sapphire_ore.json b/mods/sanctuary/src/main/resources/data/sanctuary/recipe/sapphire_from_smelting_sapphire_ore.json new file mode 100644 index 0000000..5bd84e7 --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/sanctuary/recipe/sapphire_from_smelting_sapphire_ore.json @@ -0,0 +1,10 @@ +{ + "type": "minecraft:smelting", + "cookingtime": 200, + "experience": 1.0, + "group": "sapphire", + "ingredient": "sanctuary:sapphire_ore", + "result": { + "id": "sanctuary:sapphire" + } +} diff --git a/mods/sanctuary/src/main/resources/data/sanctuary/sanctuary_recipe_collections/villages_and_trading.json b/mods/sanctuary/src/main/resources/data/sanctuary/sanctuary_recipe_collections/villages_and_trading.json index eec3552..a6037da 100644 --- a/mods/sanctuary/src/main/resources/data/sanctuary/sanctuary_recipe_collections/villages_and_trading.json +++ b/mods/sanctuary/src/main/resources/data/sanctuary/sanctuary_recipe_collections/villages_and_trading.json @@ -5,7 +5,15 @@ "minecraft:deepslate_emerald_ore", "minecraft:emerald", "minecraft:emerald_block", - "minecraft:emerald_ore" + "minecraft:emerald_ore", + "sanctuary:deepslate_ruby_ore", + "sanctuary:deepslate_sapphire_ore", + "sanctuary:ruby", + "sanctuary:ruby_block", + "sanctuary:ruby_ore", + "sanctuary:sapphire", + "sanctuary:sapphire_block", + "sanctuary:sapphire_ore" ], "advancements": [ "minecraft:adventure/hero_of_the_village", @@ -29,14 +37,42 @@ "minecraft:bell", "minecraft:deepslate_emerald_ore", "minecraft:emerald_block", - "minecraft:emerald_ore" + "minecraft:emerald_ore", + "sanctuary:deepslate_ruby_ore", + "sanctuary:deepslate_sapphire_ore", + "sanctuary:ruby_block", + "sanctuary:ruby_ore", + "sanctuary:sapphire_block", + "sanctuary:sapphire_ore" ], "items": [ "minecraft:bell", "minecraft:deepslate_emerald_ore", "minecraft:emerald", "minecraft:emerald_block", - "minecraft:emerald_ore" + "minecraft:emerald_ore", + "sanctuary:deepslate_ruby_ore", + "sanctuary:deepslate_sapphire_ore", + "sanctuary:ruby", + "sanctuary:ruby_block", + "sanctuary:ruby_ore", + "sanctuary:sapphire", + "sanctuary:sapphire_block", + "sanctuary:sapphire_ore" ] - } + }, + "additional_recipes": [ + "sanctuary:ruby", + "sanctuary:ruby_block", + "sanctuary:ruby_from_blasting_deepslate_ruby_ore", + "sanctuary:ruby_from_blasting_ruby_ore", + "sanctuary:ruby_from_smelting_deepslate_ruby_ore", + "sanctuary:ruby_from_smelting_ruby_ore", + "sanctuary:sapphire", + "sanctuary:sapphire_block", + "sanctuary:sapphire_from_blasting_deepslate_sapphire_ore", + "sanctuary:sapphire_from_blasting_sapphire_ore", + "sanctuary:sapphire_from_smelting_deepslate_sapphire_ore", + "sanctuary:sapphire_from_smelting_sapphire_ore" + ] } diff --git a/mods/sanctuary/src/main/resources/data/sanctuary/tags/block/gem_deepslate_replaceables.json b/mods/sanctuary/src/main/resources/data/sanctuary/tags/block/gem_deepslate_replaceables.json new file mode 100644 index 0000000..e5ea81d --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/sanctuary/tags/block/gem_deepslate_replaceables.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "#minecraft:deepslate_ore_replaceables" + ] +} diff --git a/mods/sanctuary/src/main/resources/data/sanctuary/tags/block/gem_stone_replaceables.json b/mods/sanctuary/src/main/resources/data/sanctuary/tags/block/gem_stone_replaceables.json new file mode 100644 index 0000000..3f98159 --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/sanctuary/tags/block/gem_stone_replaceables.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "#minecraft:stone_ore_replaceables" + ] +} diff --git a/mods/sanctuary/src/main/resources/data/sanctuary/tags/block/ruby_ores.json b/mods/sanctuary/src/main/resources/data/sanctuary/tags/block/ruby_ores.json new file mode 100644 index 0000000..ed4bb5b --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/sanctuary/tags/block/ruby_ores.json @@ -0,0 +1,7 @@ +{ + "replace": false, + "values": [ + "sanctuary:ruby_ore", + "sanctuary:deepslate_ruby_ore" + ] +} diff --git a/mods/sanctuary/src/main/resources/data/sanctuary/tags/block/sapphire_ores.json b/mods/sanctuary/src/main/resources/data/sanctuary/tags/block/sapphire_ores.json new file mode 100644 index 0000000..e0d30a5 --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/sanctuary/tags/block/sapphire_ores.json @@ -0,0 +1,7 @@ +{ + "replace": false, + "values": [ + "sanctuary:sapphire_ore", + "sanctuary:deepslate_sapphire_ore" + ] +} diff --git a/mods/sanctuary/src/main/resources/data/sanctuary/tags/item/ruby_ores.json b/mods/sanctuary/src/main/resources/data/sanctuary/tags/item/ruby_ores.json new file mode 100644 index 0000000..ed4bb5b --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/sanctuary/tags/item/ruby_ores.json @@ -0,0 +1,7 @@ +{ + "replace": false, + "values": [ + "sanctuary:ruby_ore", + "sanctuary:deepslate_ruby_ore" + ] +} diff --git a/mods/sanctuary/src/main/resources/data/sanctuary/tags/item/sapphire_ores.json b/mods/sanctuary/src/main/resources/data/sanctuary/tags/item/sapphire_ores.json new file mode 100644 index 0000000..e0d30a5 --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/sanctuary/tags/item/sapphire_ores.json @@ -0,0 +1,7 @@ +{ + "replace": false, + "values": [ + "sanctuary:sapphire_ore", + "sanctuary:deepslate_sapphire_ore" + ] +} diff --git a/mods/sanctuary/src/main/resources/data/sanctuary/tags/worldgen/biome/has_ore/ruby.json b/mods/sanctuary/src/main/resources/data/sanctuary/tags/worldgen/biome/has_ore/ruby.json new file mode 100644 index 0000000..567e1c7 --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/sanctuary/tags/worldgen/biome/has_ore/ruby.json @@ -0,0 +1,56 @@ +{ + "replace": false, + "values": [ + "#minecraft:is_overworld", + "sanctuary:cavern_bamboo_grove", + "sanctuary:cavern_birch_forest", + "sanctuary:cavern_clearing", + "sanctuary:cavern_dark_grove", + "sanctuary:cavern_dripstone_caves", + "sanctuary:cavern_dry_woodland", + "sanctuary:cavern_lush_caves", + "sanctuary:cavern_oak_forest", + "sanctuary:cavern_rocky_heath", + "sanctuary:cavern_sulfur_depths", + "sanctuary:layered_flower_meadow", + "sanctuary:layered_lower_grove", + "sanctuary:layered_meadow", + "sanctuary:layered_mossy_terraces", + "sanctuary:layered_rocky_terraces", + "sanctuary:lost_city", + "sanctuary:population_bamboo_grove", + "sanctuary:population_birch_forest", + "sanctuary:population_clearing", + "sanctuary:population_dark_grove", + "sanctuary:population_dripstone_caves", + "sanctuary:population_dry_woodland", + "sanctuary:population_lush_caves", + "sanctuary:population_oak_forest", + "sanctuary:population_rocky_heath", + "sanctuary:population_sulfur_depths", + "sanctuary:rift_bamboo_grove", + "sanctuary:rift_birch_forest", + "sanctuary:rift_clearing", + "sanctuary:rift_dark_grove", + "sanctuary:rift_dry_woodland", + "sanctuary:rift_oak_forest", + "sanctuary:rift_rocky_heath", + "sanctuary:rift_sulfur_depths", + "sanctuary:starter_forest", + "sanctuary:starter_forest_hydrology", + "sanctuary:swamp27_caves", + "sanctuary:temperate_birch_forest", + "sanctuary:temperate_dappled_forest", + "sanctuary:temperate_flower_forest", + "sanctuary:temperate_forest", + "sanctuary:temperate_plains", + "sanctuary:woodland_bamboo_grove", + "sanctuary:woodland_birch_forest", + "sanctuary:woodland_clearing", + "sanctuary:woodland_dark_grove", + "sanctuary:woodland_dry_woodland", + "sanctuary:woodland_oak_forest", + "sanctuary:woodland_rocky_heath", + "sanctuary:woodland_sulfur_depths" + ] +} diff --git a/mods/sanctuary/src/main/resources/data/sanctuary/tags/worldgen/biome/has_ore/sapphire.json b/mods/sanctuary/src/main/resources/data/sanctuary/tags/worldgen/biome/has_ore/sapphire.json new file mode 100644 index 0000000..567e1c7 --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/sanctuary/tags/worldgen/biome/has_ore/sapphire.json @@ -0,0 +1,56 @@ +{ + "replace": false, + "values": [ + "#minecraft:is_overworld", + "sanctuary:cavern_bamboo_grove", + "sanctuary:cavern_birch_forest", + "sanctuary:cavern_clearing", + "sanctuary:cavern_dark_grove", + "sanctuary:cavern_dripstone_caves", + "sanctuary:cavern_dry_woodland", + "sanctuary:cavern_lush_caves", + "sanctuary:cavern_oak_forest", + "sanctuary:cavern_rocky_heath", + "sanctuary:cavern_sulfur_depths", + "sanctuary:layered_flower_meadow", + "sanctuary:layered_lower_grove", + "sanctuary:layered_meadow", + "sanctuary:layered_mossy_terraces", + "sanctuary:layered_rocky_terraces", + "sanctuary:lost_city", + "sanctuary:population_bamboo_grove", + "sanctuary:population_birch_forest", + "sanctuary:population_clearing", + "sanctuary:population_dark_grove", + "sanctuary:population_dripstone_caves", + "sanctuary:population_dry_woodland", + "sanctuary:population_lush_caves", + "sanctuary:population_oak_forest", + "sanctuary:population_rocky_heath", + "sanctuary:population_sulfur_depths", + "sanctuary:rift_bamboo_grove", + "sanctuary:rift_birch_forest", + "sanctuary:rift_clearing", + "sanctuary:rift_dark_grove", + "sanctuary:rift_dry_woodland", + "sanctuary:rift_oak_forest", + "sanctuary:rift_rocky_heath", + "sanctuary:rift_sulfur_depths", + "sanctuary:starter_forest", + "sanctuary:starter_forest_hydrology", + "sanctuary:swamp27_caves", + "sanctuary:temperate_birch_forest", + "sanctuary:temperate_dappled_forest", + "sanctuary:temperate_flower_forest", + "sanctuary:temperate_forest", + "sanctuary:temperate_plains", + "sanctuary:woodland_bamboo_grove", + "sanctuary:woodland_birch_forest", + "sanctuary:woodland_clearing", + "sanctuary:woodland_dark_grove", + "sanctuary:woodland_dry_woodland", + "sanctuary:woodland_oak_forest", + "sanctuary:woodland_rocky_heath", + "sanctuary:woodland_sulfur_depths" + ] +} diff --git a/mods/sanctuary/src/main/resources/data/sanctuary/worldgen/feature/ore_ruby.json b/mods/sanctuary/src/main/resources/data/sanctuary/worldgen/feature/ore_ruby.json new file mode 100644 index 0000000..0821faa --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/sanctuary/worldgen/feature/ore_ruby.json @@ -0,0 +1,21 @@ +{ + "type": "sanctuary:gem_ore", + "size": 3, + "discard_chance_on_air_exposure": 0.25, + "targets": [ + { + "target": { + "predicate_type": "minecraft:tag_match", + "tag": "sanctuary:gem_stone_replaceables" + }, + "state": "sanctuary:ruby_ore" + }, + { + "target": { + "predicate_type": "minecraft:tag_match", + "tag": "sanctuary:gem_deepslate_replaceables" + }, + "state": "sanctuary:deepslate_ruby_ore" + } + ] +} diff --git a/mods/sanctuary/src/main/resources/data/sanctuary/worldgen/feature/ore_sapphire.json b/mods/sanctuary/src/main/resources/data/sanctuary/worldgen/feature/ore_sapphire.json new file mode 100644 index 0000000..2267f27 --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/sanctuary/worldgen/feature/ore_sapphire.json @@ -0,0 +1,21 @@ +{ + "type": "sanctuary:gem_ore", + "size": 3, + "discard_chance_on_air_exposure": 0.25, + "targets": [ + { + "target": { + "predicate_type": "minecraft:tag_match", + "tag": "sanctuary:gem_stone_replaceables" + }, + "state": "sanctuary:sapphire_ore" + }, + { + "target": { + "predicate_type": "minecraft:tag_match", + "tag": "sanctuary:gem_deepslate_replaceables" + }, + "state": "sanctuary:deepslate_sapphire_ore" + } + ] +} diff --git a/mods/sanctuary/src/main/resources/data/sanctuary/worldgen/placed_feature/ore_ruby.json b/mods/sanctuary/src/main/resources/data/sanctuary/worldgen/placed_feature/ore_ruby.json new file mode 100644 index 0000000..36b201b --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/sanctuary/worldgen/placed_feature/ore_ruby.json @@ -0,0 +1,27 @@ +{ + "feature": "sanctuary:ore_ruby", + "placement": [ + { + "type": "minecraft:count", + "count": 4 + }, + { + "type": "minecraft:in_square" + }, + { + "type": "minecraft:height_range", + "height": { + "type": "minecraft:uniform", + "min_inclusive": { + "absolute": 0 + }, + "max_inclusive": { + "absolute": 256 + } + } + }, + { + "type": "minecraft:biome" + } + ] +} diff --git a/mods/sanctuary/src/main/resources/data/sanctuary/worldgen/placed_feature/ore_sapphire.json b/mods/sanctuary/src/main/resources/data/sanctuary/worldgen/placed_feature/ore_sapphire.json new file mode 100644 index 0000000..fce86c1 --- /dev/null +++ b/mods/sanctuary/src/main/resources/data/sanctuary/worldgen/placed_feature/ore_sapphire.json @@ -0,0 +1,27 @@ +{ + "feature": "sanctuary:ore_sapphire", + "placement": [ + { + "type": "minecraft:count", + "count": 4 + }, + { + "type": "minecraft:in_square" + }, + { + "type": "minecraft:height_range", + "height": { + "type": "minecraft:uniform", + "min_inclusive": { + "absolute": 0 + }, + "max_inclusive": { + "absolute": 256 + } + } + }, + { + "type": "minecraft:biome" + } + ] +} diff --git a/packwiz/pack.toml b/packwiz/pack.toml index a5d35d8..f41da2d 100644 --- a/packwiz/pack.toml +++ b/packwiz/pack.toml @@ -1,6 +1,6 @@ name = "Sanctuary" author = "KOKA99CAB" -version = "beta.125" +version = "beta.126" pack-format = "packwiz:1.1.0" [index] diff --git a/scripts/data/collections-sanctuary.json b/scripts/data/collections-sanctuary.json index bf620f9..e53a911 100644 --- a/scripts/data/collections-sanctuary.json +++ b/scripts/data/collections-sanctuary.json @@ -727,5 +727,51 @@ "sanctuary:black_brick_wall" ] } + }, + "villages_and_trading": { + "additional_items": [ + "sanctuary:deepslate_ruby_ore", + "sanctuary:deepslate_sapphire_ore", + "sanctuary:ruby", + "sanctuary:ruby_block", + "sanctuary:ruby_ore", + "sanctuary:sapphire", + "sanctuary:sapphire_block", + "sanctuary:sapphire_ore" + ], + "additional_recipes": [ + "sanctuary:ruby", + "sanctuary:ruby_block", + "sanctuary:ruby_from_blasting_deepslate_ruby_ore", + "sanctuary:ruby_from_blasting_ruby_ore", + "sanctuary:ruby_from_smelting_deepslate_ruby_ore", + "sanctuary:ruby_from_smelting_ruby_ore", + "sanctuary:sapphire", + "sanctuary:sapphire_block", + "sanctuary:sapphire_from_blasting_deepslate_sapphire_ore", + "sanctuary:sapphire_from_blasting_sapphire_ore", + "sanctuary:sapphire_from_smelting_deepslate_sapphire_ore", + "sanctuary:sapphire_from_smelting_sapphire_ore" + ], + "members": { + "blocks": [ + "sanctuary:ruby_block", + "sanctuary:ruby_ore", + "sanctuary:deepslate_ruby_ore", + "sanctuary:sapphire_block", + "sanctuary:sapphire_ore", + "sanctuary:deepslate_sapphire_ore" + ], + "items": [ + "sanctuary:ruby", + "sanctuary:ruby_block", + "sanctuary:ruby_ore", + "sanctuary:deepslate_ruby_ore", + "sanctuary:sapphire", + "sanctuary:sapphire_block", + "sanctuary:sapphire_ore", + "sanctuary:deepslate_sapphire_ore" + ] + } } } diff --git a/tools/gems-textures-beta126.json b/tools/gems-textures-beta126.json new file mode 100644 index 0000000..02ab9c1 --- /dev/null +++ b/tools/gems-textures-beta126.json @@ -0,0 +1,47 @@ +{ + "minecraft": "26.3", + "version": "beta.126", + "source": "Creator-provided PNG files; copied without modification", + "files": { + "ruby.png": { + "asset": "assets/sanctuary/textures/item/ruby.png", + "sha256": "84b538e2131a962369d9ffe6cec65d79a6febf43425878b7bbc042916b20f3e0", + "source_file": "Desktop/ruby.png" + }, + "ruby_block.png": { + "asset": "assets/sanctuary/textures/block/ruby_block.png", + "sha256": "34b75f2471e6ce20999436cc779ead838fe107a5460c4f54805c8679b85e7ed7", + "source_file": "Downloads/textures gemmes/ruby_block.png" + }, + "ruby_ore.png": { + "asset": "assets/sanctuary/textures/block/ruby_ore.png", + "sha256": "0ad486547553de406817d48c568dcf64a7ae0d46b813d5c82f59206a7a69ec56", + "source_file": "Downloads/textures gemmes/ruby_ore.png" + }, + "deepslate_ruby_ore.png": { + "asset": "assets/sanctuary/textures/block/deepslate_ruby_ore.png", + "sha256": "94f6d0ba8291bf9ed52d3aeae965c0f196f9784cf1330f6196a6c6f72a757aaf", + "source_file": "Downloads/textures gemmes/deepslate_ruby_ore.png" + }, + "saphir.png": { + "asset": "assets/sanctuary/textures/item/sapphire.png", + "sha256": "4512722274de5ef1c9306cfcc8c0028e78f14d5f753f7caaf97cd7b2215ce056", + "source_file": "Desktop/saphir.png" + }, + "saphir_block.png": { + "asset": "assets/sanctuary/textures/block/sapphire_block.png", + "sha256": "90a8d8a8f5361bdb3dc055fa36beb2a4df10c5a2f2b4f3fbe0871713f67c5fbf", + "source_file": "Downloads/textures gemmes/saphir_block.png" + }, + "saphir_ore.png": { + "asset": "assets/sanctuary/textures/block/sapphire_ore.png", + "sha256": "aea35f70d7f3f7aacebe3dfa6a613af77e3d04d8c05e560bd76a7ad9d9354be5", + "source_file": "Downloads/textures gemmes/saphir_ore.png" + }, + "deepslate_saphir_ore.png": { + "asset": "assets/sanctuary/textures/block/deepslate_sapphire_ore.png", + "sha256": "724f976a166aa18b6338348aead341bcf8e1f0596fe9c6463bd70ecc626d6eb3", + "source_file": "Downloads/textures gemmes/deepslate_saphir_ore.png" + } + } +}