mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-12-14 23:53:42 +01:00
Toadstool power tool
- Fixed Saw leaving behind floating bee nests - Saws can now be used to cut down big mushrooms - Fixed getFluidState() accessing chunks of a wrapped server world (-> Fixes tree fertilizer on 1.19)
This commit is contained in:
parent
04f4adcf46
commit
7579187dd0
6 changed files with 85 additions and 49 deletions
|
@ -5633,6 +5633,7 @@ d99d5c67bdffff60789a19bd51a5c5267c75e0a4 data/create/tags/blocks/casing.json
|
||||||
74f4ba5f6f61c30e27947c6fb4557e888d018285 data/create/tags/blocks/safe_nbt.json
|
74f4ba5f6f61c30e27947c6fb4557e888d018285 data/create/tags/blocks/safe_nbt.json
|
||||||
6cdeeac1689f7b5bfd9bc40b462143d8eaf3ad0b data/create/tags/blocks/seats.json
|
6cdeeac1689f7b5bfd9bc40b462143d8eaf3ad0b data/create/tags/blocks/seats.json
|
||||||
d063e12c9ef75f39518c6d129ea35d833464d547 data/create/tags/blocks/toolboxes.json
|
d063e12c9ef75f39518c6d129ea35d833464d547 data/create/tags/blocks/toolboxes.json
|
||||||
|
8861f982c335a1f17796df4af53a7d5dc91fc85a data/create/tags/blocks/tree_attachments.json
|
||||||
50936b211d94167a35ec78c89954082a336b6269 data/create/tags/blocks/valve_handles.json
|
50936b211d94167a35ec78c89954082a336b6269 data/create/tags/blocks/valve_handles.json
|
||||||
eac71740fb12bdb38b5dfaa2268613d7ba82b809 data/create/tags/blocks/windmill_sails.json
|
eac71740fb12bdb38b5dfaa2268613d7ba82b809 data/create/tags/blocks/windmill_sails.json
|
||||||
74700d556ca80c7a1db5fd4efb09c3ddb26cad66 data/create/tags/blocks/windowable.json
|
74700d556ca80c7a1db5fd4efb09c3ddb26cad66 data/create/tags/blocks/windowable.json
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"replace": false,
|
||||||
|
"values": [
|
||||||
|
"minecraft:bee_nest",
|
||||||
|
"minecraft:vine",
|
||||||
|
"minecraft:moss_carpet",
|
||||||
|
"minecraft:shroomlight",
|
||||||
|
"minecraft:cocoa"
|
||||||
|
]
|
||||||
|
}
|
|
@ -124,6 +124,7 @@ public class AllTags {
|
||||||
WINDMILL_SAILS,
|
WINDMILL_SAILS,
|
||||||
WINDOWABLE,
|
WINDOWABLE,
|
||||||
WRENCH_PICKUP,
|
WRENCH_PICKUP,
|
||||||
|
TREE_ATTACHMENTS,
|
||||||
|
|
||||||
RELOCATION_NOT_SUPPORTED(FORGE),
|
RELOCATION_NOT_SUPPORTED(FORGE),
|
||||||
WG_STONE(FORGE),
|
WG_STONE(FORGE),
|
||||||
|
@ -414,6 +415,9 @@ public class AllTags {
|
||||||
Blocks.COMPARATOR, Blocks.OBSERVER, Blocks.REDSTONE_WALL_TORCH, Blocks.PISTON, Blocks.STICKY_PISTON,
|
Blocks.COMPARATOR, Blocks.OBSERVER, Blocks.REDSTONE_WALL_TORCH, Blocks.PISTON, Blocks.STICKY_PISTON,
|
||||||
Blocks.TRIPWIRE, Blocks.TRIPWIRE_HOOK, Blocks.DAYLIGHT_DETECTOR, Blocks.TARGET, Blocks.HOPPER);
|
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);
|
||||||
|
|
||||||
AllBlockTags.ORE_OVERRIDE_STONE.includeAll(BlockTags.STONE_ORE_REPLACEABLES);
|
AllBlockTags.ORE_OVERRIDE_STONE.includeAll(BlockTags.STONE_ORE_REPLACEABLES);
|
||||||
|
|
||||||
registerCompat();
|
registerCompat();
|
||||||
|
|
|
@ -478,8 +478,7 @@ public class SawTileEntity extends BlockBreakingKineticTileEntity {
|
||||||
public static boolean isSawable(BlockState stateToBreak) {
|
public static boolean isSawable(BlockState stateToBreak) {
|
||||||
if (stateToBreak.is(BlockTags.SAPLINGS))
|
if (stateToBreak.is(BlockTags.SAPLINGS))
|
||||||
return false;
|
return false;
|
||||||
if (stateToBreak.is(BlockTags.LOGS) || AllTags.AllBlockTags.SLIMY_LOGS.matches(stateToBreak)
|
if (TreeCutter.isLog(stateToBreak) || (stateToBreak.is(BlockTags.LEAVES)))
|
||||||
|| (stateToBreak.is(BlockTags.LEAVES)))
|
|
||||||
return true;
|
return true;
|
||||||
Block block = stateToBreak.getBlock();
|
Block block = stateToBreak.getBlock();
|
||||||
if (block instanceof BambooBlock)
|
if (block instanceof BambooBlock)
|
||||||
|
|
|
@ -8,12 +8,14 @@ import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import com.simibubi.create.AllTags;
|
import com.simibubi.create.AllTags;
|
||||||
|
import com.simibubi.create.AllTags.AllBlockTags;
|
||||||
import com.simibubi.create.compat.Mods;
|
import com.simibubi.create.compat.Mods;
|
||||||
import com.simibubi.create.compat.dynamictrees.DynamicTree;
|
import com.simibubi.create.compat.dynamictrees.DynamicTree;
|
||||||
|
|
||||||
|
@ -42,12 +44,13 @@ 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());
|
||||||
|
|
||||||
public static boolean canDynamicTreeCutFrom(Block startBlock) {
|
public static boolean canDynamicTreeCutFrom(Block startBlock) {
|
||||||
return Mods.DYNAMICTREES.runIfInstalled(() -> () -> DynamicTree.isDynamicBranch(startBlock)).orElse(false);
|
return Mods.DYNAMICTREES.runIfInstalled(() -> () -> DynamicTree.isDynamicBranch(startBlock))
|
||||||
|
.orElse(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public static Optional<AbstractBlockBreakQueue> findDynamicTree(Block startBlock, BlockPos pos) {
|
public static Optional<AbstractBlockBreakQueue> findDynamicTree(Block startBlock, BlockPos pos) {
|
||||||
if (canDynamicTreeCutFrom(startBlock))
|
if (canDynamicTreeCutFrom(startBlock))
|
||||||
return Mods.DYNAMICTREES.runIfInstalled(() -> () -> new DynamicTree(pos));
|
return Mods.DYNAMICTREES.runIfInstalled(() -> () -> new DynamicTree(pos));
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
@ -121,59 +124,63 @@ public class TreeCutter {
|
||||||
if (!isLog(reader.getBlockState(currentPos)))
|
if (!isLog(reader.getBlockState(currentPos)))
|
||||||
continue;
|
continue;
|
||||||
logs.add(currentPos);
|
logs.add(currentPos);
|
||||||
addNeighbours(currentPos, frontier, visited);
|
forNeighbours(currentPos, visited, true, p -> frontier.add(new BlockPos(p)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find all leaves
|
// Find all leaves
|
||||||
visited.clear();
|
visited.clear();
|
||||||
visited.addAll(logs);
|
visited.addAll(logs);
|
||||||
frontier.addAll(logs);
|
frontier.addAll(logs);
|
||||||
|
|
||||||
while (!frontier.isEmpty()) {
|
while (!frontier.isEmpty()) {
|
||||||
BlockPos currentPos = frontier.remove(0);
|
BlockPos prevPos = frontier.remove(0);
|
||||||
if (!logs.contains(currentPos) && visited.contains(currentPos))
|
if (!logs.contains(prevPos) && visited.contains(prevPos))
|
||||||
continue;
|
continue;
|
||||||
visited.add(currentPos);
|
|
||||||
|
|
||||||
BlockState blockState = reader.getBlockState(currentPos);
|
visited.add(prevPos);
|
||||||
boolean isLog = isLog(blockState);
|
BlockState prevState = reader.getBlockState(prevPos);
|
||||||
boolean isLeaf = isLeaf(blockState);
|
int prevLeafDistance = isLeaf(prevState) ? getLeafDistance(prevState) : 0;
|
||||||
boolean isGenericLeaf = isLeaf || isNonDecayingLeaf(blockState);
|
|
||||||
|
|
||||||
if (!isLog && !isGenericLeaf)
|
forNeighbours(prevPos, visited, false, currentPos -> {
|
||||||
continue;
|
BlockState state = reader.getBlockState(currentPos);
|
||||||
if (isGenericLeaf)
|
BlockPos subtract = currentPos.subtract(pos);
|
||||||
leaves.add(currentPos);
|
BlockPos currentPosImmutable = currentPos.immutable();
|
||||||
|
|
||||||
|
if (AllBlockTags.TREE_ATTACHMENTS.matches(state)) {
|
||||||
|
leaves.add(currentPosImmutable);
|
||||||
|
visited.add(currentPosImmutable);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
IntegerProperty distanceProperty = LeavesBlock.DISTANCE;
|
|
||||||
for (Property<?> property : blockState.getValues()
|
|
||||||
.keySet())
|
|
||||||
if (property instanceof IntegerProperty ip && property.getName()
|
|
||||||
.equals("distance"))
|
|
||||||
distanceProperty = ip;
|
|
||||||
|
|
||||||
int distance = !isLeaf ? 0 : blockState.getValue(distanceProperty);
|
|
||||||
for (Direction direction : Iterate.directions) {
|
|
||||||
BlockPos offset = currentPos.relative(direction);
|
|
||||||
if (visited.contains(offset))
|
|
||||||
continue;
|
|
||||||
BlockState state = reader.getBlockState(offset);
|
|
||||||
BlockPos subtract = offset.subtract(pos);
|
|
||||||
|
|
||||||
for (Property<?> property : state.getValues().keySet())
|
|
||||||
if (property instanceof IntegerProperty ip && property.getName().equals("distance"))
|
|
||||||
distanceProperty = ip;
|
|
||||||
|
|
||||||
int horizontalDistance = Math.max(Math.abs(subtract.getX()), Math.abs(subtract.getZ()));
|
int horizontalDistance = Math.max(Math.abs(subtract.getX()), Math.abs(subtract.getZ()));
|
||||||
if (isLeaf(state) && state.getValue(distanceProperty) > distance
|
if (horizontalDistance <= nonDecayingLeafDistance(state)) {
|
||||||
|| isNonDecayingLeaf(state) && horizontalDistance < 4)
|
leaves.add(currentPosImmutable);
|
||||||
frontier.add(offset);
|
frontier.add(currentPosImmutable);
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isLeaf(state) && getLeafDistance(state) > prevLeafDistance) {
|
||||||
|
leaves.add(currentPosImmutable);
|
||||||
|
frontier.add(currentPosImmutable);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Tree(logs, leaves);
|
return new Tree(logs, leaves);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static int getLeafDistance(BlockState state) {
|
||||||
|
IntegerProperty distanceProperty = LeavesBlock.DISTANCE;
|
||||||
|
for (Property<?> property : state.getValues()
|
||||||
|
.keySet())
|
||||||
|
if (property instanceof IntegerProperty ip && property.getName()
|
||||||
|
.equals("distance"))
|
||||||
|
distanceProperty = ip;
|
||||||
|
return state.getValue(distanceProperty);
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isChorus(BlockState stateAbove) {
|
public static boolean isChorus(BlockState stateAbove) {
|
||||||
return stateAbove.getBlock() instanceof ChorusPlantBlock || stateAbove.getBlock() instanceof ChorusFlowerBlock;
|
return stateAbove.getBlock() instanceof ChorusPlantBlock || stateAbove.getBlock() instanceof ChorusFlowerBlock;
|
||||||
}
|
}
|
||||||
|
@ -232,23 +239,32 @@ public class TreeCutter {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void addNeighbours(BlockPos pos, List<BlockPos> frontier, Set<BlockPos> visited) {
|
private static void forNeighbours(BlockPos pos, Set<BlockPos> visited, boolean up, Consumer<BlockPos> acceptor) {
|
||||||
BlockPos.betweenClosedStream(pos.offset(-1, -1, -1), pos.offset(1, 1, 1))
|
BlockPos.betweenClosedStream(pos.offset(-1, up ? 0 : -1, -1), pos.offset(1, 1, 1))
|
||||||
.filter(((Predicate<BlockPos>) visited::contains).negate())
|
.filter(((Predicate<BlockPos>) visited::contains).negate())
|
||||||
.forEach(p -> frontier.add(new BlockPos(p)));
|
.forEach(acceptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isLog(BlockState state) {
|
public static boolean isLog(BlockState state) {
|
||||||
return state.is(BlockTags.LOGS) || AllTags.AllBlockTags.SLIMY_LOGS.matches(state);
|
return state.is(BlockTags.LOGS) || AllTags.AllBlockTags.SLIMY_LOGS.matches(state)
|
||||||
|
|| state.is(Blocks.MUSHROOM_STEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isNonDecayingLeaf(BlockState state) {
|
private static int nonDecayingLeafDistance(BlockState state) {
|
||||||
return state.is(BlockTags.WART_BLOCKS) || state.getBlock() == Blocks.SHROOMLIGHT;
|
if (state.is(Blocks.RED_MUSHROOM_BLOCK))
|
||||||
|
return 2;
|
||||||
|
if (state.is(Blocks.BROWN_MUSHROOM_BLOCK))
|
||||||
|
return 3;
|
||||||
|
if (state.is(BlockTags.WART_BLOCKS) || state.is(Blocks.WEEPING_VINES) || state.is(Blocks.WEEPING_VINES_PLANT))
|
||||||
|
return 3;
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isLeaf(BlockState state) {
|
private static boolean isLeaf(BlockState state) {
|
||||||
for (Property<?> property : state.getValues().keySet())
|
for (Property<?> property : state.getValues()
|
||||||
if (property instanceof IntegerProperty && property.getName().equals("distance"))
|
.keySet())
|
||||||
|
if (property instanceof IntegerProperty && property.getName()
|
||||||
|
.equals("distance"))
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.world.level.block.Blocks;
|
import net.minecraft.world.level.block.Blocks;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
import net.minecraft.world.level.material.FluidState;
|
||||||
|
|
||||||
public class PlacementSimulationServerWorld extends WrappedServerWorld {
|
public class PlacementSimulationServerWorld extends WrappedServerWorld {
|
||||||
public HashMap<BlockPos, BlockState> blocksAdded;
|
public HashMap<BlockPos, BlockState> blocksAdded;
|
||||||
|
@ -52,5 +53,10 @@ public class PlacementSimulationServerWorld extends WrappedServerWorld {
|
||||||
return blocksAdded.get(pos);
|
return blocksAdded.get(pos);
|
||||||
return Blocks.AIR.defaultBlockState();
|
return Blocks.AIR.defaultBlockState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FluidState getFluidState(BlockPos pos) {
|
||||||
|
return getBlockState(pos).getFluidState();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue