Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## 0.3.8.112021

- Added the missing recipe-book unlocks for crafting and rebuilding pieces.
- Made the next recipes appear while the crafting table is still open.
- Keep recipe previews on the normal item model, including saved orientation variants.

## 0.3.7.112021

- Use a shovel to turn ordinary dirt and grass steps and corners into paths.
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ it into a path, using the same shovel action.

## Crafting

Recipes appear in the recipe book as you collect their ingredients. Crafting a
piece also reveals its next cuts and recombination recipes while the table is
still open.

Craft pieces from matching full blocks, slabs and steps. For example, three
full blocks in a row make six slabs, and two matching slabs placed diagonally
make four steps. Existing vanilla recipes stay available.
Expand Down
9 changes: 9 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ tasks.withType(Test).configureEach {
if (pinnedJava8.isPresent()) javaLauncher = javaToolchains.launcherFor(exactJava8Spec)
}
tasks.withType(JavaExec).configureEach {
if (providers.gradleProperty('snapshotRecipeBook').getOrElse('false').toBoolean()) {
systemProperty 'skysbuildingpieces.snapshotRecipeBook', 'true'
}
if (pinnedJava8.isPresent()) javaLauncher = javaToolchains.launcherFor(exactJava8Spec)
}

Expand Down Expand Up @@ -736,3 +739,9 @@ ext.mineralogyProfileAdditionalMods = files()
apply from: 'gradle/mineralogy-runs.gradle'
apply from: 'gradle/mineralogy-fixtures.gradle'
apply from: 'gradle/grass-slabs-release.gradle'

apply from: 'gradle/recipe-advancements.gradle'

ext.configureRecipeBookRun = configureFromForgeRun
ext.recipeBookLogConfiguration = file('src/integrationTest/resources/log4j2.xml').toURI().toString()
apply from: 'gradle/recipe-book-verification.gradle'
11 changes: 11 additions & 0 deletions docs/BUILDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,14 @@ locked native jars are available.

Verification worlds live under `build/`. Keep player worlds in the separate
ordinary game folders or another instance.

## Recipe-book resources

The build generates unlock advancements from `src/main/recipe-book/recipes.json`.
The runtime checks compare those entries with the registered recipes and exercise
inventory discovery, crafting-table discovery and recipe-book persistence.
Optional catalogue entries load only when their recipe exists.

Recipe unlocks have no shared advancement parent. Minecraft 1.12 walks that
visibility tree recursively when loading completed progress, which can overflow
with a large catalogue. The inventory and crafting unlock criteria are unchanged.
9 changes: 9 additions & 0 deletions docs/RELEASE-0.3.8.112021.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Recipe book update for Minecraft 1.12.2

Recipes now appear in the recipe book when you obtain their ingredients.
Crafting a piece also reveals its next cuts and recombination recipes while
the crafting table is open. Saved blocks, items and crafting quantities are
unchanged.

The recipe book shows the normal piece item when cycling ingredients, while
saved placement orientations remain valid for crafting and auto-fill.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ release_enabled=true
curseforge_project_id=1754162
mod_name=Sky's Building Pieces
mod_license=LGPL-2.1-only
mod_version=0.3.7.112021
mod_version=0.3.8.112021
mod_group=zone.moddev.mc.skysbuildingpieces
mod_authors=SkyBlade1978
mod_description=Extra building shapes for vanilla materials, with built-in Mineralogy support when installed. No world generation.
8 changes: 4 additions & 4 deletions gradle/grass-slabs-release.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Public main jar, used only for optional development and integration checks.
version=1.1.1.112021
coordinate=zone.moddev.mc.skysgrassslabs:SkysGrassSlabs:1.1.1.112021
sha256=E5C39421E5291F530D200872386B2C6F963BAB6310CC13A3FF8A19409E6A53B9
source.commit=6d10853578e339b3946b83bcbee4e799f77523ea
version=1.1.2.112021
coordinate=zone.moddev.mc.skysgrassslabs:SkysGrassSlabs:1.1.2.112021
sha256=6F056EA5E4ADCE363D835955967ECC4ECA93A153645A32140DE3FC7655529D9C
source.commit=b2636d8a67efa3f257a8a69293ce513e979010fd
46 changes: 46 additions & 0 deletions gradle/recipe-advancements.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import groovy.json.JsonOutput
import groovy.json.JsonSlurper

