From 6e56a72be3621a1d6b8c3f5c806abd008224104a Mon Sep 17 00:00:00 2001 From: JohnBraham Date: Wed, 11 Nov 2026 10:28:05 +0000 Subject: [PATCH 1/5] Keep slabs snowy beside higher snow-covered ground --- .github/workflows/ci.yml | 6 +-- CHANGELOG.md | 4 ++ README.md | 4 +- docs/RELEASE-1.2.1.121012.md | 7 ++++ gradle.properties | 2 +- .../gametest/SlabGameTests.java | 13 +++++++ .../mc/skysgrassslabs/SkysGrassSlabs.java | 2 +- .../block/SnowySlabAppearance.java | 37 +++++++++---------- .../skysgrassslabs/ProjectContractTest.java | 12 +++--- 9 files changed, 54 insertions(+), 33 deletions(-) create mode 100644 docs/RELEASE-1.2.1.121012.md diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bdcedde..ee67433 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -110,9 +110,9 @@ jobs: if-no-files-found: error retention-days: 30 path: | - build/libs/SkysGrassSlabs-1.2.0.121012.jar - build/libs/SkysGrassSlabs-1.2.0.121012-sources.jar - build/libs/SkysGrassSlabs-1.2.0.121012-javadoc.jar + build/libs/SkysGrassSlabs-1.2.1.121012.jar + build/libs/SkysGrassSlabs-1.2.1.121012-sources.jar + build/libs/SkysGrassSlabs-1.2.1.121012-javadoc.jar build/release/SHA256SUMS CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md index da271a4..5e9a864 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 1.2.1.121012 - Minecraft 1.21.1 (NeoForge) + +- Give slabs a snowy top beside a raised snow-covered terrace. + ## 1.1.1.121012 - Minecraft 1.21.1 (NeoForge) - Corrected snowy grass slabs so their exposed top uses the snow texture diff --git a/README.md b/README.md index 14f53b3..399e06d 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ thin layer of turf. Grass spreads naturally between full blocks and slabs, while new Overworld terrain uses grass slabs to soften suitable one block steps. -This branch is for Minecraft 1.21.1. Version `1.2.0.121012` requires NeoForge +This branch is for Minecraft 1.21.1. Version `1.2.1.121012` requires NeoForge 21.1.247 or a compatible NeoForge 21.1 build and Java 21. ## Installation @@ -34,7 +34,7 @@ or updating world changing mods. - [Gameplay and recipes](docs/GAMEPLAY.md) - [Configuration](docs/CONFIGURATION.md) - [Upgrading an older world](docs/WORLD-UPGRADES.md) -- [Release notes](docs/RELEASE-1.2.0.121012.md) +- [Release notes](docs/RELEASE-1.2.1.121012.md) ## License diff --git a/docs/RELEASE-1.2.1.121012.md b/docs/RELEASE-1.2.1.121012.md new file mode 100644 index 0000000..c935e99 --- /dev/null +++ b/docs/RELEASE-1.2.1.121012.md @@ -0,0 +1,7 @@ +# Sky's Grass Slabs 1.2.1 for Minecraft 1.21.1 + +Slabs beside a higher snow-covered terrace now keep their snowy top. +They also recognise the snow pieces supplied by Sky's Building Pieces. +Removing the surrounding snow restores their green or dirt appearance. + +This build uses Minecraft 1.21.1, NeoForge 21.1.247 and Java 21. diff --git a/gradle.properties b/gradle.properties index bcc14ac..cdb2fcc 100644 --- a/gradle.properties +++ b/gradle.properties @@ -40,7 +40,7 @@ mod_name=Sky's Grass Slabs # The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default. mod_license=LGPL-2.1-only # The mod version. See https://semver.org/ -mod_version=1.2.0.121012 +mod_version=1.2.1.121012 # The group ID for the mod. It is only important when publishing as an artifact to a Maven repository. # This should match the base package used for the mod sources. # See https://maven.apache.org/guides/mini/guide-naming-conventions.html diff --git a/src/gameTest/java/zone/moddev/mc/skysgrassslabs/gametest/SlabGameTests.java b/src/gameTest/java/zone/moddev/mc/skysgrassslabs/gametest/SlabGameTests.java index 6c4a113..0e70c32 100644 --- a/src/gameTest/java/zone/moddev/mc/skysgrassslabs/gametest/SlabGameTests.java +++ b/src/gameTest/java/zone/moddev/mc/skysgrassslabs/gametest/SlabGameTests.java @@ -299,6 +299,19 @@ public static void snowPlantsBonemealAndWaterAreTopAware(GameTestHelper helper) require(helper, !clearDirt.getValue(net.minecraft.world.level.block.SnowyDirtBlock.SNOWY), "dirt slab retained its snowy appearance after snow was removed"); + BlockPos terrace = pos.east(); + helper.getLevel().setBlock(terrace, Blocks.GRASS_BLOCK.defaultBlockState(), Block.UPDATE_ALL); + helper.getLevel().setBlock(terrace.above(), Blocks.SNOW.defaultBlockState(), Block.UPDATE_ALL); + BlockState raisedSnow = grass.updateShape(bottom, Direction.EAST, + helper.getLevel().getBlockState(terrace), helper.getLevel(), pos, terrace); + require(helper, raisedSnow.getValue(GrassSlabBlock.SNOWY), + "snow on the higher terrace did not give the slab its snowy top"); + helper.getLevel().setBlock(terrace.above(), Blocks.AIR.defaultBlockState(), Block.UPDATE_ALL); + BlockState clearedTerrace = grass.updateShape(raisedSnow, Direction.EAST, + helper.getLevel().getBlockState(terrace), helper.getLevel(), pos, terrace); + require(helper, !clearedTerrace.getValue(GrassSlabBlock.SNOWY), + "slab retained snow after the higher terrace was cleared"); + BlockState wetGrass = top.setValue(SlabBlock.WATERLOGGED, true); helper.getLevel().setBlock(pos, wetGrass, Block.UPDATE_ALL); grass.randomTick(wetGrass, helper.getLevel(), pos, RandomSource.create(3L)); diff --git a/src/main/java/zone/moddev/mc/skysgrassslabs/SkysGrassSlabs.java b/src/main/java/zone/moddev/mc/skysgrassslabs/SkysGrassSlabs.java index a8a5071..f99b659 100644 --- a/src/main/java/zone/moddev/mc/skysgrassslabs/SkysGrassSlabs.java +++ b/src/main/java/zone/moddev/mc/skysgrassslabs/SkysGrassSlabs.java @@ -35,7 +35,7 @@ public final class SkysGrassSlabs { /** Stable mod identifier and resource namespace. */ public static final String MOD_ID = "skysgrassslabs"; public static final String NAME = "Sky's Grass Slabs"; - public static final String VERSION = "1.2.0.121012"; + public static final String VERSION = "1.2.1.121012"; public static final Logger LOGGER = LogManager.getLogger(); /** Registers content, configuration, world generation, and persistent state. */ diff --git a/src/main/java/zone/moddev/mc/skysgrassslabs/block/SnowySlabAppearance.java b/src/main/java/zone/moddev/mc/skysgrassslabs/block/SnowySlabAppearance.java index 189c05f..44f0839 100644 --- a/src/main/java/zone/moddev/mc/skysgrassslabs/block/SnowySlabAppearance.java +++ b/src/main/java/zone/moddev/mc/skysgrassslabs/block/SnowySlabAppearance.java @@ -3,45 +3,42 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; +import net.minecraft.tags.BlockTags; +import net.minecraft.server.level.WorldGenRegion; +import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; /** Computes the visual snow cap from nearby vanilla snow. */ final class SnowySlabAppearance { static boolean hasNearbySnow(BlockGetter level, BlockPos pos) { - if (isSnow(level.getBlockState(pos.above()).getBlock())) { - return true; - } - for (Direction direction : Direction.Plane.HORIZONTAL) { - if (isSnow(level.getBlockState(pos.relative(direction)).getBlock())) { - return true; - } - } - return false; + return hasNearbySnow(level, pos, null, null); } static boolean hasNearbySnow(BlockGetter level, BlockPos pos, Direction changedDirection, BlockState changedState) { - if (changedDirection == Direction.UP) { - if (isSnow(changedState.getBlock())) { - return true; - } - } else if (isSnow(level.getBlockState(pos.above()).getBlock())) { + BlockState above = changedDirection == Direction.UP ? changedState : readState(level, pos.above()); + if (above.is(BlockTags.SNOW)) { return true; } for (Direction direction : Direction.Plane.HORIZONTAL) { + BlockPos neighbourPos = pos.relative(direction); BlockState neighbour = direction == changedDirection - ? changedState : level.getBlockState(pos.relative(direction)); - if (isSnow(neighbour.getBlock())) { + ? changedState : readState(level, neighbourPos); + // A higher terrace carries its snow one block above the piece's horizontal neighbour. + if (neighbour.is(BlockTags.SNOW) || neighbour.isCollisionShapeFullBlock(level, neighbourPos) + && readState(level, neighbourPos.above()).is(BlockTags.SNOW)) { return true; } } return false; } - private static boolean isSnow(Block block) { - return block == Blocks.SNOW || block == Blocks.SNOW_BLOCK; + private static BlockState readState(BlockGetter level, BlockPos pos) { + if (level instanceof Level world && !world.isLoaded(pos) + || level instanceof WorldGenRegion region && !region.hasChunk(pos.getX() >> 4, pos.getZ() >> 4)) { + return net.minecraft.world.level.block.Blocks.AIR.defaultBlockState(); + } + return level.getBlockState(pos); } private SnowySlabAppearance() { diff --git a/src/test/java/zone/moddev/mc/skysgrassslabs/ProjectContractTest.java b/src/test/java/zone/moddev/mc/skysgrassslabs/ProjectContractTest.java index e63c940..bde4dc1 100644 --- a/src/test/java/zone/moddev/mc/skysgrassslabs/ProjectContractTest.java +++ b/src/test/java/zone/moddev/mc/skysgrassslabs/ProjectContractTest.java @@ -62,14 +62,14 @@ public void playerAndMaintainerDocumentsExist() { assertTrue(Files.isRegularFile(Path.of("docs/GAMEPLAY.md"))); assertTrue(Files.isRegularFile(Path.of("docs/WORLD-UPGRADES.md"))); assertFalse(Files.exists(Path.of("docs/REPOSITORY.md"))); - assertTrue(Files.isRegularFile(Path.of("docs/RELEASE-1.2.0.121012.md"))); + assertTrue(Files.isRegularFile(Path.of("docs/RELEASE-1.2.1.121012.md"))); assertTrue(Files.isRegularFile(Path.of("docs/BETA-0.2.0.118021.md"))); } @Test public void releaseIdentityAndLicenseAreStable() throws Exception { String properties = Files.readString(Path.of("gradle.properties"), StandardCharsets.UTF_8); - assertTrue(properties.contains("mod_version=1.2.0.121012")); + assertTrue(properties.contains("mod_version=1.2.1.121012")); assertTrue(properties.contains("mod_license=LGPL-2.1-only")); assertEquals("LGPL-2.1-only", Files.readString(Path.of("LICENSE.spdx"), StandardCharsets.UTF_8).trim()); assertTrue(Files.readString(Path.of("NOTICE"), StandardCharsets.UTF_8) @@ -126,7 +126,7 @@ public void commonConfigAndWorldStateUsePermanentKeys() throws Exception { assertTrue(config.contains("push(\"compat\")")); assertTrue(config.contains("define(FORCE_REPLACE_BUILDINGBRICKS_SLABS, false)")); assertTrue(config.contains("define(FORCE_REPLACE_GRASS_SLABS_MOD_CONTENT, false)")); - assertTrue(main.contains("VERSION = \"1.2.0.121012\"")); + assertTrue(main.contains("VERSION = \"1.2.1.121012\"")); assertTrue(state.contains("skysgrassslabs_world_state")); assertTrue(state.contains("SCHEMA_VERSION = 1")); assertTrue(state.contains("schema_version")); @@ -273,9 +273,9 @@ public void continuousIntegrationTargetsTheStableBranchAndArtifacts() throws Exc } String ci = Files.readString(Path.of(".github/workflows/ci.yml"), StandardCharsets.UTF_8); - assertTrue(ci.contains("SkysGrassSlabs-1.2.0.121012.jar")); - assertTrue(ci.contains("SkysGrassSlabs-1.2.0.121012-sources.jar")); - assertTrue(ci.contains("SkysGrassSlabs-1.2.0.121012-javadoc.jar")); + assertTrue(ci.contains("SkysGrassSlabs-1.2.1.121012.jar")); + assertTrue(ci.contains("SkysGrassSlabs-1.2.1.121012-sources.jar")); + assertTrue(ci.contains("SkysGrassSlabs-1.2.1.121012-javadoc.jar")); assertTrue(ci.contains("if-no-files-found: error")); assertTrue(ci.contains("java-version: '21.0.7+6.0.LTS'")); assertTrue(ci.contains("--offline --no-daemon")); From 58d98da6136069d1097b40103b3656412b75fa73 Mon Sep 17 00:00:00 2001 From: JohnBraham Date: Wed, 11 Nov 2026 10:47:28 +0000 Subject: [PATCH 2/5] Keep exposed cold slabs snowy without a snow layer --- CHANGELOG.md | 1 + docs/GAMEPLAY.md | 3 ++- docs/RELEASE-1.2.1.121012.md | 4 +++- .../mc/skysgrassslabs/block/SnowySlabAppearance.java | 9 ++++++++- 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e9a864..03b6828 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## 1.2.1.121012 - Minecraft 1.21.1 (NeoForge) - Give slabs a snowy top beside a raised snow-covered terrace. +- Keep exposed slabs snowy in cold areas where snow layers cannot settle. ## 1.1.1.121012 - Minecraft 1.21.1 (NeoForge) diff --git a/docs/GAMEPLAY.md b/docs/GAMEPLAY.md index fed1216..e52f8c3 100644 --- a/docs/GAMEPLAY.md +++ b/docs/GAMEPLAY.md @@ -25,7 +25,8 @@ normal durability damage. Dirt path slabs do not spread grass or support plants. Grass and dirt slabs show a snow covered top and snowy side edges when vanilla -snow is nearby. This is a visual effect and does not add collision height. +snow is nearby or the slab is exposed to snowfall in a cold biome. This is a +visual effect and does not add collision height. ## Turf diff --git a/docs/RELEASE-1.2.1.121012.md b/docs/RELEASE-1.2.1.121012.md index c935e99..4808c5e 100644 --- a/docs/RELEASE-1.2.1.121012.md +++ b/docs/RELEASE-1.2.1.121012.md @@ -2,6 +2,8 @@ Slabs beside a higher snow-covered terrace now keep their snowy top. They also recognise the snow pieces supplied by Sky's Building Pieces. -Removing the surrounding snow restores their green or dirt appearance. +Exposed slabs in cold areas keep a snow cap even where a snow layer cannot +settle. In warmer areas, removing the surrounding snow restores their green +or dirt appearance. This build uses Minecraft 1.21.1, NeoForge 21.1.247 and Java 21. diff --git a/src/main/java/zone/moddev/mc/skysgrassslabs/block/SnowySlabAppearance.java b/src/main/java/zone/moddev/mc/skysgrassslabs/block/SnowySlabAppearance.java index 44f0839..4c3cc0e 100644 --- a/src/main/java/zone/moddev/mc/skysgrassslabs/block/SnowySlabAppearance.java +++ b/src/main/java/zone/moddev/mc/skysgrassslabs/block/SnowySlabAppearance.java @@ -6,6 +6,9 @@ import net.minecraft.tags.BlockTags; import net.minecraft.server.level.WorldGenRegion; import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.LightLayer; +import net.minecraft.world.level.levelgen.Heightmap; import net.minecraft.world.level.block.state.BlockState; /** Computes the visual snow cap from nearby vanilla snow. */ @@ -30,7 +33,11 @@ && readState(level, neighbourPos.above()).is(BlockTags.SNOW)) { return true; } } - return false; + // Partial tops cannot support vanilla snow layers, but exposed cold ground still needs its snow cap. + return level instanceof LevelReader reader + && reader.getBiome(pos).value().coldEnoughToSnow(pos) + && reader.getHeight(Heightmap.Types.MOTION_BLOCKING, pos.getX(), pos.getZ()) <= pos.getY() + 1 + && reader.getBrightness(LightLayer.BLOCK, pos.above()) < 10; } private static BlockState readState(BlockGetter level, BlockPos pos) { From 34dc9266c885985419361d86f91f588fbef3d8a9 Mon Sep 17 00:00:00 2001 From: JohnBraham Date: Wed, 11 Nov 2026 11:56:28 +0000 Subject: [PATCH 3/5] Respect placement permissions and collision when changing slabs --- CHANGELOG.md | 2 + .../gametest/SlabGameTests.java | 38 +++++++++++++++++++ .../skysgrassslabs/block/TurfBlockItem.java | 8 ++-- .../item/NormalizingSlabItem.java | 4 ++ 4 files changed, 49 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 03b6828..1d1a30f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## 1.2.1.121012 - Minecraft 1.21.1 (NeoForge) +- Keep slab joins from placing a full block inside a player or creature. +- Respect adventure-mode placement permissions when applying turf to dirt slabs. - Give slabs a snowy top beside a raised snow-covered terrace. - Keep exposed slabs snowy in cold areas where snow layers cannot settle. diff --git a/src/gameTest/java/zone/moddev/mc/skysgrassslabs/gametest/SlabGameTests.java b/src/gameTest/java/zone/moddev/mc/skysgrassslabs/gametest/SlabGameTests.java index 0e70c32..34a8142 100644 --- a/src/gameTest/java/zone/moddev/mc/skysgrassslabs/gametest/SlabGameTests.java +++ b/src/gameTest/java/zone/moddev/mc/skysgrassslabs/gametest/SlabGameTests.java @@ -785,6 +785,44 @@ private static void require(GameTestHelper helper, boolean condition, String mes } } + @GameTest(template = EMPTY, batch = "slabs025") + public static void slabJoiningRespectsEntityCollision(GameTestHelper helper) { + BlockPos position = helper.absolutePos(new BlockPos(2, 2, 2)); + BlockState slab = ModBlocks.DIRT_SLAB.get().defaultBlockState(); + helper.getLevel().setBlock(position, slab, Block.UPDATE_ALL); + var occupant = helper.spawn(EntityType.COW, new BlockPos(2, 2, 2)); + occupant.setPos(position.getX() + .5, position.getY() + .5, position.getZ() + .5); + require(helper, !helper.getLevel().isUnobstructed(Blocks.DIRT.defaultBlockState(), position, + CollisionContext.empty()), "The join fixture needs an obstructed upper half"); + Player player = helper.makeMockPlayer(GameType.SURVIVAL); + ItemStack held = new ItemStack(ModBlocks.DIRT_SLAB_ITEM.get()); + player.setItemInHand(InteractionHand.MAIN_HAND, held); + held.useOn(new UseOnContext(player, InteractionHand.MAIN_HAND, + new BlockHitResult(Vec3.atCenterOf(position), Direction.UP, position, false))); + require(helper, helper.getLevel().getBlockState(position).equals(slab) && held.getCount() == 1, + "Joining slabs must not put a full block inside an entity or consume the item"); + occupant.discard(); + helper.succeed(); + } + + @GameTest(template = EMPTY, batch = "slabs025") + public static void turfGreeningRespectsAdventurePermissions(GameTestHelper helper) { + BlockPos position = helper.absolutePos(new BlockPos(2, 2, 2)); + BlockState dirt = ModBlocks.DIRT_SLAB.get().defaultBlockState(); + helper.getLevel().setBlock(position, dirt, Block.UPDATE_ALL); + Player player = helper.makeMockPlayer(GameType.ADVENTURE); + player.getAbilities().mayBuild = false; + require(helper, !player.getAbilities().mayBuild, "The permission fixture must be in adventure mode"); + ItemStack held = new ItemStack(ModBlocks.TURF_ITEM.get()); + player.setItemInHand(InteractionHand.MAIN_HAND, held); + held.useOn(new UseOnContext(player, InteractionHand.MAIN_HAND, + new BlockHitResult(Vec3.atCenterOf(position), Direction.UP, position, false))); + require(helper, helper.getLevel().getBlockState(position).equals(dirt) && held.getCount() == 1, + "Turf greening must respect adventure placement permissions"); + helper.succeed(); + } + + private static final class FixedRandom extends LegacyRandomSource { private final int[] values; private int index; diff --git a/src/main/java/zone/moddev/mc/skysgrassslabs/block/TurfBlockItem.java b/src/main/java/zone/moddev/mc/skysgrassslabs/block/TurfBlockItem.java index ad86c98..07edf5b 100644 --- a/src/main/java/zone/moddev/mc/skysgrassslabs/block/TurfBlockItem.java +++ b/src/main/java/zone/moddev/mc/skysgrassslabs/block/TurfBlockItem.java @@ -37,6 +37,11 @@ public InteractionResult useOn(UseOnContext context) { if (current.getValue(SlabBlock.WATERLOGGED)) { return InteractionResult.FAIL; } + Player player = context.getPlayer(); + ItemStack held = context.getItemInHand(); + if (held.isEmpty() || player != null && !player.mayUseItemAt(pos, context.getClickedFace(), held)) { + return InteractionResult.FAIL; + } BlockState grass = SlabTransitions.grassFor(current); @@ -49,9 +54,6 @@ public InteractionResult useOn(UseOnContext context) { return InteractionResult.FAIL; } - Player player = context.getPlayer(); - ItemStack held = context.getItemInHand(); - if (player instanceof ServerPlayer serverPlayer) { CriteriaTriggers.PLACED_BLOCK.trigger(serverPlayer, pos, held); } diff --git a/src/main/java/zone/moddev/mc/skysgrassslabs/item/NormalizingSlabItem.java b/src/main/java/zone/moddev/mc/skysgrassslabs/item/NormalizingSlabItem.java index 89e428a..ff123ec 100644 --- a/src/main/java/zone/moddev/mc/skysgrassslabs/item/NormalizingSlabItem.java +++ b/src/main/java/zone/moddev/mc/skysgrassslabs/item/NormalizingSlabItem.java @@ -15,6 +15,7 @@ import net.minecraft.world.level.block.SoundType; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.SlabType; +import net.minecraft.world.phys.shapes.CollisionContext; /** Slab item that normalizes a matching pair to its vanilla full block. */ public final class NormalizingSlabItem extends BlockItem { @@ -56,6 +57,9 @@ private InteractionResult combine(UseOnContext context, BlockPos pos) { return InteractionResult.FAIL; } BlockState combined = combinedBlock.defaultBlockState(); + if (!level.isUnobstructed(combined, pos, CollisionContext.empty())) { + return InteractionResult.FAIL; + } if (!level.setBlock(pos, combined, Block.UPDATE_ALL_IMMEDIATE)) { return InteractionResult.FAIL; } From d022eba609e6cf0381183232d35768b6190f2d53 Mon Sep 17 00:00:00 2001 From: JohnBraham Date: Wed, 11 Nov 2026 15:16:47 +0000 Subject: [PATCH 4/5] Keep recipe-book buttons focused on one result --- CHANGELOG.md | 1 + .../resources/data/skysgrassslabs/recipe/dirt_from_slabs.json | 2 +- src/main/resources/data/skysgrassslabs/recipe/dirt_slab.json | 2 +- .../data/skysgrassslabs/recipe/grass_block_from_seeds.json | 2 +- .../resources/data/skysgrassslabs/recipe/grass_from_slabs.json | 2 +- src/main/resources/data/skysgrassslabs/recipe/grass_slab.json | 2 +- .../data/skysgrassslabs/recipe/grass_slab_from_seeds.json | 2 +- 7 files changed, 7 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d1a30f..a185eee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## 1.2.1.121012 - Minecraft 1.21.1 (NeoForge) +- Keep different crafting results on separate recipe-book buttons. - Keep slab joins from placing a full block inside a player or creature. - Respect adventure-mode placement permissions when applying turf to dirt slabs. - Give slabs a snowy top beside a raised snow-covered terrace. diff --git a/src/main/resources/data/skysgrassslabs/recipe/dirt_from_slabs.json b/src/main/resources/data/skysgrassslabs/recipe/dirt_from_slabs.json index 8678997..7ad86f1 100644 --- a/src/main/resources/data/skysgrassslabs/recipe/dirt_from_slabs.json +++ b/src/main/resources/data/skysgrassslabs/recipe/dirt_from_slabs.json @@ -1,5 +1,5 @@ { - "type": "minecraft:crafting_shaped", + "group": "skys/result/minecraft/dirt", "type": "minecraft:crafting_shaped", "pattern": [ "SS" ], diff --git a/src/main/resources/data/skysgrassslabs/recipe/dirt_slab.json b/src/main/resources/data/skysgrassslabs/recipe/dirt_slab.json index 9fb77b4..3a1bcb2 100644 --- a/src/main/resources/data/skysgrassslabs/recipe/dirt_slab.json +++ b/src/main/resources/data/skysgrassslabs/recipe/dirt_slab.json @@ -1,5 +1,5 @@ { - "type": "minecraft:crafting_shaped", + "group": "skys/result/skysgrassslabs/dirt_slab", "type": "minecraft:crafting_shaped", "category": "building", "pattern": ["###"], "key": { "#": { "item": "minecraft:dirt" } }, diff --git a/src/main/resources/data/skysgrassslabs/recipe/grass_block_from_seeds.json b/src/main/resources/data/skysgrassslabs/recipe/grass_block_from_seeds.json index a2b47ff..aaff801 100644 --- a/src/main/resources/data/skysgrassslabs/recipe/grass_block_from_seeds.json +++ b/src/main/resources/data/skysgrassslabs/recipe/grass_block_from_seeds.json @@ -1,5 +1,5 @@ { - "type": "minecraft:crafting_shapeless", + "group": "skys/result/minecraft/grass_block", "type": "minecraft:crafting_shapeless", "category": "building", "ingredients": [ { "item": "minecraft:dirt" }, diff --git a/src/main/resources/data/skysgrassslabs/recipe/grass_from_slabs.json b/src/main/resources/data/skysgrassslabs/recipe/grass_from_slabs.json index 44d7f7e..1b1f283 100644 --- a/src/main/resources/data/skysgrassslabs/recipe/grass_from_slabs.json +++ b/src/main/resources/data/skysgrassslabs/recipe/grass_from_slabs.json @@ -1,5 +1,5 @@ { - "type": "minecraft:crafting_shaped", + "group": "skys/result/minecraft/grass_block", "type": "minecraft:crafting_shaped", "pattern": [ "SS" ], diff --git a/src/main/resources/data/skysgrassslabs/recipe/grass_slab.json b/src/main/resources/data/skysgrassslabs/recipe/grass_slab.json index ec37d1a..10576d7 100644 --- a/src/main/resources/data/skysgrassslabs/recipe/grass_slab.json +++ b/src/main/resources/data/skysgrassslabs/recipe/grass_slab.json @@ -1,5 +1,5 @@ { - "type": "minecraft:crafting_shaped", + "group": "skys/result/skysgrassslabs/grass_slab", "type": "minecraft:crafting_shaped", "category": "building", "pattern": ["###"], "key": { "#": { "item": "minecraft:grass_block" } }, diff --git a/src/main/resources/data/skysgrassslabs/recipe/grass_slab_from_seeds.json b/src/main/resources/data/skysgrassslabs/recipe/grass_slab_from_seeds.json index ed29d39..fedafeb 100644 --- a/src/main/resources/data/skysgrassslabs/recipe/grass_slab_from_seeds.json +++ b/src/main/resources/data/skysgrassslabs/recipe/grass_slab_from_seeds.json @@ -1,5 +1,5 @@ { - "type": "minecraft:crafting_shapeless", + "group": "skys/result/skysgrassslabs/grass_slab", "type": "minecraft:crafting_shapeless", "category": "building", "ingredients": [ { "item": "skysgrassslabs:dirt_slab" }, From 6112dfdba8c0ab7956ec16d9b076ecda349cf231 Mon Sep 17 00:00:00 2001 From: JohnBraham Date: Wed, 11 Nov 2026 16:41:05 +0000 Subject: [PATCH 5/5] Limit CurseForge uploads to one attempt --- .github/workflows/deploy-release.yml | 1 + docs/RELEASE-1.2.1.121012.md | 3 +++ .../zone/moddev/mc/skysgrassslabs/ProjectContractTest.java | 1 + 3 files changed, 5 insertions(+) diff --git a/.github/workflows/deploy-release.yml b/.github/workflows/deploy-release.yml index 1d13f67..fe81dce 100644 --- a/.github/workflows/deploy-release.yml +++ b/.github/workflows/deploy-release.yml @@ -505,6 +505,7 @@ jobs: with: curseforge-token: ${{ secrets.CURSEFORGE_TOKEN }} curseforge-id: ${{ needs.preflight.outputs.curseforge_project_id }} + curseforge-retry-attempts: 1 name: Sky's Grass Slabs ${{ needs.preflight.outputs.release_version }} for Minecraft ${{ needs.preflight.outputs.minecraft_version }} (${{ needs.preflight.outputs.loader_display }}) version: ${{ needs.preflight.outputs.release_version }} version-type: ${{ inputs.curseforge_release_level }} diff --git a/docs/RELEASE-1.2.1.121012.md b/docs/RELEASE-1.2.1.121012.md index 4808c5e..2302ae5 100644 --- a/docs/RELEASE-1.2.1.121012.md +++ b/docs/RELEASE-1.2.1.121012.md @@ -6,4 +6,7 @@ Exposed slabs in cold areas keep a snow cap even where a snow layer cannot settle. In warmer areas, removing the surrounding snow restores their green or dirt appearance. +Different crafting results now have separate recipe-book buttons. Slab joins +also respect placement permissions and leave room for players and creatures. + This build uses Minecraft 1.21.1, NeoForge 21.1.247 and Java 21. diff --git a/src/test/java/zone/moddev/mc/skysgrassslabs/ProjectContractTest.java b/src/test/java/zone/moddev/mc/skysgrassslabs/ProjectContractTest.java index bde4dc1..5828507 100644 --- a/src/test/java/zone/moddev/mc/skysgrassslabs/ProjectContractTest.java +++ b/src/test/java/zone/moddev/mc/skysgrassslabs/ProjectContractTest.java @@ -88,6 +88,7 @@ public void releaseDispatcherIsExplicitAndUsesTheImmutableBundle() throws Except assertTrue(properties.contains("loader_code=2")); assertTrue(properties.contains("curseforge_project_id=1677588")); assertTrue(workflow.contains("confirm_live_publication:")); + assertTrue(workflow.contains("curseforge-retry-attempts: 1")); assertFalse(workflow.contains(" environment:\n name: release")); assertTrue(workflow.contains("CURSEFORGE_TOKEN: ${{ secrets.CURSEFORGE_TOKEN }}")); assertTrue(workflow.contains("MAVEN_UPLOAD_URL: ${{ secrets.MAVEN_UPLOAD_URL }}"));