From 2518c2007142043bd5937a1fd0f6d17fe59e5f32 Mon Sep 17 00:00:00 2001 From: koka Date: Mon, 31 Aug 2026 13:25:27 +0200 Subject: [PATCH] feat(sanctuary): add craftable banner cape --- CHANGELOG.md | 9 + README.md | 4 +- build.gradle | 495 +++++++++++------- gradle.properties | 4 +- ...25-craftable-banner-cape-to-alpha.226.json | 49 ++ pack/packwiz/index.toml | 22 +- pack/packwiz/pack.toml | 4 +- pack/prism/modrinth.index.json | 2 +- pack/release.json | 4 +- sanctuary/build.gradle | 105 +++- .../client/SanctuaryBannerCapeLayer.java | 98 ++++ .../client/SanctuaryCapeRenderState.java | 8 + .../sanctuary/client/SanctuaryClient.java | 1 + .../client/SanctuaryClientCapes.java | 20 +- .../gameplay/SanctuaryCapeService.java | 4 +- .../sanctuary/gameplay/SanctuaryCapes.java | 15 +- .../mixin/client/AvatarRenderStateMixin.java | 23 + .../mixin/client/AvatarRendererMixin.java | 9 +- .../sanctuary/network/CapeSyncPayload.java | 45 +- .../network/SanctuaryNetworking.java | 2 +- .../assets/sanctuary/items/white_cape.json | 34 ++ .../assets/sanctuary/lang/en_us.json | 1 + .../assets/sanctuary/lang/fr_fr.json | 1 + .../assets/sanctuary/lang/ru_ru.json | 1 + .../data/sanctuary/recipe/white_cape.json | 16 + .../sanctuary/recipe/white_cape_banner.json | 8 + sanctuary/src/main/resources/fabric.mod.json | 2 +- .../src/main/resources/sanctuary.mixins.json | 1 + .../network/CapeSyncPayloadSmoke.java | 40 ++ 29 files changed, 785 insertions(+), 242 deletions(-) create mode 100644 pack/migrations/26.2.0-alpha.225-craftable-banner-cape-to-alpha.226.json create mode 100644 sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/client/SanctuaryBannerCapeLayer.java create mode 100644 sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/client/SanctuaryCapeRenderState.java create mode 100644 sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/mixin/client/AvatarRenderStateMixin.java create mode 100644 sanctuary/src/main/resources/assets/sanctuary/items/white_cape.json create mode 100644 sanctuary/src/main/resources/data/sanctuary/recipe/white_cape.json create mode 100644 sanctuary/src/main/resources/data/sanctuary/recipe/white_cape_banner.json create mode 100644 sanctuary/src/test/java/fr/koka99cab/sanctuary26/sanctuary/network/CapeSyncPayloadSmoke.java diff --git a/CHANGELOG.md b/CHANGELOG.md index c735f88..b522ddb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,15 @@ Ce journal suit les **versions du modpack**. Lorsqu'un seul module change, sa ve - Depuis `26.2.0-alpha.6`, le pack et les modules ont des versions indépendantes. I Like To Move It et Only Fun deviennent les cinquième et sixième modules actifs dans l'alpha 46. - Les versions ci-dessous ont été reconstituées à partir des JAR archivés, des packs locaux et du code source actuel. Les dates n'étant pas enregistrées de manière fiable, elles ne sont pas inventées. +## `26.2.0-alpha.226` + +Module modifié : **Sanctuary `0.0.0-alpha.130`**. Les neuf autres modules conservent leur version issue de l'alpha.225. + +- ajoute `sanctuary:white_cape`, une cape blanche craftable avec six laines blanches disposées comme une porte, en deux colonnes de trois ; +- permet d'associer simplement la cape et n'importe quelle bannière dans l'établi afin d'en conserver la couleur de fond et jusqu'à six motifs ; +- affiche les motifs dans l'inventaire et sur la cape équipée, avec la physique native des capes, y compris en multijoueur ; +- conserve les sauvegardes Sanctuary en data v13 ; le payload d'apparence transporte désormais la couleur et les motifs bornés, donc le protocole Sanctuary passe de 23 à 24 et client comme serveur doivent être mis à jour, sans nouveau monde ni réinitialisation. + ## `26.2.0-alpha.225` Modules modifiés : **Another World `0.0.0-alpha.56`**, **It's Alive `0.0.0-alpha.38`**, **I Like To Move It `0.0.0-alpha.18`**, **Only Fun `0.0.0-alpha.27`** et **Sanctuary `0.0.0-alpha.129`**. Les cinq autres modules conservent leur version issue de l'alpha.224. diff --git a/README.md b/README.md index e228b61..6d8bafc 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ Licence : **GNU GPL 3.0 or Later** (`GPL-3.0-or-later`) Les descriptions FR/EN/RU sont déclarées dans chaque `fabric.mod.json` et dans les fichiers de langue. Les images fournies servent d'icônes Fabric de leur module. -Version courante du pack distribué : **`26.2.0-alpha.225`**. Cette release distribue Another World **`0.0.0-alpha.56`**, It's Alive **`0.0.0-alpha.38`**, I Like To Move It **`0.0.0-alpha.18`**, Only Fun **`0.0.0-alpha.27`** et Sanctuary **`0.0.0-alpha.129`** ; les cinq autres modules conservent leur version issue de l'alpha.224. +Version courante du pack distribué : **`26.2.0-alpha.226`**. Cette release distribue Sanctuary **`0.0.0-alpha.130`** ; les neuf autres modules conservent leur version issue de l'alpha.225. L’alpha.225 corrige quatre tickets : posséder un coffre-fort devient obligatoire pour en braquer un autre, les familiers temporaires ne donnent plus de butin, d’expérience, de lootbox ni de progression de quête, les seize variantes Canaplia survivent à tout leur cycle de culture, et le Magic Carpet retrouve la texture historique du Totem de Notch à la place de la laine violette. Les IDs, sauvegardes, formats de données et protocoles restent compatibles. @@ -116,6 +116,8 @@ L’alpha.173 centralise l’audio du Miner : une seule boucle de frappe sur le L’alpha.171 rassemble les **46 capes** dans un onglet créatif dédié « Capes ». Elles ne sont plus mélangées à l’onglet vanilla Tools & Utilities et ne sont donc affichées qu’une seule fois. +L’alpha.226 ajoute une 47e cape, `sanctuary:white_cape`, distincte de la collection Only Fun. Elle se fabrique avec six laines blanches en deux colonnes de trois, puis accepte une bannière dans une recette simple pour en conserver la couleur et jusqu’à six motifs ; les motifs s’affichent dans l’inventaire comme une fois la cape équipée. + L’alpha.170 ajoute les pictogrammes fournis aux emplacements vides de la cape et du familier. Ils disparaissent dès qu’une cape ou un œuf est équipé, sans modifier les objets, la persistance ni le protocole. L’alpha.169 agrandit la collection de 13 à **46 capes équipables**. Les 33 nouvelles textures 64×32 fournies sont conservées telles quelles, avec une icône d’inventaire, un modèle et des traductions FR/EN/RU pour chaque cape. Elles utilisent le slot, la persistance et le rendu multijoueur déjà existants, restent sans recette et rejoignent toutes la lootbox de capes Only Fun. Les caméras Canon restent accessibles dans la lootbox normale et peuvent désormais aussi apparaître directement, très rarement, dans les coffres d’exploration et du donjon de cobblestone. diff --git a/build.gradle b/build.gradle index 3c106f7..5cd5e2a 100644 --- a/build.gradle +++ b/build.gradle @@ -2916,9 +2916,9 @@ tasks.register("verifyNotchEncounter") { def textureHash = MessageDigest.getInstance("SHA-256").digest(texture.bytes).encodeHex().toString() if (rootProject.itsalive_version != "0.0.0-alpha.38" || rootProject.ouch_version != "0.0.0-alpha.11" - || rootProject.sanctuary_version != "0.0.0-alpha.129" + || rootProject.sanctuary_version != "0.0.0-alpha.130" || rootProject.masterkey_version != "0.0.0-alpha.9" - || rootProject.pack_version != "26.2.0-alpha.225" + || rootProject.pack_version != "26.2.0-alpha.226" || manifests.itsalive.custom?.sanctuary26?.data_version != 4 || manifests.sanctuary.custom?.sanctuary26?.data_version != 13 || manifests.ouch.depends?.itsalive != ">=0.0.0-alpha.37" @@ -3007,10 +3007,10 @@ tasks.register("verifyMagicCarpet") { "iliketomoveit/src/main/resources/assets/iliketomoveit/models/item/magic_carpet.json")) def carpetTexture = file( "iliketomoveit/src/main/resources/assets/iliketomoveit/textures/item/magic_carpet.png") - if (rootProject.pack_version != "26.2.0-alpha.225" + if (rootProject.pack_version != "26.2.0-alpha.226" || rootProject.iliketomoveit_version != "0.0.0-alpha.18" || rootProject.onlyfun_version != "0.0.0-alpha.27" - || rootProject.sanctuary_version != "0.0.0-alpha.129" + || rootProject.sanctuary_version != "0.0.0-alpha.130" || manifests.iliketomoveit.custom?.sanctuary26?.data_version != 4 || manifests.iliketomoveit.custom?.sanctuary26?.network_protocol != 5 || manifests.iliketomoveit.depends?.sanctuary != ">=0.0.0-alpha.127" @@ -3019,7 +3019,7 @@ tasks.register("verifyMagicCarpet") { || manifests.onlyfun.depends?.iliketomoveit != ">=0.0.0-alpha.17" || manifests.onlyfun.depends?.sanctuary != ">=0.0.0-alpha.129" || manifests.sanctuary.custom?.sanctuary26?.data_version != 13 - || manifests.sanctuary.custom?.sanctuary26?.network_protocol != 23 + || manifests.sanctuary.custom?.sanctuary26?.network_protocol != 24 || migration.status != "released" || migration.source?.pack_version != "26.2.0-alpha.223" || migration.target?.pack_version != "26.2.0-alpha.224" @@ -3640,8 +3640,8 @@ tasks.register("verifyProgressivePauseMenuRelease") { [(locale): new JsonSlurper().parse(file( "sanctuary/src/main/resources/assets/sanctuary/lang/${locale}.json"))] } - if (rootProject.pack_version != "26.2.0-alpha.225" - || rootProject.sanctuary_version != "0.0.0-alpha.129" + if (rootProject.pack_version != "26.2.0-alpha.226" + || rootProject.sanctuary_version != "0.0.0-alpha.130" || rootProject.onlyfun_version != "0.0.0-alpha.27" || release.pack_version != rootProject.pack_version || index.versionId != rootProject.pack_version || migration.source?.modules != [sanctuary: "0.0.0-alpha.108", onlyfun: "0.0.0-alpha.17"] @@ -3690,7 +3690,7 @@ tasks.register("verifyMirrorLavenderDrawerRelease") { def redStonerRegistry = file( "redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/registry/RedStonerRegistries.java").text def drawerRecipe = file("redstoner/src/main/resources/data/redstoner/recipe/drawer.json") - if (rootProject.pack_version != "26.2.0-alpha.225" + if (rootProject.pack_version != "26.2.0-alpha.226" || rootProject.anotherworld_version != "0.0.0-alpha.56" || rootProject.redstoner_version != "0.0.0-alpha.13" || release.pack_version != rootProject.pack_version || index.versionId != rootProject.pack_version @@ -4482,9 +4482,9 @@ tasks.register("verifyShopPricingLayoutRelease") { "pack/migrations/26.2.0-alpha.192-shop-pricing-layout-to-alpha.193.json")) def release = new JsonSlurper().parse(file("pack/release.json")) def index = new JsonSlurper().parse(file("pack/prism/modrinth.index.json")) - if (rootProject.pack_version != "26.2.0-alpha.225" + if (rootProject.pack_version != "26.2.0-alpha.226" || rootProject.onlyfun_version != "0.0.0-alpha.27" - || rootProject.sanctuary_version != "0.0.0-alpha.129" + || rootProject.sanctuary_version != "0.0.0-alpha.130" || release.pack_version != rootProject.pack_version || index.versionId != rootProject.pack_version || migration.source?.pack_version != "26.2.0-alpha.192" || migration.target?.pack_version != "26.2.0-alpha.193" @@ -4527,7 +4527,7 @@ tasks.register("verifyCuisineCropsRelease") { def climate = file("itsalive/src/main/java/fr/koka99cab/sanctuary26/itsalive/agriculture/ClimateCropForaging.java").text def rice = file("itsalive/src/main/java/fr/koka99cab/sanctuary26/itsalive/agriculture/RiceCropBlock.java").text def bean = file("itsalive/src/main/java/fr/koka99cab/sanctuary26/itsalive/agriculture/BeanCropBlock.java").text - if (rootProject.pack_version != "26.2.0-alpha.225" + if (rootProject.pack_version != "26.2.0-alpha.226" || rootProject.itsalive_version != "0.0.0-alpha.38" || release.pack_version != rootProject.pack_version || index.versionId != rootProject.pack_version || migration.source?.pack_version != "26.2.0-alpha.193" @@ -4576,9 +4576,9 @@ tasks.register("verifyShopCsvBossGatesRelease") { def bossGate = file("onlyfun/src/main/java/fr/koka99cab/sanctuary26/onlyfun/shop/OnlyFunBossShopGate.java").text def catalog = file("onlyfun/src/main/java/fr/koka99cab/sanctuary26/onlyfun/shop/OnlyFunShopCatalog.java").text def offerCatalog = file("sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/shop/ShopOfferCatalog.java").text - if (rootProject.pack_version != "26.2.0-alpha.225" + if (rootProject.pack_version != "26.2.0-alpha.226" || rootProject.onlyfun_version != "0.0.0-alpha.27" - || rootProject.sanctuary_version != "0.0.0-alpha.129" + || rootProject.sanctuary_version != "0.0.0-alpha.130" || release.pack_version != rootProject.pack_version || index.versionId != rootProject.pack_version || migration.source?.pack_version != "26.2.0-alpha.194" || migration.source?.modules != [onlyfun: "0.0.0-alpha.18", sanctuary: "0.0.0-alpha.110"] @@ -4623,7 +4623,7 @@ tasks.register("verifyCulinaryMailboxGrappleFixesRelease") { def release = new JsonSlurper().parse(file("pack/release.json")) def prism = new JsonSlurper().parse(file("pack/prism/modrinth.index.json")) def packwiz = file("pack/packwiz/pack.toml").text - if (rootProject.pack_version != "26.2.0-alpha.225" + if (rootProject.pack_version != "26.2.0-alpha.226" || migration.source?.pack_version != "26.2.0-alpha.195" || migration.target?.pack_version != "26.2.0-alpha.196" || migration.target?.modules != [ @@ -4641,10 +4641,10 @@ tasks.register("verifyCulinaryMailboxGrappleFixesRelease") { || migration.distribution?.jei?.target != "30.26.0.182" || migration.compatibility?.save_migration_required != false || migration.compatibility?.registry_ids_changed != false - || release.pack_version != "26.2.0-alpha.225" - || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.225.mrpack" - || prism.versionId != "26.2.0-alpha.225" - || !packwiz.contains('version = "26.2.0-alpha.225"')) { + || release.pack_version != "26.2.0-alpha.226" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.226.mrpack" + || prism.versionId != "26.2.0-alpha.226" + || !packwiz.contains('version = "26.2.0-alpha.226"')) { throw new GradleException("The alpha.196 culinary, mailbox and grapple release contract is incomplete") } } @@ -4669,9 +4669,9 @@ tasks.register("verifyQuestRequestsCauldronBatchesRelease") { def prism = new JsonSlurper().parse(file("pack/prism/modrinth.index.json")) def packwiz = file("pack/packwiz/pack.toml").text def sanctuaryManifest = new JsonSlurper().parse(file("sanctuary/src/main/resources/fabric.mod.json")) - if (rootProject.pack_version != "26.2.0-alpha.225" + if (rootProject.pack_version != "26.2.0-alpha.226" || rootProject.itsalive_version != "0.0.0-alpha.38" - || rootProject.sanctuary_version != "0.0.0-alpha.129" + || rootProject.sanctuary_version != "0.0.0-alpha.130" || migration.source?.pack_version != "26.2.0-alpha.196" || migration.target?.pack_version != "26.2.0-alpha.197" || migration.target?.modules != [itsalive: "0.0.0-alpha.29", sanctuary: "0.0.0-alpha.113"] @@ -4688,11 +4688,11 @@ tasks.register("verifyQuestRequestsCauldronBatchesRelease") { || migration.distribution?.jei?.prism_source != "30.24.0.176" || migration.distribution?.jei?.target != "30.26.0.186" || migration.compatibility?.sanctuary_target_network_protocol != 19 - || sanctuaryManifest.custom?.sanctuary26?.network_protocol != 23 - || release.pack_version != "26.2.0-alpha.225" - || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.225.mrpack" - || prism.versionId != "26.2.0-alpha.225" - || !packwiz.contains('version = "26.2.0-alpha.225"')) { + || sanctuaryManifest.custom?.sanctuary26?.network_protocol != 24 + || release.pack_version != "26.2.0-alpha.226" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.226.mrpack" + || prism.versionId != "26.2.0-alpha.226" + || !packwiz.contains('version = "26.2.0-alpha.226"')) { throw new GradleException("The alpha.197 quest-request and cauldron-batch release contract is incomplete") } } @@ -4719,7 +4719,7 @@ tasks.register("verifyFermentationBarrelAutomationRelease") { def packwiz = file("pack/packwiz/pack.toml").text def packwizIndex = file("pack/packwiz/index.toml").text def itsAliveManifest = new JsonSlurper().parse(file("itsalive/src/main/resources/fabric.mod.json")) - if (rootProject.pack_version != "26.2.0-alpha.225" + if (rootProject.pack_version != "26.2.0-alpha.226" || rootProject.itsalive_version != "0.0.0-alpha.38" || migration.source?.pack_version != "26.2.0-alpha.197" || migration.target?.pack_version != "26.2.0-alpha.198" @@ -4738,10 +4738,10 @@ tasks.register("verifyFermentationBarrelAutomationRelease") { || migration.distribution?.packwiz_index_refreshed != true || itsAliveManifest.custom?.sanctuary26?.data_version != 4 || itsAliveManifest.custom?.sanctuary26?.network_protocol != 4 - || release.pack_version != "26.2.0-alpha.225" - || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.225.mrpack" - || prism.versionId != "26.2.0-alpha.225" - || !packwiz.contains('version = "26.2.0-alpha.225"') + || release.pack_version != "26.2.0-alpha.226" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.226.mrpack" + || prism.versionId != "26.2.0-alpha.226" + || !packwiz.contains('version = "26.2.0-alpha.226"') || !packwizIndex.contains('file = "mods/itsalive-0.0.0-alpha.38.jar"')) { throw new GradleException("The alpha.198 fermentation barrel release contract is incomplete") } @@ -4769,9 +4769,9 @@ tasks.register("verifyQuestRequestContractsRelease") { def packwiz = file("pack/packwiz/pack.toml").text def packwizIndex = file("pack/packwiz/index.toml").text def sanctuaryManifest = new JsonSlurper().parse(file("sanctuary/src/main/resources/fabric.mod.json")) - if (rootProject.pack_version != "26.2.0-alpha.225" + if (rootProject.pack_version != "26.2.0-alpha.226" || rootProject.itsalive_version != "0.0.0-alpha.38" - || rootProject.sanctuary_version != "0.0.0-alpha.129" + || rootProject.sanctuary_version != "0.0.0-alpha.130" || migration.source?.pack_version != "26.2.0-alpha.198" || migration.source?.modules?.sanctuary != "0.0.0-alpha.114" || migration.target?.pack_version != "26.2.0-alpha.199" @@ -4782,13 +4782,13 @@ tasks.register("verifyQuestRequestContractsRelease") { || migration.quest_request_contracts?.right_click_shows_details_before_claim != true || migration.quest_request_contracts?.chat_accept_revalidates_distance_owner_sign_and_claim != true || migration.compatibility?.sanctuary_target_network_protocol != 20 - || sanctuaryManifest.custom?.sanctuary26?.network_protocol != 23 - || release.pack_version != "26.2.0-alpha.225" - || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.225.mrpack" - || prism.versionId != "26.2.0-alpha.225" - || !packwiz.contains('version = "26.2.0-alpha.225"') + || sanctuaryManifest.custom?.sanctuary26?.network_protocol != 24 + || release.pack_version != "26.2.0-alpha.226" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.226.mrpack" + || prism.versionId != "26.2.0-alpha.226" + || !packwiz.contains('version = "26.2.0-alpha.226"') || !packwizIndex.contains('file = "mods/itsalive-0.0.0-alpha.38.jar"') - || !packwizIndex.contains('file = "mods/sanctuary-0.0.0-alpha.129.jar"')) { + || !packwizIndex.contains('file = "mods/sanctuary-0.0.0-alpha.130.jar"')) { throw new GradleException("The alpha.199 quest-request contract release is incomplete") } } @@ -4824,7 +4824,7 @@ tasks.register("verifyWeatherTntAmbianceRelease") { def ambianceManifest = new JsonSlurper().parse(file("ambiance/src/main/resources/fabric.mod.json")) def ouchManifest = new JsonSlurper().parse(file("ouch/src/main/resources/fabric.mod.json")) def rootBuild = file("build.gradle").text - if (rootProject.pack_version != "26.2.0-alpha.225" + if (rootProject.pack_version != "26.2.0-alpha.226" || rootProject.ambiance_version != "0.0.0-alpha.22" || rootProject.ouch_version != "0.0.0-alpha.11" || migration.source?.pack_version != "26.2.0-alpha.199" @@ -4858,10 +4858,10 @@ tasks.register("verifyWeatherTntAmbianceRelease") { || !weatherTnt.contains("AmbianceDailyWeather.CLEAR") || !weatherTnt.contains("CLEAR_WEATHER_TICKS = 864_000") || weatherTnt.contains("setWeatherParameters") - || release.pack_version != "26.2.0-alpha.225" - || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.225.mrpack" - || prism.versionId != "26.2.0-alpha.225" - || !packwiz.contains('version = "26.2.0-alpha.225"') + || release.pack_version != "26.2.0-alpha.226" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.226.mrpack" + || prism.versionId != "26.2.0-alpha.226" + || !packwiz.contains('version = "26.2.0-alpha.226"') || !packwizIndex.contains('file = "mods/ambiance-0.0.0-alpha.22.jar"') || !packwizIndex.contains('file = "mods/ouch-0.0.0-alpha.11.jar"')) { throw new GradleException("The alpha.200 Weather TNT and Ambiance release is incomplete") @@ -4890,8 +4890,8 @@ tasks.register("verifyQuestRequestEscrowRelease") { def packwiz = file("pack/packwiz/pack.toml").text def packwizIndex = file("pack/packwiz/index.toml").text def sanctuaryManifest = new JsonSlurper().parse(file("sanctuary/src/main/resources/fabric.mod.json")) - if (rootProject.pack_version != "26.2.0-alpha.225" - || rootProject.sanctuary_version != "0.0.0-alpha.129" + if (rootProject.pack_version != "26.2.0-alpha.226" + || rootProject.sanctuary_version != "0.0.0-alpha.130" || migration.source?.pack_version != "26.2.0-alpha.200" || migration.source?.modules?.sanctuary != "0.0.0-alpha.115" || migration.target?.pack_version != "26.2.0-alpha.201" @@ -4904,12 +4904,12 @@ tasks.register("verifyQuestRequestEscrowRelease") { || migration.quest_request_escrow?.reward_delivery_to_claimant_mailbox != true || migration.compatibility?.sanctuary_target_network_protocol != 21 || sanctuaryManifest.custom?.sanctuary26?.data_version != 13 - || sanctuaryManifest.custom?.sanctuary26?.network_protocol != 23 - || release.pack_version != "26.2.0-alpha.225" - || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.225.mrpack" - || prism.versionId != "26.2.0-alpha.225" - || !packwiz.contains('version = "26.2.0-alpha.225"') - || !packwizIndex.contains('file = "mods/sanctuary-0.0.0-alpha.129.jar"')) { + || sanctuaryManifest.custom?.sanctuary26?.network_protocol != 24 + || release.pack_version != "26.2.0-alpha.226" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.226.mrpack" + || prism.versionId != "26.2.0-alpha.226" + || !packwiz.contains('version = "26.2.0-alpha.226"') + || !packwizIndex.contains('file = "mods/sanctuary-0.0.0-alpha.130.jar"')) { throw new GradleException("The alpha.201 quest-request escrow release is incomplete") } } @@ -4944,11 +4944,11 @@ tasks.register("verifyWaystoneShopCulinaryAlpha202Release") { "iliketomoveit/src/main/resources/fabric.mod.json")) def sanctuaryManifest = new JsonSlurper().parse(file( "sanctuary/src/main/resources/fabric.mod.json")) - if (rootProject.pack_version != "26.2.0-alpha.225" + if (rootProject.pack_version != "26.2.0-alpha.226" || rootProject.anotherworld_version != "0.0.0-alpha.56" || rootProject.itsalive_version != "0.0.0-alpha.38" || rootProject.iliketomoveit_version != "0.0.0-alpha.18" - || rootProject.sanctuary_version != "0.0.0-alpha.129" + || rootProject.sanctuary_version != "0.0.0-alpha.130" || migration.source?.pack_version != "26.2.0-alpha.201" || migration.source?.modules != [ itsalive: "0.0.0-alpha.30", @@ -4983,15 +4983,15 @@ tasks.register("verifyWaystoneShopCulinaryAlpha202Release") { || moveItManifest.custom?.sanctuary26?.data_version != 4 || moveItManifest.custom?.sanctuary26?.network_protocol != 5 || sanctuaryManifest.custom?.sanctuary26?.data_version != 13 - || sanctuaryManifest.custom?.sanctuary26?.network_protocol != 23 - || release.pack_version != "26.2.0-alpha.225" - || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.225.mrpack" - || prism.versionId != "26.2.0-alpha.225" - || !packwiz.contains('version = "26.2.0-alpha.225"') + || sanctuaryManifest.custom?.sanctuary26?.network_protocol != 24 + || release.pack_version != "26.2.0-alpha.226" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.226.mrpack" + || prism.versionId != "26.2.0-alpha.226" + || !packwiz.contains('version = "26.2.0-alpha.226"') || !packwizIndex.contains('file = "mods/anotherworld-0.0.0-alpha.56.jar"') || !packwizIndex.contains('file = "mods/itsalive-0.0.0-alpha.38.jar"') || !packwizIndex.contains('file = "mods/iliketomoveit-0.0.0-alpha.18.jar"') - || !packwizIndex.contains('file = "mods/sanctuary-0.0.0-alpha.129.jar"')) { + || !packwizIndex.contains('file = "mods/sanctuary-0.0.0-alpha.130.jar"')) { throw new GradleException("The alpha.202 Waystone, Shop and culinary lectern release is incomplete") } } @@ -5104,9 +5104,9 @@ tasks.register("verifySafeVaultFeature") { def image = javax.imageio.ImageIO.read(file("anotherworld/src/main/resources/assets/anotherworld/textures/${path}")) image == null || image.width != size[0] || image.height != size[1] }.keySet() - if (rootProject.pack_version != "26.2.0-alpha.225" + if (rootProject.pack_version != "26.2.0-alpha.226" || rootProject.anotherworld_version != "0.0.0-alpha.56" - || rootProject.sanctuary_version != "0.0.0-alpha.129" + || rootProject.sanctuary_version != "0.0.0-alpha.130" || migration.schema_version != 1 || migration.source?.pack_version != "26.2.0-alpha.201" || migration.target?.pack_version != "26.2.0-alpha.202" @@ -5296,7 +5296,7 @@ tasks.register("verifySafeVaultInterfaceAlpha203Release") { def packwiz = file("pack/packwiz/pack.toml").text def packwizIndex = file("pack/packwiz/index.toml").text def jeiFiles = prism.files.findAll { it.path == "mods/jei-26.2-fabric-30.29.0.198.jar" } - if (rootProject.pack_version != "26.2.0-alpha.225" + if (rootProject.pack_version != "26.2.0-alpha.226" || rootProject.anotherworld_version != "0.0.0-alpha.56" || migration.source?.pack_version != "26.2.0-alpha.202" || migration.source?.modules != [anotherworld: "0.0.0-alpha.50"] @@ -5314,9 +5314,9 @@ tasks.register("verifySafeVaultInterfaceAlpha203Release") { || migration.distribution?.jei?.modrinth_version_id != "XXTFqqwG" || migration.distribution?.jei?.prism_manifest_updated != true || release.pack_version != rootProject.pack_version - || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.225.mrpack" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.226.mrpack" || prism.versionId != rootProject.pack_version - || !packwiz.contains('version = "26.2.0-alpha.225"') + || !packwiz.contains('version = "26.2.0-alpha.226"') || !packwizIndex.contains('file = "mods/anotherworld-0.0.0-alpha.56.jar"') || packwizIndex.contains('file = "mods/anotherworld-0.0.0-alpha.50.jar"') || jeiFiles.size() != 1 @@ -5342,7 +5342,7 @@ tasks.register("verifySafeVaultFixAlpha204Release") { def packwiz = file("pack/packwiz/pack.toml").text def packwizIndex = file("pack/packwiz/index.toml").text def jeiFiles = prism.files.findAll { it.path == "mods/jei-26.2-fabric-30.29.0.198.jar" } - if (rootProject.pack_version != "26.2.0-alpha.225" + if (rootProject.pack_version != "26.2.0-alpha.226" || rootProject.anotherworld_version != "0.0.0-alpha.56" || migration.source?.pack_version != "26.2.0-alpha.203" || migration.source?.modules != [anotherworld: "0.0.0-alpha.51"] @@ -5368,9 +5368,9 @@ tasks.register("verifySafeVaultFixAlpha204Release") { || migration.distribution?.jei?.modrinth_version_id != "OcMayhUH" || migration.distribution?.jei?.prism_manifest_updated != true || release.pack_version != rootProject.pack_version - || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.225.mrpack" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.226.mrpack" || prism.versionId != rootProject.pack_version - || !packwiz.contains('version = "26.2.0-alpha.225"') + || !packwiz.contains('version = "26.2.0-alpha.226"') || !packwizIndex.contains('file = "mods/anotherworld-0.0.0-alpha.56.jar"') || packwizIndex.contains('file = "mods/anotherworld-0.0.0-alpha.51.jar"') || jeiFiles.size() != 1 @@ -5396,7 +5396,7 @@ tasks.register("verifySafeVaultCubeAlpha205Release") { def packwiz = file("pack/packwiz/pack.toml").text def packwizIndex = file("pack/packwiz/index.toml").text def jeiFiles = prism.files.findAll { it.path == "mods/jei-26.2-fabric-30.29.0.198.jar" } - if (rootProject.pack_version != "26.2.0-alpha.225" + if (rootProject.pack_version != "26.2.0-alpha.226" || rootProject.anotherworld_version != "0.0.0-alpha.56" || migration.source?.pack_version != "26.2.0-alpha.204" || migration.source?.modules != [anotherworld: "0.0.0-alpha.52"] @@ -5425,9 +5425,9 @@ tasks.register("verifySafeVaultCubeAlpha205Release") { || migration.distribution?.jei?.modrinth_version_id != "NtfJDMhk" || migration.distribution?.jei?.prism_manifest_updated != true || release.pack_version != rootProject.pack_version - || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.225.mrpack" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.226.mrpack" || prism.versionId != rootProject.pack_version - || !packwiz.contains('version = "26.2.0-alpha.225"') + || !packwiz.contains('version = "26.2.0-alpha.226"') || !packwizIndex.contains('file = "mods/anotherworld-0.0.0-alpha.56.jar"') || packwizIndex.contains('file = "mods/anotherworld-0.0.0-alpha.52.jar"') || jeiFiles.size() != 1 @@ -5454,7 +5454,7 @@ tasks.register("verifySafeVaultCtmAlpha206Release") { def packwiz = file("pack/packwiz/pack.toml").text def packwizIndex = file("pack/packwiz/index.toml").text def jeiFiles = prism.files.findAll { it.path == "mods/jei-26.2-fabric-30.29.0.198.jar" } - if (rootProject.pack_version != "26.2.0-alpha.225" + if (rootProject.pack_version != "26.2.0-alpha.226" || rootProject.anotherworld_version != "0.0.0-alpha.56" || migration.source?.pack_version != "26.2.0-alpha.205" || migration.source?.modules != [anotherworld: "0.0.0-alpha.53"] @@ -5477,9 +5477,9 @@ tasks.register("verifySafeVaultCtmAlpha206Release") { || migration.compatibility?.pack_release_updated != true || migration.distribution?.packwiz_index_refreshed != true || release.pack_version != rootProject.pack_version - || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.225.mrpack" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.226.mrpack" || prism.versionId != rootProject.pack_version - || !packwiz.contains('version = "26.2.0-alpha.225"') + || !packwiz.contains('version = "26.2.0-alpha.226"') || !packwizIndex.contains('file = "mods/anotherworld-0.0.0-alpha.56.jar"') || packwizIndex.contains('file = "mods/anotherworld-0.0.0-alpha.53.jar"') || jeiFiles.size() != 1 @@ -5506,7 +5506,7 @@ tasks.register("verifySafeVaultUnlimitedAlpha207Release") { def packwiz = file("pack/packwiz/pack.toml").text def packwizIndex = file("pack/packwiz/index.toml").text def jeiFiles = prism.files.findAll { it.path == "mods/jei-26.2-fabric-30.29.0.198.jar" } - if (rootProject.pack_version != "26.2.0-alpha.225" + if (rootProject.pack_version != "26.2.0-alpha.226" || rootProject.anotherworld_version != "0.0.0-alpha.56" || migration.source?.pack_version != "26.2.0-alpha.206" || migration.source?.modules != [anotherworld: "0.0.0-alpha.54"] @@ -5536,9 +5536,9 @@ tasks.register("verifySafeVaultUnlimitedAlpha207Release") { || migration.compatibility?.pack_release_updated != true || migration.distribution?.packwiz_index_refreshed != true || release.pack_version != rootProject.pack_version - || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.225.mrpack" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.226.mrpack" || prism.versionId != rootProject.pack_version - || !packwiz.contains('version = "26.2.0-alpha.225"') + || !packwiz.contains('version = "26.2.0-alpha.226"') || !packwizIndex.contains('file = "mods/anotherworld-0.0.0-alpha.56.jar"') || packwizIndex.contains('file = "mods/anotherworld-0.0.0-alpha.54.jar"') || jeiFiles.size() != 1 @@ -5594,7 +5594,7 @@ tasks.register("verifyCanapliaFoundation") { "itsalive/src/main/java/fr/koka99cab/sanctuary26/itsalive/ItsAliveMod.java").text def visualApiSource = file( "ambiance/src/main/java/fr/koka99cab/sanctuary26/ambiance/api/visual/AmbianceVisualEffectApi.java").text - if (rootProject.pack_version != "26.2.0-alpha.225" + if (rootProject.pack_version != "26.2.0-alpha.226" || rootProject.itsalive_version != "0.0.0-alpha.38" || rootProject.ambiance_version != "0.0.0-alpha.22" || migration.issue != 35 @@ -5846,7 +5846,7 @@ tasks.register("verifyCanapliaAlpha209Release") { ambiance: "0.0.0-alpha.14", itsalive: "0.0.0-alpha.33", onlyfun: "0.0.0-alpha.20"] - if (rootProject.pack_version != "26.2.0-alpha.225" + if (rootProject.pack_version != "26.2.0-alpha.226" || rootProject.ambiance_version != "0.0.0-alpha.22" || rootProject.itsalive_version != "0.0.0-alpha.38" || rootProject.onlyfun_version != "0.0.0-alpha.27" @@ -5894,9 +5894,9 @@ tasks.register("verifyCanapliaAlpha209Release") { || fixMigration.compatibility?.network_protocol_changed != false || fixMigration.distribution?.pack_release_updated != true || release.pack_version != rootProject.pack_version - || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.225.mrpack" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.226.mrpack" || prism.versionId != rootProject.pack_version - || !packwiz.contains('version = "26.2.0-alpha.225"') + || !packwiz.contains('version = "26.2.0-alpha.226"') || !packwizIndex.contains('file = "mods/ambiance-0.0.0-alpha.22.jar"') || !packwizIndex.contains('file = "mods/itsalive-0.0.0-alpha.38.jar"') || !packwizIndex.contains('file = "mods/onlyfun-0.0.0-alpha.27.jar"') @@ -5948,7 +5948,7 @@ tasks.register("verifyAlpha210Release") { itsalive: "0.0.0-alpha.35"] def currentModules = [ ambiance: "0.0.0-alpha.22", - sanctuary: "0.0.0-alpha.129", + sanctuary: "0.0.0-alpha.130", onlyfun: "0.0.0-alpha.27", ouch: "0.0.0-alpha.11", masterkey: "0.0.0-alpha.9", @@ -5965,8 +5965,8 @@ tasks.register("verifyAlpha210Release") { def jeiFiles = prism.files.findAll { it.path == "mods/jei-26.2-fabric-30.29.0.198.jar" } - if (rootProject.pack_version != "26.2.0-alpha.225" - || rootProject.sanctuary_version != "0.0.0-alpha.129" + if (rootProject.pack_version != "26.2.0-alpha.226" + || rootProject.sanctuary_version != "0.0.0-alpha.130" || rootProject.onlyfun_version != "0.0.0-alpha.27" || rootProject.iliketomoveit_version != "0.0.0-alpha.18" || rootProject.itsalive_version != "0.0.0-alpha.38" @@ -6004,17 +6004,17 @@ tasks.register("verifyAlpha210Release") { || migration.distribution?.jei?.modrinth_version_id != "qaCQ7LGO" || migration.distribution?.jei?.packwiz_and_prism_synchronized != true || manifests.sanctuary.custom?.sanctuary26?.data_version != 13 - || manifests.sanctuary.custom?.sanctuary26?.network_protocol != 23 + || manifests.sanctuary.custom?.sanctuary26?.network_protocol != 24 || manifests.onlyfun.custom?.sanctuary26?.data_version != 2 || manifests.onlyfun.custom?.sanctuary26?.network_protocol != 3 || manifests.iliketomoveit.custom?.sanctuary26?.data_version != 4 || manifests.iliketomoveit.custom?.sanctuary26?.network_protocol != 5 || manifests.itsalive.custom?.sanctuary26?.data_version != 4 || manifests.itsalive.custom?.sanctuary26?.network_protocol != 4 - || release.pack_version != "26.2.0-alpha.225" - || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.225.mrpack" - || prism.versionId != "26.2.0-alpha.225" - || !packwiz.contains('version = "26.2.0-alpha.225"') + || release.pack_version != "26.2.0-alpha.226" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.226.mrpack" + || prism.versionId != "26.2.0-alpha.226" + || !packwiz.contains('version = "26.2.0-alpha.226"') || requiredJars.any { !packwizIndex.contains(it) } || obsoleteJars.any { packwizIndex.contains(it) } || jeiFiles.size() != 1 @@ -6061,7 +6061,7 @@ tasks.register("verifyAlpha211Release") { ouch: "0.0.0-alpha.10", sanctuary: "0.0.0-alpha.119"] def currentModules = expectedTarget + [ - sanctuary: "0.0.0-alpha.129", + sanctuary: "0.0.0-alpha.130", onlyfun: "0.0.0-alpha.27", ambiance: "0.0.0-alpha.22", iliketomoveit: "0.0.0-alpha.18", @@ -6072,7 +6072,7 @@ tasks.register("verifyAlpha211Release") { def expectedDataVersions = [ambiance: 2, itsalive: 3, onlyfun: 2, ouch: 1, sanctuary: 11] def workspaceDataVersions = [ambiance: 2, itsalive: 4, onlyfun: 2, ouch: 1, sanctuary: 13] def expectedProtocols = [ambiance: 6, itsalive: 4, onlyfun: 3, ouch: 1, sanctuary: 22] - def workspaceProtocols = expectedProtocols + [sanctuary: 23] + def workspaceProtocols = expectedProtocols + [sanctuary: 24] def manifests = expectedTarget.collectEntries { id, version -> [(id): new JsonSlurper().parse(file("${id}/src/main/resources/fabric.mod.json"))] } @@ -6095,7 +6095,7 @@ tasks.register("verifyAlpha211Release") { def jeiFiles = prism.files.findAll { it.path == "mods/jei-26.2-fabric-30.29.0.198.jar" } - if (rootProject.pack_version != "26.2.0-alpha.225" + if (rootProject.pack_version != "26.2.0-alpha.226" || workspaceModules.any { id, version -> rootProject.property("${id}_version") != version } || migration.source?.pack_version != "26.2.0-alpha.210" || migration.source?.modules != expectedSource @@ -6123,9 +6123,9 @@ tasks.register("verifyAlpha211Release") { || migration.distribution?.prism_modrinth_index_updated != true || migration.distribution?.shared_client_server_mrpack != true || release.pack_version != rootProject.pack_version - || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.225.mrpack" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.226.mrpack" || prism.versionId != rootProject.pack_version - || !packwiz.contains('version = "26.2.0-alpha.225"') + || !packwiz.contains('version = "26.2.0-alpha.226"') || requiredJars.any { !packwizIndex.contains(it) } || obsoleteJars.any { packwizIndex.contains(it) } || prism.files?.size() != 5 @@ -6133,7 +6133,7 @@ tasks.register("verifyAlpha211Release") { || jeiFiles[0].hashes?.sha1 != "652e964c71a699fdfdd96cda265ea703b13c6ef4" || jeiFiles[0].hashes?.sha512 != "06131c9528549840e07ddc9634e23454cd454380d7749a23d818f0efe0dacc02874e967ceb74a24ee82efb13e0fe2df4026f988a68f54f890586967e91dcaa5b" || !changelog.contains("## `26.2.0-alpha.211`") - || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.225`**")) { + || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.226`**")) { throw new GradleException("The alpha.211 Abjection and gameplay-polish release is incomplete") } } @@ -6167,8 +6167,8 @@ tasks.register("verifyAlpha212Release") { def jeiFiles = prism.files.findAll { it.path == "mods/jei-26.2-fabric-30.29.0.198.jar" } - if (rootProject.pack_version != "26.2.0-alpha.225" - || rootProject.sanctuary_version != "0.0.0-alpha.129" + if (rootProject.pack_version != "26.2.0-alpha.226" + || rootProject.sanctuary_version != "0.0.0-alpha.130" || migration.source?.pack_version != "26.2.0-alpha.211" || migration.source?.modules != [sanctuary: "0.0.0-alpha.119"] || migration.target?.pack_version != "26.2.0-alpha.212" @@ -6187,18 +6187,18 @@ tasks.register("verifyAlpha212Release") { || migration.distribution?.prism_modrinth_index_updated != true || migration.distribution?.shared_client_server_mrpack != true || manifest.custom?.sanctuary26?.data_version != 13 - || manifest.custom?.sanctuary26?.network_protocol != 23 + || manifest.custom?.sanctuary26?.network_protocol != 24 || !minecraftMixin.contains('method = "pickBlockOrEntity"') - || release.pack_version != "26.2.0-alpha.225" - || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.225.mrpack" - || prism.versionId != "26.2.0-alpha.225" + || release.pack_version != "26.2.0-alpha.226" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.226.mrpack" + || prism.versionId != "26.2.0-alpha.226" || prism.files?.size() != 5 || jeiFiles.size() != 1 - || !packwiz.contains('version = "26.2.0-alpha.225"') - || !packwizIndex.contains('file = "mods/sanctuary-0.0.0-alpha.129.jar"') + || !packwiz.contains('version = "26.2.0-alpha.226"') + || !packwizIndex.contains('file = "mods/sanctuary-0.0.0-alpha.130.jar"') || packwizIndex.contains('file = "mods/sanctuary-0.0.0-alpha.119.jar"') || !changelog.contains("## `26.2.0-alpha.212`") - || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.225`**")) { + || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.226`**")) { throw new GradleException("The alpha.212 Black Market startup-fix release is incomplete") } } @@ -6232,7 +6232,7 @@ tasks.register("verifyAlpha213Release") { def jeiFiles = prism.files.findAll { it.path == "mods/jei-26.2-fabric-30.29.0.198.jar" } - if (rootProject.pack_version != "26.2.0-alpha.225" + if (rootProject.pack_version != "26.2.0-alpha.226" || rootProject.ambiance_version != "0.0.0-alpha.22" || migration.source?.pack_version != "26.2.0-alpha.212" || migration.source?.modules != [ambiance: "0.0.0-alpha.15"] @@ -6256,16 +6256,16 @@ tasks.register("verifyAlpha213Release") { || manifest.custom?.sanctuary26?.network_protocol != 6 || !levelEventMixin.contains('@Mixin(LevelEventHandler.class)') || !levelEventMixin.contains('@Inject(method = "levelEvent"') - || release.pack_version != "26.2.0-alpha.225" - || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.225.mrpack" - || prism.versionId != "26.2.0-alpha.225" + || release.pack_version != "26.2.0-alpha.226" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.226.mrpack" + || prism.versionId != "26.2.0-alpha.226" || prism.files?.size() != 5 || jeiFiles.size() != 1 - || !packwiz.contains('version = "26.2.0-alpha.225"') + || !packwiz.contains('version = "26.2.0-alpha.226"') || !packwizIndex.contains('file = "mods/ambiance-0.0.0-alpha.22.jar"') || packwizIndex.contains('file = "mods/ambiance-0.0.0-alpha.15.jar"') || !changelog.contains("## `26.2.0-alpha.213`") - || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.225`**")) { + || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.226`**")) { throw new GradleException("The alpha.213 Ambiance startup-fix release is incomplete") } } @@ -6300,7 +6300,7 @@ tasks.register("verifyAlpha214Release") { "ambiance/src/main/java/fr/koka99cab/sanctuary26/ambiance/client/audio/WhiteDiscAudioPlayer.java").text def urlSmoke = file( "ambiance/src/test/java/fr/koka99cab/sanctuary26/ambiance/white_disc/WhiteDiscUrlSmoke.java").text - if (rootProject.pack_version != "26.2.0-alpha.225" + if (rootProject.pack_version != "26.2.0-alpha.226" || rootProject.ambiance_version != "0.0.0-alpha.22" || migration.source?.pack_version != "26.2.0-alpha.213" || migration.source?.modules != [ambiance: "0.0.0-alpha.16"] @@ -6329,16 +6329,16 @@ tasks.register("verifyAlpha214Release") { || !audioPlayer.contains('message.ambiance.white_disc.loading') || !audioPlayer.contains('message.ambiance.white_disc.failed') || !urlSmoke.contains("https://youtu.be/Ue5ZBe-GzSM?si=78LSbtBQzUYzhA2Y") - || release.pack_version != "26.2.0-alpha.225" - || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.225.mrpack" - || prism.versionId != "26.2.0-alpha.225" + || release.pack_version != "26.2.0-alpha.226" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.226.mrpack" + || prism.versionId != "26.2.0-alpha.226" || prism.files?.size() != 5 - || !packwiz.contains('version = "26.2.0-alpha.225"') + || !packwiz.contains('version = "26.2.0-alpha.226"') || !packwizIndex.contains('file = "mods/ambiance-0.0.0-alpha.22.jar"') || packwizIndex.contains('file = "mods/ambiance-0.0.0-alpha.16.jar"') || !changelog.contains("## `26.2.0-alpha.214`") || changelog.contains("## Modifications non distribuées") - || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.225`**")) { + || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.226`**")) { throw new GradleException("The alpha.214 white-disc solo synchronization release is incomplete") } } @@ -6379,7 +6379,7 @@ tasks.register("verifyAlpha215Release") { "ambiance/src/main/java/fr/koka99cab/sanctuary26/ambiance/client/audio/LavaplayerAudioStream.java").text def playbackSmoke = file( "ambiance/src/test/java/fr/koka99cab/sanctuary26/ambiance/client/audio/WhiteDiscPlaybackSmoke.java").text - if (rootProject.pack_version != "26.2.0-alpha.225" + if (rootProject.pack_version != "26.2.0-alpha.226" || rootProject.ambiance_version != "0.0.0-alpha.22" || migration.source?.pack_version != "26.2.0-alpha.214" || migration.source?.modules != [ambiance: "0.0.0-alpha.17"] @@ -6419,16 +6419,16 @@ tasks.register("verifyAlpha215Release") { || !playbackSmoke.contains("https://www.youtube.com/watch?v=Ue5ZBe-GzSM") || !playbackSmoke.contains("stream.paddedSilenceBytes() != 0L") || !playbackSmoke.contains("stream.decodedTimelineMillis() != 4_000L") - || release.pack_version != "26.2.0-alpha.225" - || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.225.mrpack" - || prism.versionId != "26.2.0-alpha.225" + || release.pack_version != "26.2.0-alpha.226" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.226.mrpack" + || prism.versionId != "26.2.0-alpha.226" || prism.files?.size() != 5 - || !packwiz.contains('version = "26.2.0-alpha.225"') + || !packwiz.contains('version = "26.2.0-alpha.226"') || !packwizIndex.contains('file = "mods/ambiance-0.0.0-alpha.22.jar"') || packwizIndex.contains('file = "mods/ambiance-0.0.0-alpha.17.jar"') || !changelog.contains("## `26.2.0-alpha.215`") || changelog.contains("## Modifications non distribuées") - || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.225`**")) { + || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.226`**")) { throw new GradleException("The alpha.215 resilient white-disc playback release is incomplete") } } @@ -6473,7 +6473,7 @@ tasks.register("verifyAlpha216Release") { "ambiance/src/test/java/fr/koka99cab/sanctuary26/ambiance/client/audio/LavaplayerAudioStreamSmoke.java").text def playbackSmoke = file( "ambiance/src/test/java/fr/koka99cab/sanctuary26/ambiance/client/audio/WhiteDiscPlaybackSmoke.java").text - if (rootProject.pack_version != "26.2.0-alpha.225" + if (rootProject.pack_version != "26.2.0-alpha.226" || rootProject.ambiance_version != "0.0.0-alpha.22" || migration.source?.pack_version != "26.2.0-alpha.215" || migration.source?.modules != [ambiance: "0.0.0-alpha.18"] @@ -6517,16 +6517,16 @@ tasks.register("verifyAlpha216Release") { || !playbackSmoke.contains("stream.paddedSilenceBytes() != 0L") || !playbackSmoke.contains("stream.decodedTimelineMillis() != 4_000L") || !playbackSmoke.contains("LavaplayerAudioStream.SAMPLE_RATE * 2 * 4") - || release.pack_version != "26.2.0-alpha.225" - || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.225.mrpack" - || prism.versionId != "26.2.0-alpha.225" + || release.pack_version != "26.2.0-alpha.226" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.226.mrpack" + || prism.versionId != "26.2.0-alpha.226" || prism.files?.size() != 5 - || !packwiz.contains('version = "26.2.0-alpha.225"') + || !packwiz.contains('version = "26.2.0-alpha.226"') || !packwizIndex.contains('file = "mods/ambiance-0.0.0-alpha.22.jar"') || packwizIndex.contains('file = "mods/ambiance-0.0.0-alpha.18.jar"') || !changelog.contains("## `26.2.0-alpha.216`") || changelog.contains("## Modifications non distribuées") - || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.225`**")) { + || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.226`**")) { throw new GradleException("The alpha.216 white-disc audio-quality release is incomplete") } } @@ -6561,7 +6561,7 @@ tasks.register("verifyAlpha217Release") { "ambiance/src/main/java/fr/koka99cab/sanctuary26/ambiance/client/audio/WhiteDiscAudioPlayer.java").text def streamSmoke = file( "ambiance/src/test/java/fr/koka99cab/sanctuary26/ambiance/client/audio/LavaplayerAudioStreamSmoke.java").text - if (rootProject.pack_version != "26.2.0-alpha.225" + if (rootProject.pack_version != "26.2.0-alpha.226" || rootProject.ambiance_version != "0.0.0-alpha.22" || migration.source?.pack_version != "26.2.0-alpha.216" || migration.source?.modules != [ambiance: "0.0.0-alpha.19"] @@ -6592,16 +6592,16 @@ tasks.register("verifyAlpha217Release") { || !audioPlayer.contains("PLAYBACK_PITCH = 1.0F") || audioPlayer.count("channel.setPitch(PLAYBACK_PITCH)") != 2 || !streamSmoke.contains("WhiteDiscAudioPlayer.PLAYBACK_PITCH - 1.0F") - || release.pack_version != "26.2.0-alpha.225" - || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.225.mrpack" - || prism.versionId != "26.2.0-alpha.225" + || release.pack_version != "26.2.0-alpha.226" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.226.mrpack" + || prism.versionId != "26.2.0-alpha.226" || prism.files?.size() != 5 - || !packwiz.contains('version = "26.2.0-alpha.225"') + || !packwiz.contains('version = "26.2.0-alpha.226"') || !packwizIndex.contains('file = "mods/ambiance-0.0.0-alpha.22.jar"') || packwizIndex.contains('file = "mods/ambiance-0.0.0-alpha.19.jar"') || !changelog.contains("## `26.2.0-alpha.217`") || changelog.contains("## Modifications non distribuées") - || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.225`**")) { + || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.226`**")) { throw new GradleException("The alpha.217 white-disc pitch release is incomplete") } } @@ -6649,7 +6649,7 @@ tasks.register("verifyAlpha218Release") { def targetModules = [ redstoner: "0.0.0-alpha.11", onlyfun: "0.0.0-alpha.25", sanctuary: "0.0.0-alpha.121"] def currentModules = targetModules + [redstoner: "0.0.0-alpha.13", - sanctuary: "0.0.0-alpha.129", onlyfun: "0.0.0-alpha.27", + sanctuary: "0.0.0-alpha.130", onlyfun: "0.0.0-alpha.27", iliketomoveit: "0.0.0-alpha.18", ambiance: "0.0.0-alpha.22", itsalive: "0.0.0-alpha.38", ouch: "0.0.0-alpha.11", masterkey: "0.0.0-alpha.9"] def requiredJars = currentModules.collect { id, version -> @@ -6658,7 +6658,7 @@ tasks.register("verifyAlpha218Release") { def obsoleteJars = sourceModules.collect { id, version -> "file = \"mods/${id}-${version}.jar\"" } - if (rootProject.pack_version != "26.2.0-alpha.225" + if (rootProject.pack_version != "26.2.0-alpha.226" || rootProject.redstoner_version != "0.0.0-alpha.13" || currentModules.findAll { id, version -> id != "redstoner" && id != "sanctuary" && id != "onlyfun" && id != "iliketomoveit" @@ -6667,7 +6667,7 @@ tasks.register("verifyAlpha218Release") { } || rootProject.onlyfun_version != "0.0.0-alpha.27" || rootProject.iliketomoveit_version != "0.0.0-alpha.18" - || rootProject.sanctuary_version != "0.0.0-alpha.129" + || rootProject.sanctuary_version != "0.0.0-alpha.130" || migration.source?.pack_version != "26.2.0-alpha.217" || migration.source?.modules != sourceModules || migration.target?.pack_version != "26.2.0-alpha.218" @@ -6692,20 +6692,20 @@ tasks.register("verifyAlpha218Release") { || manifests.onlyfun.custom?.sanctuary26?.data_version != 2 || manifests.onlyfun.custom?.sanctuary26?.network_protocol != 3 || manifests.sanctuary.custom?.sanctuary26?.data_version != 13 - || manifests.sanctuary.custom?.sanctuary26?.network_protocol != 23 + || manifests.sanctuary.custom?.sanctuary26?.network_protocol != 24 || !rules.contains("MAX_CONTAINERS = 128") || !rules.contains("PAGE_SIZE = 54") || !networking.contains("PROTOCOL_VERSION = 7") || !onlyFunPolicy.contains('namespace.equals("redstoner") && path.equals("storage_terminal")') || !blackMarketPolicy.contains('namespace.equals("redstoner") && path.equals("storage_terminal")') || release.pack_version != rootProject.pack_version - || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.225.mrpack" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.226.mrpack" || prism.versionId != rootProject.pack_version - || !packwiz.contains('version = "26.2.0-alpha.225"') + || !packwiz.contains('version = "26.2.0-alpha.226"') || requiredJars.any { !packwizIndex.contains(it) } || obsoleteJars.any { packwizIndex.contains(it) } || !changelog.contains("## `26.2.0-alpha.218`") - || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.225`**")) { + || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.226`**")) { throw new GradleException("The alpha.218 Storage Terminal release is incomplete") } } @@ -6750,7 +6750,7 @@ tasks.register("verifyAlpha219Release") { def targetModules = [ sanctuary: "0.0.0-alpha.122", iliketomoveit: "0.0.0-alpha.16", ambiance: "0.0.0-alpha.21"] def currentModules = targetModules + [ - ambiance: "0.0.0-alpha.22", sanctuary: "0.0.0-alpha.129", + ambiance: "0.0.0-alpha.22", sanctuary: "0.0.0-alpha.130", iliketomoveit: "0.0.0-alpha.18", onlyfun: "0.0.0-alpha.27", itsalive: "0.0.0-alpha.38", ouch: "0.0.0-alpha.11", masterkey: "0.0.0-alpha.9"] def workspaceModules = currentModules @@ -6768,7 +6768,7 @@ tasks.register("verifyAlpha219Release") { include "**/*golden*days*.zip", "**/*golden*days*.jar" exclude "**/build/**", "**/.gradle/**", "**/.git/**" }.files - if (rootProject.pack_version != "26.2.0-alpha.225" + if (rootProject.pack_version != "26.2.0-alpha.226" || workspaceModules.any { id, version -> rootProject.property("${id}_version") != version } || migration.source?.pack_version != "26.2.0-alpha.218" || migration.source?.modules != sourceModules @@ -6794,21 +6794,21 @@ tasks.register("verifyAlpha219Release") { || migration.compatibility?.ambiance_data_version != 2 || migration.compatibility?.ambiance_network_protocol != 6 || manifests.sanctuary.custom?.sanctuary26?.data_version != 13 - || manifests.sanctuary.custom?.sanctuary26?.network_protocol != 23 + || manifests.sanctuary.custom?.sanctuary26?.network_protocol != 24 || manifests.iliketomoveit.custom?.sanctuary26?.data_version != 4 || manifests.iliketomoveit.custom?.sanctuary26?.network_protocol != 5 || manifests.ambiance.custom?.sanctuary26?.data_version != 2 || manifests.ambiance.custom?.sanctuary26?.network_protocol != 6 || release.pack_version != rootProject.pack_version - || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.225.mrpack" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.226.mrpack" || prism.versionId != rootProject.pack_version || prism.files.any { it.path.toLowerCase().contains("golden-days") } - || !packwiz.contains('version = "26.2.0-alpha.225"') + || !packwiz.contains('version = "26.2.0-alpha.226"') || requiredJars.any { !packwizIndex.contains(it) } || obsoleteJars.any { packwizIndex.contains(it) } || !forbiddenGoldenArchives.isEmpty() || !changelog.contains("## `26.2.0-alpha.219`") - || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.225`**")) { + || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.226`**")) { throw new GradleException("The alpha.219 finite Alpha/Indev release is incomplete") } } @@ -6847,7 +6847,7 @@ tasks.register("verifyAlpha220Release") { "redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/client/gui/StorageTerminalScreen.java").text def networking = file( "redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/network/RedStonerNetworking.java").text - if (rootProject.pack_version != "26.2.0-alpha.225" + if (rootProject.pack_version != "26.2.0-alpha.226" || rootProject.redstoner_version != "0.0.0-alpha.13" || migration.source?.pack_version != "26.2.0-alpha.219" || migration.source?.modules != [redstoner: "0.0.0-alpha.11"] @@ -6888,13 +6888,13 @@ tasks.register("verifyAlpha220Release") { || networking.contains("storage_terminal_snapshot") || networking.contains("storage_terminal_action") || release.pack_version != rootProject.pack_version - || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.225.mrpack" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.226.mrpack" || prism.versionId != rootProject.pack_version - || !packwiz.contains('version = "26.2.0-alpha.225"') + || !packwiz.contains('version = "26.2.0-alpha.226"') || !packwizIndex.contains('file = "mods/redstoner-0.0.0-alpha.13.jar"') || packwizIndex.contains('file = "mods/redstoner-0.0.0-alpha.11.jar"') || !changelog.contains("## `26.2.0-alpha.220`") - || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.225`**")) { + || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.226`**")) { throw new GradleException("The alpha.220 Storage Terminal menu release is incomplete") } } @@ -6942,7 +6942,7 @@ tasks.register("verifyAlpha221Release") { def playbackSmoke = file( "ambiance/src/test/java/fr/koka99cab/sanctuary26/ambiance/client/audio/WhiteDiscPlaybackSmoke.java").text def contract = migration.white_disc_native_rate - if (rootProject.pack_version != "26.2.0-alpha.225" + if (rootProject.pack_version != "26.2.0-alpha.226" || rootProject.ambiance_version != "0.0.0-alpha.22" || migration.source?.pack_version != "26.2.0-alpha.220" || migration.source?.modules != [ambiance: "0.0.0-alpha.21"] @@ -6991,13 +6991,13 @@ tasks.register("verifyAlpha221Release") { || !playbackSmoke.contains("PCM cadence: 100%% speed") || !whiteDiscDocumentation.contains("48 000 Hz") || release.pack_version != rootProject.pack_version - || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.225.mrpack" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.226.mrpack" || prism.versionId != rootProject.pack_version - || !packwiz.contains('version = "26.2.0-alpha.225"') + || !packwiz.contains('version = "26.2.0-alpha.226"') || !packwizIndex.contains('file = "mods/ambiance-0.0.0-alpha.22.jar"') || packwizIndex.contains('file = "mods/ambiance-0.0.0-alpha.21.jar"') || !changelog.contains("## `26.2.0-alpha.221`") - || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.225`**")) { + || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.226`**")) { throw new GradleException("The alpha.221 native-rate white-disc release is incomplete") } } @@ -7076,9 +7076,9 @@ tasks.register("verifyAlpha222Release") { def jeiFiles = prism.files.findAll { it.path == "mods/jei-26.2-fabric-30.29.0.198.jar" } - if (rootProject.pack_version != "26.2.0-alpha.225" + if (rootProject.pack_version != "26.2.0-alpha.226" || rootProject.redstoner_version != "0.0.0-alpha.13" - || rootProject.sanctuary_version != "0.0.0-alpha.129" + || rootProject.sanctuary_version != "0.0.0-alpha.130" || migration.source?.pack_version != "26.2.0-alpha.221" || migration.source?.modules != [ redstoner: "0.0.0-alpha.12", sanctuary: "0.0.0-alpha.122"] @@ -7121,7 +7121,7 @@ tasks.register("verifyAlpha222Release") { || manifests.redstoner.custom?.sanctuary26?.data_version != 3 || manifests.redstoner.custom?.sanctuary26?.network_protocol != 7 || manifests.sanctuary.custom?.sanctuary26?.data_version != 13 - || manifests.sanctuary.custom?.sanctuary26?.network_protocol != 23 + || manifests.sanctuary.custom?.sanctuary26?.network_protocol != 24 || !rules.contains("MAX_SEARCH_LENGTH = 32") || !rules.contains("compactCount(int count)") || !layout.contains("Keeps terminal slot identities stable") @@ -7151,12 +7151,12 @@ tasks.register("verifyAlpha222Release") { || !questEditor.contains("QuestIdSuggestions.suggest") || !suggestions.contains("Normalizer.Form.NFD") || !suggestions.contains("public static final int LIMIT = 5") - || release.pack_version != "26.2.0-alpha.225" - || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.225.mrpack" - || prism.versionId != "26.2.0-alpha.225" - || !packwiz.contains('version = "26.2.0-alpha.225"') + || release.pack_version != "26.2.0-alpha.226" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.226.mrpack" + || prism.versionId != "26.2.0-alpha.226" + || !packwiz.contains('version = "26.2.0-alpha.226"') || !packwizIndex.contains('file = "mods/redstoner-0.0.0-alpha.13.jar"') - || !packwizIndex.contains('file = "mods/sanctuary-0.0.0-alpha.129.jar"') + || !packwizIndex.contains('file = "mods/sanctuary-0.0.0-alpha.130.jar"') || packwizIndex.contains('file = "mods/redstoner-0.0.0-alpha.12.jar"') || packwizIndex.contains('file = "mods/sanctuary-0.0.0-alpha.122.jar"') || !packwizJei.contains('filename = "jei-26.2-fabric-30.29.0.198.jar"') @@ -7165,7 +7165,7 @@ tasks.register("verifyAlpha222Release") { || jeiFiles[0].hashes?.sha1 != "652e964c71a699fdfdd96cda265ea703b13c6ef4" || jeiFiles[0].hashes?.sha512 != "06131c9528549840e07ddc9634e23454cd454380d7749a23d818f0efe0dacc02874e967ceb74a24ee82efb13e0fe2df4026f988a68f54f890586967e91dcaa5b" || !changelog.contains("## `26.2.0-alpha.222`") - || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.225`**")) { + || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.226`**")) { throw new GradleException("The alpha.222 terminal-search and quest-tracker release is incomplete") } } @@ -7235,8 +7235,8 @@ tasks.register("verifyAlpha223Release") { def jeiFiles = prism.files.findAll { it.path == "mods/jei-26.2-fabric-30.29.0.198.jar" } - if (rootProject.pack_version != "26.2.0-alpha.225" - || rootProject.sanctuary_version != "0.0.0-alpha.129" + if (rootProject.pack_version != "26.2.0-alpha.226" + || rootProject.sanctuary_version != "0.0.0-alpha.130" || migration.source?.pack_version != "26.2.0-alpha.222" || migration.source?.modules != [sanctuary: "0.0.0-alpha.124"] || migration.target?.pack_version != "26.2.0-alpha.223" @@ -7273,7 +7273,7 @@ tasks.register("verifyAlpha223Release") { || migration.distribution?.jei?.modrinth_version_id != "67Dvn8sL" || migration.distribution?.jei?.packwiz_and_prism_synchronized != true || manifest.custom?.sanctuary26?.data_version != 13 - || manifest.custom?.sanctuary26?.network_protocol != 23 + || manifest.custom?.sanctuary26?.network_protocol != 24 || !inventorySort.contains("COOLDOWN_TICKS = 8") || !inventorySort.contains("if (row == 0) continue") || !inventorySort.contains("SanctuaryInventorySorter.compactAndSort") @@ -7286,7 +7286,7 @@ tasks.register("verifyAlpha223Release") { || !inventorySort.contains("sortOpenContainer") || !inventorySort.contains("instanceof ChestMenu") || !networking.contains("SanctuaryInventorySort.sort(context.player(), payload.container())") - || !networking.contains("PROTOCOL_VERSION = 23") + || !networking.contains("PROTOCOL_VERSION = 24") || !displayMode.contains('TEXT("text")') || !displayMode.contains('PANEL("panel")') || !questHud.contains("renderText(") @@ -7300,11 +7300,11 @@ tasks.register("verifyAlpha223Release") { || !questSync.contains("case EMERALD -> 2") || !inventorySmoke.contains("Hotbar snapshot must remain untouched") || !displaySmoke.contains("QuestTrackerDisplayMode.PANEL.next()") - || release.pack_version != "26.2.0-alpha.225" - || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.225.mrpack" - || prism.versionId != "26.2.0-alpha.225" - || !packwiz.contains('version = "26.2.0-alpha.225"') - || !packwizIndex.contains('file = "mods/sanctuary-0.0.0-alpha.129.jar"') + || release.pack_version != "26.2.0-alpha.226" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.226.mrpack" + || prism.versionId != "26.2.0-alpha.226" + || !packwiz.contains('version = "26.2.0-alpha.226"') + || !packwizIndex.contains('file = "mods/sanctuary-0.0.0-alpha.130.jar"') || packwizIndex.contains('file = "mods/sanctuary-0.0.0-alpha.124.jar"') || !packwizJei.contains('filename = "jei-26.2-fabric-30.29.0.198.jar"') || !packwizJei.contains('version = "67Dvn8sL"') @@ -7312,7 +7312,7 @@ tasks.register("verifyAlpha223Release") { || jeiFiles[0].hashes?.sha1 != "652e964c71a699fdfdd96cda265ea703b13c6ef4" || jeiFiles[0].hashes?.sha512 != "06131c9528549840e07ddc9634e23454cd454380d7749a23d818f0efe0dacc02874e967ceb74a24ee82efb13e0fe2df4026f988a68f54f890586967e91dcaa5b" || !changelog.contains("## `26.2.0-alpha.223`") - || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.225`**")) { + || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.226`**")) { throw new GradleException("The alpha.223 inventory-sort and quest-tracker display release is incomplete") } } @@ -7356,7 +7356,7 @@ tasks.register("verifyAlpha224Release") { iliketomoveit: "0.0.0-alpha.17", onlyfun: "0.0.0-alpha.26", sanctuary: "0.0.0-alpha.128"] def currentModules = targetModules + [ itsalive: "0.0.0-alpha.38", iliketomoveit: "0.0.0-alpha.18", - onlyfun: "0.0.0-alpha.27", sanctuary: "0.0.0-alpha.129"] + onlyfun: "0.0.0-alpha.27", sanctuary: "0.0.0-alpha.130"] def inventorySort = file( "sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/gameplay/SanctuaryInventorySort.java").text def clientProgress = file( @@ -7375,7 +7375,7 @@ tasks.register("verifyAlpha224Release") { }.collect { id, version -> "file = \"mods/${id}-${version}.jar\"" } - if (rootProject.pack_version != "26.2.0-alpha.225" + if (rootProject.pack_version != "26.2.0-alpha.226" || currentModules.any { id, version -> rootProject.property("${id}_version") != version } || migration.status != "released" || migration.source?.pack_version != "26.2.0-alpha.223" @@ -7408,7 +7408,7 @@ tasks.register("verifyAlpha224Release") { || manifests.itsalive.custom?.sanctuary26?.data_version != 4 || manifests.iliketomoveit.custom?.sanctuary26?.data_version != 4 || manifests.sanctuary.custom?.sanctuary26?.data_version != 13 - || manifests.sanctuary.custom?.sanctuary26?.network_protocol != 23 + || manifests.sanctuary.custom?.sanctuary26?.network_protocol != 24 || !inventorySort.contains("instanceof ChestMenu") || !inventorySort.contains("instanceof ShulkerBoxMenu") || !inventorySort.contains("instanceof HopperMenu") @@ -7417,15 +7417,15 @@ tasks.register("verifyAlpha224Release") { || !clientProgress.contains("SanctuaryHotbarRowsClient.requestVisualRow(client, 0, currentRows)") || !sortPayload.contains("buffer.writeBoolean(container)") || !sortPayload.contains("buffer.readBoolean()") - || !networking.contains("PROTOCOL_VERSION = 23") - || release.pack_version != "26.2.0-alpha.225" - || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.225.mrpack" - || prism.versionId != "26.2.0-alpha.225" - || !packwiz.contains('version = "26.2.0-alpha.225"') + || !networking.contains("PROTOCOL_VERSION = 24") + || release.pack_version != "26.2.0-alpha.226" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.226.mrpack" + || prism.versionId != "26.2.0-alpha.226" + || !packwiz.contains('version = "26.2.0-alpha.226"') || requiredJars.any { !packwizIndex.contains(it) } || obsoleteJars.any { packwizIndex.contains(it) } || !changelog.contains("## `26.2.0-alpha.224`") - || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.225`**")) { + || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.226`**")) { throw new GradleException("The alpha.224 Notch, Magic Carpet and container-sort release is incomplete") } } @@ -7476,6 +7476,7 @@ tasks.register("verifyAlpha225Release") { anotherworld: "0.0.0-alpha.56", itsalive: "0.0.0-alpha.38", iliketomoveit: "0.0.0-alpha.18", onlyfun: "0.0.0-alpha.27", sanctuary: "0.0.0-alpha.129"] + def currentModules = targetModules + [sanctuary: "0.0.0-alpha.130"] def workspaceModules = moduleIds.collectEntries { id -> [(id): project(":${id}").version.toString()] } @@ -7516,8 +7517,8 @@ tasks.register("verifyAlpha225Release") { "iliketomoveit/src/main/resources/assets/iliketomoveit/textures/item/magic_carpet.png") def carpetTextureHash = MessageDigest.getInstance("SHA-256") .digest(carpetTexture.bytes).encodeHex().toString() - if (rootProject.pack_version != "26.2.0-alpha.225" - || targetModules.any { id, version -> rootProject.property("${id}_version") != version } + if (rootProject.pack_version != "26.2.0-alpha.226" + || currentModules.any { id, version -> rootProject.property("${id}_version") != version } || migration.status != "released" || migration.source?.pack_version != "26.2.0-alpha.224" || migration.source?.modules != sourceModules @@ -7569,19 +7570,134 @@ tasks.register("verifyAlpha225Release") { || !lootboxes.contains("SanctuaryEntityPolicy.isTemporaryCompanion") || carpetModel.textures?.layer0 != "iliketomoveit:item/magic_carpet" || carpetTextureHash != "3e4527d24a37f0632b27d2c857b047c581db07eaa41befaffbf28043a8ed86cc" - || release.pack_version != "26.2.0-alpha.225" - || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.225.mrpack" - || prism.versionId != "26.2.0-alpha.225" - || !packwiz.contains('version = "26.2.0-alpha.225"') + || release.pack_version != "26.2.0-alpha.226" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.226.mrpack" + || prism.versionId != "26.2.0-alpha.226" + || !packwiz.contains('version = "26.2.0-alpha.226"') || requiredJars.any { !packwizIndex.contains(it) } || obsoleteJars.any { packwizIndex.contains(it) } || !changelog.contains("## `26.2.0-alpha.225`") - || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.225`**")) { + || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.226`**")) { throw new GradleException("The alpha.225 four-ticket bug-fix release is incomplete") } } } +tasks.register("verifyAlpha226Release") { + group = "verification" + description = "Checks the Sanctuary 26.2.0-alpha.226 craftable banner cape release." + inputs.file(file("pack/migrations/26.2.0-alpha.225-craftable-banner-cape-to-alpha.226.json")) + inputs.file(file("pack/release.json")) + inputs.file(file("pack/prism/modrinth.index.json")) + inputs.file(file("pack/packwiz/pack.toml")) + inputs.file(file("pack/packwiz/index.toml")) + inputs.file(file("CHANGELOG.md")) + inputs.file(file("README.md")) + inputs.file(file("sanctuary/src/main/resources/fabric.mod.json")) + inputs.file(file("sanctuary/src/main/resources/data/sanctuary/recipe/white_cape.json")) + inputs.file(file("sanctuary/src/main/resources/data/sanctuary/recipe/white_cape_banner.json")) + inputs.file(file("sanctuary/src/main/resources/assets/sanctuary/items/white_cape.json")) + inputs.files(fileTree("sanctuary/src/main/resources/assets/sanctuary/lang") { include "*.json" }) + inputs.files( + file("sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/gameplay/SanctuaryCapes.java"), + file("sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/network/CapeSyncPayload.java"), + file("sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/network/SanctuaryNetworking.java"), + file("sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/client/SanctuaryBannerCapeLayer.java"), + file("sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/mixin/client/AvatarRendererMixin.java"), + file("onlyfun/src/main/java/fr/koka99cab/sanctuary26/onlyfun/loot/OnlyFunGenerator.java")) + doLast { + def migration = new JsonSlurper().parse(file( + "pack/migrations/26.2.0-alpha.225-craftable-banner-cape-to-alpha.226.json")) + def release = new JsonSlurper().parse(file("pack/release.json")) + def prism = new JsonSlurper().parse(file("pack/prism/modrinth.index.json")) + def packwiz = file("pack/packwiz/pack.toml").text + def packwizIndex = file("pack/packwiz/index.toml").text + def changelog = file("CHANGELOG.md").text + def readme = file("README.md").text + def manifest = new JsonSlurper().parse(file("sanctuary/src/main/resources/fabric.mod.json")) + def baseRecipe = new JsonSlurper().parse(file( + "sanctuary/src/main/resources/data/sanctuary/recipe/white_cape.json")) + def bannerRecipe = new JsonSlurper().parse(file( + "sanctuary/src/main/resources/data/sanctuary/recipe/white_cape_banner.json")) + def itemDefinition = new JsonSlurper().parse(file( + "sanctuary/src/main/resources/assets/sanctuary/items/white_cape.json")) + def locales = ["fr_fr", "en_us", "ru_ru"].collect { + new JsonSlurper().parse(file("sanctuary/src/main/resources/assets/sanctuary/lang/${it}.json")) + } + def capes = file( + "sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/gameplay/SanctuaryCapes.java").text + def payload = file( + "sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/network/CapeSyncPayload.java").text + def networking = file( + "sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/network/SanctuaryNetworking.java").text + def renderer = file( + "sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/client/SanctuaryBannerCapeLayer.java").text + def avatarMixin = file( + "sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/mixin/client/AvatarRendererMixin.java").text + def onlyFun = file( + "onlyfun/src/main/java/fr/koka99cab/sanctuary26/onlyfun/loot/OnlyFunGenerator.java").text + def workspaceModules = moduleIds.collectEntries { id -> + [(id): project(":${id}").version.toString()] + } + def requiredJars = workspaceModules.collect { id, version -> + "file = \"mods/${id}-${version}.jar\"" + } + if (rootProject.pack_version != "26.2.0-alpha.226" + || rootProject.sanctuary_version != "0.0.0-alpha.130" + || migration.status != "released" + || migration.source?.pack_version != "26.2.0-alpha.225" + || migration.source?.modules != [sanctuary: "0.0.0-alpha.129"] + || migration.target?.pack_version != "26.2.0-alpha.226" + || migration.target?.modules != [sanctuary: "0.0.0-alpha.130"] + || migration.white_cape?.item_id != "sanctuary:white_cape" + || migration.white_cape?.crafting_material_count != 6 + || migration.white_cape?.maximum_pattern_layers != 6 + || migration.white_cape?.included_in_onlyfun_lootbox != false + || migration.compatibility?.sanctuary_data_version != 13 + || migration.compatibility?.sanctuary_source_network_protocol != 23 + || migration.compatibility?.sanctuary_target_network_protocol != 24 + || migration.compatibility?.sanctuary_network_protocol_changed != true + || migration.compatibility?.existing_saves_supported != true + || migration.compatibility?.new_world_required != false + || migration.compatibility?.save_reset_required != false + || manifest.custom?.sanctuary26?.data_version != 13 + || manifest.custom?.sanctuary26?.network_protocol != 24 + || baseRecipe.type != "minecraft:crafting_shaped" + || baseRecipe.pattern != ["WW", "WW", "WW"] + || baseRecipe.key?.W != "minecraft:white_wool" + || baseRecipe.result?.id != "sanctuary:white_cape" + || baseRecipe.result?.count != 1 + || bannerRecipe.type != "minecraft:crafting_special_shielddecoration" + || bannerRecipe.banner != "#minecraft:banners" + || bannerRecipe.target != "sanctuary:white_cape" + || bannerRecipe.result?.id != "sanctuary:white_cape" + || itemDefinition.model?.type != "minecraft:special" + || itemDefinition.model?.model?.type != "minecraft:banner" + || itemDefinition.model?.model?.color != "white" + || locales.any { !it.containsKey("item.sanctuary.white_cape") } + || !capes.contains('WHITE_CAPE_PATH = "white_cape"') + || !capes.contains("isBannerCape") + || !payload.contains("MAX_PATTERN_LAYERS = 6") + || !payload.contains("DataComponents.BASE_COLOR") + || !payload.contains("DataComponents.BANNER_PATTERNS") + || !networking.contains("PROTOCOL_VERSION = 24") + || !renderer.contains("BannerRenderer.submitPatterns") + || !renderer.contains("LivingEntityRenderLayerRegistrationCallback") + || !avatarMixin.contains("appearance.bannerCape()") + || onlyFun.contains('"white_cape"') + || release.pack_version != "26.2.0-alpha.226" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.226.mrpack" + || prism.versionId != "26.2.0-alpha.226" + || !packwiz.contains('version = "26.2.0-alpha.226"') + || requiredJars.any { !packwizIndex.contains(it) } + || packwizIndex.contains('file = "mods/sanctuary-0.0.0-alpha.129.jar"') + || !changelog.contains("## `26.2.0-alpha.226`") + || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.226`**")) { + throw new GradleException("The alpha.226 craftable banner cape release is incomplete") + } + } +} + tasks.named("verifyWorkspace") { dependsOn tasks.named("verifyAlpha213Release") dependsOn tasks.named("verifyAlpha214Release") @@ -7596,6 +7712,7 @@ tasks.named("verifyWorkspace") { dependsOn tasks.named("verifyAlpha223Release") dependsOn tasks.named("verifyAlpha224Release") dependsOn tasks.named("verifyAlpha225Release") + dependsOn tasks.named("verifyAlpha226Release") } tasks.named("check") { diff --git a/gradle.properties b/gradle.properties index 5e09187..06bbc13 100644 --- a/gradle.properties +++ b/gradle.properties @@ -28,7 +28,7 @@ iliketomoveit_version=0.0.0-alpha.18 iliketomoveit_lifecycle=active onlyfun_version=0.0.0-alpha.27 onlyfun_lifecycle=active -sanctuary_version=0.0.0-alpha.129 +sanctuary_version=0.0.0-alpha.130 sanctuary_lifecycle=active -pack_version=26.2.0-alpha.225 +pack_version=26.2.0-alpha.226 maven_group=fr.koka99cab.sanctuary26 diff --git a/pack/migrations/26.2.0-alpha.225-craftable-banner-cape-to-alpha.226.json b/pack/migrations/26.2.0-alpha.225-craftable-banner-cape-to-alpha.226.json new file mode 100644 index 0000000..3ddd5e2 --- /dev/null +++ b/pack/migrations/26.2.0-alpha.225-craftable-banner-cape-to-alpha.226.json @@ -0,0 +1,49 @@ +{ + "schema_version": 1, + "status": "released", + "source": { + "pack_version": "26.2.0-alpha.225", + "modules": { + "sanctuary": "0.0.0-alpha.129" + } + }, + "target": { + "pack_version": "26.2.0-alpha.226", + "modules": { + "sanctuary": "0.0.0-alpha.130" + } + }, + "white_cape": { + "owner": "sanctuary", + "item_id": "sanctuary:white_cape", + "crafting_material": "minecraft:white_wool", + "crafting_material_count": 6, + "crafting_pattern": ["WW", "WW", "WW"], + "banner_decoration_recipe": "cape_plus_banner", + "accepted_banners": "#minecraft:banners", + "base_color_preserved": true, + "maximum_pattern_layers": 6, + "inventory_pattern_rendering": true, + "equipped_pattern_rendering": true, + "vanilla_cape_physics": true, + "included_in_onlyfun_lootbox": false + }, + "compatibility": { + "existing_saves_supported": true, + "new_world_required": false, + "save_reset_required": false, + "registry_ids_added": ["sanctuary:white_cape"], + "persistent_data_formats_changed": false, + "sanctuary_data_version": 13, + "sanctuary_source_network_protocol": 23, + "sanctuary_target_network_protocol": 24, + "sanctuary_network_protocol_changed": true, + "client_server_update_required": true + }, + "distribution": { + "pack_release_updated": true, + "packwiz_index_refreshed": true, + "prism_modrinth_index_updated": true, + "shared_client_server_mrpack": true + } +} diff --git a/pack/packwiz/index.toml b/pack/packwiz/index.toml index e518c1d..5f8a939 100644 --- a/pack/packwiz/index.toml +++ b/pack/packwiz/index.toml @@ -14,15 +14,15 @@ hash = "41f4f4c88c71d0a23446d5014f7407d55ad477441847099cad24492b032335a0" [[files]] file = "mods/ambiance-0.0.0-alpha.22.jar" -hash = "d6c44f09ddc455ae0cec02a1568e07036f11a3b2d105659e9aa14289357ddb47" +hash = "0e862db1c5efb5c0745b82f991d5480f4305822c3d3f53ed38e2d2d47efabee1" [[files]] file = "mods/anotherworld-0.0.0-alpha.56.jar" -hash = "ede131b654d26110af8c7e64238c1b5f99634c3e1307346953ad6ab622ccfedc" +hash = "cec8ed493f3c86e4c4481081be110382407f7a5c631b7cf27dd80f80c6f2e92a" [[files]] file = "mods/events-0.0.0-alpha.0.jar" -hash = "9ccc30733117ab9984df3d69b98ab82d731578a6c35116595c96f2362ea22b76" +hash = "16bf9fc194988086f51ba6987546b6aa5bc634fe8fcb118b88540ed16991049c" [[files]] file = "mods/fabric-api.pw.toml" @@ -31,7 +31,7 @@ metafile = true [[files]] file = "mods/iliketomoveit-0.0.0-alpha.18.jar" -hash = "f0ccb5a3f411cb01bcf328a139a1f90e8357587c549778f98354d910d69b2616" +hash = "94044341de08c9b89e0c1e6af6857da64b472fadbc94051ab76fc3cf1a0f0006" [[files]] file = "mods/iris.pw.toml" @@ -40,7 +40,7 @@ metafile = true [[files]] file = "mods/itsalive-0.0.0-alpha.38.jar" -hash = "6dab7b2dca11cc1cd9789ed66cc8403b849cb73227d965d979eeebcf5c201309" +hash = "a42885703439646687ac281b1c124d1cddb3ca0595a41d930733b94bd8f1aa2f" [[files]] file = "mods/jei.pw.toml" @@ -49,23 +49,23 @@ metafile = true [[files]] file = "mods/masterkey-0.0.0-alpha.9.jar" -hash = "ab0241386a0958505622487318c2e2e269e57e793ef873ed71dac8e0f420338b" +hash = "979c14e0a527be63688e97af8349be07b027d3149107c3e9e728a2b1e1ec65ff" [[files]] file = "mods/onlyfun-0.0.0-alpha.27.jar" -hash = "15dbc6a9c3d4fef699c1f62f989c1d47e366cc781747c76640f5de668ea00510" +hash = "023ba80a8f3326a6b534b343753d5630d3be0700d25613ea21057cbfe44fdc73" [[files]] file = "mods/ouch-0.0.0-alpha.11.jar" -hash = "5bc1e244309a8835ef1d7869225201179cbee12853fb2f2390bfd47f2fcc3c4a" +hash = "2c15c9d0adeb315b2c3a6796f27c9dc62dd33365f35ea584552d97500b833eb8" [[files]] file = "mods/redstoner-0.0.0-alpha.13.jar" -hash = "d913aac62b6e7152c5751ea0ddc820a98a0b74c3864f4c0bdbfc3b44eeaa3417" +hash = "753835558c1037e39ca669737190013bd59a3ab16f7d5156c52e940c54ff9c60" [[files]] -file = "mods/sanctuary-0.0.0-alpha.129.jar" -hash = "0b67c37680e5004b7f08ac9de32b501fc8f2025fe5a7649858948f14a5d8f5f5" +file = "mods/sanctuary-0.0.0-alpha.130.jar" +hash = "8906be26de369903a0d5152d80a95a1c47b3468e4afca17ab4683b8300ad69a9" [[files]] file = "mods/simple-voice-chat.pw.toml" diff --git a/pack/packwiz/pack.toml b/pack/packwiz/pack.toml index 594a73d..74dff38 100644 --- a/pack/packwiz/pack.toml +++ b/pack/packwiz/pack.toml @@ -1,12 +1,12 @@ name = "Sanctuary 26.2" author = "KOKA99CAB" -version = "26.2.0-alpha.225" +version = "26.2.0-alpha.226" pack-format = "packwiz:1.1.0" [index] file = "index.toml" hash-format = "sha256" -hash = "19d66dcd7dbbc8e1a9471dcb259a9c9aad727acbc8428f114a48c05c2fd1d8de" +hash = "d3b929a596081adc3960866a2f939d4155d1b67ecb22bfe6050931a7d1d0f0a2" [versions] fabric = "0.19.3" diff --git a/pack/prism/modrinth.index.json b/pack/prism/modrinth.index.json index 8593c1f..c9b04fb 100644 --- a/pack/prism/modrinth.index.json +++ b/pack/prism/modrinth.index.json @@ -3,7 +3,7 @@ "game": "minecraft", "name": "Sanctuary 26.2", "summary": "Sanctuary 26.2 — progression, exploration, worldgen and multiplayer systems by KOKA99CAB.", - "versionId": "26.2.0-alpha.225", + "versionId": "26.2.0-alpha.226", "files": [ { "path": "mods/fabric-api-0.158.0+26.2.jar", diff --git a/pack/release.json b/pack/release.json index 8e51c3a..1e7ece6 100644 --- a/pack/release.json +++ b/pack/release.json @@ -1,6 +1,6 @@ { "schema_version": 1, - "pack_version": "26.2.0-alpha.225", + "pack_version": "26.2.0-alpha.226", "release_channel": "alpha", "minecraft_version": "26.2", "fabric_loader_version": "0.19.3", @@ -9,7 +9,7 @@ "project_id": "FgOqyAXd", "project_slug": "sanctuary-koka99", "project_url": "https://modrinth.com/modpack/sanctuary-koka99", - "primary_file": "sanctuary-26.2.0-alpha.225.mrpack", + "primary_file": "sanctuary-26.2.0-alpha.226.mrpack", "shared_client_server_pack": true, "update_owner": "packwiz-installer", "check_on_launch": true, diff --git a/sanctuary/build.gradle b/sanctuary/build.gradle index 9d22301..7c17862 100644 --- a/sanctuary/build.gradle +++ b/sanctuary/build.gradle @@ -116,6 +116,14 @@ tasks.register("capeJoinSyncSmoke", JavaExec) { mainClass = "fr.koka99cab.sanctuary26.sanctuary.gameplay.CapeJoinSyncQueueSmoke" } +tasks.register("capeSyncPayloadSmoke", JavaExec) { + group = "verification" + description = "Checks banner cape colors and the six-pattern network bound." + dependsOn tasks.named("testClasses") + classpath = sourceSets.test.runtimeClasspath + mainClass = "fr.koka99cab.sanctuary26.sanctuary.network.CapeSyncPayloadSmoke" +} + tasks.register("inventorySortSmoke", JavaExec) { group = "verification" description = "Checks that storage stacks merge and sort while the hotbar row stays out of the sort." @@ -183,7 +191,7 @@ tasks.register("verifyBlackMarket") { def questData = file("src/main/java/fr/koka99cab/sanctuary26/sanctuary/shop/QuestBoardData.java").text def quests = file("src/main/java/fr/koka99cab/sanctuary26/sanctuary/shop/QuestBoardService.java").text def inventoryView = file("src/main/java/fr/koka99cab/sanctuary26/sanctuary/api/inventory/SanctuaryPlayerInventoryView.java").text - if (project.version.toString() != "0.0.0-alpha.129" + if (project.version.toString() != "0.0.0-alpha.130" || !data.contains('SAVE_KEY = "black_market"') || !data.contains("DATA_VERSION = 2") || !data.contains("ItemStack.CODEC.fieldOf(\"item\")") || !data.contains("replaceListing") || !service.contains("LISTING_FEE_RUBIES = 1") || !service.contains("COMMISSION_PERCENT = 5") @@ -197,7 +205,7 @@ tasks.register("verifyBlackMarket") { || !minecraftMixin.contains('method = "pickBlockOrEntity"') || !middleClickPayload.contains('SanctuaryMod.id("c2s/black_market_interact")') || !middleClickPayload.contains("No client position, listing ID, item or price is trusted") - || !network.contains("PROTOCOL_VERSION = 23") + || !network.contains("PROTOCOL_VERSION = 24") || !network.contains("BlackMarketService.middleClick(context.player())") || !service.contains("loadedDeliveryBox") || !service.contains("PARCEL_RETENTION_MILLIS") || !policy.contains("DataComponents.CONTAINER") || !policy.contains("DataComponents.BUNDLE_CONTENTS") @@ -1193,12 +1201,12 @@ tasks.register("verifySanctuary") { def manifest = new JsonSlurper().parse(file("src/main/resources/fabric.mod.json")) if (manifest.custom?.sanctuary26?.data_version != 13 - || manifest.custom?.sanctuary26?.network_protocol != 23 + || manifest.custom?.sanctuary26?.network_protocol != 24 || manifest.depends?.jei != ">=30.24.0.176" || manifest.depends?."fabric-api" != ">=0.155.0+26.2" || !manifest.entrypoints?.client?.contains("fr.koka99cab.sanctuary26.sanctuary.client.SanctuaryClient") || !manifest.mixins?.contains("sanctuary.mixins.json")) { - throw new GradleException("Sanctuary must expose data v13, protocol 22, JEI and the client entrypoint") + throw new GradleException("Sanctuary must expose data v13, protocol 24, JEI and the client entrypoint") } def capeMigration = new JsonSlurper().parse(rootProject.file( "pack/migrations/26.2.0-alpha.155-cape-equipment-to-alpha.156.json")) @@ -2899,7 +2907,7 @@ tasks.register("verifyShopCurrencyRowsRelease") { "src/main/java/fr/koka99cab/sanctuary26/sanctuary/shop/BlackMarketService.java").text def shop = file( "src/main/java/fr/koka99cab/sanctuary26/sanctuary/shop/ShopService.java").text - if (project.version.toString() != "0.0.0-alpha.129" + if (project.version.toString() != "0.0.0-alpha.130" || migration.target?.modules?.sanctuary != "0.0.0-alpha.117" || migration.shop_currency_inventory?.all_unlocked_rows_counted != true || migration.shop_currency_inventory?.overflow_rows_counted != true @@ -3065,7 +3073,7 @@ tasks.register("verifyProgressivePauseMenu") { "pack/migrations/26.2.0-alpha.190-progressive-pause-menu-to-alpha.191.json")) def pauseMenu = file("src/main/java/fr/koka99cab/sanctuary26/sanctuary/mixin/client/PauseScreenMixin.java").text def costs = file("src/main/java/fr/koka99cab/sanctuary26/sanctuary/progression/SanctuaryProgressionCosts.java").text - if (project.version.toString() != "0.0.0-alpha.129" + if (project.version.toString() != "0.0.0-alpha.130" || migration.target?.pack_version != "26.2.0-alpha.191" || migration.target?.modules?.sanctuary != "0.0.0-alpha.109" || migration.pause_menu?.progression_full_width != true @@ -3103,7 +3111,7 @@ tasks.register("verifyShopPricingLayout") { "pack/migrations/26.2.0-alpha.192-shop-pricing-layout-to-alpha.193.json")) def screen = file("src/main/java/fr/koka99cab/sanctuary26/sanctuary/client/SanctuaryShopScreen.java").text def progression = file("src/main/java/fr/koka99cab/sanctuary26/sanctuary/shop/ShopProgression.java").text - if (project.version.toString() != "0.0.0-alpha.129" + if (project.version.toString() != "0.0.0-alpha.130" || migration.target?.modules?.sanctuary != "0.0.0-alpha.110" || migration.shop_layout?.locked_offer_buttons != 6 || migration.shop_layout?.button_slots != [4, 5, 6, 7, 8, 9] @@ -3134,7 +3142,7 @@ tasks.register("verifyShopCsvBossGates") { "pack/migrations/26.2.0-alpha.194-shop-csv-boss-gates-to-alpha.195.json")) def provider = file("src/main/java/fr/koka99cab/sanctuary26/sanctuary/shop/ShopCatalogProvider.java").text def catalog = file("src/main/java/fr/koka99cab/sanctuary26/sanctuary/shop/ShopOfferCatalog.java").text - if (project.version.toString() != "0.0.0-alpha.129" + if (project.version.toString() != "0.0.0-alpha.130" || migration.target?.pack_version != "26.2.0-alpha.195" || migration.target?.modules?.sanctuary != "0.0.0-alpha.111" || migration.compatibility?.sanctuary_data_version != 11 @@ -3165,7 +3173,7 @@ tasks.register("verifyDeliveryBoxOrientation") { def blockstate = new JsonSlurper().parse( file("src/main/resources/assets/sanctuary/blockstates/delivery_box.json")) def expectedVariants = ["facing=north", "facing=east", "facing=south", "facing=west"].toSet() - if (project.version.toString() != "0.0.0-alpha.129" + if (project.version.toString() != "0.0.0-alpha.130" || migration.target?.modules?.sanctuary != "0.0.0-alpha.112" || migration.mailbox?.id != "sanctuary:delivery_box" || migration.mailbox?.horizontal_facing != true @@ -3193,7 +3201,7 @@ tasks.register("verifyInventoryShiftClick") { def mixin = file("src/main/java/fr/koka99cab/sanctuary26/sanctuary/mixin/AbstractContainerMenuMixin.java").text def screen = file("src/main/java/fr/koka99cab/sanctuary26/sanctuary/mixin/client/AbstractContainerScreenMixin.java").text def gui = file("INVENTORY_GUI.md").text - if (project.version.toString() != "0.0.0-alpha.129" + if (project.version.toString() != "0.0.0-alpha.130" || !transfer.contains("shouldAppendOverflow") || !transfer.contains("isVanillaStorageRange") || !transfer.contains("hotbarStart") @@ -3239,7 +3247,7 @@ tasks.register("verifyQuestRequests") { new JsonSlurper().parse(file("src/main/resources/data/sanctuary/loot_table/blocks/${path}.json")) .pools[0].entries[0].name } - if (project.version.toString() != "0.0.0-alpha.129" + if (project.version.toString() != "0.0.0-alpha.130" || migration.target?.modules?.sanctuary != "0.0.0-alpha.113" || migration.quest_requests?.save_key != "quest_requests" || migration.quest_requests?.data_version != 1 @@ -3251,7 +3259,7 @@ tasks.register("verifyQuestRequests") { || !data.contains('SAVE_KEY = "quest_requests"') || !data.contains("DATA_VERSION = 3") || !service.contains("PlayerBlockBreakEvents.BEFORE") || !service.contains("player.blockPosition().distSqr(payload.pos()) > 64.0D") - || !network.contains("PROTOCOL_VERSION = 23") + || !network.contains("PROTOCOL_VERSION = 24") || !network.contains("QuestRequestSubmitPayload.ID") || !network.contains("QuestRequestAcceptPayload.ID") || !registry.contains('SanctuaryMod.id("quest_request_sign")') @@ -3297,7 +3305,7 @@ tasks.register("verifyQuestRequestContracts") { def locales = ["fr_fr", "en_us", "ru_ru"].collectEntries { locale -> [(locale): new JsonSlurper().parse(file("src/main/resources/assets/sanctuary/lang/${locale}.json"))] } - if (project.version.toString() != "0.0.0-alpha.129" + if (project.version.toString() != "0.0.0-alpha.130" || migration.source?.pack_version != "26.2.0-alpha.198" || migration.source?.modules?.sanctuary != "0.0.0-alpha.114" || migration.target?.pack_version != "26.2.0-alpha.199" @@ -3317,7 +3325,7 @@ tasks.register("verifyQuestRequestContracts") { || !service.contains('REWARD_LOAN = "loan"') || !service.contains('PLAYER.equals(targetKind)') || !screen.contains("rewardQuantity") || !screen.contains("killTargetIndex") - || !network.contains("PROTOCOL_VERSION = 23") + || !network.contains("PROTOCOL_VERSION = 24") || standingModel.textures?.all != "sanctuary:block/pink_quest_request_sign" || itemModel.textures?.layer0 != "sanctuary:item/pink_quest_request_sign" || blockTexture == null || blockTexture.width != 32 || blockTexture.height != 32 @@ -3366,7 +3374,7 @@ tasks.register("verifyQuestRequestEscrow") { def locales = ["fr_fr", "en_us", "ru_ru"].collectEntries { locale -> [(locale): new JsonSlurper().parse(file("src/main/resources/assets/sanctuary/lang/${locale}.json"))] } - if (project.version.toString() != "0.0.0-alpha.129" + if (project.version.toString() != "0.0.0-alpha.130" || migration.source?.pack_version != "26.2.0-alpha.200" || migration.source?.modules?.sanctuary != "0.0.0-alpha.115" || migration.target?.pack_version != "26.2.0-alpha.201" @@ -3387,7 +3395,7 @@ tasks.register("verifyQuestRequestEscrow") { || !service.contains('"quest_request_reward"') || !service.contains('"quest_request_delivery"') || service.contains("sanctuary_quest_accept") - || !network.contains("PROTOCOL_VERSION = 23") + || !network.contains("PROTOCOL_VERSION = 24") || !network.contains("QuestRequestAcceptPayload.ID") || !network.contains("QuestRequestConfirmPayload.ID") || !acceptPayload.contains("readUtf(36)") @@ -3411,6 +3419,68 @@ tasks.named("verifySanctuary") { dependsOn tasks.named("verifyInventoryShiftClick") } +tasks.register("verifyCraftableBannerCape") { + group = "verification" + description = "Checks the white wool recipe, banner decoration and equipped pattern rendering." + inputs.file(rootProject.file( + "pack/migrations/26.2.0-alpha.225-craftable-banner-cape-to-alpha.226.json")) + inputs.file(file("src/main/resources/data/sanctuary/recipe/white_cape.json")) + inputs.file(file("src/main/resources/data/sanctuary/recipe/white_cape_banner.json")) + inputs.file(file("src/main/resources/assets/sanctuary/items/white_cape.json")) + inputs.files(fileTree("src/main/resources/assets/sanctuary/lang") { include "*.json" }) + inputs.files( + file("src/main/java/fr/koka99cab/sanctuary26/sanctuary/gameplay/SanctuaryCapes.java"), + file("src/main/java/fr/koka99cab/sanctuary26/sanctuary/network/CapeSyncPayload.java"), + file("src/main/java/fr/koka99cab/sanctuary26/sanctuary/network/SanctuaryNetworking.java"), + file("src/main/java/fr/koka99cab/sanctuary26/sanctuary/client/SanctuaryBannerCapeLayer.java")) + doLast { + def migration = new JsonSlurper().parse(rootProject.file( + "pack/migrations/26.2.0-alpha.225-craftable-banner-cape-to-alpha.226.json")) + def baseRecipe = new JsonSlurper().parse(file( + "src/main/resources/data/sanctuary/recipe/white_cape.json")) + def bannerRecipe = new JsonSlurper().parse(file( + "src/main/resources/data/sanctuary/recipe/white_cape_banner.json")) + def itemDefinition = new JsonSlurper().parse(file( + "src/main/resources/assets/sanctuary/items/white_cape.json")) + def capes = file( + "src/main/java/fr/koka99cab/sanctuary26/sanctuary/gameplay/SanctuaryCapes.java").text + def payload = file( + "src/main/java/fr/koka99cab/sanctuary26/sanctuary/network/CapeSyncPayload.java").text + def networking = file( + "src/main/java/fr/koka99cab/sanctuary26/sanctuary/network/SanctuaryNetworking.java").text + def renderer = file( + "src/main/java/fr/koka99cab/sanctuary26/sanctuary/client/SanctuaryBannerCapeLayer.java").text + def locales = ["fr_fr", "en_us", "ru_ru"].collect { + new JsonSlurper().parse(file("src/main/resources/assets/sanctuary/lang/${it}.json")) + } + if (project.version.toString() != "0.0.0-alpha.130" + || migration.target?.modules?.sanctuary != "0.0.0-alpha.130" + || migration.white_cape?.crafting_material_count != 6 + || migration.white_cape?.maximum_pattern_layers != 6 + || baseRecipe.pattern != ["WW", "WW", "WW"] + || baseRecipe.key?.W != "minecraft:white_wool" + || baseRecipe.result?.id != "sanctuary:white_cape" + || bannerRecipe.type != "minecraft:crafting_special_shielddecoration" + || bannerRecipe.banner != "#minecraft:banners" + || bannerRecipe.target != "sanctuary:white_cape" + || itemDefinition.model?.type != "minecraft:special" + || itemDefinition.model?.model?.type != "minecraft:banner" + || locales.any { !it.containsKey("item.sanctuary.white_cape") } + || !capes.contains('WHITE_CAPE_PATH = "white_cape"') + || !payload.contains("MAX_PATTERN_LAYERS = 6") + || !payload.contains("DataComponents.BASE_COLOR") + || !payload.contains("DataComponents.BANNER_PATTERNS") + || !networking.contains("PROTOCOL_VERSION = 24") + || !renderer.contains("BannerRenderer.submitPatterns")) { + throw new GradleException("Sanctuary alpha.130 craftable banner cape is incomplete") + } + } +} + +tasks.named("verifySanctuary") { + dependsOn tasks.named("verifyCraftableBannerCape") +} + tasks.register("verifyAlphaIndev") { group = "verification" description = "Checks the alpha.122 finite Indev world, migration and attribution contract." @@ -3438,7 +3508,7 @@ tasks.register("verifyAlphaIndev") { def locales = ["fr_fr", "en_us", "ru_ru"].collect { new JsonSlurper().parse(file("src/main/resources/assets/sanctuary/lang/${it}.json")) } - if (project.version.toString() != "0.0.0-alpha.129" + if (project.version.toString() != "0.0.0-alpha.130" || migration.target?.modules?.sanctuary != "0.0.0-alpha.122" || migration.alpha_world?.dimension != "sanctuary:alpha" || migration.alpha_world?.legacy_dimension != "portals:alpha" @@ -3475,6 +3545,7 @@ tasks.named("check") { dependsOn tasks.named("questIdSuggestionsSmoke") dependsOn tasks.named("alphaIndevGeneratorSmoke") dependsOn tasks.named("capeJoinSyncSmoke") + dependsOn tasks.named("capeSyncPayloadSmoke") dependsOn tasks.named("inventorySortSmoke") dependsOn tasks.named("entityPolicySmoke") dependsOn tasks.named("verifyAlphaIndev") diff --git a/sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/client/SanctuaryBannerCapeLayer.java b/sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/client/SanctuaryBannerCapeLayer.java new file mode 100644 index 0000000..e991735 --- /dev/null +++ b/sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/client/SanctuaryBannerCapeLayer.java @@ -0,0 +1,98 @@ +package fr.koka99cab.sanctuary26.sanctuary.client; + +import com.mojang.blaze3d.vertex.PoseStack; +import fr.koka99cab.sanctuary26.sanctuary.SanctuaryMod; +import net.fabricmc.fabric.api.client.rendering.v1.LivingEntityRenderLayerRegistrationCallback; +import net.fabricmc.fabric.api.client.rendering.v1.ModelLayerRegistry; +import net.minecraft.client.model.geom.ModelLayerLocation; +import net.minecraft.client.model.geom.PartPose; +import net.minecraft.client.model.geom.builders.CubeDeformation; +import net.minecraft.client.model.geom.builders.CubeListBuilder; +import net.minecraft.client.model.geom.builders.LayerDefinition; +import net.minecraft.client.model.geom.builders.MeshDefinition; +import net.minecraft.client.model.geom.builders.PartDefinition; +import net.minecraft.client.model.player.PlayerCapeModel; +import net.minecraft.client.model.player.PlayerModel; +import net.minecraft.client.renderer.SubmitNodeCollector; +import net.minecraft.client.renderer.blockentity.BannerRenderer; +import net.minecraft.client.renderer.entity.EntityRendererProvider; +import net.minecraft.client.renderer.entity.RenderLayerParent; +import net.minecraft.client.renderer.entity.layers.RenderLayer; +import net.minecraft.client.renderer.entity.player.AvatarRenderer; +import net.minecraft.client.renderer.entity.state.AvatarRenderState; +import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.client.resources.model.EquipmentAssetManager; +import net.minecraft.client.resources.model.EquipmentClientInfo; +import net.minecraft.core.component.DataComponents; +import net.minecraft.world.entity.EntityTypes; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.equipment.Equippable; + +/** Renders a banner-decorated cape with vanilla cape physics and banner pattern sprites. */ +public final class SanctuaryBannerCapeLayer extends RenderLayer { + private static final ModelLayerLocation MODEL_LAYER = + new ModelLayerLocation(SanctuaryMod.id("banner_cape"), "main"); + private final PlayerCapeModel model; + private final EquipmentAssetManager equipmentAssets; + private final EntityRendererProvider.Context context; + + private SanctuaryBannerCapeLayer(RenderLayerParent parent, + EntityRendererProvider.Context context) { + super(parent); + this.context = context; + this.model = new PlayerCapeModel(context.bakeLayer(MODEL_LAYER)); + this.equipmentAssets = context.getEquipmentAssets(); + } + + public static void initialize() { + ModelLayerRegistry.registerModelLayer(MODEL_LAYER, SanctuaryBannerCapeLayer::createLayer); + LivingEntityRenderLayerRegistrationCallback.EVENT.register((entityType, renderer, helper, context) -> { + if (entityType == EntityTypes.PLAYER && renderer instanceof AvatarRenderer avatarRenderer) { + register(helper, avatarRenderer, context); + } + }); + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + private static void register(LivingEntityRenderLayerRegistrationCallback.RegistrationHelper helper, + AvatarRenderer renderer, EntityRendererProvider.Context context) { + RenderLayerParent parent = + (RenderLayerParent) (RenderLayerParent) renderer; + helper.register(new SanctuaryBannerCapeLayer(parent, context)); + } + + private static LayerDefinition createLayer() { + MeshDefinition mesh = PlayerModel.createMesh(CubeDeformation.NONE, false); + PartDefinition root = mesh.getRoot().clearRecursively(); + PartDefinition body = root.getChild("body"); + body.addOrReplaceChild("cape", CubeListBuilder.create().texOffs(0, 0) + .addBox(-5.0F, 0.0F, -1.0F, 10.0F, 16.0F, 1.0F, + CubeDeformation.NONE, 2.0F, 2.5F), + PartPose.offsetAndRotation(0.0F, 0.0F, 2.0F, 0.0F, (float) Math.PI, 0.0F)); + return LayerDefinition.create(mesh, 64, 64); + } + + @Override + public void submit(PoseStack poseStack, SubmitNodeCollector collector, int packedLight, + AvatarRenderState state, float yRot, float xRot) { + SanctuaryClientCapes.Appearance appearance = + ((SanctuaryCapeRenderState) state).sanctuary$capeAppearance(); + if (state.isInvisible || appearance == null || !appearance.bannerCape() + || hasLayer(state.chestEquipment, EquipmentClientInfo.LayerType.WINGS)) return; + + poseStack.pushPose(); + if (hasLayer(state.chestEquipment, EquipmentClientInfo.LayerType.HUMANOID)) { + poseStack.translate(0.0F, -0.053125F, 0.06875F); + } + BannerRenderer.submitPatterns(context.getSprites(), poseStack, collector, packedLight, + OverlayTexture.NO_OVERLAY, model, state, true, appearance.baseColor(), + appearance.patterns(), null); + poseStack.popPose(); + } + + private boolean hasLayer(ItemStack stack, EquipmentClientInfo.LayerType layerType) { + Equippable equippable = stack.get(DataComponents.EQUIPPABLE); + return equippable != null && equippable.assetId().isPresent() + && !equipmentAssets.get(equippable.assetId().get()).getLayers(layerType).isEmpty(); + } +} diff --git a/sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/client/SanctuaryCapeRenderState.java b/sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/client/SanctuaryCapeRenderState.java new file mode 100644 index 0000000..7d06d26 --- /dev/null +++ b/sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/client/SanctuaryCapeRenderState.java @@ -0,0 +1,8 @@ +package fr.koka99cab.sanctuary26.sanctuary.client; + +/** Mixin-backed bridge carrying equipped cape data into the extracted render state. */ +public interface SanctuaryCapeRenderState { + SanctuaryClientCapes.Appearance sanctuary$capeAppearance(); + + void sanctuary$setCapeAppearance(SanctuaryClientCapes.Appearance appearance); +} diff --git a/sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/client/SanctuaryClient.java b/sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/client/SanctuaryClient.java index ffaf40d..3785995 100644 --- a/sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/client/SanctuaryClient.java +++ b/sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/client/SanctuaryClient.java @@ -119,6 +119,7 @@ public final class SanctuaryClient implements ClientModInitializer { SanctuaryBulkActionsClient.initialize(); SanctuaryHealthPreview.register(); CelestialSpyglassSelection.register(); + SanctuaryBannerCapeLayer.initialize(); EntityRendererRegistry.register(SanctuaryRegistries.SEAT, NoopRenderer::new); ClientTickEvents.END_CLIENT_TICK.register(SanctuaryClient::tick); ClientPlayNetworking.registerGlobalReceiver(ProgressionSnapshotPayload.ID, (payload, context) -> diff --git a/sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/client/SanctuaryClientCapes.java b/sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/client/SanctuaryClientCapes.java index ec56cd7..53dd995 100644 --- a/sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/client/SanctuaryClientCapes.java +++ b/sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/client/SanctuaryClientCapes.java @@ -6,25 +6,33 @@ import java.util.HashMap; import java.util.Map; import java.util.UUID; import net.minecraft.resources.Identifier; +import net.minecraft.world.item.DyeColor; +import net.minecraft.world.level.block.entity.BannerPatternLayers; /** Client mirror of server-authoritative equipped cape choices. */ public final class SanctuaryClientCapes { - private static final Map TEXTURES = new HashMap<>(); + private static final Map APPEARANCES = new HashMap<>(); private SanctuaryClientCapes() { } public static void update(CapeSyncPayload payload) { Identifier texture = SanctuaryCapes.texture(payload.capeItemId()); - if (texture == null) TEXTURES.remove(payload.playerId()); - else TEXTURES.put(payload.playerId(), texture); + boolean bannerCape = SanctuaryCapes.isBannerCape(payload.capeItemId()); + if (texture == null && !bannerCape) APPEARANCES.remove(payload.playerId()); + else APPEARANCES.put(payload.playerId(), new Appearance( + texture, bannerCape, payload.baseColor(), payload.patterns())); } - public static Identifier texture(UUID playerId) { - return TEXTURES.get(playerId); + public static Appearance appearance(UUID playerId) { + return APPEARANCES.get(playerId); } public static void clear() { - TEXTURES.clear(); + APPEARANCES.clear(); + } + + public record Appearance(Identifier texture, boolean bannerCape, DyeColor baseColor, + BannerPatternLayers patterns) { } } diff --git a/sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/gameplay/SanctuaryCapeService.java b/sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/gameplay/SanctuaryCapeService.java index 186f524..6b43c8e 100644 --- a/sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/gameplay/SanctuaryCapeService.java +++ b/sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/gameplay/SanctuaryCapeService.java @@ -62,7 +62,7 @@ public final class SanctuaryCapeService { private static void send(ServerPlayer receiver, ServerPlayer owner) { if (!ServerPlayNetworking.canSend(receiver, CapeSyncPayload.ID)) return; - String capeId = SanctuaryCapes.itemId(SanctuaryInventoryCapacity.equippedCape(owner)); - ServerPlayNetworking.send(receiver, new CapeSyncPayload(owner.getUUID(), capeId)); + ServerPlayNetworking.send(receiver, CapeSyncPayload.fromStack( + owner.getUUID(), SanctuaryInventoryCapacity.equippedCape(owner))); } } diff --git a/sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/gameplay/SanctuaryCapes.java b/sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/gameplay/SanctuaryCapes.java index b90b95b..2839b4d 100644 --- a/sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/gameplay/SanctuaryCapes.java +++ b/sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/gameplay/SanctuaryCapes.java @@ -14,8 +14,10 @@ import net.minecraft.world.item.CreativeModeTab; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; -/** Registration and immutable visual definitions for Sanctuary's collectible capes. */ +/** Registration and immutable visual definitions for Sanctuary's equippable capes. */ public final class SanctuaryCapes { + public static final String WHITE_CAPE_PATH = "white_cape"; + public static final String WHITE_CAPE_ID = "sanctuary:" + WHITE_CAPE_PATH; public static final List PATHS = List.of( "transgender_cape", "mojang_cape", "founders_cape", "nes_cape", "pride_cape", "pink_cape", "feesh_gang_cape", "gameboy_cape", "blue_cape", "chicken_cape", @@ -28,7 +30,7 @@ public final class SanctuaryCapes { "vanilla_cape", "java_edition_cape", "migration_cape", "creeper_anniversary_cape", "java_twitch_cape", "minecon_enderman_cape", "iron_golem_minecon_cape", "minecon_2013_cape", "crafter_twitchcon_cape", "minecon_pickaxe_cape", "minecon_2011_cape", "mojang_classic_cape", - "blue_scroll_cape" + "blue_scroll_cape", WHITE_CAPE_PATH ); private static final Map DEFINITIONS = registerDefinitions(); private static final ResourceKey CREATIVE_TAB_KEY = ResourceKey.create( @@ -74,6 +76,10 @@ public final class SanctuaryCapes { return definition == null ? null : definition.texture(); } + public static boolean isBannerCape(String itemId) { + return WHITE_CAPE_ID.equals(itemId); + } + public static List definitions() { return List.copyOf(DEFINITIONS.values()); } @@ -85,8 +91,9 @@ public final class SanctuaryCapes { ResourceKey key = ResourceKey.create(Registries.ITEM, id); Item item = Registry.register(BuiltInRegistries.ITEM, key, new SanctuaryCapeItem(new Item.Properties().stacksTo(1).setId(key))); - definitions.put(id, new Definition(id, item, - SanctuaryMod.id("entity/cape/" + path))); + Identifier texture = WHITE_CAPE_PATH.equals(path) + ? null : SanctuaryMod.id("entity/cape/" + path); + definitions.put(id, new Definition(id, item, texture)); } return Map.copyOf(definitions); } diff --git a/sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/mixin/client/AvatarRenderStateMixin.java b/sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/mixin/client/AvatarRenderStateMixin.java new file mode 100644 index 0000000..a287283 --- /dev/null +++ b/sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/mixin/client/AvatarRenderStateMixin.java @@ -0,0 +1,23 @@ +package fr.koka99cab.sanctuary26.sanctuary.mixin.client; + +import fr.koka99cab.sanctuary26.sanctuary.client.SanctuaryCapeRenderState; +import fr.koka99cab.sanctuary26.sanctuary.client.SanctuaryClientCapes; +import net.minecraft.client.renderer.entity.state.AvatarRenderState; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; + +/** Stores the server-authoritative dynamic cape appearance on each extracted player state. */ +@Mixin(AvatarRenderState.class) +abstract class AvatarRenderStateMixin implements SanctuaryCapeRenderState { + @Unique private SanctuaryClientCapes.Appearance sanctuary$capeAppearance; + + @Override + public SanctuaryClientCapes.Appearance sanctuary$capeAppearance() { + return sanctuary$capeAppearance; + } + + @Override + public void sanctuary$setCapeAppearance(SanctuaryClientCapes.Appearance appearance) { + sanctuary$capeAppearance = appearance; + } +} diff --git a/sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/mixin/client/AvatarRendererMixin.java b/sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/mixin/client/AvatarRendererMixin.java index a89c0da..963ec96 100644 --- a/sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/mixin/client/AvatarRendererMixin.java +++ b/sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/mixin/client/AvatarRendererMixin.java @@ -1,6 +1,7 @@ package fr.koka99cab.sanctuary26.sanctuary.mixin.client; import fr.koka99cab.sanctuary26.sanctuary.client.SanctuaryClientCapes; +import fr.koka99cab.sanctuary26.sanctuary.client.SanctuaryCapeRenderState; import net.minecraft.client.renderer.entity.player.AvatarRenderer; import net.minecraft.client.renderer.entity.state.AvatarRenderState; import net.minecraft.core.ClientAsset; @@ -21,7 +22,13 @@ abstract class AvatarRendererMixin { ) private void sanctuary$applyEquippedCape(Avatar avatar, AvatarRenderState state, float partialTick, CallbackInfo ci) { - Identifier texture = SanctuaryClientCapes.texture(avatar.getUUID()); + SanctuaryClientCapes.Appearance appearance = SanctuaryClientCapes.appearance(avatar.getUUID()); + ((SanctuaryCapeRenderState) state).sanctuary$setCapeAppearance(appearance); + if (appearance == null || appearance.bannerCape()) { + if (appearance != null) state.showCape = false; + return; + } + Identifier texture = appearance.texture(); PlayerSkin skin = state.skin; if (texture == null || skin == null) return; state.skin = PlayerSkin.insecure(skin.body(), new ClientAsset.ResourceTexture(texture), diff --git a/sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/network/CapeSyncPayload.java b/sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/network/CapeSyncPayload.java index 034f943..b10cf61 100644 --- a/sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/network/CapeSyncPayload.java +++ b/sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/network/CapeSyncPayload.java @@ -1,13 +1,22 @@ package fr.koka99cab.sanctuary26.sanctuary.network; import fr.koka99cab.sanctuary26.sanctuary.SanctuaryMod; +import fr.koka99cab.sanctuary26.sanctuary.gameplay.SanctuaryCapes; +import java.util.ArrayList; +import java.util.List; import java.util.UUID; +import net.minecraft.core.component.DataComponents; import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.codec.StreamCodec; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; +import net.minecraft.world.item.DyeColor; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.entity.BannerPatternLayers; /** Announces one player's currently equipped Sanctuary cape to clients. */ -public record CapeSyncPayload(UUID playerId, String capeItemId) implements CustomPacketPayload { +public record CapeSyncPayload(UUID playerId, String capeItemId, DyeColor baseColor, + BannerPatternLayers patterns) implements CustomPacketPayload { + public static final int MAX_PATTERN_LAYERS = 6; public static final Type ID = new Type<>(SanctuaryMod.id("s2c/cape_sync")); public static final StreamCodec CODEC = CustomPacketPayload.codec(CapeSyncPayload::write, CapeSyncPayload::new); @@ -15,15 +24,47 @@ public record CapeSyncPayload(UUID playerId, String capeItemId) implements Custo public CapeSyncPayload { if (playerId == null) throw new IllegalArgumentException("Cape player UUID cannot be null"); capeItemId = capeItemId == null ? "" : capeItemId; + baseColor = baseColor == null ? DyeColor.WHITE : baseColor; + patterns = bounded(patterns); } private CapeSyncPayload(RegistryFriendlyByteBuf buffer) { - this(buffer.readUUID(), buffer.readUtf(128)); + this(buffer.readUUID(), buffer.readUtf(128), DyeColor.STREAM_CODEC.decode(buffer), readPatterns(buffer)); } private void write(RegistryFriendlyByteBuf buffer) { buffer.writeUUID(playerId); buffer.writeUtf(capeItemId, 128); + DyeColor.STREAM_CODEC.encode(buffer, baseColor); + buffer.writeVarInt(patterns.layers().size()); + patterns.layers().forEach(layer -> BannerPatternLayers.Layer.STREAM_CODEC.encode(buffer, layer)); + } + + public static CapeSyncPayload fromStack(UUID playerId, ItemStack stack) { + String capeItemId = SanctuaryCapes.itemId(stack); + DyeColor baseColor = stack.get(DataComponents.BASE_COLOR); + BannerPatternLayers patterns = stack.get(DataComponents.BANNER_PATTERNS); + return new CapeSyncPayload(playerId, capeItemId, baseColor, patterns); + } + + private static BannerPatternLayers readPatterns(RegistryFriendlyByteBuf buffer) { + int size = buffer.readVarInt(); + if (size < 0 || size > MAX_PATTERN_LAYERS) { + throw new IllegalArgumentException("Cape banner pattern count must be between 0 and " + + MAX_PATTERN_LAYERS + ": " + size); + } + List layers = new ArrayList<>(size); + for (int i = 0; i < size; i++) { + layers.add(BannerPatternLayers.Layer.STREAM_CODEC.decode(buffer)); + } + return layers.isEmpty() ? BannerPatternLayers.EMPTY : new BannerPatternLayers(List.copyOf(layers)); + } + + private static BannerPatternLayers bounded(BannerPatternLayers patterns) { + if (patterns == null || patterns.layers().isEmpty()) return BannerPatternLayers.EMPTY; + List layers = patterns.layers(); + if (layers.size() <= MAX_PATTERN_LAYERS) return patterns; + return new BannerPatternLayers(List.copyOf(layers.subList(0, MAX_PATTERN_LAYERS))); } @Override public Type type() { return ID; } diff --git a/sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/network/SanctuaryNetworking.java b/sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/network/SanctuaryNetworking.java index e8ca10e..fc54827 100644 --- a/sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/network/SanctuaryNetworking.java +++ b/sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/network/SanctuaryNetworking.java @@ -24,7 +24,7 @@ import net.minecraft.server.level.ServerPlayer; * Networking contract for Sanctuary. Payload IDs must use the module namespace. */ public final class SanctuaryNetworking { - public static final int PROTOCOL_VERSION = 23; + public static final int PROTOCOL_VERSION = 24; private static boolean initialized; private SanctuaryNetworking() { diff --git a/sanctuary/src/main/resources/assets/sanctuary/items/white_cape.json b/sanctuary/src/main/resources/assets/sanctuary/items/white_cape.json new file mode 100644 index 0000000..81e67dd --- /dev/null +++ b/sanctuary/src/main/resources/assets/sanctuary/items/white_cape.json @@ -0,0 +1,34 @@ +{ + "model": { + "type": "minecraft:special", + "base": "minecraft:item/template_banner", + "model": { + "type": "minecraft:banner", + "color": "white" + }, + "transformation": { + "left_rotation": [ + 0.0, + 0.0, + 0.0, + 1.0 + ], + "right_rotation": [ + 0.0, + 0.0, + 0.0, + 1.0 + ], + "scale": [ + 0.6666667, + -0.6666667, + -0.6666667 + ], + "translation": [ + 0.5, + 0.0, + 0.5 + ] + } + } +} diff --git a/sanctuary/src/main/resources/assets/sanctuary/lang/en_us.json b/sanctuary/src/main/resources/assets/sanctuary/lang/en_us.json index c93645c..6a56acb 100644 --- a/sanctuary/src/main/resources/assets/sanctuary/lang/en_us.json +++ b/sanctuary/src/main/resources/assets/sanctuary/lang/en_us.json @@ -514,6 +514,7 @@ "item.sanctuary.minecon_2011_cape": "Minecon 2011 Cape", "item.sanctuary.mojang_classic_cape": "Mojang Classic Cape", "item.sanctuary.blue_scroll_cape": "Blue Scroll Cape", + "item.sanctuary.white_cape": "White Cape", "dimension.sanctuary.alpha": "Alpha / Indev Island", "screen.sanctuary.atlas.landmark.boss": "Defeated boss", "message.sanctuary.notch_defeated": "Notch Titan has been defeated. The victory is now recorded in this world." diff --git a/sanctuary/src/main/resources/assets/sanctuary/lang/fr_fr.json b/sanctuary/src/main/resources/assets/sanctuary/lang/fr_fr.json index 2f34034..1724b36 100644 --- a/sanctuary/src/main/resources/assets/sanctuary/lang/fr_fr.json +++ b/sanctuary/src/main/resources/assets/sanctuary/lang/fr_fr.json @@ -514,6 +514,7 @@ "item.sanctuary.minecon_2011_cape": "Cape Minecon 2011", "item.sanctuary.mojang_classic_cape": "Cape Mojang classique", "item.sanctuary.blue_scroll_cape": "Cape parchemin bleu", + "item.sanctuary.white_cape": "Cape blanche", "dimension.sanctuary.alpha": "Île Alpha / Indev", "screen.sanctuary.atlas.landmark.boss": "Boss vaincu", "message.sanctuary.notch_defeated": "Notch Titan a été vaincu. La victoire est désormais inscrite dans ce monde." diff --git a/sanctuary/src/main/resources/assets/sanctuary/lang/ru_ru.json b/sanctuary/src/main/resources/assets/sanctuary/lang/ru_ru.json index b726ea5..3a90618 100644 --- a/sanctuary/src/main/resources/assets/sanctuary/lang/ru_ru.json +++ b/sanctuary/src/main/resources/assets/sanctuary/lang/ru_ru.json @@ -470,6 +470,7 @@ "item.sanctuary.minecon_2011_cape": "Плащ Minecon 2011", "item.sanctuary.mojang_classic_cape": "Классический плащ Mojang", "item.sanctuary.blue_scroll_cape": "Плащ синего свитка", + "item.sanctuary.white_cape": "Белый плащ", "dimension.sanctuary.alpha": "Остров Альфа / Indev", "screen.sanctuary.atlas.landmark.boss": "Побеждённый босс", "message.sanctuary.notch_defeated": "Нотч-Титан побеждён. Победа навсегда записана в этом мире." diff --git a/sanctuary/src/main/resources/data/sanctuary/recipe/white_cape.json b/sanctuary/src/main/resources/data/sanctuary/recipe/white_cape.json new file mode 100644 index 0000000..c8c15e4 --- /dev/null +++ b/sanctuary/src/main/resources/data/sanctuary/recipe/white_cape.json @@ -0,0 +1,16 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "equipment", + "key": { + "W": "minecraft:white_wool" + }, + "pattern": [ + "WW", + "WW", + "WW" + ], + "result": { + "count": 1, + "id": "sanctuary:white_cape" + } +} diff --git a/sanctuary/src/main/resources/data/sanctuary/recipe/white_cape_banner.json b/sanctuary/src/main/resources/data/sanctuary/recipe/white_cape_banner.json new file mode 100644 index 0000000..a3504b1 --- /dev/null +++ b/sanctuary/src/main/resources/data/sanctuary/recipe/white_cape_banner.json @@ -0,0 +1,8 @@ +{ + "type": "minecraft:crafting_special_shielddecoration", + "banner": "#minecraft:banners", + "result": { + "id": "sanctuary:white_cape" + }, + "target": "sanctuary:white_cape" +} diff --git a/sanctuary/src/main/resources/fabric.mod.json b/sanctuary/src/main/resources/fabric.mod.json index de9b416..cbed638 100644 --- a/sanctuary/src/main/resources/fabric.mod.json +++ b/sanctuary/src/main/resources/fabric.mod.json @@ -33,7 +33,7 @@ "system_type": "gameplay-system", "namespace": "sanctuary", "data_version": 13, - "network_protocol": 23, + "network_protocol": 24, "lifecycle": "${lifecycle}", "pack_version": "${pack_version}", "descriptions": { diff --git a/sanctuary/src/main/resources/sanctuary.mixins.json b/sanctuary/src/main/resources/sanctuary.mixins.json index 03751ad..794af4b 100644 --- a/sanctuary/src/main/resources/sanctuary.mixins.json +++ b/sanctuary/src/main/resources/sanctuary.mixins.json @@ -18,6 +18,7 @@ ], "client": [ "client.AbstractButtonMixin", + "client.AvatarRenderStateMixin", "client.AvatarRendererMixin", "client.AbstractContainerScreenAccessor", "client.AbstractContainerScreenMixin", diff --git a/sanctuary/src/test/java/fr/koka99cab/sanctuary26/sanctuary/network/CapeSyncPayloadSmoke.java b/sanctuary/src/test/java/fr/koka99cab/sanctuary26/sanctuary/network/CapeSyncPayloadSmoke.java new file mode 100644 index 0000000..44f9edf --- /dev/null +++ b/sanctuary/src/test/java/fr/koka99cab/sanctuary26/sanctuary/network/CapeSyncPayloadSmoke.java @@ -0,0 +1,40 @@ +package fr.koka99cab.sanctuary26.sanctuary.network; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import net.minecraft.core.Holder; +import net.minecraft.resources.Identifier; +import net.minecraft.world.item.DyeColor; +import net.minecraft.world.level.block.entity.BannerPattern; +import net.minecraft.world.level.block.entity.BannerPatternLayers; + +/** Executable coverage for the bounded banner appearance carried by cape synchronization. */ +public final class CapeSyncPayloadSmoke { + private CapeSyncPayloadSmoke() { + } + + public static void main(String[] args) { + List layers = new ArrayList<>(); + Holder pattern = Holder.direct(new BannerPattern( + Identifier.withDefaultNamespace("base"), "block.minecraft.banner.base.white")); + for (int i = 0; i < 8; i++) { + layers.add(new BannerPatternLayers.Layer(pattern, DyeColor.BLUE)); + } + + CapeSyncPayload payload = new CapeSyncPayload(UUID.fromString( + "12345678-1234-5678-9abc-def012345678"), "sanctuary:white_cape", DyeColor.RED, + new BannerPatternLayers(List.copyOf(layers))); + require(payload.baseColor() == DyeColor.RED, "Banner base color was not preserved"); + require(payload.patterns().layers().size() == CapeSyncPayload.MAX_PATTERN_LAYERS, + "Cape synchronization did not cap banner patterns at six"); + + CapeSyncPayload blank = new CapeSyncPayload(UUID.randomUUID(), "", null, null); + require(blank.baseColor() == DyeColor.WHITE, "Blank cape payload did not default to white"); + require(blank.patterns().layers().isEmpty(), "Blank cape payload carried patterns"); + } + + private static void require(boolean condition, String message) { + if (!condition) throw new IllegalStateException(message); + } +} -- 2.54.0