mirror of
				https://github.com/SquidDev-CC/CC-Tweaked
				synced 2025-10-31 13:42:59 +00:00 
			
		
		
		
	Allow placing items against some blocks
We define a tag which allows specifying which blocks can be used. Right now this is is just cauldrons and hives, as they have "placing into" semantics. Closes #1305. Many thanks to Lindsay-Needs-Sleep for their initial work on this! Fixes #1008. I believe also fixes #854.
This commit is contained in:
		| @@ -14,6 +14,8 @@ import net.minecraft.world.item.Item; | |||||||
| import net.minecraft.world.item.context.UseOnContext; | import net.minecraft.world.item.context.UseOnContext; | ||||||
| import net.minecraft.world.level.Level; | import net.minecraft.world.level.Level; | ||||||
| import net.minecraft.world.level.block.Block; | import net.minecraft.world.level.block.Block; | ||||||
|  | import net.minecraft.world.level.block.state.BlockState; | ||||||
|  | import net.minecraft.world.phys.BlockHitResult; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Tags provided by ComputerCraft. |  * Tags provided by ComputerCraft. | ||||||
| @@ -65,6 +67,12 @@ public class ComputerCraftTags { | |||||||
|          */ |          */ | ||||||
|         public static final TagKey<Block> TURTLE_HOE_BREAKABLE = make("turtle_hoe_harvestable"); |         public static final TagKey<Block> TURTLE_HOE_BREAKABLE = make("turtle_hoe_harvestable"); | ||||||
| 
 | 
 | ||||||
|  |         /** | ||||||
|  |          * Block which can be {@linkplain BlockState#use(Level, Player, InteractionHand, BlockHitResult) used} when | ||||||
|  |          * calling {@code turtle.place()}. | ||||||
|  |          */ | ||||||
|  |         public static final TagKey<Block> TURTLE_CAN_USE = make("turtle_can_use"); | ||||||
|  | 
 | ||||||
|         private static TagKey<Block> make(String name) { |         private static TagKey<Block> make(String name) { | ||||||
|             return TagKey.create(Registries.BLOCK, new ResourceLocation(ComputerCraftAPI.MOD_ID, name)); |             return TagKey.create(Registries.BLOCK, new ResourceLocation(ComputerCraftAPI.MOD_ID, name)); | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -57,6 +57,8 @@ class TagProvider { | |||||||
| 
 | 
 | ||||||
|         tags.tag(ComputerCraftTags.Blocks.TURTLE_SWORD_BREAKABLE).addTag(BlockTags.WOOL).add(Blocks.COBWEB); |         tags.tag(ComputerCraftTags.Blocks.TURTLE_SWORD_BREAKABLE).addTag(BlockTags.WOOL).add(Blocks.COBWEB); | ||||||
| 
 | 
 | ||||||
|  |         tags.tag(ComputerCraftTags.Blocks.TURTLE_CAN_USE).addTag(BlockTags.CAULDRONS).addTag(BlockTags.BEEHIVES); | ||||||
|  | 
 | ||||||
|         // Make all blocks aside from command computer mineable. |         // Make all blocks aside from command computer mineable. | ||||||
|         tags.tag(BlockTags.MINEABLE_WITH_PICKAXE).add( |         tags.tag(BlockTags.MINEABLE_WITH_PICKAXE).add( | ||||||
|             ModRegistry.Blocks.COMPUTER_NORMAL.get(), |             ModRegistry.Blocks.COMPUTER_NORMAL.get(), | ||||||
|   | |||||||
| @@ -53,6 +53,7 @@ import java.util.List; | |||||||
| import java.util.function.BiFunction; | import java.util.function.BiFunction; | ||||||
| import java.util.function.Consumer; | import java.util.function.Consumer; | ||||||
| import java.util.function.Function; | import java.util.function.Function; | ||||||
|  | import java.util.function.Predicate; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * This extends {@linkplain dan200.computercraft.impl.PlatformHelper the API's loader abstraction layer}, adding |  * This extends {@linkplain dan200.computercraft.impl.PlatformHelper the API's loader abstraction layer}, adding | ||||||
| @@ -385,13 +386,15 @@ public interface PlatformHelper extends dan200.computercraft.impl.PlatformHelper | |||||||
|      * Place an item against a block. |      * Place an item against a block. | ||||||
|      * <p> |      * <p> | ||||||
|      * Implementations should largely mirror {@link ServerPlayerGameMode#useItemOn(ServerPlayer, Level, ItemStack, InteractionHand, BlockHitResult)} |      * Implementations should largely mirror {@link ServerPlayerGameMode#useItemOn(ServerPlayer, Level, ItemStack, InteractionHand, BlockHitResult)} | ||||||
|      * (including any loader-specific modifications), except they should skip the call to {@link BlockState#use(Level, Player, InteractionHand, BlockHitResult)}. |      * (including any loader-specific modifications), except the call to {@link BlockState#use(Level, Player, InteractionHand, BlockHitResult)} | ||||||
|  |      * should only be evaluated when {@code canUseBlock} evaluates to true. | ||||||
|      * |      * | ||||||
|      * @param player      The player which is placing this item. |      * @param player      The player which is placing this item. | ||||||
|      * @param stack       The item to place. |      * @param stack       The item to place. | ||||||
|      * @param hit         The collision with the block we're placing against. |      * @param hit         The collision with the block we're placing against. | ||||||
|  |      * @param canUseBlock Test whether the block should be interacted with first. | ||||||
|      * @return Whether any interaction occurred. |      * @return Whether any interaction occurred. | ||||||
|      * @see ServerPlayerGameMode#useItemOn(ServerPlayer, Level, ItemStack, InteractionHand, BlockHitResult) |      * @see ServerPlayerGameMode#useItemOn(ServerPlayer, Level, ItemStack, InteractionHand, BlockHitResult) | ||||||
|      */ |      */ | ||||||
|     InteractionResult useOn(ServerPlayer player, ItemStack stack, BlockHitResult hit); |     InteractionResult useOn(ServerPlayer player, ItemStack stack, BlockHitResult hit, Predicate<BlockState> canUseBlock); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -22,6 +22,7 @@ import net.minecraft.network.chat.Component; | |||||||
| import net.minecraft.server.level.ServerLevel; | import net.minecraft.server.level.ServerLevel; | ||||||
| import net.minecraft.world.InteractionHand; | import net.minecraft.world.InteractionHand; | ||||||
| import net.minecraft.world.InteractionResult; | import net.minecraft.world.InteractionResult; | ||||||
|  | import net.minecraft.world.entity.player.Player; | ||||||
| import net.minecraft.world.item.*; | import net.minecraft.world.item.*; | ||||||
| import net.minecraft.world.item.context.BlockPlaceContext; | import net.minecraft.world.item.context.BlockPlaceContext; | ||||||
| import net.minecraft.world.item.context.UseOnContext; | import net.minecraft.world.item.context.UseOnContext; | ||||||
| @@ -29,6 +30,7 @@ import net.minecraft.world.level.Level; | |||||||
| import net.minecraft.world.level.block.Block; | import net.minecraft.world.level.block.Block; | ||||||
| import net.minecraft.world.level.block.entity.BlockEntity; | import net.minecraft.world.level.block.entity.BlockEntity; | ||||||
| import net.minecraft.world.level.block.entity.SignBlockEntity; | import net.minecraft.world.level.block.entity.SignBlockEntity; | ||||||
|  | import net.minecraft.world.level.block.state.BlockState; | ||||||
| import net.minecraft.world.phys.BlockHitResult; | import net.minecraft.world.phys.BlockHitResult; | ||||||
| import net.minecraft.world.phys.EntityHitResult; | import net.minecraft.world.phys.EntityHitResult; | ||||||
| import net.minecraft.world.phys.Vec3; | import net.minecraft.world.phys.Vec3; | ||||||
| @@ -153,7 +155,7 @@ public class TurtlePlaceCommand implements TurtleCommand { | |||||||
| 
 | 
 | ||||||
|     private static boolean deployOnBlock( |     private static boolean deployOnBlock( | ||||||
|         ItemStack stack, ITurtleAccess turtle, TurtlePlayer turtlePlayer, BlockPos position, Direction side, |         ItemStack stack, ITurtleAccess turtle, TurtlePlayer turtlePlayer, BlockPos position, Direction side, | ||||||
|         @Nullable Object[] extraArguments, boolean allowReplace, @Nullable ErrorMessage outErrorMessage |         @Nullable Object[] extraArguments, boolean adjacent, @Nullable ErrorMessage outErrorMessage | ||||||
|     ) { |     ) { | ||||||
|         // Re-orient the fake player |         // Re-orient the fake player | ||||||
|         var playerDir = side.getOpposite(); |         var playerDir = side.getOpposite(); | ||||||
| @@ -169,14 +171,14 @@ public class TurtlePlaceCommand implements TurtleCommand { | |||||||
|         // Check if there's something suitable to place onto |         // Check if there's something suitable to place onto | ||||||
|         var hit = new BlockHitResult(new Vec3(hitX, hitY, hitZ), side, position, false); |         var hit = new BlockHitResult(new Vec3(hitX, hitY, hitZ), side, position, false); | ||||||
|         var context = new UseOnContext(turtlePlayer.player(), InteractionHand.MAIN_HAND, hit); |         var context = new UseOnContext(turtlePlayer.player(), InteractionHand.MAIN_HAND, hit); | ||||||
|         if (!canDeployOnBlock(new BlockPlaceContext(context), turtle, turtlePlayer, position, side, allowReplace, outErrorMessage)) { |         if (!canDeployOnBlock(new BlockPlaceContext(context), turtle, turtlePlayer, position, side, adjacent, outErrorMessage)) { | ||||||
|             return false; |             return false; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         var item = stack.getItem(); |         var item = stack.getItem(); | ||||||
|         var existingTile = turtle.getLevel().getBlockEntity(position); |         var existingTile = turtle.getLevel().getBlockEntity(position); | ||||||
| 
 | 
 | ||||||
|         var placed = doDeployOnBlock(stack, turtlePlayer, hit).consumesAction(); |         var placed = doDeployOnBlock(stack, turtlePlayer, hit, adjacent).consumesAction(); | ||||||
| 
 | 
 | ||||||
|         // Set text on signs |         // Set text on signs | ||||||
|         if (placed && item instanceof SignItem && extraArguments != null && extraArguments.length >= 1 && extraArguments[0] instanceof String message) { |         if (placed && item instanceof SignItem && extraArguments != null && extraArguments.length >= 1 && extraArguments[0] instanceof String message) { | ||||||
| @@ -198,18 +200,23 @@ public class TurtlePlaceCommand implements TurtleCommand { | |||||||
|      * @param stack        The stack the player is using. |      * @param stack        The stack the player is using. | ||||||
|      * @param turtlePlayer The player which represents the turtle |      * @param turtlePlayer The player which represents the turtle | ||||||
|      * @param hit          Where the block we're placing against was clicked. |      * @param hit          Where the block we're placing against was clicked. | ||||||
|  |      * @param adjacent     If the block is directly adjacent to the turtle, and so can be interacted with via | ||||||
|  |      *                     {@link BlockState#use(Level, Player, InteractionHand, BlockHitResult)}. | ||||||
|      * @return If this item was deployed. |      * @return If this item was deployed. | ||||||
|      */ |      */ | ||||||
|     private static InteractionResult doDeployOnBlock( |     private static InteractionResult doDeployOnBlock(ItemStack stack, TurtlePlayer turtlePlayer, BlockHitResult hit, boolean adjacent) { | ||||||
|         ItemStack stack, TurtlePlayer turtlePlayer, BlockHitResult hit |         var result = PlatformHelper.get().useOn( | ||||||
|     ) { |             turtlePlayer.player(), stack, hit, | ||||||
|         var result = PlatformHelper.get().useOn(turtlePlayer.player(), stack, hit); |             adjacent ? x -> x.is(ComputerCraftTags.Blocks.TURTLE_CAN_USE) : x -> false | ||||||
|  |         ); | ||||||
|         if (result != InteractionResult.PASS) return result; |         if (result != InteractionResult.PASS) return result; | ||||||
| 
 | 
 | ||||||
|  |         var level = turtlePlayer.player().level; | ||||||
|  | 
 | ||||||
|         // We special case some items which we allow to place "normally". Yes, this is very ugly. |         // We special case some items which we allow to place "normally". Yes, this is very ugly. | ||||||
|         var item = stack.getItem(); |         var item = stack.getItem(); | ||||||
|         if (item instanceof BucketItem || item instanceof PlaceOnWaterBlockItem || stack.is(ComputerCraftTags.Items.TURTLE_CAN_PLACE)) { |         if (item instanceof BucketItem || item instanceof PlaceOnWaterBlockItem || stack.is(ComputerCraftTags.Items.TURTLE_CAN_PLACE)) { | ||||||
|             return turtlePlayer.player().gameMode.useItem(turtlePlayer.player(), turtlePlayer.player().level, stack, InteractionHand.MAIN_HAND); |             return turtlePlayer.player().gameMode.useItem(turtlePlayer.player(), level, stack, InteractionHand.MAIN_HAND); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         return InteractionResult.PASS; |         return InteractionResult.PASS; | ||||||
|   | |||||||
| @@ -55,6 +55,7 @@ import java.util.List; | |||||||
| import java.util.function.BiFunction; | import java.util.function.BiFunction; | ||||||
| import java.util.function.Consumer; | import java.util.function.Consumer; | ||||||
| import java.util.function.Function; | import java.util.function.Function; | ||||||
|  | import java.util.function.Predicate; | ||||||
| 
 | 
 | ||||||
| @AutoService({ PlatformHelper.class, dan200.computercraft.impl.PlatformHelper.class, ComputerCraftAPIService.class }) | @AutoService({ PlatformHelper.class, dan200.computercraft.impl.PlatformHelper.class, ComputerCraftAPIService.class }) | ||||||
| public class TestPlatformHelper extends AbstractComputerCraftAPI implements PlatformHelper { | public class TestPlatformHelper extends AbstractComputerCraftAPI implements PlatformHelper { | ||||||
| @@ -202,7 +203,7 @@ public class TestPlatformHelper extends AbstractComputerCraftAPI implements Plat | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public InteractionResult useOn(ServerPlayer player, ItemStack stack, BlockHitResult hit) { |     public InteractionResult useOn(ServerPlayer player, ItemStack stack, BlockHitResult hit, Predicate<BlockState> canUseBlock) { | ||||||
|         throw new UnsupportedOperationException("Cannot interact with the world inside tests"); |         throw new UnsupportedOperationException("Cannot interact with the world inside tests"); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|   | |||||||
| @@ -185,7 +185,7 @@ class Turtle_Test { | |||||||
|      * |      * | ||||||
|      * Currently not required as turtles can no longer right-click cauldrons. |      * Currently not required as turtles can no longer right-click cauldrons. | ||||||
|      */ |      */ | ||||||
|     @GameTest(required = false) |     @GameTest | ||||||
|     fun Cleaned_with_cauldrons(helper: GameTestHelper) = helper.sequence { |     fun Cleaned_with_cauldrons(helper: GameTestHelper) = helper.sequence { | ||||||
|         thenOnComputer { |         thenOnComputer { | ||||||
|             val details = getTurtleItemDetail(1, true) |             val details = getTurtleItemDetail(1, true) | ||||||
|   | |||||||
| @@ -23,6 +23,7 @@ import net.minecraft.gametest.framework.GameTestSequence | |||||||
| import org.apache.logging.log4j.LogManager | import org.apache.logging.log4j.LogManager | ||||||
| import java.io.InputStream | import java.io.InputStream | ||||||
| import java.util.* | import java.util.* | ||||||
|  | import java.util.concurrent.CancellationException | ||||||
| import java.util.concurrent.ConcurrentLinkedDeque | import java.util.concurrent.ConcurrentLinkedDeque | ||||||
| import java.util.concurrent.atomic.AtomicReference | import java.util.concurrent.atomic.AtomicReference | ||||||
| 
 | 
 | ||||||
| @@ -46,7 +47,7 @@ object ManagedComputers : ILuaMachine.Factory { | |||||||
|                 task() |                 task() | ||||||
|                 monitor.result.set(Result.success(Unit)) |                 monitor.result.set(Result.success(Unit)) | ||||||
|             } catch (e: Throwable) { |             } catch (e: Throwable) { | ||||||
|                 if (e !is AssertionError) LOGGER.error("Computer $label failed", e) |                 if (e !is AssertionError && e !is CancellationException) LOGGER.error("Computer $label failed", e) | ||||||
|                 monitor.result.set(Result.failure(e)) |                 monitor.result.set(Result.failure(e)) | ||||||
|                 throw e |                 throw e | ||||||
|             } finally { |             } finally { | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| { | { | ||||||
|     DataVersion: 2730, |     DataVersion: 3218, | ||||||
|     size: [3, 3, 3], |     size: [3, 3, 3], | ||||||
|     data: [ |     data: [ | ||||||
|         {pos: [0, 0, 0], state: "minecraft:polished_andesite"}, |         {pos: [0, 0, 0], state: "minecraft:polished_andesite"}, | ||||||
| @@ -15,7 +15,7 @@ | |||||||
|         {pos: [0, 1, 1], state: "minecraft:air"}, |         {pos: [0, 1, 1], state: "minecraft:air"}, | ||||||
|         {pos: [0, 1, 2], state: "minecraft:air"}, |         {pos: [0, 1, 2], state: "minecraft:air"}, | ||||||
|         {pos: [1, 1, 0], state: "computercraft:turtle_normal{facing:south,waterlogged:false}", nbt: {ComputerId: 1, Fuel: 0, Items: [{Count: 1b, Slot: 0b, id: "computercraft:turtle_normal", tag: {Color: 13388876, ComputerId: 0, display: {Name: '{"text":"Clean turtle"}'}}}], Label: "turtle_test.cleaned_with_cauldrons", On: 1b, Owner: {LowerId: -6876936588741668278L, Name: "Dev", UpperId: 4039158846114182220L}, Slot: 0, id: "computercraft:turtle_normal"}}, |         {pos: [1, 1, 0], state: "computercraft:turtle_normal{facing:south,waterlogged:false}", nbt: {ComputerId: 1, Fuel: 0, Items: [{Count: 1b, Slot: 0b, id: "computercraft:turtle_normal", tag: {Color: 13388876, ComputerId: 0, display: {Name: '{"text":"Clean turtle"}'}}}], Label: "turtle_test.cleaned_with_cauldrons", On: 1b, Owner: {LowerId: -6876936588741668278L, Name: "Dev", UpperId: 4039158846114182220L}, Slot: 0, id: "computercraft:turtle_normal"}}, | ||||||
|         {pos: [1, 1, 1], state: "minecraft:cauldron{level:3}"}, |         {pos: [1, 1, 1], state: "minecraft:water_cauldron{level:3}"}, | ||||||
|         {pos: [1, 1, 2], state: "minecraft:air"}, |         {pos: [1, 1, 2], state: "minecraft:air"}, | ||||||
|         {pos: [2, 1, 0], state: "minecraft:air"}, |         {pos: [2, 1, 0], state: "minecraft:air"}, | ||||||
|         {pos: [2, 1, 1], state: "minecraft:air"}, |         {pos: [2, 1, 1], state: "minecraft:air"}, | ||||||
| @@ -33,8 +33,8 @@ | |||||||
|     entities: [], |     entities: [], | ||||||
|     palette: [ |     palette: [ | ||||||
|         "minecraft:polished_andesite", |         "minecraft:polished_andesite", | ||||||
|         "computercraft:turtle_normal{facing:south,waterlogged:false}", |  | ||||||
|         "minecraft:air", |         "minecraft:air", | ||||||
|         "minecraft:cauldron{level:3}" |         "minecraft:water_cauldron{level:3}", | ||||||
|  |         "computercraft:turtle_normal{facing:south,waterlogged:false}" | ||||||
|     ] |     ] | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								projects/fabric/src/generated/resources/data/computercraft/tags/blocks/turtle_can_use.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								projects/fabric/src/generated/resources/data/computercraft/tags/blocks/turtle_can_use.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | {"replace": false, "values": ["#minecraft:cauldrons", "#minecraft:beehives"]} | ||||||
| @@ -77,10 +77,7 @@ import java.util.ArrayList; | |||||||
| import java.util.Collection; | import java.util.Collection; | ||||||
| import java.util.Iterator; | import java.util.Iterator; | ||||||
| import java.util.List; | import java.util.List; | ||||||
| import java.util.function.BiFunction; | import java.util.function.*; | ||||||
| import java.util.function.Consumer; |  | ||||||
| import java.util.function.Function; |  | ||||||
| import java.util.function.Supplier; |  | ||||||
| 
 | 
 | ||||||
| @AutoService(dan200.computercraft.impl.PlatformHelper.class) | @AutoService(dan200.computercraft.impl.PlatformHelper.class) | ||||||
| public class PlatformHelperImpl implements PlatformHelper { | public class PlatformHelperImpl implements PlatformHelper { | ||||||
| @@ -303,10 +300,16 @@ public class PlatformHelperImpl implements PlatformHelper { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public InteractionResult useOn(ServerPlayer player, ItemStack stack, BlockHitResult hit) { |     public InteractionResult useOn(ServerPlayer player, ItemStack stack, BlockHitResult hit, Predicate<BlockState> canUseBlock) { | ||||||
|         var result = UseBlockCallback.EVENT.invoker().interact(player, player.level, InteractionHand.MAIN_HAND, hit); |         var result = UseBlockCallback.EVENT.invoker().interact(player, player.level, InteractionHand.MAIN_HAND, hit); | ||||||
|         if (result != InteractionResult.PASS) return result; |         if (result != InteractionResult.PASS) return result; | ||||||
| 
 | 
 | ||||||
|  |         var block = player.level.getBlockState(hit.getBlockPos()); | ||||||
|  |         if (!block.isAir() && canUseBlock.test(block)) { | ||||||
|  |             var useResult = block.use(player.level, player, InteractionHand.MAIN_HAND, hit); | ||||||
|  |             if (useResult.consumesAction()) return useResult; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         return stack.useOn(new UseOnContext(player, InteractionHand.MAIN_HAND, hit)); |         return stack.useOn(new UseOnContext(player, InteractionHand.MAIN_HAND, hit)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								projects/forge/src/generated/resources/data/computercraft/tags/blocks/turtle_can_use.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								projects/forge/src/generated/resources/data/computercraft/tags/blocks/turtle_can_use.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | {"values": ["#minecraft:cauldrons", "#minecraft:beehives"]} | ||||||
| @@ -74,10 +74,7 @@ import net.minecraftforge.registries.RegistryObject; | |||||||
| 
 | 
 | ||||||
| import javax.annotation.Nullable; | import javax.annotation.Nullable; | ||||||
| import java.util.*; | import java.util.*; | ||||||
| import java.util.function.BiFunction; | import java.util.function.*; | ||||||
| import java.util.function.Consumer; |  | ||||||
| import java.util.function.Function; |  | ||||||
| import java.util.function.Supplier; |  | ||||||
| 
 | 
 | ||||||
| @AutoService(dan200.computercraft.impl.PlatformHelper.class) | @AutoService(dan200.computercraft.impl.PlatformHelper.class) | ||||||
| public class PlatformHelperImpl implements PlatformHelper { | public class PlatformHelperImpl implements PlatformHelper { | ||||||
| @@ -318,17 +315,25 @@ public class PlatformHelperImpl implements PlatformHelper { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public InteractionResult useOn(ServerPlayer player, ItemStack stack, BlockHitResult hit) { |     public InteractionResult useOn(ServerPlayer player, ItemStack stack, BlockHitResult hit, Predicate<BlockState> canUseBlock) { | ||||||
|         var level = player.level; |         var level = player.level; | ||||||
|         var pos = hit.getBlockPos(); |         var pos = hit.getBlockPos(); | ||||||
|         var event = ForgeHooks.onRightClickBlock(player, InteractionHand.MAIN_HAND, pos, hit); |         var event = ForgeHooks.onRightClickBlock(player, InteractionHand.MAIN_HAND, pos, hit); | ||||||
|         if (event.isCanceled()) return event.getCancellationResult(); |         if (event.isCanceled()) return event.getCancellationResult(); | ||||||
| 
 | 
 | ||||||
|         var context = new UseOnContext(player, InteractionHand.MAIN_HAND, hit); |         var context = new UseOnContext(player, InteractionHand.MAIN_HAND, hit); | ||||||
|         if (event.getUseItem() == Event.Result.DENY) return InteractionResult.PASS; |         if (event.getUseItem() != Event.Result.DENY) { | ||||||
| 
 |  | ||||||
|             var result = stack.onItemUseFirst(context); |             var result = stack.onItemUseFirst(context); | ||||||
|         return result != InteractionResult.PASS ? result : stack.useOn(context); |             if (result != InteractionResult.PASS) return result; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         var block = level.getBlockState(hit.getBlockPos()); | ||||||
|  |         if (event.getUseBlock() != Event.Result.DENY && !block.isAir() && canUseBlock.test(block)) { | ||||||
|  |             var useResult = block.use(level, player, InteractionHand.MAIN_HAND, hit); | ||||||
|  |             if (useResult.consumesAction()) return useResult; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return event.getUseItem() == Event.Result.DENY ? InteractionResult.PASS : stack.useOn(context); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private record RegistryWrapperImpl<T>( |     private record RegistryWrapperImpl<T>( | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Jonathan Coates
					Jonathan Coates