diff --git a/verification/src/changes/accepted-bukkit-public-api-changes.json b/verification/src/changes/accepted-bukkit-public-api-changes.json index fd21c268d8..1c50324290 100644 --- a/verification/src/changes/accepted-bukkit-public-api-changes.json +++ b/verification/src/changes/accepted-bukkit-public-api-changes.json @@ -8,5 +8,15 @@ "ANNOTATION_REMOVED" ] } + ], + "Replaced by default method": [ + { + "type": "com.sk89q.worldedit.bukkit.BukkitBlockRegistry", + "member": "Method com.sk89q.worldedit.bukkit.BukkitBlockRegistry.getMaterial(com.sk89q.worldedit.world.block.BlockType)", + "changes": [ + "METHOD_REMOVED", + "ANNOTATION_REMOVED" + ] + } ] } diff --git a/verification/src/changes/accepted-core-public-api-changes.json b/verification/src/changes/accepted-core-public-api-changes.json index 4876c13d16..40c9cacc19 100644 --- a/verification/src/changes/accepted-core-public-api-changes.json +++ b/verification/src/changes/accepted-core-public-api-changes.json @@ -22,6 +22,22 @@ "changes": [ "METHOD_REMOVED" ] + }, + { + "type": "com.sk89q.worldedit.EditSession", + "member": "Method com.sk89q.worldedit.EditSession.makeCuboidFaces(com.sk89q.worldedit.regions.Region,int,com.sk89q.worldedit.function.pattern.Pattern)", + "changes": [ + "METHOD_NOW_FINAL" + ] + } + ], + "Why on earth is this even an issue?": [ + { + "type": "com.sk89q.worldedit.world.registry.BlockMaterial", + "member": "Method com.sk89q.worldedit.world.registry.BlockMaterial.isFullCube()", + "changes": [ + "METHOD_ABSTRACT_NOW_DEFAULT" + ] } ] } diff --git a/verification/src/changes/accepted-sponge-public-api-changes.json b/verification/src/changes/accepted-sponge-public-api-changes.json index 2c63c08510..3afedbaad5 100644 --- a/verification/src/changes/accepted-sponge-public-api-changes.json +++ b/verification/src/changes/accepted-sponge-public-api-changes.json @@ -1,2 +1,18 @@ { + "Replaced by default method": [ + { + "type": "com.sk89q.worldedit.sponge.SpongeBlockRegistry", + "member": "Method com.sk89q.worldedit.sponge.SpongeBlockRegistry.getMaterial(com.sk89q.worldedit.world.block.BlockType)", + "changes": [ + "METHOD_REMOVED" + ] + }, + { + "type": "com.sk89q.worldedit.sponge.SpongeBlockMaterial", + "member": "Method com.sk89q.worldedit.sponge.SpongeBlockMaterial.isFullCube()", + "changes": [ + "METHOD_REMOVED" + ] + } + ] } diff --git a/worldedit-bukkit/adapters/adapter-1.21.11/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_11/PaperweightAdapter.java b/worldedit-bukkit/adapters/adapter-1.21.11/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_11/PaperweightAdapter.java index 816930823e..2b9efe661a 100644 --- a/worldedit-bukkit/adapters/adapter-1.21.11/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_11/PaperweightAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1.21.11/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_11/PaperweightAdapter.java @@ -439,7 +439,7 @@ public void setBiome(Location location, BiomeType biome) { return new PaperweightWorldNativeAccess(this, new WeakReference<>(((CraftWorld) world).getHandle())); } - private static net.minecraft.core.Direction adapt(Direction face) { + public static net.minecraft.core.Direction adapt(Direction face) { return switch (face) { case NORTH -> net.minecraft.core.Direction.NORTH; case SOUTH -> net.minecraft.core.Direction.SOUTH; @@ -586,6 +586,11 @@ public BlockMaterial getBlockMaterial(BlockType blockType) { return new PaperweightBlockMaterial(mcBlockState); } + @Override + public BlockMaterial getBlockMaterial(BlockState blockState) { + return new PaperweightBlockMaterial(adapt(blockState)); + } + @SuppressWarnings({ "unchecked", "rawtypes" }) private static final LoadingCache> PROPERTY_CACHE = CacheBuilder.newBuilder().build(new CacheLoader<>() { @Override diff --git a/worldedit-bukkit/adapters/adapter-1.21.11/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_11/PaperweightBlockMaterial.java b/worldedit-bukkit/adapters/adapter-1.21.11/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_11/PaperweightBlockMaterial.java index 2113b1ee1d..be4093123d 100644 --- a/worldedit-bukkit/adapters/adapter-1.21.11/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_11/PaperweightBlockMaterial.java +++ b/worldedit-bukkit/adapters/adapter-1.21.11/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_11/PaperweightBlockMaterial.java @@ -19,7 +19,9 @@ package com.sk89q.worldedit.bukkit.adapter.impl.v1_21_11; -import com.sk89q.worldedit.world.registry.BlockMaterial; +import com.sk89q.worldedit.blocks.ShapeType; +import com.sk89q.worldedit.internal.block.AbstractBlockMaterial; +import com.sk89q.worldedit.util.Direction; import net.minecraft.core.BlockPos; import net.minecraft.world.Clearable; import net.minecraft.world.level.EmptyBlockGetter; @@ -27,8 +29,10 @@ import net.minecraft.world.level.block.EntityBlock; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.material.PushReaction; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; -public class PaperweightBlockMaterial implements BlockMaterial { +public class PaperweightBlockMaterial extends AbstractBlockMaterial { private final BlockState block; @@ -42,8 +46,21 @@ public boolean isAir() { } @Override - public boolean isFullCube() { - return Block.isShapeFullBlock(block.getShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO)); + protected VoxelShape getShape(ShapeType shapeType) { + return switch (shapeType) { + case SHAPE -> block.getShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO, CollisionContext.empty()); + case VISUAL_SHAPE -> block.getVisualShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO, CollisionContext.empty()); + }; + } + + @Override + protected boolean isShapeFullBlock(VoxelShape shape) { + return Block.isShapeFullBlock(shape); + } + + @Override + protected boolean isFaceFull(VoxelShape shape, Direction face) { + return Block.isFaceFull(shape, PaperweightAdapter.adapt(face)); } @Override diff --git a/worldedit-bukkit/adapters/adapter-1.21.4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_4/PaperweightAdapter.java b/worldedit-bukkit/adapters/adapter-1.21.4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_4/PaperweightAdapter.java index fcf1579cea..0f4e284390 100644 --- a/worldedit-bukkit/adapters/adapter-1.21.4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_4/PaperweightAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1.21.4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_4/PaperweightAdapter.java @@ -427,7 +427,7 @@ public void setBiome(Location location, BiomeType biome) { return new PaperweightWorldNativeAccess(this, new WeakReference<>(((CraftWorld) world).getHandle())); } - private static net.minecraft.core.Direction adapt(Direction face) { + public static net.minecraft.core.Direction adapt(Direction face) { return switch (face) { case NORTH -> net.minecraft.core.Direction.NORTH; case SOUTH -> net.minecraft.core.Direction.SOUTH; @@ -567,6 +567,11 @@ public BlockMaterial getBlockMaterial(BlockType blockType) { return new PaperweightBlockMaterial(mcBlockState); } + @Override + public BlockMaterial getBlockMaterial(BlockState blockState) { + return new PaperweightBlockMaterial(adapt(blockState)); + } + @SuppressWarnings({ "unchecked", "rawtypes" }) private static final LoadingCache> PROPERTY_CACHE = CacheBuilder.newBuilder().build(new CacheLoader<>() { @Override diff --git a/worldedit-bukkit/adapters/adapter-1.21.4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_4/PaperweightBlockMaterial.java b/worldedit-bukkit/adapters/adapter-1.21.4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_4/PaperweightBlockMaterial.java index 10c1f7d222..a9f2a91f5c 100644 --- a/worldedit-bukkit/adapters/adapter-1.21.4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_4/PaperweightBlockMaterial.java +++ b/worldedit-bukkit/adapters/adapter-1.21.4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_4/PaperweightBlockMaterial.java @@ -19,7 +19,9 @@ package com.sk89q.worldedit.bukkit.adapter.impl.v1_21_4; -import com.sk89q.worldedit.world.registry.BlockMaterial; +import com.sk89q.worldedit.blocks.ShapeType; +import com.sk89q.worldedit.internal.block.AbstractBlockMaterial; +import com.sk89q.worldedit.util.Direction; import net.minecraft.core.BlockPos; import net.minecraft.world.Clearable; import net.minecraft.world.level.EmptyBlockGetter; @@ -27,8 +29,10 @@ import net.minecraft.world.level.block.EntityBlock; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.material.PushReaction; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; -public class PaperweightBlockMaterial implements BlockMaterial { +public class PaperweightBlockMaterial extends AbstractBlockMaterial { private final BlockState block; @@ -42,8 +46,21 @@ public boolean isAir() { } @Override - public boolean isFullCube() { - return Block.isShapeFullBlock(block.getShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO)); + protected VoxelShape getShape(ShapeType shapeType) { + return switch (shapeType) { + case SHAPE -> block.getShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO, CollisionContext.empty()); + case VISUAL_SHAPE -> block.getVisualShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO, CollisionContext.empty()); + }; + } + + @Override + protected boolean isShapeFullBlock(VoxelShape shape) { + return Block.isShapeFullBlock(shape); + } + + @Override + protected boolean isFaceFull(VoxelShape shape, Direction face) { + return Block.isFaceFull(shape, PaperweightAdapter.adapt(face)); } @Override diff --git a/worldedit-bukkit/adapters/adapter-1.21.5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_5/PaperweightAdapter.java b/worldedit-bukkit/adapters/adapter-1.21.5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_5/PaperweightAdapter.java index 4d48915dee..dbde1b24cc 100644 --- a/worldedit-bukkit/adapters/adapter-1.21.5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_5/PaperweightAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1.21.5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_5/PaperweightAdapter.java @@ -427,7 +427,7 @@ public void setBiome(Location location, BiomeType biome) { return new PaperweightWorldNativeAccess(this, new WeakReference<>(((CraftWorld) world).getHandle())); } - private static net.minecraft.core.Direction adapt(Direction face) { + public static net.minecraft.core.Direction adapt(Direction face) { return switch (face) { case NORTH -> net.minecraft.core.Direction.NORTH; case SOUTH -> net.minecraft.core.Direction.SOUTH; @@ -565,6 +565,11 @@ public BlockMaterial getBlockMaterial(BlockType blockType) { return new PaperweightBlockMaterial(mcBlockState); } + @Override + public BlockMaterial getBlockMaterial(BlockState blockState) { + return new PaperweightBlockMaterial(adapt(blockState)); + } + @SuppressWarnings({ "unchecked", "rawtypes" }) private static final LoadingCache> PROPERTY_CACHE = CacheBuilder.newBuilder().build(new CacheLoader<>() { @Override diff --git a/worldedit-bukkit/adapters/adapter-1.21.5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_5/PaperweightBlockMaterial.java b/worldedit-bukkit/adapters/adapter-1.21.5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_5/PaperweightBlockMaterial.java index bb44cd3fec..69011c6a56 100644 --- a/worldedit-bukkit/adapters/adapter-1.21.5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_5/PaperweightBlockMaterial.java +++ b/worldedit-bukkit/adapters/adapter-1.21.5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_5/PaperweightBlockMaterial.java @@ -19,7 +19,9 @@ package com.sk89q.worldedit.bukkit.adapter.impl.v1_21_5; -import com.sk89q.worldedit.world.registry.BlockMaterial; +import com.sk89q.worldedit.blocks.ShapeType; +import com.sk89q.worldedit.internal.block.AbstractBlockMaterial; +import com.sk89q.worldedit.util.Direction; import net.minecraft.core.BlockPos; import net.minecraft.world.Clearable; import net.minecraft.world.level.EmptyBlockGetter; @@ -27,8 +29,10 @@ import net.minecraft.world.level.block.EntityBlock; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.material.PushReaction; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; -public class PaperweightBlockMaterial implements BlockMaterial { +public class PaperweightBlockMaterial extends AbstractBlockMaterial { private final BlockState block; @@ -42,8 +46,21 @@ public boolean isAir() { } @Override - public boolean isFullCube() { - return Block.isShapeFullBlock(block.getShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO)); + protected VoxelShape getShape(ShapeType shapeType) { + return switch (shapeType) { + case SHAPE -> block.getShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO, CollisionContext.empty()); + case VISUAL_SHAPE -> block.getVisualShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO, CollisionContext.empty()); + }; + } + + @Override + protected boolean isShapeFullBlock(VoxelShape shape) { + return Block.isShapeFullBlock(shape); + } + + @Override + protected boolean isFaceFull(VoxelShape shape, Direction face) { + return Block.isFaceFull(shape, PaperweightAdapter.adapt(face)); } @Override diff --git a/worldedit-bukkit/adapters/adapter-1.21.6/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_6/PaperweightAdapter.java b/worldedit-bukkit/adapters/adapter-1.21.6/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_6/PaperweightAdapter.java index b7fb495d5f..5f01b19927 100644 --- a/worldedit-bukkit/adapters/adapter-1.21.6/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_6/PaperweightAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1.21.6/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_6/PaperweightAdapter.java @@ -440,7 +440,7 @@ public void setBiome(Location location, BiomeType biome) { return new PaperweightWorldNativeAccess(this, new WeakReference<>(((CraftWorld) world).getHandle())); } - private static net.minecraft.core.Direction adapt(Direction face) { + public static net.minecraft.core.Direction adapt(Direction face) { return switch (face) { case NORTH -> net.minecraft.core.Direction.NORTH; case SOUTH -> net.minecraft.core.Direction.SOUTH; @@ -587,6 +587,11 @@ public BlockMaterial getBlockMaterial(BlockType blockType) { return new PaperweightBlockMaterial(mcBlockState); } + @Override + public BlockMaterial getBlockMaterial(BlockState blockState) { + return new PaperweightBlockMaterial(adapt(blockState)); + } + @SuppressWarnings({ "unchecked", "rawtypes" }) private static final LoadingCache> PROPERTY_CACHE = CacheBuilder.newBuilder().build(new CacheLoader<>() { @Override diff --git a/worldedit-bukkit/adapters/adapter-1.21.6/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_6/PaperweightBlockMaterial.java b/worldedit-bukkit/adapters/adapter-1.21.6/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_6/PaperweightBlockMaterial.java index 8042660f50..18f03a222f 100644 --- a/worldedit-bukkit/adapters/adapter-1.21.6/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_6/PaperweightBlockMaterial.java +++ b/worldedit-bukkit/adapters/adapter-1.21.6/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_6/PaperweightBlockMaterial.java @@ -19,7 +19,9 @@ package com.sk89q.worldedit.bukkit.adapter.impl.v1_21_6; -import com.sk89q.worldedit.world.registry.BlockMaterial; +import com.sk89q.worldedit.blocks.ShapeType; +import com.sk89q.worldedit.internal.block.AbstractBlockMaterial; +import com.sk89q.worldedit.util.Direction; import net.minecraft.core.BlockPos; import net.minecraft.world.Clearable; import net.minecraft.world.level.EmptyBlockGetter; @@ -27,8 +29,10 @@ import net.minecraft.world.level.block.EntityBlock; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.material.PushReaction; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; -public class PaperweightBlockMaterial implements BlockMaterial { +public class PaperweightBlockMaterial extends AbstractBlockMaterial { private final BlockState block; @@ -42,8 +46,21 @@ public boolean isAir() { } @Override - public boolean isFullCube() { - return Block.isShapeFullBlock(block.getShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO)); + protected VoxelShape getShape(ShapeType shapeType) { + return switch (shapeType) { + case SHAPE -> block.getShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO, CollisionContext.empty()); + case VISUAL_SHAPE -> block.getVisualShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO, CollisionContext.empty()); + }; + } + + @Override + protected boolean isShapeFullBlock(VoxelShape shape) { + return Block.isShapeFullBlock(shape); + } + + @Override + protected boolean isFaceFull(VoxelShape shape, Direction face) { + return Block.isFaceFull(shape, PaperweightAdapter.adapt(face)); } @Override diff --git a/worldedit-bukkit/adapters/adapter-1.21.9/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_9/PaperweightAdapter.java b/worldedit-bukkit/adapters/adapter-1.21.9/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_9/PaperweightAdapter.java index 65692f02f5..33761d9f25 100644 --- a/worldedit-bukkit/adapters/adapter-1.21.9/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_9/PaperweightAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1.21.9/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_9/PaperweightAdapter.java @@ -439,7 +439,7 @@ public void setBiome(Location location, BiomeType biome) { return new PaperweightWorldNativeAccess(this, new WeakReference<>(((CraftWorld) world).getHandle())); } - private static net.minecraft.core.Direction adapt(Direction face) { + public static net.minecraft.core.Direction adapt(Direction face) { return switch (face) { case NORTH -> net.minecraft.core.Direction.NORTH; case SOUTH -> net.minecraft.core.Direction.SOUTH; @@ -586,6 +586,11 @@ public BlockMaterial getBlockMaterial(BlockType blockType) { return new PaperweightBlockMaterial(mcBlockState); } + @Override + public BlockMaterial getBlockMaterial(BlockState blockState) { + return new PaperweightBlockMaterial(adapt(blockState)); + } + @SuppressWarnings({ "unchecked", "rawtypes" }) private static final LoadingCache> PROPERTY_CACHE = CacheBuilder.newBuilder().build(new CacheLoader<>() { @Override diff --git a/worldedit-bukkit/adapters/adapter-1.21.9/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_9/PaperweightBlockMaterial.java b/worldedit-bukkit/adapters/adapter-1.21.9/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_9/PaperweightBlockMaterial.java index 1df238afb7..bccc5f3ea5 100644 --- a/worldedit-bukkit/adapters/adapter-1.21.9/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_9/PaperweightBlockMaterial.java +++ b/worldedit-bukkit/adapters/adapter-1.21.9/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_9/PaperweightBlockMaterial.java @@ -19,7 +19,9 @@ package com.sk89q.worldedit.bukkit.adapter.impl.v1_21_9; -import com.sk89q.worldedit.world.registry.BlockMaterial; +import com.sk89q.worldedit.blocks.ShapeType; +import com.sk89q.worldedit.internal.block.AbstractBlockMaterial; +import com.sk89q.worldedit.util.Direction; import net.minecraft.core.BlockPos; import net.minecraft.world.Clearable; import net.minecraft.world.level.EmptyBlockGetter; @@ -27,8 +29,10 @@ import net.minecraft.world.level.block.EntityBlock; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.material.PushReaction; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; -public class PaperweightBlockMaterial implements BlockMaterial { +public class PaperweightBlockMaterial extends AbstractBlockMaterial { private final BlockState block; @@ -42,8 +46,21 @@ public boolean isAir() { } @Override - public boolean isFullCube() { - return Block.isShapeFullBlock(block.getShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO)); + protected VoxelShape getShape(ShapeType shapeType) { + return switch (shapeType) { + case SHAPE -> block.getShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO, CollisionContext.empty()); + case VISUAL_SHAPE -> block.getVisualShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO, CollisionContext.empty()); + }; + } + + @Override + protected boolean isShapeFullBlock(VoxelShape shape) { + return Block.isShapeFullBlock(shape); + } + + @Override + protected boolean isFaceFull(VoxelShape shape, Direction face) { + return Block.isFaceFull(shape, PaperweightAdapter.adapt(face)); } @Override diff --git a/worldedit-bukkit/adapters/adapter-26.1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v26_1/PaperweightAdapter.java b/worldedit-bukkit/adapters/adapter-26.1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v26_1/PaperweightAdapter.java index 60f922d154..fd8a3f01c1 100644 --- a/worldedit-bukkit/adapters/adapter-26.1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v26_1/PaperweightAdapter.java +++ b/worldedit-bukkit/adapters/adapter-26.1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v26_1/PaperweightAdapter.java @@ -456,7 +456,7 @@ public void setBiome(Location location, BiomeType biome) { return new PaperweightWorldNativeAccess(this, new WeakReference<>(((CraftWorld) world).getHandle())); } - private static net.minecraft.core.Direction adapt(Direction face) { + public static net.minecraft.core.Direction adapt(Direction face) { return switch (face) { case NORTH -> net.minecraft.core.Direction.NORTH; case SOUTH -> net.minecraft.core.Direction.SOUTH; @@ -603,6 +603,11 @@ public BlockMaterial getBlockMaterial(BlockType blockType) { return new PaperweightBlockMaterial(mcBlockState); } + @Override + public BlockMaterial getBlockMaterial(BlockState blockState) { + return new PaperweightBlockMaterial(adapt(blockState)); + } + @SuppressWarnings({ "unchecked", "rawtypes" }) private static final LoadingCache> PROPERTY_CACHE = CacheBuilder.newBuilder().build(new CacheLoader<>() { @Override diff --git a/worldedit-bukkit/adapters/adapter-26.1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v26_1/PaperweightBlockMaterial.java b/worldedit-bukkit/adapters/adapter-26.1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v26_1/PaperweightBlockMaterial.java index 157d92e47f..4344ac59ac 100644 --- a/worldedit-bukkit/adapters/adapter-26.1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v26_1/PaperweightBlockMaterial.java +++ b/worldedit-bukkit/adapters/adapter-26.1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v26_1/PaperweightBlockMaterial.java @@ -19,7 +19,9 @@ package com.sk89q.worldedit.bukkit.adapter.impl.v26_1; -import com.sk89q.worldedit.world.registry.BlockMaterial; +import com.sk89q.worldedit.blocks.ShapeType; +import com.sk89q.worldedit.internal.block.AbstractBlockMaterial; +import com.sk89q.worldedit.util.Direction; import net.minecraft.core.BlockPos; import net.minecraft.world.Clearable; import net.minecraft.world.level.EmptyBlockGetter; @@ -27,8 +29,10 @@ import net.minecraft.world.level.block.EntityBlock; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.material.PushReaction; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; -public class PaperweightBlockMaterial implements BlockMaterial { +public class PaperweightBlockMaterial extends AbstractBlockMaterial { private final BlockState block; @@ -42,8 +46,21 @@ public boolean isAir() { } @Override - public boolean isFullCube() { - return Block.isShapeFullBlock(block.getShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO)); + protected VoxelShape getShape(ShapeType shapeType) { + return switch (shapeType) { + case SHAPE -> block.getShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO, CollisionContext.empty()); + case VISUAL_SHAPE -> block.getVisualShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO, CollisionContext.empty()); + }; + } + + @Override + protected boolean isShapeFullBlock(VoxelShape shape) { + return Block.isShapeFullBlock(shape); + } + + @Override + protected boolean isFaceFull(VoxelShape shape, Direction face) { + return Block.isFaceFull(shape, PaperweightAdapter.adapt(face)); } @Override diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitBlockRegistry.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitBlockRegistry.java index 70cd562329..9147712967 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitBlockRegistry.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitBlockRegistry.java @@ -35,7 +35,7 @@ import javax.annotation.Nullable; public class BukkitBlockRegistry implements BlockRegistry { - private final Map materialMap = new HashMap<>(); + private final Map materialMap = new HashMap<>(); @Override public Component getRichName(BlockType blockType) { @@ -47,15 +47,16 @@ public Component getRichName(BlockType blockType) { @Nullable @Override - public BlockMaterial getMaterial(BlockType blockType) { - Material mat = BukkitAdapter.adapt(blockType); - if (mat == null) { - return null; - } - return materialMap.computeIfAbsent(mat, material -> { + public BlockMaterial getMaterial(BlockState blockState) { + return materialMap.computeIfAbsent(blockState, _ -> { + Material material = BukkitAdapter.adapt(blockState.getBlockType()); + if (material == null) { + // return null means create no mapping + return null; + } BlockMaterial platformMaterial = null; if (WorldEditPlugin.getInstance().getBukkitImplAdapter() != null) { - platformMaterial = WorldEditPlugin.getInstance().getBukkitImplAdapter().getBlockMaterial(blockType); + platformMaterial = WorldEditPlugin.getInstance().getBukkitImplAdapter().getBlockMaterial(blockState); } return new BukkitBlockMaterial(platformMaterial, material); }); diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplAdapter.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplAdapter.java index 041b4872a9..daed9fafb8 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplAdapter.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplAdapter.java @@ -161,6 +161,17 @@ default void tickWatchdog() { @Nullable BlockMaterial getBlockMaterial(BlockType blockType); + /** + * Gets the block material for the given block state. + * + * @param blockState the block state + * @return the material + */ + @Nullable + default BlockMaterial getBlockMaterial(BlockState blockState) { + return getBlockMaterial(blockState.getBlockType()); + } + /** * Get a map of {@code string -> property}. * diff --git a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/CoreMcAdapter.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/CoreMcAdapter.java index 913701596d..e6785b576c 100644 --- a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/CoreMcAdapter.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/CoreMcAdapter.java @@ -25,6 +25,7 @@ import com.sk89q.worldedit.coremc.internal.CoreMcCommandSender; import com.sk89q.worldedit.coremc.internal.CoreMcPlatform; import com.sk89q.worldedit.coremc.internal.CoreMcPlayer; +import com.sk89q.worldedit.coremc.internal.CoreMcTransmogrifier; import com.sk89q.worldedit.coremc.internal.CoreMcWorld; import com.sk89q.worldedit.coremc.internal.NBTConverter; import com.sk89q.worldedit.coremc.mixin.AccessorCommandSourceStack; @@ -121,14 +122,7 @@ public Vec3 toVec3(BlockVector3 vector) { } public net.minecraft.core.Direction adapt(Direction face) { - return switch (face) { - case NORTH -> net.minecraft.core.Direction.NORTH; - case SOUTH -> net.minecraft.core.Direction.SOUTH; - case WEST -> net.minecraft.core.Direction.WEST; - case EAST -> net.minecraft.core.Direction.EAST; - case DOWN -> net.minecraft.core.Direction.DOWN; - default -> net.minecraft.core.Direction.UP; - }; + return CoreMcTransmogrifier.transmogToMinecraft(face); } public Direction adaptEnumFacing(@Nullable net.minecraft.core.Direction face) { diff --git a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcBlockMaterial.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcBlockMaterial.java index 16c5f731b5..54ed09cb24 100644 --- a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcBlockMaterial.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcBlockMaterial.java @@ -19,7 +19,9 @@ package com.sk89q.worldedit.coremc.internal; -import com.sk89q.worldedit.world.registry.BlockMaterial; +import com.sk89q.worldedit.blocks.ShapeType; +import com.sk89q.worldedit.internal.block.AbstractBlockMaterial; +import com.sk89q.worldedit.util.Direction; import net.minecraft.core.BlockPos; import net.minecraft.world.Clearable; import net.minecraft.world.level.EmptyBlockGetter; @@ -27,12 +29,14 @@ import net.minecraft.world.level.block.EntityBlock; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.material.PushReaction; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; /** * Minecraft block material implementation for platforms sharing native code. * Pulls as much info as possible from the Minecraft BlockState. */ -public final class CoreMcBlockMaterial implements BlockMaterial { +public final class CoreMcBlockMaterial extends AbstractBlockMaterial { private final BlockState block; @@ -46,8 +50,21 @@ public boolean isAir() { } @Override - public boolean isFullCube() { - return Block.isShapeFullBlock(block.getShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO)); + protected VoxelShape getShape(ShapeType shapeType) { + return switch (shapeType) { + case SHAPE -> block.getShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO, CollisionContext.empty()); + case VISUAL_SHAPE -> block.getVisualShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO, CollisionContext.empty()); + }; + } + + @Override + protected boolean isShapeFullBlock(VoxelShape shape) { + return Block.isShapeFullBlock(shape); + } + + @Override + protected boolean isFaceFull(VoxelShape shape, Direction face) { + return Block.isFaceFull(shape, CoreMcTransmogrifier.transmogToMinecraft(face)); } @Override diff --git a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcBlockRegistry.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcBlockRegistry.java index 6d6119d0a4..cacae6e1c6 100644 --- a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcBlockRegistry.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcBlockRegistry.java @@ -52,10 +52,9 @@ public Component getRichName(BlockType blockType) { } @Override - public BlockMaterial getMaterial(BlockType blockType) { - Block block = platform.getAdapter().toNativeBlock(blockType); + public BlockMaterial getMaterial(BlockState blockState) { return materialMap.computeIfAbsent( - block.defaultBlockState(), + platform.getAdapter().toNativeBlockState(blockState), CoreMcBlockMaterial::new ); } diff --git a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcTransmogrifier.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcTransmogrifier.java index e1945d8b4a..2ea045e46e 100644 --- a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcTransmogrifier.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcTransmogrifier.java @@ -71,6 +71,17 @@ public CoreMcTransmogrifier(CoreMcPlatform platform) { this.platform = platform; } + public static net.minecraft.core.Direction transmogToMinecraft(Direction face) { + return switch (face) { + case NORTH -> net.minecraft.core.Direction.NORTH; + case SOUTH -> net.minecraft.core.Direction.SOUTH; + case WEST -> net.minecraft.core.Direction.WEST; + case EAST -> net.minecraft.core.Direction.EAST; + case DOWN -> net.minecraft.core.Direction.DOWN; + default -> net.minecraft.core.Direction.UP; + }; + } + public Property transmogToWorldEditProperty(net.minecraft.world.level.block.state.properties.Property property) { return propertyCache.getUnchecked(property); } @@ -104,7 +115,7 @@ private net.minecraft.world.level.block.state.BlockState transmogToMinecraftProp if (property instanceof net.minecraft.world.level.block.state.properties.EnumProperty) { if (property.getValueClass() == net.minecraft.core.Direction.class) { Direction dir = (Direction) value; - value = platform.getAdapter().adapt(dir); + value = transmogToMinecraft(dir); } else { String enumName = (String) value; value = ((net.minecraft.world.level.block.state.properties.EnumProperty) property).getValue((String) value).orElseThrow(() -> diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java index 0ec0725942..6b4774f9db 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java @@ -21,6 +21,7 @@ import com.google.common.collect.ImmutableList; import com.google.errorprone.annotations.InlineMe; +import com.sk89q.worldedit.blocks.ShapeType; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.event.extent.EditSessionEvent; @@ -129,17 +130,21 @@ import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockTypes; import com.sk89q.worldedit.world.generation.TreeType; +import com.sk89q.worldedit.world.registry.BlockMaterial; import com.sk89q.worldedit.world.registry.LegacyMapper; import org.apache.logging.log4j.Logger; import java.util.ArrayDeque; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Queue; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import javax.annotation.Nullable; @@ -2655,6 +2660,43 @@ public int deformRegion(final Region region, final Transform targetTransform, fi return affected; } + private static Direction[] getBlockedDirections(Extent extent, BlockVector3 position) { + BlockState blockState = extent.getBlock(position); + BlockType blockType = blockState.getBlockType(); + BlockMaterial material = blockState.getMaterial(); + + if (material.isAir()) { + return NO_DIRECTIONS; + } + if (material.isLiquid()) { + return NO_DIRECTIONS; + } + Direction[] blockedDirections = BLOCKED_DIRECTIONS_OVERRIDE.get(blockType); + if (blockedDirections != null) { + return blockedDirections; + } + if (material.isFullCube(ShapeType.VISUAL_SHAPE)) { + return CARDINAL_UPRIGHT_DIRECTIONS; + } + + Direction[] result = new Direction[CARDINAL_UPRIGHT_DIRECTIONS.length]; + int count = 0; + + for (Direction direction : CARDINAL_UPRIGHT_DIRECTIONS) { + if (material.isFullFace(ShapeType.VISUAL_SHAPE, direction)) { + result[count++] = direction; + } + } + + // Short-cut for blocks that are blocked in all directions but for some reason not isFullCube + // This enables == comparison later + if (count == 6) { + return CARDINAL_UPRIGHT_DIRECTIONS; + } + + return Arrays.copyOf(result, count); + } + /** * Hollows out the region (Semi-well-defined for non-cuboid selections). * @@ -2664,67 +2706,142 @@ public int deformRegion(final Region region, final Transform targetTransform, fi * * @return number of blocks affected * @throws MaxChangedBlocksException thrown if too many blocks are changed + * @deprecated Use {@link EditSession#hollowOutRegion(Region, int, Pattern, boolean, Collection, boolean)} instead. */ - public int hollowOutRegion(Region region, int thickness, Pattern pattern) throws MaxChangedBlocksException { + @InlineMe(replacement = "this.hollowOutRegion(region, thickness, pattern, true, null, false)") + @Deprecated + public final int hollowOutRegion(Region region, int thickness, Pattern pattern) throws MaxChangedBlocksException { + return hollowOutRegion(region, thickness, pattern, true, null, false); + } + + /** + * Hollows out the region (bounding-box mode is semi-well-defined for non-cuboid selections). + * The startingPositions parameter takes precedence over usePlacementPosition. + * + * @param region the region to hollow out. + * @param thickness the thickness of the shell to leave (manhattan distance) + * @param pattern The block pattern to use + * @param openSides Open up faces touching the bounding box. This matches the legacy behaviour. + * @param startingPositions Positions to consider as 'outside'. If null, use the selection bounding box + * @param useBlockGeometry Consider block geometry for visibility calculation + * @return number of blocks affected + * @throws MaxChangedBlocksException thrown if too many blocks are changed + */ + public int hollowOutRegion(Region region, int thickness, Pattern pattern, boolean openSides, Collection startingPositions, boolean useBlockGeometry) throws MaxChangedBlocksException { int affected = 0; - final Set outside = new HashSet<>(); + final Set visible = new HashSet<>(); + if (startingPositions == null) { + // Initialize BFS with selection bounding box + final BlockVector3 min = region.getMinimumPoint(); + final BlockVector3 max = region.getMaximumPoint(); - final BlockVector3 min = region.getMinimumPoint(); - final BlockVector3 max = region.getMaximumPoint(); + final int minX = min.x(); + final int minY = min.y(); + final int minZ = min.z(); + final int maxX = max.x(); + final int maxY = max.y(); + final int maxZ = max.z(); - final int minX = min.x(); - final int minY = min.y(); - final int minZ = min.z(); - final int maxX = max.x(); - final int maxY = max.y(); - final int maxZ = max.z(); + for (int x = minX; x <= maxX; ++x) { + for (int y = minY; y <= maxY; ++y) { + visible.add(BlockVector3.at(x, y, minZ)); + visible.add(BlockVector3.at(x, y, maxZ)); + } + } - for (int x = minX; x <= maxX; ++x) { for (int y = minY; y <= maxY; ++y) { - recurseHollow(region, BlockVector3.at(x, y, minZ), outside); - recurseHollow(region, BlockVector3.at(x, y, maxZ), outside); + for (int z = minZ; z <= maxZ; ++z) { + visible.add(BlockVector3.at(minX, y, z)); + visible.add(BlockVector3.at(maxX, y, z)); + } } - } - for (int y = minY; y <= maxY; ++y) { for (int z = minZ; z <= maxZ; ++z) { - recurseHollow(region, BlockVector3.at(minX, y, z), outside); - recurseHollow(region, BlockVector3.at(maxX, y, z), outside); + for (int x = minX; x <= maxX; ++x) { + visible.add(BlockVector3.at(x, minY, z)); + visible.add(BlockVector3.at(x, maxY, z)); + } + } + + if (openSides) { + // Remove movement blockers from visible list + visible.removeIf(blockVector3 -> getBlock(blockVector3).getBlockType().getMaterial().isMovementBlocker()); } + } else { + visible.addAll(startingPositions); } - for (int z = minZ; z <= maxZ; ++z) { - for (int x = minX; x <= maxX; ++x) { - recurseHollow(region, BlockVector3.at(x, minY, z), outside); - recurseHollow(region, BlockVector3.at(x, maxY, z), outside); + // Do BFS to find more visible blocks + final Queue queue = new ArrayDeque<>(visible); + while (!queue.isEmpty()) { + final BlockVector3 current = queue.poll(); + + Direction[] blockedDirections; + if (useBlockGeometry) { + // Get blocked directions for this block + blockedDirections = getBlockedDirections(this, current); + + // Short-cut if blocked in all directions + if (blockedDirections == CARDINAL_UPRIGHT_DIRECTIONS) { + continue; + } + } else { + final BlockState block = getBlock(current); + if (block.getBlockType().getMaterial().isMovementBlocker()) { + // In non-geometry mode, all movement blockers are assumed to be blocked in all directions, so short-cut here + continue; + } + + // All other blocks are assumed to have no blocked directions + blockedDirections = NO_DIRECTIONS; + } + + outer: + for (Direction direction : CARDINAL_UPRIGHT_DIRECTIONS) { + // Check if this direction is blocked + for (Direction blockedDirection : blockedDirections) { + if (blockedDirection == direction) { + continue outer; // skip this direction + } + } + + final BlockVector3 neighbor = current.add(direction.toBlockVector()); + + if (!region.contains(neighbor)) { + continue; + } + + if (!visible.add(neighbor)) { + continue; + } + + queue.add(neighbor); } } - final Set newOutside = new HashSet<>(); + // Expand by $thickness blocks + final Set newVisible = new HashSet<>(); for (int i = 1; i < thickness; ++i) { outer: for (BlockVector3 position : region) { - for (BlockVector3 recurseDirection : recurseDirections) { + for (BlockVector3 recurseDirection : CARDINAL_UPRIGHT_OFFSETS) { BlockVector3 neighbor = position.add(recurseDirection); - if (outside.contains(neighbor)) { - newOutside.add(position); + if (visible.contains(neighbor)) { + newVisible.add(position); continue outer; } } } - outside.addAll(newOutside); - newOutside.clear(); + visible.addAll(newVisible); + newVisible.clear(); } - outer: for (BlockVector3 position : region) { - for (BlockVector3 recurseDirection : recurseDirections) { - BlockVector3 neighbor = position.add(recurseDirection); - - if (outside.contains(neighbor)) { - continue outer; - } + // Remove everything else in the selection + for (BlockVector3 position : region) { + if (visible.contains(position)) { + continue; } if (setBlock(position, pattern.applyBlock(position))) { @@ -2915,31 +3032,6 @@ private static Set getHollowed(Set vset) { return returnset; } - private void recurseHollow(Region region, BlockVector3 origin, Set outside) { - var queue = new ArrayDeque(); - queue.addLast(origin); - - while (!queue.isEmpty()) { - final BlockVector3 current = queue.removeFirst(); - final BlockState block = getBlock(current); - if (block.getBlockType().getMaterial().isMovementBlocker()) { - continue; - } - - if (!outside.add(current)) { - continue; - } - - if (!region.contains(current)) { - continue; - } - - for (BlockVector3 recurseDirection : recurseDirections) { - queue.addLast(current.add(recurseDirection)); - } - } - } - /** * Generate a biome shape for the given expression. * @@ -3071,7 +3163,7 @@ public int morph(BlockVector3 position, double brushSize, int minErodeFaces, int totalFaces = 0; highestFreq = 0; highestState = blockState; - for (BlockVector3 vec3 : recurseDirections) { + for (BlockVector3 vec3 : CARDINAL_UPRIGHT_OFFSETS) { BlockState adj = currentBuffer[x + 1 + vec3.x()][y + 1 + vec3.y()][z + 1 + vec3.z()]; if (!adj.getBlockType().getMaterial().isLiquid() && !adj.getBlockType().getMaterial().isAir()) { @@ -3124,7 +3216,7 @@ public int morph(BlockVector3 position, double brushSize, int minErodeFaces, int totalFaces = 0; highestFreq = 0; highestState = blockState; - for (BlockVector3 vec3 : recurseDirections) { + for (BlockVector3 vec3 : CARDINAL_UPRIGHT_OFFSETS) { BlockState adj = currentBuffer[x + 1 + vec3.x()][y + 1 + vec3.y()][z + 1 + vec3.z()]; if (adj.getBlockType().getMaterial().isLiquid() || adj.getBlockType().getMaterial().isAir()) { continue; @@ -3167,14 +3259,80 @@ public int morph(BlockVector3 position, double brushSize, int minErodeFaces, int return changed; } - private static final BlockVector3[] recurseDirections = { - Direction.NORTH.toBlockVector(), - Direction.EAST.toBlockVector(), - Direction.SOUTH.toBlockVector(), - Direction.WEST.toBlockVector(), - Direction.UP.toBlockVector(), - Direction.DOWN.toBlockVector(), - }; + /** + * Contains no directions. + */ + private static final Direction[] NO_DIRECTIONS = {}; + /** + * Contains all cardinal and upright directions. + */ + private static final Direction[] CARDINAL_UPRIGHT_DIRECTIONS = Arrays.stream(Direction.values()) + .filter(direction -> direction.isCardinal() || direction.isUpright()) + .toArray(Direction[]::new); + /** + * Contains the offset vectors for all cardinal and upright directions. + */ + private static final BlockVector3[] CARDINAL_UPRIGHT_OFFSETS = Arrays.stream(CARDINAL_UPRIGHT_DIRECTIONS) + .map(Direction::toBlockVector) + .toArray(BlockVector3[]::new); + + /** + * Some blocks need a special case for one reason or another. + */ + private static final Map BLOCKED_DIRECTIONS_OVERRIDE = new HashMap<>(); + + static { + Arrays.asList( + // fullcubes that you can see through on all 6 sides + BlockTypes.SPAWNER, + BlockTypes.BEACON, + BlockTypes.MANGROVE_ROOTS, + BlockTypes.ICE, + + // You can see through some of the doors/trapdoors, which is not reflected in their visual shape + // Commented lines are opaque and kept for reference + BlockTypes.OAK_DOOR, + BlockTypes.OAK_TRAPDOOR, + // BlockTypes.SPRUCE_DOOR, + // BlockTypes.SPRUCE_TRAPDOOR, + // BlockTypes.BIRCH_DOOR, + // BlockTypes.BIRCH_TRAPDOOR, + BlockTypes.JUNGLE_DOOR, + BlockTypes.JUNGLE_TRAPDOOR, + BlockTypes.ACACIA_DOOR, + BlockTypes.ACACIA_TRAPDOOR, + // BlockTypes.DARK_OAK_DOOR, + // BlockTypes.DARK_OAK_TRAPDOOR, + // BlockTypes.MANGROVE_DOOR, + BlockTypes.MANGROVE_TRAPDOOR, + BlockTypes.CHERRY_DOOR, + BlockTypes.CHERRY_TRAPDOOR, + // BlockTypes.PALE_OAK_DOOR, + // BlockTypes.PALE_OAK_TRAPDOOR, + BlockTypes.BAMBOO_DOOR, + BlockTypes.BAMBOO_TRAPDOOR, + BlockTypes.CRIMSON_DOOR, + BlockTypes.CRIMSON_TRAPDOOR, + BlockTypes.WARPED_DOOR, + BlockTypes.WARPED_TRAPDOOR, + BlockTypes.IRON_DOOR, + BlockTypes.IRON_TRAPDOOR + ).forEach(blockType -> { + BLOCKED_DIRECTIONS_OVERRIDE.put(blockType, NO_DIRECTIONS); + }); + + // The copper doors/trapdoors are too many to list individually + java.util.regex.Pattern pattern = java.util.regex.Pattern.compile("^.*:(?:.*_)?(?:copper_door|copper_trapdoor)(?:_.*)?$"); + for (BlockType blockType : BlockType.REGISTRY) { + if (pattern.matcher(blockType.id()).matches()) { + BLOCKED_DIRECTIONS_OVERRIDE.put(blockType, NO_DIRECTIONS); + } + } + + // These are visual fullcubes, but they're mostly open: + BLOCKED_DIRECTIONS_OVERRIDE.put(BlockTypes.TRIAL_SPAWNER, new Direction[] { Direction.UP }); + BLOCKED_DIRECTIONS_OVERRIDE.put(BlockTypes.VAULT, new Direction[] { Direction.UP, Direction.DOWN }); + } private static double lengthSq(double x, double y, double z) { return (x * x) + (y * y) + (z * z); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/blocks/ShapeType.java b/worldedit-core/src/main/java/com/sk89q/worldedit/blocks/ShapeType.java new file mode 100644 index 0000000000..726aada042 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/blocks/ShapeType.java @@ -0,0 +1,25 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.blocks; + +public enum ShapeType { + SHAPE, + VISUAL_SHAPE, +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java index e258169d62..2aaeb0a408 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java @@ -79,8 +79,11 @@ import org.enginehub.piston.annotation.param.Arg; import org.enginehub.piston.annotation.param.ArgFlag; import org.enginehub.piston.annotation.param.Switch; +import org.enginehub.piston.exception.CommandException; import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; import java.util.List; import static com.sk89q.worldedit.command.util.Logging.LogMode.ALL; @@ -548,15 +551,36 @@ public int deform(Actor actor, LocalSession session, EditSession editSession, ) @CommandPermissions("worldedit.region.hollow") @Logging(REGION) - public int hollow(Actor actor, EditSession editSession, + public int hollow(Actor actor, EditSession editSession, LocalSession session, @Selection Region region, - @Arg(desc = "Thickness of the shell to leave", def = "0") + @Arg(desc = "Thickness of the shell to leave", def = "1") int thickness, @Arg(desc = "The pattern of blocks to replace the hollowed area with", def = "air") - Pattern pattern) throws WorldEditException { - checkCommandArgument(thickness >= 0, "Thickness must be >= 0"); - - int affected = editSession.hollowOutRegion(region, thickness, pattern); + Pattern pattern, + @Switch(name = 'o', desc = "Open up faces touching the bounding box. This matches the legacy behaviour.") + boolean openSides, + @Switch(name = 'p', desc = "Consider placement position as 'outside' instead of the selection bounding box. Overrides -o.") + boolean usePlacementPosition, + @Switch(name = 'g', desc = "Consider block geometry for visibility calculation") + boolean useBlockGeometry) throws WorldEditException { + checkCommandArgument(thickness >= 1, "Thickness must be >= 1"); + + final Collection startingPositions; + if (usePlacementPosition) { + BlockVector3 placementPosition = session.getPlacementPosition(actor); + if (!region.contains(placementPosition)) { + throw new CommandException( + TextComponent.of("Placement position must be inside selection (") + .append(session.getPlacement().getInfo()) + .append(TextComponent.of(")")), + ImmutableList.of() + ); + } + startingPositions = Collections.singletonList(placementPosition); + } else { + startingPositions = null; + } + int affected = editSession.hollowOutRegion(region, thickness, pattern, openSides, startingPositions, useBlockGeometry); actor.printInfo(TranslatableComponent.of("worldedit.hollow.changed", TextComponent.of(affected))); return affected; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/FullCubeMask.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/FullCubeMask.java index d7a8a8165b..6983c8cb05 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/FullCubeMask.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/FullCubeMask.java @@ -19,6 +19,7 @@ package com.sk89q.worldedit.function.mask; +import com.sk89q.worldedit.blocks.ShapeType; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.block.BlockState; @@ -33,7 +34,7 @@ public FullCubeMask(Extent extent) { public boolean test(BlockVector3 vector) { Extent extent = getExtent(); BlockState block = extent.getBlock(vector); - return block.getBlockType().getMaterial().isFullCube(); + return block.getBlockType().getMaterial().isFullCube(ShapeType.SHAPE); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/block/AbstractBlockMaterial.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/block/AbstractBlockMaterial.java new file mode 100644 index 0000000000..f199fc9a66 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/block/AbstractBlockMaterial.java @@ -0,0 +1,77 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.internal.block; + +import com.sk89q.worldedit.blocks.ShapeType; +import com.sk89q.worldedit.util.Direction; +import com.sk89q.worldedit.util.concurrency.LazyReference; +import com.sk89q.worldedit.world.registry.BlockMaterial; + +import java.util.EnumMap; +import java.util.EnumSet; + +public abstract class AbstractBlockMaterial implements BlockMaterial { + @SuppressWarnings("this-escape") + public LazyReference> isFullCube = LazyReference.from(() -> { + EnumSet enumSet = EnumSet.noneOf(ShapeType.class); + for (ShapeType shapeType : ShapeType.values()) { + if (isShapeFullBlock(getShape(shapeType))) { + enumSet.add(shapeType); + } + } + + return enumSet; + }); + + @SuppressWarnings("this-escape") + public LazyReference>> isFullFace = LazyReference.from(() -> { + EnumMap> enumMap = new EnumMap<>(Direction.class); + for (Direction face : Direction.values()) { + if (!face.isUpright() && !face.isCardinal()) { + continue; + } + + EnumSet enumSet = EnumSet.noneOf(ShapeType.class); + for (ShapeType shapeType : ShapeType.values()) { + if (isFaceFull(getShape(shapeType), face)) { + enumSet.add(shapeType); + } + } + enumMap.put(face, enumSet); + } + return enumMap; + }); + + @Override + public boolean isFullCube(ShapeType shapeType) { + return isFullCube.getValue().contains(shapeType); + } + + @Override + public boolean isFullFace(ShapeType shapeType, Direction face) { + return isFullFace.getValue().get(face).contains(shapeType); + } + + protected abstract VS getShape(ShapeType shapeType); + + protected abstract boolean isShapeFullBlock(VS shape); + + protected abstract boolean isFaceFull(VS shape, Direction face); +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockState.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockState.java index cb94239af9..b11f207ad0 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockState.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockState.java @@ -19,9 +19,12 @@ package com.sk89q.worldedit.world.block; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.extension.platform.Capability; import com.sk89q.worldedit.internal.block.BlockStateIdAccess; import com.sk89q.worldedit.registry.state.Property; import com.sk89q.worldedit.util.concurrency.LazyReference; +import com.sk89q.worldedit.world.registry.BlockMaterial; import org.enginehub.linbus.tree.LinCompoundTag; import java.util.HashSet; @@ -74,6 +77,11 @@ public BlockType getBlockType() { return this.blockType; } + public BlockMaterial getMaterial() { + return WorldEdit.getInstance().getPlatformManager() + .queryCapability(Capability.GAME_HOOKS).getRegistries().getBlockRegistry().getMaterial(this); + } + @Override public BlockState with(final Property property, final V value) { if (this.stateListIndex == -1) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockType.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockType.java index 66fa710d4c..d5a4dc80b3 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockType.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockType.java @@ -72,7 +72,7 @@ public class BlockType implements Keyed { @SuppressWarnings("this-escape") private final LazyReference blockMaterial = LazyReference.from(() -> WorldEdit.getInstance().getPlatformManager() - .queryCapability(Capability.GAME_HOOKS).getRegistries().getBlockRegistry().getMaterial(this)); + .queryCapability(Capability.GAME_HOOKS).getRegistries().getBlockRegistry().getMaterial(getDefaultState())); @SuppressWarnings("this-escape") @Deprecated private final LazyReference name = LazyReference.from(() -> WorldEdit.getInstance().getPlatformManager() diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BlockMaterial.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BlockMaterial.java index d280f2cc0e..b9c02a79b8 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BlockMaterial.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BlockMaterial.java @@ -19,6 +19,9 @@ package com.sk89q.worldedit.world.registry; +import com.sk89q.worldedit.blocks.ShapeType; +import com.sk89q.worldedit.util.Direction; + /** * Describes the material for a block. */ @@ -36,7 +39,28 @@ public interface BlockMaterial { * * @return the value of the test */ - boolean isFullCube(); + default boolean isFullCube() { + return isFullCube(ShapeType.SHAPE); + } + + /** + * Get whether this block is a full sized cube. + * + * @param shapeType which shape of the block to test + * @return the value of the test + */ + boolean isFullCube(ShapeType shapeType); + + /** + * Get whether this face is a full sized face. + * + * @param shapeType which shape of the block to test + * @param face the face to test + * @return the value of the test + */ + default boolean isFullFace(ShapeType shapeType, Direction face) { + return isFullCube(shapeType); + } /** * Get whether this block is opaque. diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BlockRegistry.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BlockRegistry.java index 12f6b51ca1..92692f1de9 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BlockRegistry.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BlockRegistry.java @@ -19,6 +19,7 @@ package com.sk89q.worldedit.world.registry; +import com.sk89q.worldedit.internal.util.NonAbstractForCompatibility; import com.sk89q.worldedit.registry.state.Property; import com.sk89q.worldedit.util.formatting.text.Component; import com.sk89q.worldedit.world.block.BlockState; @@ -59,9 +60,30 @@ default String getName(BlockType blockType) { * * @param blockType the block * @return the material, or null if the material information is not known + * @deprecated Use {@link BlockRegistry#getMaterial(BlockState)} instead. */ + @Deprecated @Nullable - BlockMaterial getMaterial(BlockType blockType); + default BlockMaterial getMaterial(BlockType blockType) { + return getMaterial(blockType.getDefaultState()); + } + + /** + * Get the material for the given block state. + * + * @param blockState the block state + * @return the material, or null if the material information is not known + * @apiNote This must be overridden by new subclasses. See {@link NonAbstractForCompatibility} + * for details + */ + @NonAbstractForCompatibility( + delegateName = "getMaterial", + delegateParams = { BlockType.class } + ) + @Nullable + default BlockMaterial getMaterial(BlockState blockState) { + return getMaterial(blockState.getBlockType()); + } /** * Get an unmodifiable map of states for this block. diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BundledBlockRegistry.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BundledBlockRegistry.java index 714fb50839..9e91177761 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BundledBlockRegistry.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BundledBlockRegistry.java @@ -69,8 +69,8 @@ public String getName(BlockType blockType) { @Nullable @Override - public BlockMaterial getMaterial(BlockType blockType) { - return new PassthroughBlockMaterial(BundledBlockData.getInstance().getMaterialById(blockType.id())); + public BlockMaterial getMaterial(BlockType blockState) { + return new PassthroughBlockMaterial(BundledBlockData.getInstance().getMaterialById(blockState.id())); } @Nullable diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/PassthroughBlockMaterial.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/PassthroughBlockMaterial.java index e868276a63..b93c17ec53 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/PassthroughBlockMaterial.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/PassthroughBlockMaterial.java @@ -19,6 +19,9 @@ package com.sk89q.worldedit.world.registry; +import com.sk89q.worldedit.blocks.ShapeType; +import com.sk89q.worldedit.util.Direction; + import javax.annotation.Nullable; import static com.sk89q.worldedit.util.GuavaUtil.firstNonNull; @@ -49,8 +52,13 @@ public boolean isAir() { } @Override - public boolean isFullCube() { - return blockMaterial.isFullCube(); + public boolean isFullCube(ShapeType shapeType) { + return blockMaterial.isFullCube(shapeType); + } + + @Override + public boolean isFullFace(ShapeType shapeType, Direction face) { + return blockMaterial.isFullFace(shapeType, face); } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/SimpleBlockMaterial.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/SimpleBlockMaterial.java index de70a38619..d2cc6c92d1 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/SimpleBlockMaterial.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/SimpleBlockMaterial.java @@ -19,6 +19,8 @@ package com.sk89q.worldedit.world.registry; +import com.sk89q.worldedit.blocks.ShapeType; + class SimpleBlockMaterial implements BlockMaterial { private boolean isAir; @@ -51,7 +53,7 @@ public void setIsAir(boolean isAir) { } @Override - public boolean isFullCube() { + public boolean isFullCube(ShapeType shapeType) { return fullCube; } diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeAdapter.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeAdapter.java index 8339c5321f..a4200702ae 100644 --- a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeAdapter.java +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeAdapter.java @@ -235,6 +235,17 @@ public static Direction adapt(org.spongepowered.api.util.Direction direction) { return Direction.valueOf(direction.name()); } + public static net.minecraft.core.Direction adapt(Direction face) { + return switch (face) { + case NORTH -> net.minecraft.core.Direction.NORTH; + case SOUTH -> net.minecraft.core.Direction.SOUTH; + case WEST -> net.minecraft.core.Direction.WEST; + case EAST -> net.minecraft.core.Direction.EAST; + case DOWN -> net.minecraft.core.Direction.DOWN; + default -> net.minecraft.core.Direction.UP; + }; + } + public static Vector3i adaptVector3i(BlockVector3 bv3) { return new Vector3i(bv3.x(), bv3.y(), bv3.z()); } diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeBlockMaterial.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeBlockMaterial.java index 4dd6622de4..a88a8530d5 100644 --- a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeBlockMaterial.java +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeBlockMaterial.java @@ -19,7 +19,9 @@ package com.sk89q.worldedit.sponge; -import com.sk89q.worldedit.world.registry.BlockMaterial; +import com.sk89q.worldedit.blocks.ShapeType; +import com.sk89q.worldedit.internal.block.AbstractBlockMaterial; +import com.sk89q.worldedit.util.Direction; import net.minecraft.core.BlockPos; import net.minecraft.world.Clearable; import net.minecraft.world.level.EmptyBlockGetter; @@ -27,13 +29,15 @@ import net.minecraft.world.level.block.EntityBlock; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.material.PushReaction; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; /** * Sponge block material that pulls as much info as possible from the Minecraft * Material, and passes the rest to another implementation, typically the * bundled block info. */ -public class SpongeBlockMaterial implements BlockMaterial { +public class SpongeBlockMaterial extends AbstractBlockMaterial { private final BlockState block; @@ -47,8 +51,21 @@ public boolean isAir() { } @Override - public boolean isFullCube() { - return Block.isShapeFullBlock(block.getShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO)); + protected VoxelShape getShape(ShapeType shapeType) { + return switch (shapeType) { + case SHAPE -> block.getShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO, CollisionContext.empty()); + case VISUAL_SHAPE -> block.getVisualShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO, CollisionContext.empty()); + }; + } + + @Override + protected boolean isShapeFullBlock(VoxelShape shape) { + return Block.isShapeFullBlock(shape); + } + + @Override + protected boolean isFaceFull(VoxelShape shape, Direction face) { + return Block.isFaceFull(shape, SpongeAdapter.adapt(face)); } @Override diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeBlockRegistry.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeBlockRegistry.java index 5c0434d36a..f304d8ac53 100644 --- a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeBlockRegistry.java +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeBlockRegistry.java @@ -50,19 +50,16 @@ public Component getRichName(BlockType blockType) { } @Override - public BlockMaterial getMaterial(BlockType blockType) { - org.spongepowered.api.block.BlockType spongeBlockType = - Sponge.game().registry(RegistryTypes.BLOCK_TYPE) - .value(ResourceKey.resolve(blockType.id())); + public BlockMaterial getMaterial(BlockState blockState) { return materialMap.computeIfAbsent( - spongeBlockType.defaultState(), - m -> { - net.minecraft.world.level.block.state.BlockState blockState = - (net.minecraft.world.level.block.state.BlockState) m; - return new SpongeBlockMaterial( - blockState - ); - } + SpongeAdapter.adapt(blockState), + m -> { + net.minecraft.world.level.block.state.BlockState mcBlockState = + (net.minecraft.world.level.block.state.BlockState) m; + return new SpongeBlockMaterial( + mcBlockState + ); + } ); }