// Recipe IDs and exact ingredient variants are checked against the live registry.
def recipeBookManifest = layout.projectDirectory.file('src/main/recipe-book/recipes.json')
def recipeBookOutput = layout.buildDirectory.dir('generated/recipe-advancements')
def generateRecipeAdvancements = tasks.register('generateRecipeAdvancements') {
inputs.file(recipeBookManifest)
outputs.dir(recipeBookOutput)
doLast {
File output = recipeBookOutput.get().asFile
delete output
List entries = new JsonSlurper().parse(recipeBookManifest.asFile) as List
Set<String> ids = new HashSet<>()
entries.each { entry ->
String recipe = entry.recipe
String owner = project.mod_id
if (entry.owner != owner || !ids.add(recipe) || entry.ingredients.isEmpty()) {
throw new GradleException("Invalid recipe-book entry: ${recipe}")
}
String path = recipe.split(':', 2)[1]
Map criteria = [:]
List<String> requirements = []
entry.ingredients.eachWithIndex { ingredient, index ->
String key = entry.ingredients.size() == 1 ? 'has_ingredient' : 'has_ingredient_' + index
criteria[key] = [trigger: 'minecraft:inventory_changed', conditions: [items: [ingredient]]]
requirements.add(key)
}
criteria.has_the_recipe = [trigger: 'minecraft:recipe_unlocked', conditions: [recipe: recipe]]
requirements.add('has_the_recipe')
// A shared parent makes 1.12 recurse through thousands of learned recipes on login.
// Independent hidden unlocks keep the same recipe-book behaviour without that recursion.
Map advancement = [rewards: [recipes: [recipe]],
criteria: criteria, requirements: [requirements]]
if (project.mod_id != 'skysgrassslabs') {
// Optional catalogues and recovery recipes must not leave phantom unlocks.
advancement.conditions = [[type: 'skysbuildingpieces:recipe_exists', recipe: recipe]]
}
File target = new File(output, "assets/${owner}/advancements/recipes/${path}.json")
target.parentFile.mkdirs()
target.setText(JsonOutput.prettyPrint(JsonOutput.toJson(advancement)) + '\n', 'UTF-8')
}
}
}
sourceSets.main.resources.srcDir(generateRecipeAdvancements)
tasks.named('processResources') { dependsOn generateRecipeAdvancements }
53 changes: 53 additions & 0 deletions gradle/recipe-book-verification.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Recipe-book checks get their own server runs rather than sharing one long gameplay tick.
def bookDirectory = layout.buildDirectory.dir('recipe-book-test-run')
def prepareBook = tasks.register('prepareRecipeBookTest') {
dependsOn tasks.named('integrationTestModJar')
doLast {
File directory = bookDirectory.get().asFile
if (directory.canonicalFile != new File(buildDir, 'recipe-book-test-run').canonicalFile) {
throw new GradleException('Recipe-book verification must stay inside the build directory')
}
delete directory
copy {
from tasks.named('integrationTestModJar', Jar).flatMap { it.archiveFile }
into new File(directory, 'mods')
}
new File(directory, 'eula.txt').setText('eula=true\n', 'UTF-8')
['banned-players.json', 'banned-ips.json', 'ops.json', 'whitelist.json'].each {
new File(directory, it).setText('[]\n', 'UTF-8')
}
new File(directory, 'server.properties').setText('''level-name=world
level-seed=4815162342
online-mode=false
server-ip=127.0.0.1
server-port=0
generate-structures=false
spawn-animals=false
spawn-monsters=false
max-tick-time=120000
''', 'UTF-8')
if (project.ext.has('recipeBookExtraMods')) {
copy { from project.ext.recipeBookExtraMods; into new File(directory, 'mods') }
}
}
}
def bookTasks = [:]
['fresh', 'reload'].each { phase ->
bookTasks[phase] = tasks.register('integrationRecipeBook' + phase.capitalize() + 'Process', JavaExec) {
dependsOn phase == 'fresh' ? prepareBook : bookTasks.fresh
workingDir bookDirectory
systemProperty 'skysbuildingpieces.integrationPhase', 'recipe-book-' + phase
systemProperty 'log4j.configurationFile', project.ext.recipeBookLogConfiguration
project.ext.configureRecipeBookRun(delegate, 'runServer')
doLast {
if (!new File(bookDirectory.get().asFile, 'world/recipe-book-' + phase + '.pass').isFile()) {
throw new GradleException('Recipe-book ' + phase + ' verification did not complete')
}
if (!fileTree(new File(bookDirectory.get().asFile, 'crash-reports')).isEmpty()) {
throw new GradleException('Recipe-book verification produced a crash report')
}
}
}
}
tasks.register('integrationRecipeBookTest') { dependsOn bookTasks.reload }
tasks.named('check') { dependsOn tasks.named('integrationRecipeBookTest') }
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ public void tick(TickEvent.ClientTickEvent event) {

System.out.println("BUILDING_PIECES_CREATIVE_TAB_PASS entries=" + creative.size());

RecipePreviewModels.check(minecraft);

int checked = 0;

for (PieceBlock block : Pieces.BLOCKS.values()) {
Expand Down
Loading
Loading