diff --git a/src/generated/resources/.cache/8e794e243511ea3d808ffb90a97ef5ee71d8d5f9 b/src/generated/resources/.cache/8e794e243511ea3d808ffb90a97ef5ee71d8d5f9 index b2e7e8145..66db76316 100644 --- a/src/generated/resources/.cache/8e794e243511ea3d808ffb90a97ef5ee71d8d5f9 +++ b/src/generated/resources/.cache/8e794e243511ea3d808ffb90a97ef5ee71d8d5f9 @@ -1,4 +1,4 @@ -// 1.19.2 2022-09-17T21:51:07.3812115 Registrate Provider for create [Recipes, Advancements, Loot tables, Tags (blocks), Tags (items), Tags (fluids), Tags (entity_types), Blockstates, Item models, Lang (en_us/en_ud)] +// 1.19.2 2022-09-21T09:09:19.8483732 Registrate Provider for create [Recipes, Advancements, Loot tables, Tags (blocks), Tags (items), Tags (fluids), Tags (entity_types), Blockstates, Item models, Lang (en_us/en_ud)] 60bbdf92d2ac9824ea6144955c74043a6005f79d assets/create/blockstates/acacia_window.json 6a67703c2697d81b7dc83e9d72a66f9c9ff08383 assets/create/blockstates/acacia_window_pane.json c3ae87b62e81d8e9476eccd793bb1548d74c66a1 assets/create/blockstates/adjustable_chain_gearshift.json @@ -4489,6 +4489,7 @@ e3510f08cc217e52b58692dcc7f3eda0289ff751 data/create/tags/blocks/passive_boiler_ 5ac75e77c57ab675e5d36a1e2bd7d37804b7de05 data/create/tags/blocks/safe_nbt.json 79418bd729cef417b322cef9b491e7ae83317d61 data/create/tags/blocks/seats.json 5def5088f7fd31b80e6f28c1c4ea146aa9d7d15b data/create/tags/blocks/toolboxes.json +a8271a2fcefafde4a6589193c50c41edcba1dad7 data/create/tags/blocks/tree_attachments.json da739ad2160e7df4e0e5cc89587670ce5e9450c3 data/create/tags/blocks/valve_handles.json 72143286fb5cb372a0696550e2eac76ca50e6fbc data/create/tags/blocks/windmill_sails.json 35133e95f1c8fdd7a1c21afcc231fc0bffefb9a8 data/create/tags/blocks/windowable.json diff --git a/src/generated/resources/data/create/tags/blocks/tree_attachments.json b/src/generated/resources/data/create/tags/blocks/tree_attachments.json index dc79f54a0..37e12f197 100644 --- a/src/generated/resources/data/create/tags/blocks/tree_attachments.json +++ b/src/generated/resources/data/create/tags/blocks/tree_attachments.json @@ -1,10 +1,10 @@ { - "replace": false, "values": [ "minecraft:bee_nest", "minecraft:vine", "minecraft:moss_carpet", "minecraft:shroomlight", - "minecraft:cocoa" + "minecraft:cocoa", + "minecraft:mangrove_propagule" ] } \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/AllTags.java b/src/main/java/com/simibubi/create/AllTags.java index 0d4e62e15..7ac2ab1b4 100644 --- a/src/main/java/com/simibubi/create/AllTags.java +++ b/src/main/java/com/simibubi/create/AllTags.java @@ -417,7 +417,7 @@ public class AllTags { Blocks.TRIPWIRE, Blocks.TRIPWIRE_HOOK, Blocks.DAYLIGHT_DETECTOR, Blocks.TARGET, Blocks.HOPPER); AllBlockTags.TREE_ATTACHMENTS.add(Blocks.BEE_NEST, Blocks.VINE, Blocks.MOSS_CARPET, Blocks.SHROOMLIGHT, - Blocks.COCOA); + Blocks.COCOA, Blocks.MANGROVE_PROPAGULE); AllBlockTags.ORE_OVERRIDE_STONE.includeAll(BlockTags.STONE_ORE_REPLACEABLES); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawTileEntity.java index 01382d641..fa556597d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawTileEntity.java @@ -14,7 +14,6 @@ import com.google.common.base.Suppliers; import com.google.common.collect.ImmutableList; import com.simibubi.create.AllRecipeTypes; import com.simibubi.create.AllSoundEvents; -import com.simibubi.create.AllTags; import com.simibubi.create.content.contraptions.components.actors.BlockBreakingKineticTileEntity; import com.simibubi.create.content.contraptions.itemAssembly.SequencedAssemblyRecipe; import com.simibubi.create.content.contraptions.processing.ProcessingInventory; @@ -480,6 +479,8 @@ public class SawTileEntity extends BlockBreakingKineticTileEntity { return false; if (TreeCutter.isLog(stateToBreak) || (stateToBreak.is(BlockTags.LEAVES))) return true; + if (TreeCutter.isRoot(stateToBreak)) + return true; Block block = stateToBreak.getBlock(); if (block instanceof BambooBlock) return true; diff --git a/src/main/java/com/simibubi/create/content/curiosities/TreeFertilizerItem.java b/src/main/java/com/simibubi/create/content/curiosities/TreeFertilizerItem.java index 47ae26065..4c1c9f48e 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/TreeFertilizerItem.java +++ b/src/main/java/com/simibubi/create/content/curiosities/TreeFertilizerItem.java @@ -12,6 +12,7 @@ import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.BonemealableBlock; +import net.minecraft.world.level.block.MangrovePropaguleBlock; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.BlockStateProperties; @@ -28,6 +29,10 @@ public class TreeFertilizerItem extends Item { Block block = state.getBlock(); if (block instanceof BonemealableBlock bonemealableBlock && state.is(BlockTags.SAPLINGS)) { + if (state.getOptionalValue(MangrovePropaguleBlock.HANGING) + .orElse(false)) + return InteractionResult.PASS; + if (context.getLevel().isClientSide) { BoneMealItem.addGrowthParticles(context.getLevel(), context.getClickedPos(), 100); return InteractionResult.SUCCESS; @@ -89,7 +94,13 @@ public class TreeFertilizerItem extends Item { protected TreesDreamWorld(ServerLevel wrapped, BlockPos saplingPos) { super(wrapped); - soil = wrapped.getBlockState(saplingPos.below()); + BlockState stateUnderSapling = wrapped.getBlockState(saplingPos.below()); + + // Tree features don't seem to succeed with mud as soil + if (stateUnderSapling.is(BlockTags.DIRT)) + stateUnderSapling = Blocks.DIRT.defaultBlockState(); + + soil = stateUnderSapling; } @Override diff --git a/src/main/java/com/simibubi/create/foundation/utility/TreeCutter.java b/src/main/java/com/simibubi/create/foundation/utility/TreeCutter.java index 9cfe0d88f..2ebe05c19 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/TreeCutter.java +++ b/src/main/java/com/simibubi/create/foundation/utility/TreeCutter.java @@ -41,7 +41,9 @@ import net.minecraft.world.level.block.state.properties.IntegerProperty; import net.minecraft.world.level.block.state.properties.Property; public class TreeCutter { - public static final Tree NO_TREE = new Tree(Collections.emptyList(), Collections.emptyList()); + + public static final Tree NO_TREE = + new Tree(Collections.emptyList(), Collections.emptyList(), Collections.emptyList()); public static boolean canDynamicTreeCutFrom(Block startBlock) { return Mods.DYNAMICTREES.runIfInstalled(() -> () -> DynamicTree.isDynamicBranch(startBlock)) @@ -69,6 +71,7 @@ public class TreeCutter { List logs = new ArrayList<>(); List leaves = new ArrayList<>(); + List attachments = new ArrayList<>(); Set visited = new HashSet<>(); List frontier = new LinkedList<>(); @@ -83,7 +86,7 @@ public class TreeCutter { logs.add(current); } Collections.reverse(logs); - return new Tree(logs, leaves); + return new Tree(logs, leaves, attachments); } // Chorus @@ -103,7 +106,7 @@ public class TreeCutter { } } Collections.reverse(logs); - return new Tree(logs, leaves); + return new Tree(logs, leaves, attachments); } // Regular Tree @@ -114,40 +117,60 @@ public class TreeCutter { BlockPos.betweenClosedStream(pos.offset(-1, 0, -1), pos.offset(1, 1, 1)) .forEach(p -> frontier.add(new BlockPos(p))); - // Find all logs + // Find all logs & roots + boolean hasRoots = false; while (!frontier.isEmpty()) { BlockPos currentPos = frontier.remove(0); - if (visited.contains(currentPos)) + if (!visited.add(currentPos)) continue; - visited.add(currentPos); - if (!isLog(reader.getBlockState(currentPos))) + BlockState currentState = reader.getBlockState(currentPos); + if (isRoot(currentState)) + hasRoots = true; + else if (!isLog(currentState)) continue; logs.add(currentPos); - forNeighbours(currentPos, visited, true, p -> frontier.add(new BlockPos(p))); + forNeighbours(currentPos, visited, SearchDirection.UP, p -> frontier.add(new BlockPos(p))); } - // Find all leaves visited.clear(); visited.addAll(logs); frontier.addAll(logs); + if (hasRoots) { + while (!frontier.isEmpty()) { + BlockPos currentPos = frontier.remove(0); + if (!logs.contains(currentPos) && !visited.add(currentPos)) + continue; + + BlockState currentState = reader.getBlockState(currentPos); + if (!isRoot(currentState)) + continue; + logs.add(currentPos); + forNeighbours(currentPos, visited, SearchDirection.DOWN, p -> frontier.add(new BlockPos(p))); + } + + visited.clear(); + visited.addAll(logs); + frontier.addAll(logs); + } + + // Find all leaves while (!frontier.isEmpty()) { BlockPos prevPos = frontier.remove(0); - if (!logs.contains(prevPos) && visited.contains(prevPos)) + if (!logs.contains(prevPos) && !visited.add(prevPos)) continue; - visited.add(prevPos); BlockState prevState = reader.getBlockState(prevPos); int prevLeafDistance = isLeaf(prevState) ? getLeafDistance(prevState) : 0; - forNeighbours(prevPos, visited, false, currentPos -> { + forNeighbours(prevPos, visited, SearchDirection.BOTH, currentPos -> { BlockState state = reader.getBlockState(currentPos); BlockPos subtract = currentPos.subtract(pos); BlockPos currentPosImmutable = currentPos.immutable(); if (AllBlockTags.TREE_ATTACHMENTS.matches(state)) { - leaves.add(currentPosImmutable); + attachments.add(currentPosImmutable); visited.add(currentPosImmutable); return; } @@ -168,7 +191,7 @@ public class TreeCutter { }); } - return new Tree(logs, leaves); + return new Tree(logs, leaves, attachments); } private static int getLeafDistance(BlockState state) { @@ -215,12 +238,17 @@ public class TreeCutter { while (!frontier.isEmpty()) { BlockPos currentPos = frontier.remove(0); + BlockPos belowPos = currentPos.below(); + visited.add(currentPos); boolean lowerLayer = currentPos.getY() == posY; - if (!isLog(reader.getBlockState(currentPos))) + BlockState currentState = reader.getBlockState(currentPos); + BlockState belowState = reader.getBlockState(belowPos); + + if (!isLog(currentState) && !isRoot(currentState)) continue; - if (!lowerLayer && !pos.equals(currentPos.below()) && isLog(reader.getBlockState(currentPos.below()))) + if (!lowerLayer && !pos.equals(belowPos) && (isLog(belowState) || isRoot(belowState))) return false; for (Direction direction : Iterate.directions) { @@ -239,12 +267,29 @@ public class TreeCutter { return true; } - private static void forNeighbours(BlockPos pos, Set visited, boolean up, Consumer acceptor) { - BlockPos.betweenClosedStream(pos.offset(-1, up ? 0 : -1, -1), pos.offset(1, 1, 1)) + private enum SearchDirection { + UP(0, 1), DOWN(-1, 0), BOTH(-1, 1); + + int minY; + int maxY; + + private SearchDirection(int minY, int maxY) { + this.minY = minY; + this.maxY = maxY; + } + } + + private static void forNeighbours(BlockPos pos, Set visited, SearchDirection direction, + Consumer acceptor) { + BlockPos.betweenClosedStream(pos.offset(-1, direction.minY, -1), pos.offset(1, direction.maxY, 1)) .filter(((Predicate) visited::contains).negate()) .forEach(acceptor); } + public static boolean isRoot(BlockState state) { + return state.is(Blocks.MANGROVE_ROOTS); + } + public static boolean isLog(BlockState state) { return state.is(BlockTags.LOGS) || AllTags.AllBlockTags.SLIMY_LOGS.matches(state) || state.is(Blocks.MUSHROOM_STEM); @@ -272,15 +317,18 @@ public class TreeCutter { public static class Tree extends AbstractBlockBreakQueue { private final List logs; private final List leaves; + private final List attachments; - public Tree(List logs, List leaves) { + public Tree(List logs, List leaves, List attachments) { this.logs = logs; this.leaves = leaves; + this.attachments = attachments; } @Override public void destroyBlocks(Level world, ItemStack toDamage, @Nullable Player playerEntity, BiConsumer drop) { + attachments.forEach(makeCallbackFor(world, 1 / 32f, toDamage, playerEntity, drop)); logs.forEach(makeCallbackFor(world, 1 / 2f, toDamage, playerEntity, drop)); leaves.forEach(makeCallbackFor(world, 1 / 8f, toDamage, playerEntity, drop)); }