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: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -137,9 +137,9 @@ jobs:
if-no-files-found: error
retention-days: 30
path: |
build/libs/SkysBuildingPieces-0.3.10.121012.jar
build/libs/SkysBuildingPieces-0.3.10.121012-sources.jar
build/libs/SkysBuildingPieces-0.3.10.121012-javadoc.jar
build/libs/SkysBuildingPieces-0.3.11.121012.jar
build/libs/SkysBuildingPieces-0.3.11.121012-sources.jar
build/libs/SkysBuildingPieces-0.3.11.121012-javadoc.jar
build/release/SHA256SUMS
CHANGELOG.md

Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelog

## 0.3.11.121012

- Fix fuel checks for stone, soil and other non-wood pieces in recipe viewers. This also covers the BOP and Mineralogy pieces.
- Keep datapack fuel settings working for non-wood pieces.

## 0.3.10.121012

- Give each crafting result a stable recipe-book button, with alternative ways to make that item grouped together.
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ release_enabled=true
curseforge_project_id=1754162
mod_name=Sky's Building Pieces
mod_license=LGPL-2.1-only
mod_version=0.3.10.121012
mod_version=0.3.11.121012
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.
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,10 @@ private void audit(MinecraftServer server, DeferredAudit pending) {
int recipes = 0;
int stacks = 0;

if (pending == null && (phase.equals("fresh") || phase.equals("reload"))) {
FuelChecks.run();
}

if (phase.equals("water")) {
WaterloggingChecks.run(world);
} else if (phase.equals("staging")) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ public void tick(net.neoforged.neoforge.client.event.ClientTickEvent.Post event)
&& !minecraft.getConnection().getRecipeManager().getRecipes().isEmpty()) {
RecipeBookGroupChecks.run(minecraft);
RecipePreviewModels.check(minecraft);
FuelChecks.run();
org.apache.logging.log4j.LogManager.getLogger().info("BUILDING_PIECES_CLIENT_FUEL_PASS context=with_world");
colours(minecraft);
SnowCoverClientChecks.run(minecraft);
net.minecraft.world.item.CreativeModeTabs.tryRebuildTabContents(minecraft.level.enabledFeatures(),
Expand All @@ -99,6 +101,8 @@ public void tick(net.neoforged.neoforge.client.event.ClientTickEvent.Post event)
org.lwjgl.glfw.GLFW.glfwHideWindow(minecraft.getWindow().getWindow());

ConfigScreenChecks.run(minecraft);
FuelChecks.run();
org.apache.logging.log4j.LogManager.getLogger().info("BUILDING_PIECES_CLIENT_FUEL_PASS context=before_world");
var availableCreative = PiecesTab.entries();

for (net.minecraft.world.item.Item retired : Pieces.RETIRED_TEMPLATES.values()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,92 @@

import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.RecipeType;
import net.minecraft.core.registries.BuiltInRegistries;
import net.neoforged.neoforge.registries.datamaps.builtin.NeoForgeDataMaps;
import zone.moddev.mc.skysbuildingpieces.content.PieceItem;
import zone.moddev.mc.skysbuildingpieces.content.Pieces;

/** Cutting and recombining wood must not multiply its furnace fuel value. */
/** Recipe viewers ask about every item, including pieces that cannot burn. */
public final class FuelChecks {
public static void run() {
int cases = 0;
for (var block : Pieces.playableBlocks()) {
var definition = block.definition(block.defaultBlockState());
if (!definition.type.equals("wood")) {
reportedItems();
configuredNonWoodFuel();
int woodCases = 0;
int otherCases = 0;
for (var registered : BuiltInRegistries.ITEM) {
if (!(registered instanceof PieceItem item)) {
continue;
}
PieceItem item = (PieceItem) block.asItem();
ItemStack full = Pieces.stack(Pieces.nativeState(definition, "full"), 1);
int divisor = switch (block.palette.shape) {
var definition = zone.moddev.mc.skysbuildingpieces.catalogue.Catalogue.INSTANCE.materials.get(item.material);
boolean wooden = definition.type.equals("wood");
ItemStack full = wooden ? Pieces.stack(Pieces.nativeState(definition, "full"), 1) : ItemStack.EMPTY;
var dataFuel = item.builtInRegistryHolder().getData(NeoForgeDataMaps.FURNACE_FUELS);
int defaultFuel = dataFuel == null ? 0 : dataFuel.burnTime();
int divisor = switch (item.piece.palette.shape) {
case SLAB, VERTICAL_SLAB -> 2;
case STEP, HORIZONTAL_STEP, VERTICAL_STEP -> 4;
case CORNER -> 8;
default -> 1;
};
for (var furnace : java.util.List.of(RecipeType.SMELTING, RecipeType.SMOKING, RecipeType.BLASTING)) {
int original = Math.max(0, full.getBurnTime(furnace));
// A null recipe type is the general fuel query used by recipe viewers.
for (var furnace : java.util.Arrays.asList(null, RecipeType.SMELTING, RecipeType.SMOKING, RecipeType.BLASTING)) {
int expected = wooden ? Math.max(0, full.getBurnTime(furnace)) / divisor : defaultFuel;
int actual = new ItemStack(item).getBurnTime(furnace);
if (actual != original / divisor) {
throw new AssertionError("Wood fuel changed through cutting: " + definition.id + "/"
+ block.palette.shape + " expected=" + original / divisor + " actual=" + actual);
if (actual != expected) {
throw new AssertionError("Piece fuel differs from its material or configured default: "
+ BuiltInRegistries.ITEM.getKey(item) + " recipe=" + furnace
+ " expected=" + expected + " actual=" + actual);
}
cases++;
if (wooden) {
woodCases++;
} else {
otherCases++;
}
}
}
if (woodCases == 0 || otherCases == 0) {
throw new AssertionError("Fuel checks must include both wood and non-wood pieces");
}
org.apache.logging.log4j.LogManager.getLogger().info(
"BUILDING_PIECES_FUEL_PASS wood_cases={} nonwood_cases={} general_query=true",
woodCases, otherCases);
}

private static void reportedItems() {
java.util.List<String> failures = new java.util.ArrayList<>();
for (String identity : new String[] { "skysbuildingpieces:mineralogy_tuff_corner",
"skysbuildingpiecesbop:crag_rock_slab" }) {
var id = net.minecraft.resources.ResourceLocation.parse(identity);
if (!BuiltInRegistries.ITEM.containsKey(id)) {
continue;
}
try {
int burnTime = new ItemStack(BuiltInRegistries.ITEM.get(id)).getBurnTime(null);
org.apache.logging.log4j.LogManager.getLogger().info(
"BUILDING_PIECES_REPORTED_FUEL_QUERY item={} burn_time={}", identity, burnTime);
} catch (IllegalStateException failure) {
failures.add(identity + ": " + failure.getMessage());
}
}
if (!failures.isEmpty()) {
throw new AssertionError("Reported recipe-viewer fuel queries failed: " + failures);
}
}

private static void configuredNonWoodFuel() {
Integer expected = Integer.getInteger("skysbuildingpieces.expectedSnowCornerFuel");
if (expected == null) {
return;
}
var item = BuiltInRegistries.ITEM.get(net.minecraft.resources.ResourceLocation.parse(
"skysbuildingpieces:snow_corner"));
int actual = new ItemStack(item).getBurnTime(RecipeType.SMELTING);
if (actual != expected) {
throw new AssertionError("The non-wood fuel data map was ignored: expected=" + expected
+ " actual=" + actual);
}
org.apache.logging.log4j.LogManager.getLogger().info("BUILDING_PIECES_FUEL_PASS cases=" + cases);
org.apache.logging.log4j.LogManager.getLogger().info(
"BUILDING_PIECES_CONFIGURED_FUEL_PASS item=skysbuildingpieces:snow_corner burn_time={}", actual);
}

private FuelChecks() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public void started(ServerStartedEvent event) {
String phase = System.getProperty("skysbuildingpieces.integrationPhase", "");
needsGameplay = !(phase.startsWith("sylvester") || phase.startsWith("retired-rocks-")
|| phase.startsWith("bop-legacy-") || phase.equals("path-upgrade")
|| phase.startsWith("recipe-book-") || phase.startsWith("legacy-"));
|| phase.startsWith("recipe-book-") || phase.startsWith("legacy-") || phase.startsWith("fuel-"));
if (needsGameplay) {
GameplayChecks.prepare(server.getLevel(Level.OVERWORLD));
}
Expand Down Expand Up @@ -111,6 +111,8 @@ public void tick(net.neoforged.neoforge.event.tick.ServerTickEvent.Post event) {
org.apache.logging.log4j.LogManager.getLogger().info("RECIPE_BOOK_PHASE_PASS " + phase);
} else if (phase.startsWith("legacy-")) {
LegacyFixture.run(world, phase);
} else if (phase.startsWith("fuel-")) {
FuelChecks.run();
} else if (phase.equals("compat")) {
NativeLegacyChecks.run(world);
CompatibilityChecks.run(world);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
@Mod(SkysBuildingPieces.ID)
public final class SkysBuildingPieces {
public static final String ID = "skysbuildingpieces";
public static final String VERSION = "0.3.10.121012";
public static final String VERSION = "0.3.11.121012";
public static final Logger LOGGER = LogManager.getLogger();
public static boolean forceReplace;
public static Block HOLDER;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,9 @@ public Component getName(ItemStack stack) {
public int getBurnTime(ItemStack stack, net.minecraft.world.item.crafting.RecipeType<?> recipeType) {
Catalogue.MaterialDef definition = Catalogue.INSTANCE.materials.get(material);
if (!definition.type.equals("wood")) {
return -1;
// NeoForge rejects negative burn times. Keep its normal data-map lookup
// so non-fuels return zero and modpacks can still configure other fuels.
return super.getBurnTime(stack, recipeType);
}
ItemStack full = Pieces.stack(Pieces.nativeState(definition, "full"), 1);
int fullBurnTime = full == null ? 0 : Math.max(0, full.getBurnTime(recipeType));
Expand Down
Loading