Sanctuary 26.2.0-alpha.198 — automatisation du tonneau de fermentation #4
@@ -6,6 +6,18 @@ 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.198`
|
||||
|
||||
Modules modifiés : **It's Alive `0.0.0-alpha.30`** et **Sanctuary `0.0.0-alpha.114`**. Les huit autres modules restent inchangés.
|
||||
|
||||
- limite chaque emplacement d'entrée du tonneau de fermentation à une seule unité ;
|
||||
- refuse les doublons et les ingrédients qui ne peuvent plus compléter aucune recette de fermentation chargée ;
|
||||
- bloque ainsi les hoppers dès qu'une recette complète est assemblée, au lieu d'absorber progressivement tout leur inventaire ;
|
||||
- expose dans le `BlockState` du tonneau les transitions vide, un à quatre ingrédients et résultat prêt afin que les observateurs vanilla émettent une impulsion fiable ;
|
||||
- conserve le comparateur pour lire le remplissage et l'état prêt sans générer d'impulsion à chaque tick de fermentation ;
|
||||
- aligne le shift-clic de l’inventaire étendu sur vanilla : la hotbar alimente toutes les rangées de stockage débloquées, rangées 5 et 6 comprises, tandis que le stockage et l’overflow n’alimentent que la hotbar ;
|
||||
- conserve les piles déjà présentes dans les anciennes sauvegardes, tous les IDs, les données It's Alive v1 et le protocole 3, sans migration destructive.
|
||||
|
||||
## `26.2.0-alpha.197`
|
||||
|
||||
Modules modifiés : **It's Alive `0.0.0-alpha.29`** et **Sanctuary `0.0.0-alpha.113`**. Les huit autres modules restent inchangés.
|
||||
|
||||
@@ -22,9 +22,9 @@ 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 local : **`26.2.0-alpha.197`**. Sanctuary passe en **`0.0.0-alpha.114`** ; It's Alive reste à **`0.0.0-alpha.29`** et les huit autres modules restent inchangés.
|
||||
Version courante du pack local : **`26.2.0-alpha.198`**. It's Alive passe en **`0.0.0-alpha.30`** et Sanctuary en **`0.0.0-alpha.114`** ; les huit autres modules restent inchangés.
|
||||
|
||||
Le shift-clic de l’inventaire suit le comportement vanilla sur toutes les rangées débloquées : la hotbar alimente le stockage, rangées 5 et 6 comprises, et une rangée de stockage ou d’overflow n’alimente que la hotbar.
|
||||
L’alpha.198 borne l’automatisation du tonneau de fermentation : chaque emplacement n’accepte qu’une unité utile à une recette encore réalisable, les doublons invalides sont refusés et les observateurs suivent les changements visibles du contenu sans impulsion de progression parasite. Elle intègre aussi la correction de Chris : le shift-clic de l’inventaire suit le comportement vanilla sur toutes les rangées débloquées, y compris les rangées 5 et 6, tandis qu’une rangée de stockage ou d’overflow n’alimente que la hotbar.
|
||||
|
||||
L’alpha.197 ajoute un panneau communautaire de demandes de quêtes dans Sanctuary. Le demandeur renseigne son pseudonyme, un objectif, un type KILL/BRING/PAY, une quantité et une cible validée par le serveur ; un autre joueur prend la demande au clic droit et peut l’abandonner accroupi. Le panneau reste récupérable uniquement par son propriétaire ou un opérateur. La marmite It’s Alive regroupe désormais jusqu’à 64 objets strictement identiques dans une même pile logique et cuit un lot borné par l’ingrédient le plus rare et la capacité de sortie, afin de produire directement une pile de sel, de crème ou d’autres préparations.
|
||||
|
||||
|
||||
+68
-18
@@ -3427,7 +3427,7 @@ 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.197"
|
||||
if (rootProject.pack_version != "26.2.0-alpha.198"
|
||||
|| rootProject.sanctuary_version != "0.0.0-alpha.114"
|
||||
|| rootProject.onlyfun_version != "0.0.0-alpha.19"
|
||||
|| release.pack_version != rootProject.pack_version || index.versionId != rootProject.pack_version
|
||||
@@ -3477,7 +3477,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.197"
|
||||
if (rootProject.pack_version != "26.2.0-alpha.198"
|
||||
|| rootProject.anotherworld_version != "0.0.0-alpha.49"
|
||||
|| rootProject.redstoner_version != "0.0.0-alpha.10"
|
||||
|| release.pack_version != rootProject.pack_version || index.versionId != rootProject.pack_version
|
||||
@@ -4121,7 +4121,7 @@ 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.197"
|
||||
if (rootProject.pack_version != "26.2.0-alpha.198"
|
||||
|| rootProject.onlyfun_version != "0.0.0-alpha.19"
|
||||
|| rootProject.sanctuary_version != "0.0.0-alpha.114"
|
||||
|| release.pack_version != rootProject.pack_version || index.versionId != rootProject.pack_version
|
||||
@@ -4166,8 +4166,8 @@ 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.197"
|
||||
|| rootProject.itsalive_version != "0.0.0-alpha.29"
|
||||
if (rootProject.pack_version != "26.2.0-alpha.198"
|
||||
|| rootProject.itsalive_version != "0.0.0-alpha.30"
|
||||
|| release.pack_version != rootProject.pack_version || index.versionId != rootProject.pack_version
|
||||
|| migration.source?.pack_version != "26.2.0-alpha.193"
|
||||
|| migration.source?.modules != [itsalive: "0.0.0-alpha.26"]
|
||||
@@ -4215,7 +4215,7 @@ 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.197"
|
||||
if (rootProject.pack_version != "26.2.0-alpha.198"
|
||||
|| rootProject.onlyfun_version != "0.0.0-alpha.19"
|
||||
|| rootProject.sanctuary_version != "0.0.0-alpha.114"
|
||||
|| release.pack_version != rootProject.pack_version || index.versionId != rootProject.pack_version
|
||||
@@ -4261,7 +4261,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.197"
|
||||
if (rootProject.pack_version != "26.2.0-alpha.198"
|
||||
|| migration.source?.pack_version != "26.2.0-alpha.195"
|
||||
|| migration.target?.pack_version != "26.2.0-alpha.196"
|
||||
|| migration.target?.modules != [
|
||||
@@ -4279,10 +4279,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.197"
|
||||
|| release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.197.mrpack"
|
||||
|| prism.versionId != "26.2.0-alpha.197"
|
||||
|| !packwiz.contains('version = "26.2.0-alpha.197"')) {
|
||||
|| release.pack_version != "26.2.0-alpha.198"
|
||||
|| release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.198.mrpack"
|
||||
|| prism.versionId != "26.2.0-alpha.198"
|
||||
|| !packwiz.contains('version = "26.2.0-alpha.198"')) {
|
||||
throw new GradleException("The alpha.196 culinary, mailbox and grapple release contract is incomplete")
|
||||
}
|
||||
}
|
||||
@@ -4307,9 +4307,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.197"
|
||||
|| rootProject.itsalive_version != "0.0.0-alpha.29"
|
||||
|| rootProject.sanctuary_version != "0.0.0-alpha.113"
|
||||
if (rootProject.pack_version != "26.2.0-alpha.198"
|
||||
|| rootProject.itsalive_version != "0.0.0-alpha.30"
|
||||
|| rootProject.sanctuary_version != "0.0.0-alpha.114"
|
||||
|| 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"]
|
||||
@@ -4327,10 +4327,10 @@ tasks.register("verifyQuestRequestsCauldronBatchesRelease") {
|
||||
|| migration.distribution?.jei?.target != "30.26.0.186"
|
||||
|| migration.compatibility?.sanctuary_target_network_protocol != 19
|
||||
|| sanctuaryManifest.custom?.sanctuary26?.network_protocol != 19
|
||||
|| release.pack_version != "26.2.0-alpha.197"
|
||||
|| release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.197.mrpack"
|
||||
|| prism.versionId != "26.2.0-alpha.197"
|
||||
|| !packwiz.contains('version = "26.2.0-alpha.197"')) {
|
||||
|| release.pack_version != "26.2.0-alpha.198"
|
||||
|| release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.198.mrpack"
|
||||
|| prism.versionId != "26.2.0-alpha.198"
|
||||
|| !packwiz.contains('version = "26.2.0-alpha.198"')) {
|
||||
throw new GradleException("The alpha.197 quest-request and cauldron-batch release contract is incomplete")
|
||||
}
|
||||
}
|
||||
@@ -4340,6 +4340,56 @@ tasks.named("verifyWorkspace") {
|
||||
dependsOn tasks.named("verifyQuestRequestsCauldronBatchesRelease")
|
||||
}
|
||||
|
||||
tasks.register("verifyFermentationBarrelAutomationRelease") {
|
||||
group = "verification"
|
||||
description = "Checks the complete Sanctuary 26.2.0-alpha.198 fermentation barrel release."
|
||||
inputs.file(file("pack/migrations/26.2.0-alpha.197-fermentation-barrel-automation-to-alpha.198.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("itsalive/src/main/resources/fabric.mod.json"))
|
||||
doLast {
|
||||
def migration = new JsonSlurper().parse(file(
|
||||
"pack/migrations/26.2.0-alpha.197-fermentation-barrel-automation-to-alpha.198.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 itsAliveManifest = new JsonSlurper().parse(file("itsalive/src/main/resources/fabric.mod.json"))
|
||||
if (rootProject.pack_version != "26.2.0-alpha.198"
|
||||
|| rootProject.itsalive_version != "0.0.0-alpha.30"
|
||||
|| migration.source?.pack_version != "26.2.0-alpha.197"
|
||||
|| migration.target?.pack_version != "26.2.0-alpha.198"
|
||||
|| migration.target?.modules != [itsalive: "0.0.0-alpha.30", sanctuary: "0.0.0-alpha.114"]
|
||||
|| migration.fermentation_barrel?.maximum_units_per_input_slot != 1
|
||||
|| migration.fermentation_barrel?.loaded_recipe_prefix_filter != true
|
||||
|| migration.fermentation_barrel?.observer_state?.vanilla_neighbor_updates != true
|
||||
|| migration.inventory_shift_click?.owner != "sanctuary"
|
||||
|| migration.inventory_shift_click?.hotbar_to_all_unlocked_storage_rows != true
|
||||
|| migration.inventory_shift_click?.storage_and_overflow_to_hotbar_only != true
|
||||
|| migration.inventory_shift_click?.shift_double_click_respects_inventory_groups != true
|
||||
|| migration.compatibility?.itsalive_data_version != 1
|
||||
|| migration.compatibility?.itsalive_network_protocol != 3
|
||||
|| migration.compatibility?.save_migration_required != false
|
||||
|| migration.compatibility?.registry_ids_changed != false
|
||||
|| migration.distribution?.packwiz_index_refreshed != true
|
||||
|| itsAliveManifest.custom?.sanctuary26?.data_version != 1
|
||||
|| itsAliveManifest.custom?.sanctuary26?.network_protocol != 3
|
||||
|| release.pack_version != "26.2.0-alpha.198"
|
||||
|| release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.198.mrpack"
|
||||
|| prism.versionId != "26.2.0-alpha.198"
|
||||
|| !packwiz.contains('version = "26.2.0-alpha.198"')
|
||||
|| !packwizIndex.contains('file = "mods/itsalive-0.0.0-alpha.30.jar"')) {
|
||||
throw new GradleException("The alpha.198 fermentation barrel release contract is incomplete")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.named("verifyWorkspace") {
|
||||
dependsOn tasks.named("verifyFermentationBarrelAutomationRelease")
|
||||
}
|
||||
|
||||
tasks.named("check") {
|
||||
dependsOn tasks.named("verifyWorkspace")
|
||||
dependsOn tasks.named("verifyTransport")
|
||||
|
||||
+2
-2
@@ -18,7 +18,7 @@ redstoner_version=0.0.0-alpha.10
|
||||
redstoner_lifecycle=active
|
||||
anotherworld_version=0.0.0-alpha.49
|
||||
anotherworld_lifecycle=active
|
||||
itsalive_version=0.0.0-alpha.29
|
||||
itsalive_version=0.0.0-alpha.30
|
||||
itsalive_lifecycle=active
|
||||
ouch_version=0.0.0-alpha.8
|
||||
ouch_lifecycle=active
|
||||
@@ -30,5 +30,5 @@ onlyfun_version=0.0.0-alpha.19
|
||||
onlyfun_lifecycle=active
|
||||
sanctuary_version=0.0.0-alpha.114
|
||||
sanctuary_lifecycle=active
|
||||
pack_version=26.2.0-alpha.197
|
||||
pack_version=26.2.0-alpha.198
|
||||
maven_group=fr.koka99cab.sanctuary26
|
||||
|
||||
@@ -220,6 +220,7 @@ Planche Dalle bois Planche
|
||||
- L'ingrédient ou le résultat est visible sur le couvercle et l'overlay indique le temps restant.
|
||||
- Un clic droit récupère le produit fini ; sinon il retire le dernier ingrédient.
|
||||
- Hopper au-dessus ou sur les côtés : ingrédients ; hopper dessous : résultat.
|
||||
- Chaque emplacement d'entrée accepte une seule unité. L'automatisation refuse les doublons et tout ajout qui ne peut plus compléter une recette connue, puis se verrouille naturellement dès que la recette est complète.
|
||||
|
||||
### Redstone et comparateurs
|
||||
|
||||
@@ -227,6 +228,8 @@ Les six postes — presse, moulin, poêle, marmite, four et tonneau — fourniss
|
||||
|
||||
Les observateurs suivent le comportement vanilla : ils émettent une impulsion quand le bloc change réellement d'état visible, par exemple lorsque la presse change de niveau, que la marmite change de mélange ou qu'un appareil s'allume ou s'éteint. Ils ne réagissent pas à chaque tick de progression ni aux changements d'inventaire invisibles ; pour ces informations, il faut utiliser un comparateur.
|
||||
|
||||
Le tonneau de fermentation expose également ses transitions de contenu : vide, un à quatre ingrédients acceptés, puis résultat prêt. Un observateur placé contre lui réagit à chacune de ces transitions, mais pas à chaque tick de macération.
|
||||
|
||||
## Ingrédients de base connus
|
||||
|
||||
Ces transformations sont disponibles sans page secrète.
|
||||
|
||||
+55
-3
@@ -11,6 +11,14 @@ tasks.register("culinaryBatchingSmoke", JavaExec) {
|
||||
mainClass = "fr.koka99cab.sanctuary26.itsalive.culinary.recipe.CulinaryBatchingSmoke"
|
||||
}
|
||||
|
||||
tasks.register("culinaryPartialMatchingSmoke", JavaExec) {
|
||||
group = "verification"
|
||||
description = "Checks shapeless recipe prefixes used by hopper-fed fermentation barrels."
|
||||
dependsOn tasks.named("testClasses")
|
||||
classpath = sourceSets.test.runtimeClasspath
|
||||
mainClass = "fr.koka99cab.sanctuary26.itsalive.culinary.recipe.CulinaryPartialMatchingSmoke"
|
||||
}
|
||||
|
||||
tasks.named("test") {
|
||||
// Quantity contracts are executable smoke tasks, not JUnit engine tests.
|
||||
failOnNoDiscoveredTests = false
|
||||
@@ -409,7 +417,7 @@ tasks.register("verifyItsAlive") {
|
||||
def climateSource = file("src/main/java/fr/koka99cab/sanctuary26/itsalive/agriculture/ClimateCropForaging.java").text
|
||||
def pineappleSource = file("src/main/java/fr/koka99cab/sanctuary26/itsalive/agriculture/PineappleItem.java").text
|
||||
def worldgenSource = file("src/main/java/fr/koka99cab/sanctuary26/itsalive/agriculture/ItsAliveAgricultureWorldGeneration.java").text
|
||||
if (project.version.toString() != "0.0.0-alpha.29"
|
||||
if (project.version.toString() != "0.0.0-alpha.30"
|
||||
|| climateMigration.target?.pack_version != "26.2.0-alpha.157"
|
||||
|| climateMigration.target?.modules?.itsalive != "0.0.0-alpha.24"
|
||||
|| !climateSource.contains("PlayerBlockBreakEvents.AFTER.register")
|
||||
@@ -1141,7 +1149,7 @@ tasks.register("verifyCulinaryReliability") {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (project.version.toString() != "0.0.0-alpha.29"
|
||||
if (project.version.toString() != "0.0.0-alpha.30"
|
||||
|| migration.target?.modules?.itsalive != "0.0.0-alpha.28"
|
||||
|| migration.culinary_fixes?.food_press_contents_destroyed_on_break != true
|
||||
|| migration.culinary_fixes?.comparator_contract?.blocks?.size() != 6
|
||||
@@ -1179,7 +1187,7 @@ tasks.register("verifyCauldronBatching") {
|
||||
def recipe = file("src/main/java/fr/koka99cab/sanctuary26/itsalive/culinary/recipe/CulinaryProcessRecipe.java").text
|
||||
def cauldron = file("src/main/java/fr/koka99cab/sanctuary26/itsalive/culinary/block/entity/CookingCauldronBlockEntity.java").text
|
||||
def timed = file("src/main/java/fr/koka99cab/sanctuary26/itsalive/culinary/block/entity/AbstractTimedCulinaryBlockEntity.java").text
|
||||
if (project.version.toString() != "0.0.0-alpha.29"
|
||||
if (project.version.toString() != "0.0.0-alpha.30"
|
||||
|| migration.target?.modules?.itsalive != "0.0.0-alpha.29"
|
||||
|| migration.cauldron_batches?.logical_stack_limit != 64
|
||||
|| migration.cauldron_batches?.identity != "same_item_same_components"
|
||||
@@ -1198,9 +1206,53 @@ tasks.register("verifyCauldronBatching") {
|
||||
}
|
||||
}
|
||||
|
||||
tasks.register("verifyFermentationBarrelAutomation") {
|
||||
group = "verification"
|
||||
description = "Checks alpha.30 bounded hopper input and vanilla observer states for fermentation barrels."
|
||||
inputs.file(rootProject.file(
|
||||
"pack/migrations/26.2.0-alpha.197-fermentation-barrel-automation-to-alpha.198.json"))
|
||||
inputs.file(file("src/main/java/fr/koka99cab/sanctuary26/itsalive/culinary/block/FermentationBarrelBlock.java"))
|
||||
inputs.file(file("src/main/java/fr/koka99cab/sanctuary26/itsalive/culinary/block/entity/FermentationBarrelBlockEntity.java"))
|
||||
inputs.file(file("src/main/java/fr/koka99cab/sanctuary26/itsalive/culinary/recipe/CulinaryProcessRecipe.java"))
|
||||
inputs.file(file("src/main/java/fr/koka99cab/sanctuary26/itsalive/culinary/recipe/CulinaryPartialMatching.java"))
|
||||
inputs.file(file("src/main/resources/assets/itsalive/blockstates/fermentation_barrel.json"))
|
||||
doLast {
|
||||
def migration = new JsonSlurper().parse(rootProject.file(
|
||||
"pack/migrations/26.2.0-alpha.197-fermentation-barrel-automation-to-alpha.198.json"))
|
||||
def block = file("src/main/java/fr/koka99cab/sanctuary26/itsalive/culinary/block/FermentationBarrelBlock.java").text
|
||||
def barrel = file("src/main/java/fr/koka99cab/sanctuary26/itsalive/culinary/block/entity/FermentationBarrelBlockEntity.java").text
|
||||
def recipe = file("src/main/java/fr/koka99cab/sanctuary26/itsalive/culinary/recipe/CulinaryProcessRecipe.java").text
|
||||
def partialMatching = file("src/main/java/fr/koka99cab/sanctuary26/itsalive/culinary/recipe/CulinaryPartialMatching.java").text
|
||||
def blockstate = new JsonSlurper().parse(
|
||||
file("src/main/resources/assets/itsalive/blockstates/fermentation_barrel.json"))
|
||||
if (project.version.toString() != "0.0.0-alpha.30"
|
||||
|| migration.source?.modules?.itsalive != "0.0.0-alpha.29"
|
||||
|| migration.target?.modules?.itsalive != "0.0.0-alpha.30"
|
||||
|| migration.fermentation_barrel?.maximum_units_per_input_slot != 1
|
||||
|| migration.fermentation_barrel?.loaded_recipe_prefix_filter != true
|
||||
|| migration.fermentation_barrel?.further_input_rejected_when_recipe_complete != true
|
||||
|| migration.fermentation_barrel?.observer_state?.property != "contents"
|
||||
|| migration.fermentation_barrel?.observer_state?.progress_tick_updates != false
|
||||
|| migration.compatibility?.existing_input_stacks_preserved != true
|
||||
|| !block.contains('IntegerProperty.create("contents", 0, 5)')
|
||||
|| !block.contains("builder.add(FACING, CONTENTS)")
|
||||
|| !barrel.contains("getMaxStackSize(ItemStack stack)")
|
||||
|| !barrel.contains("!getItem(slot).isEmpty()")
|
||||
|| !barrel.contains("CulinaryRecipeTypes.acceptsPartial")
|
||||
|| !barrel.contains("state.setValue(FermentationBarrelBlock.CONTENTS, contents), Block.UPDATE_ALL")
|
||||
|| !recipe.contains("acceptsPartial(List<ItemStack> stacks)")
|
||||
|| !partialMatching.contains("canAssignDistinctIngredients")
|
||||
|| blockstate.multipart?.size() != 6) {
|
||||
throw new GradleException("It's Alive alpha.30 fermentation barrel automation contract is incomplete")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.named("check") {
|
||||
dependsOn tasks.named("verifyItsAlive")
|
||||
dependsOn tasks.named("verifyCulinaryReliability")
|
||||
dependsOn tasks.named("verifyCauldronBatching")
|
||||
dependsOn tasks.named("culinaryBatchingSmoke")
|
||||
dependsOn tasks.named("verifyFermentationBarrelAutomation")
|
||||
dependsOn tasks.named("culinaryPartialMatchingSmoke")
|
||||
}
|
||||
|
||||
+7
-2
@@ -26,11 +26,14 @@ import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.StateDefinition;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
import net.minecraft.world.level.block.state.properties.EnumProperty;
|
||||
import net.minecraft.world.level.block.state.properties.IntegerProperty;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
|
||||
/** World-time fermentation inventory with top/side input and bottom hopper output. */
|
||||
public final class FermentationBarrelBlock extends BaseEntityBlock {
|
||||
public static final EnumProperty<Direction> FACING = BlockStateProperties.FACING;
|
||||
/** 0 empty, 1-4 accepted ingredients, 5 finished product. */
|
||||
public static final IntegerProperty CONTENTS = IntegerProperty.create("contents", 0, 5);
|
||||
private final Supplier<? extends BlockEntityType<FermentationBarrelBlockEntity>> blockEntityType;
|
||||
private final MapCodec<FermentationBarrelBlock> instanceCodec;
|
||||
|
||||
@@ -41,7 +44,9 @@ public final class FermentationBarrelBlock extends BaseEntityBlock {
|
||||
super(properties);
|
||||
this.blockEntityType = blockEntityType;
|
||||
this.instanceCodec = MapCodec.unit(this);
|
||||
registerDefaultState(stateDefinition.any().setValue(FACING, Direction.NORTH));
|
||||
registerDefaultState(stateDefinition.any()
|
||||
.setValue(FACING, Direction.NORTH)
|
||||
.setValue(CONTENTS, 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -173,6 +178,6 @@ public final class FermentationBarrelBlock extends BaseEntityBlock {
|
||||
|
||||
@Override
|
||||
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
|
||||
builder.add(FACING);
|
||||
builder.add(FACING, CONTENTS);
|
||||
}
|
||||
}
|
||||
|
||||
+51
-2
@@ -5,6 +5,8 @@ import fr.koka99cab.sanctuary26.itsalive.culinary.block.FermentationBarrelBlock;
|
||||
import fr.koka99cab.sanctuary26.itsalive.culinary.recipe.CulinaryProcessRecipe;
|
||||
import fr.koka99cab.sanctuary26.itsalive.culinary.recipe.CulinaryRecipeInput;
|
||||
import fr.koka99cab.sanctuary26.itsalive.culinary.recipe.CulinaryRecipeTypes;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
@@ -12,6 +14,7 @@ import net.minecraft.resources.Identifier;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.RecipeHolder;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.storage.ValueInput;
|
||||
@@ -41,6 +44,7 @@ public final class FermentationBarrelBlockEntity extends AbstractCulinaryContain
|
||||
ServerLevel level, BlockPos pos, BlockState state, FermentationBarrelBlockEntity barrel
|
||||
) {
|
||||
barrel.process(level);
|
||||
barrel.syncObservableState();
|
||||
}
|
||||
|
||||
private void process(ServerLevel level) {
|
||||
@@ -84,7 +88,14 @@ public final class FermentationBarrelBlockEntity extends AbstractCulinaryContain
|
||||
}
|
||||
|
||||
public int insertIngredient(ItemStack source, int amount) {
|
||||
return insert(source, amount, 0, INPUT_SLOTS, this::isFermentationIngredient);
|
||||
if (source.isEmpty() || amount <= 0) return 0;
|
||||
for (int slot = 0; slot < INPUT_SLOTS; slot++) {
|
||||
if (!canPlaceItem(slot, source)) continue;
|
||||
items.set(slot, source.copyWithCount(1));
|
||||
contentsChanged(slot);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private boolean isFermentationIngredient(ItemStack stack) {
|
||||
@@ -177,7 +188,20 @@ public final class FermentationBarrelBlockEntity extends AbstractCulinaryContain
|
||||
|
||||
@Override
|
||||
public boolean canPlaceItem(int slot, ItemStack stack) {
|
||||
return slot >= 0 && slot < INPUT_SLOTS && isFermentationIngredient(stack);
|
||||
if (slot < 0 || slot >= INPUT_SLOTS || !getItem(slot).isEmpty()
|
||||
|| hasFinishedProduct() || !isFermentationIngredient(stack)
|
||||
|| !(level instanceof ServerLevel serverLevel)) {
|
||||
return false;
|
||||
}
|
||||
List<ItemStack> candidate = new ArrayList<>(inputView(0, INPUT_SLOTS));
|
||||
candidate.set(slot, stack.copyWithCount(1));
|
||||
return CulinaryRecipeTypes.acceptsPartial(
|
||||
serverLevel, CulinaryAppliance.FERMENTATION_BARREL, candidate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxStackSize(ItemStack stack) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -204,6 +228,12 @@ public final class FermentationBarrelBlockEntity extends AbstractCulinaryContain
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void sync() {
|
||||
super.sync();
|
||||
syncObservableState();
|
||||
}
|
||||
|
||||
private void resetFermentation() {
|
||||
if (startedAtGameTime >= 0 || activeRecipe != null || activeDuration != 0) {
|
||||
startedAtGameTime = -1L;
|
||||
@@ -213,6 +243,25 @@ public final class FermentationBarrelBlockEntity extends AbstractCulinaryContain
|
||||
}
|
||||
}
|
||||
|
||||
private void syncObservableState() {
|
||||
if (level == null) return;
|
||||
int contents = hasFinishedProduct() ? 5 : occupiedInputSlots();
|
||||
BlockState state = getBlockState();
|
||||
if (state.hasProperty(FermentationBarrelBlock.CONTENTS)
|
||||
&& state.getValue(FermentationBarrelBlock.CONTENTS) != contents) {
|
||||
level.setBlock(worldPosition,
|
||||
state.setValue(FermentationBarrelBlock.CONTENTS, contents), Block.UPDATE_ALL);
|
||||
}
|
||||
}
|
||||
|
||||
private int occupiedInputSlots() {
|
||||
int occupied = 0;
|
||||
for (int slot = 0; slot < INPUT_SLOTS; slot++) {
|
||||
if (!getItem(slot).isEmpty()) occupied++;
|
||||
}
|
||||
return occupied;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void saveAdditional(ValueOutput output) {
|
||||
super.saveAdditional(output);
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
package fr.koka99cab.sanctuary26.itsalive.culinary.recipe;
|
||||
|
||||
/** Pure bipartite matching used to validate shapeless recipe prefixes. */
|
||||
public final class CulinaryPartialMatching {
|
||||
private CulinaryPartialMatching() {
|
||||
}
|
||||
|
||||
public static boolean canAssignDistinctIngredients(boolean[][] compatibility) {
|
||||
if (compatibility.length == 0) return true;
|
||||
int ingredientCount = compatibility[0].length;
|
||||
if (compatibility.length > ingredientCount) return false;
|
||||
for (boolean[] row : compatibility) {
|
||||
if (row.length != ingredientCount) {
|
||||
throw new IllegalArgumentException("Compatibility matrix must be rectangular");
|
||||
}
|
||||
}
|
||||
return assign(compatibility, 0, new boolean[ingredientCount]);
|
||||
}
|
||||
|
||||
private static boolean assign(boolean[][] compatibility, int stackIndex, boolean[] usedIngredients) {
|
||||
if (stackIndex >= compatibility.length) return true;
|
||||
for (int ingredientIndex = 0; ingredientIndex < usedIngredients.length; ingredientIndex++) {
|
||||
if (usedIngredients[ingredientIndex] || !compatibility[stackIndex][ingredientIndex]) continue;
|
||||
usedIngredients[ingredientIndex] = true;
|
||||
if (assign(compatibility, stackIndex + 1, usedIngredients)) return true;
|
||||
usedIngredients[ingredientIndex] = false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
+18
@@ -4,6 +4,7 @@ import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.MapCodec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import fr.koka99cab.sanctuary26.itsalive.culinary.CulinaryAppliance;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf;
|
||||
@@ -79,6 +80,23 @@ public final class CulinaryProcessRecipe implements Recipe<CulinaryRecipeInput>
|
||||
return assignIngredient(0, stacks, new int[stacks.size()], assignment) ? assignment : null;
|
||||
}
|
||||
|
||||
/** True when every occupied slot can still become part of this recipe. */
|
||||
public boolean acceptsPartial(List<ItemStack> stacks) {
|
||||
List<ItemStack> occupied = new ArrayList<>();
|
||||
for (ItemStack stack : stacks) {
|
||||
if (!stack.isEmpty()) occupied.add(stack);
|
||||
}
|
||||
if (occupied.size() > ingredients.size()) return false;
|
||||
boolean[][] compatibility = new boolean[occupied.size()][ingredients.size()];
|
||||
for (int stackIndex = 0; stackIndex < occupied.size(); stackIndex++) {
|
||||
for (int ingredientIndex = 0; ingredientIndex < ingredients.size(); ingredientIndex++) {
|
||||
compatibility[stackIndex][ingredientIndex] =
|
||||
ingredients.get(ingredientIndex).test(occupied.get(stackIndex));
|
||||
}
|
||||
}
|
||||
return CulinaryPartialMatching.canAssignDistinctIngredients(compatibility);
|
||||
}
|
||||
|
||||
private int[] matchingDistinctSlots(List<ItemStack> stacks) {
|
||||
int[] assignment = new int[ingredients.size()];
|
||||
Arrays.fill(assignment, -1);
|
||||
|
||||
+15
@@ -2,6 +2,7 @@ package fr.koka99cab.sanctuary26.itsalive.culinary.recipe;
|
||||
|
||||
import fr.koka99cab.sanctuary26.itsalive.ItsAliveMod;
|
||||
import fr.koka99cab.sanctuary26.itsalive.culinary.CulinaryAppliance;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
@@ -79,4 +80,18 @@ public final class CulinaryRecipeTypes {
|
||||
.anyMatch(recipe -> recipe.appliance() == appliance
|
||||
&& recipe.ingredients().stream().anyMatch(ingredient -> ingredient.test(stack)));
|
||||
}
|
||||
|
||||
/** True when all supplied stacks form a valid, shapeless prefix of one loaded recipe. */
|
||||
public static boolean acceptsPartial(
|
||||
ServerLevel level,
|
||||
CulinaryAppliance appliance,
|
||||
List<ItemStack> stacks
|
||||
) {
|
||||
if (type == null) return false;
|
||||
return level.getServer().getRecipeManager().getRecipes().stream()
|
||||
.map(RecipeHolder::value)
|
||||
.filter(CulinaryProcessRecipe.class::isInstance)
|
||||
.map(CulinaryProcessRecipe.class::cast)
|
||||
.anyMatch(recipe -> recipe.appliance() == appliance && recipe.acceptsPartial(stacks));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"variants": {
|
||||
"facing=down": { "model": "itsalive:block/fermentation_barrel", "x": 180 },
|
||||
"facing=east": { "model": "itsalive:block/fermentation_barrel", "x": 90, "y": 90 },
|
||||
"facing=north": { "model": "itsalive:block/fermentation_barrel", "x": 90 },
|
||||
"facing=south": { "model": "itsalive:block/fermentation_barrel", "x": 90, "y": 180 },
|
||||
"facing=up": { "model": "itsalive:block/fermentation_barrel" },
|
||||
"facing=west": { "model": "itsalive:block/fermentation_barrel", "x": 90, "y": 270 }
|
||||
}
|
||||
"multipart": [
|
||||
{ "when": { "facing": "down" }, "apply": { "model": "itsalive:block/fermentation_barrel", "x": 180 } },
|
||||
{ "when": { "facing": "east" }, "apply": { "model": "itsalive:block/fermentation_barrel", "x": 90, "y": 90 } },
|
||||
{ "when": { "facing": "north" }, "apply": { "model": "itsalive:block/fermentation_barrel", "x": 90 } },
|
||||
{ "when": { "facing": "south" }, "apply": { "model": "itsalive:block/fermentation_barrel", "x": 90, "y": 180 } },
|
||||
{ "when": { "facing": "up" }, "apply": { "model": "itsalive:block/fermentation_barrel" } },
|
||||
{ "when": { "facing": "west" }, "apply": { "model": "itsalive:block/fermentation_barrel", "x": 90, "y": 270 } }
|
||||
]
|
||||
}
|
||||
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
package fr.koka99cab.sanctuary26.itsalive.culinary.recipe;
|
||||
|
||||
/** Pure recipe-prefix smoke for hopper-fed culinary appliances. */
|
||||
public final class CulinaryPartialMatchingSmoke {
|
||||
private CulinaryPartialMatchingSmoke() {
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
expect(true, new boolean[0][0], "empty prefix");
|
||||
expect(true, new boolean[][] {{true, false, false}}, "single valid ingredient");
|
||||
expect(true, new boolean[][] {{false, true}, {true, false}}, "shapeless assignment");
|
||||
expect(false, new boolean[][] {{true, false}, {true, false}}, "duplicate ingredient");
|
||||
expect(false, new boolean[][] {{false, false}}, "unrelated ingredient");
|
||||
expect(false, new boolean[][] {{true}, {true}}, "too many ingredients");
|
||||
}
|
||||
|
||||
private static void expect(boolean expected, boolean[][] compatibility, String label) {
|
||||
boolean actual = CulinaryPartialMatching.canAssignDistinctIngredients(compatibility);
|
||||
if (actual != expected) {
|
||||
throw new AssertionError(label + ": expected " + expected + ", got " + actual);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"schema_version": 1,
|
||||
"source": {
|
||||
"pack_version": "26.2.0-alpha.197",
|
||||
"modules": {
|
||||
"itsalive": "0.0.0-alpha.29",
|
||||
"sanctuary": "0.0.0-alpha.113"
|
||||
}
|
||||
},
|
||||
"target": {
|
||||
"pack_version": "26.2.0-alpha.198",
|
||||
"modules": {
|
||||
"itsalive": "0.0.0-alpha.30",
|
||||
"sanctuary": "0.0.0-alpha.114"
|
||||
}
|
||||
},
|
||||
"fermentation_barrel": {
|
||||
"id": "itsalive:fermentation_barrel",
|
||||
"input_slots": 4,
|
||||
"maximum_units_per_input_slot": 1,
|
||||
"loaded_recipe_prefix_filter": true,
|
||||
"duplicate_ingredients_rejected_unless_recipe_requires_them": true,
|
||||
"further_input_rejected_when_recipe_complete": true,
|
||||
"observer_state": {
|
||||
"property": "contents",
|
||||
"empty": 0,
|
||||
"accepted_ingredients": "1-4",
|
||||
"result_ready": 5,
|
||||
"vanilla_neighbor_updates": true,
|
||||
"progress_tick_updates": false
|
||||
}
|
||||
},
|
||||
"inventory_shift_click": {
|
||||
"owner": "sanctuary",
|
||||
"hotbar_to_all_unlocked_storage_rows": true,
|
||||
"storage_and_overflow_to_hotbar_only": true,
|
||||
"shift_double_click_respects_inventory_groups": true
|
||||
},
|
||||
"distribution": {
|
||||
"packwiz_index_refreshed": true
|
||||
},
|
||||
"compatibility": {
|
||||
"itsalive_data_version": 1,
|
||||
"itsalive_network_protocol": 3,
|
||||
"existing_input_stacks_preserved": true,
|
||||
"save_migration_required": false,
|
||||
"registry_ids_changed": false
|
||||
}
|
||||
}
|
||||
+12
-12
@@ -14,15 +14,15 @@ hash = "41f4f4c88c71d0a23446d5014f7407d55ad477441847099cad24492b032335a0"
|
||||
|
||||
[[files]]
|
||||
file = "mods/ambiance-0.0.0-alpha.11.jar"
|
||||
hash = "d8a2f1936e9c43ad36e3ffab5f791315970a66f374bf3f6fc387d56107203898"
|
||||
hash = "70c23a4e4059eaf52f99e4a31585169c6599b4e33ad7554cddbbec536096cc64"
|
||||
|
||||
[[files]]
|
||||
file = "mods/anotherworld-0.0.0-alpha.49.jar"
|
||||
hash = "992c86f16136a9c013888ced20d863528d4f6c48244bb1d342c189b3ac4ad739"
|
||||
hash = "69f6c36628503f5abf04ec3f9e8351d7b3e5468829573733590641a9078760d0"
|
||||
|
||||
[[files]]
|
||||
file = "mods/events-0.0.0-alpha.0.jar"
|
||||
hash = "a637271a50be68666a9eb86bd4a817f19d0592f81127b96746377cb2558394e0"
|
||||
hash = "2cd283f8b85055a405947a41325f9780b98046b659a24a95c3279d96c97205d5"
|
||||
|
||||
[[files]]
|
||||
file = "mods/fabric-api.pw.toml"
|
||||
@@ -31,7 +31,7 @@ metafile = true
|
||||
|
||||
[[files]]
|
||||
file = "mods/iliketomoveit-0.0.0-alpha.13.jar"
|
||||
hash = "d2b1c2c0769a3da4a7374ae8f39311531b48683dea277f8c3f084d77c50b795b"
|
||||
hash = "b1b33c5fe7089b8d1baac4ce5fbd0ee386def1456b71af6f761d6ae800e61690"
|
||||
|
||||
[[files]]
|
||||
file = "mods/iris.pw.toml"
|
||||
@@ -39,8 +39,8 @@ hash = "84a3cef87679c0d21dceb4641167dc0368b9a3593698f6a3632485e9b3a8d5da"
|
||||
metafile = true
|
||||
|
||||
[[files]]
|
||||
file = "mods/itsalive-0.0.0-alpha.29.jar"
|
||||
hash = "2ccfc7b6aead6d00f5dc84a4627acba9ab9da70229c066799089dd98de826b90"
|
||||
file = "mods/itsalive-0.0.0-alpha.30.jar"
|
||||
hash = "57a7a91b47c5648710fa165a894c785c5958afe07f7d7f4e3ef4d0cc38cacd8b"
|
||||
|
||||
[[files]]
|
||||
file = "mods/jei.pw.toml"
|
||||
@@ -49,23 +49,23 @@ metafile = true
|
||||
|
||||
[[files]]
|
||||
file = "mods/masterkey-0.0.0-alpha.8.jar"
|
||||
hash = "11f885417f45cc6fa752f561ecb475ad43a99071f88fd6a0f0521a292a93642e"
|
||||
hash = "90803d3a67065ee02cca4fc32c8f18301e93e1ff2c4c8002feb5f28c7ec014da"
|
||||
|
||||
[[files]]
|
||||
file = "mods/onlyfun-0.0.0-alpha.19.jar"
|
||||
hash = "d9b5e7bfd96aac0bc2cfc6394249c86c74ad58d6685a3af37bb090682377a23a"
|
||||
hash = "86c7f88ec348f678cb873d2386df38ca300928f4b0e7c350cae722ba42389986"
|
||||
|
||||
[[files]]
|
||||
file = "mods/ouch-0.0.0-alpha.8.jar"
|
||||
hash = "4152c0ecbdde7450c49c7e28367efa02ae666bb29dbb247ac90da3393e6485a0"
|
||||
hash = "bd57342e13832fe67e7abeb0f2768170552fd868668a6f6940cd73f57dd7b37c"
|
||||
|
||||
[[files]]
|
||||
file = "mods/redstoner-0.0.0-alpha.10.jar"
|
||||
hash = "73262d1f88f820935ce3e59e1884bce66c6f1883bf5becbc9d2136a64d862011"
|
||||
hash = "2259c2a982c14d29f27c7a0908aeee11b7156b2823202a200aa89af24703eb23"
|
||||
|
||||
[[files]]
|
||||
file = "mods/sanctuary-0.0.0-alpha.113.jar"
|
||||
hash = "31155aad4c2030a5ede42b1b1d16cba191eaa0ade65051ff4d3973bf2db94c42"
|
||||
file = "mods/sanctuary-0.0.0-alpha.114.jar"
|
||||
hash = "7e45eb1a6756ed9a95d79d794b7c2e7a6918388fd9e5286160cd890d1dfaf0f6"
|
||||
|
||||
[[files]]
|
||||
file = "mods/simple-voice-chat.pw.toml"
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
name = "Sanctuary 26.2"
|
||||
author = "KOKA99CAB"
|
||||
version = "26.2.0-alpha.197"
|
||||
version = "26.2.0-alpha.198"
|
||||
pack-format = "packwiz:1.1.0"
|
||||
|
||||
[index]
|
||||
file = "index.toml"
|
||||
hash-format = "sha256"
|
||||
hash = "c191cd8a9c30d94babee9696a0d67268368f943c44fa26da45e1ba9996db03c7"
|
||||
hash = "55cce7f3d86dbb8546626ea5f3ed5596efa656ab41f528d8b7ed963470b81219"
|
||||
|
||||
[versions]
|
||||
fabric = "0.19.3"
|
||||
|
||||
@@ -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.197",
|
||||
"versionId": "26.2.0-alpha.198",
|
||||
"files": [
|
||||
{
|
||||
"path": "mods/fabric-api-0.158.0+26.2.jar",
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"schema_version": 1,
|
||||
"pack_version": "26.2.0-alpha.197",
|
||||
"pack_version": "26.2.0-alpha.198",
|
||||
"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.197.mrpack",
|
||||
"primary_file": "sanctuary-26.2.0-alpha.198.mrpack",
|
||||
"shared_client_server_pack": true,
|
||||
"update_owner": "packwiz-installer",
|
||||
"check_on_launch": true,
|
||||
|
||||
@@ -3097,4 +3097,3 @@ tasks.named("check") {
|
||||
dependsOn tasks.named("celestialGraphSmoke")
|
||||
dependsOn tasks.named("questRequestModelSmoke")
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user