diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/FacingTriggerableBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/FacingTriggerableBlockBehavior.java index df3a1d8e4..46ba21d25 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/FacingTriggerableBlockBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/FacingTriggerableBlockBehavior.java @@ -6,7 +6,6 @@ import net.momirealms.craftengine.bukkit.util.BlockStateUtils; import net.momirealms.craftengine.core.block.CustomBlock; import net.momirealms.craftengine.core.block.ImmutableBlockState; import net.momirealms.craftengine.core.block.properties.Property; -import net.momirealms.craftengine.core.entity.player.Player; import net.momirealms.craftengine.core.item.context.BlockPlaceContext; import net.momirealms.craftengine.core.util.Direction; import net.momirealms.craftengine.core.util.Key; @@ -67,15 +66,10 @@ public abstract class FacingTriggerableBlockBehavior extends BukkitBlockBehavior @Override public ImmutableBlockState updateStateForPlacement(BlockPlaceContext context, ImmutableBlockState state) { - Player player = context.getPlayer(); - Direction direction = player.getDirection().opposite(); - float yRot = player.yRot(); - if (yRot > 45 && yRot < 90) direction = Direction.UP; - if (yRot < -45 && yRot > -90) direction = Direction.DOWN; - return state.owner().value().defaultState().with(this.facingProperty, direction); + return state.owner().value().defaultState().with(this.facingProperty, context.getNearestLookingDirection().opposite()); } - protected boolean blockCheck(Object blockState) { + protected boolean blockCheckByBlockState(Object blockState) { if (blockState == null || FastNMS.INSTANCE.method$BlockStateBase$isAir(blockState)) { return false; } @@ -83,6 +77,10 @@ public abstract class FacingTriggerableBlockBehavior extends BukkitBlockBehavior .filter(state -> !state.isEmpty()) .map(state -> state.owner().value().id()) .orElseGet(() -> BlockStateUtils.getBlockOwnerIdFromState(blockState)); + return blockCheckByKey(blockId); + } + + protected boolean blockCheckByKey(Key blockId) { return this.blocks.contains(blockId) == this.whitelistMode; } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/PickaxeBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/PickaxeBlockBehavior.java index cc559a057..bc27bf3ab 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/PickaxeBlockBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/PickaxeBlockBehavior.java @@ -44,7 +44,7 @@ public class PickaxeBlockBehavior extends FacingTriggerableBlockBehavior { ImmutableBlockState blockState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(state)); if (blockState == null || blockState.isEmpty()) return; Object blockPos = FastNMS.INSTANCE.method$BlockPos$relative(pos, DirectionUtils.toNMSDirection(blockState.get(this.facingProperty))); - if (blockCheck(FastNMS.INSTANCE.method$BlockGetter$getBlockState(level, blockPos))) { + if (blockCheckByBlockState(FastNMS.INSTANCE.method$BlockGetter$getBlockState(level, blockPos))) { FastNMS.INSTANCE.method$LevelWriter$destroyBlock(level, blockPos, true, null, 512); } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/PlaceBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/PlaceBlockBehavior.java index b36fb6be3..443259fee 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/PlaceBlockBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/PlaceBlockBehavior.java @@ -1,6 +1,5 @@ package net.momirealms.craftengine.bukkit.block.behavior; -import net.momirealms.craftengine.bukkit.api.CraftEngineBlocks; import net.momirealms.craftengine.bukkit.block.BukkitBlockManager; import net.momirealms.craftengine.bukkit.item.BukkitItemManager; import net.momirealms.craftengine.bukkit.item.behavior.BlockItemBehavior; @@ -10,23 +9,24 @@ import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MEntityType import net.momirealms.craftengine.bukkit.util.BlockStateUtils; import net.momirealms.craftengine.bukkit.util.DirectionUtils; import net.momirealms.craftengine.bukkit.util.LocationUtils; +import net.momirealms.craftengine.bukkit.world.BukkitWorldManager; import net.momirealms.craftengine.core.block.BlockBehavior; import net.momirealms.craftengine.core.block.CustomBlock; import net.momirealms.craftengine.core.block.ImmutableBlockState; -import net.momirealms.craftengine.core.block.UpdateOption; import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory; import net.momirealms.craftengine.core.block.properties.Property; +import net.momirealms.craftengine.core.entity.player.InteractionHand; +import net.momirealms.craftengine.core.entity.player.InteractionResult; import net.momirealms.craftengine.core.item.CustomItem; import net.momirealms.craftengine.core.item.Item; import net.momirealms.craftengine.core.item.behavior.ItemBehavior; -import net.momirealms.craftengine.core.plugin.CraftEngine; +import net.momirealms.craftengine.core.item.context.PlaceBlockBlockPlaceContext; import net.momirealms.craftengine.core.util.Direction; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.MiscUtils; import net.momirealms.craftengine.core.util.ResourceConfigUtils; +import net.momirealms.craftengine.core.world.BlockHitResult; import net.momirealms.craftengine.core.world.BlockPos; -import org.bukkit.Location; -import org.bukkit.Material; import org.bukkit.inventory.ItemStack; import javax.annotation.Nullable; @@ -74,7 +74,7 @@ public class PlaceBlockBehavior extends FacingTriggerableBlockBehavior { boolean flag = false; if (CoreReflections.clazz$BlockItem.isInstance(itemStack1)) { Object block = FastNMS.INSTANCE.method$BlockItem$getBlock(itemStack1); - if (blockCheck(FastNMS.INSTANCE.method$Block$defaultState(block))) { + if (blockCheckByBlockState(FastNMS.INSTANCE.method$Block$defaultState(block))) { Object blockHitResult = FastNMS.INSTANCE.constructor$BlockHitResult( FastNMS.INSTANCE.method$BlockPos$getCenter(LocationUtils.toBlockPos(blockPos1)), DirectionUtils.toNMSDirection(opposite), @@ -88,7 +88,6 @@ public class PlaceBlockBehavior extends FacingTriggerableBlockBehavior { flag = FastNMS.INSTANCE.method$InteractionResult$consumesAction(interactionResult); } } - if (!flag) { Item item = BukkitItemManager.instance().wrap(FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(itemStack)); Optional> optionalCustomItem = item.getCustomItem(); @@ -96,21 +95,21 @@ public class PlaceBlockBehavior extends FacingTriggerableBlockBehavior { CustomItem customItem = optionalCustomItem.get(); for (ItemBehavior itemBehavior : customItem.behaviors()) { if (itemBehavior instanceof BlockItemBehavior blockItemBehavior) { - Optional optionalBlock = BukkitBlockManager.instance().blockById(blockItemBehavior.block()); - if (optionalBlock.isEmpty()) { - CraftEngine.instance().logger().warn("Failed to place unknown block " + blockItemBehavior.block()); - continue; - } - ImmutableBlockState placeBlockState = optionalBlock.get().defaultState(); - if (!blockCheck(placeBlockState.customBlockState().handle())) { - continue; - } - Location placeLocation = new Location(FastNMS.INSTANCE.method$Level$getCraftWorld(level), blockPos1.x(), blockPos1.y(), blockPos1.z()); - if (placeLocation.getBlock().getType() != Material.AIR) { - break; - } - // TODO: 修复放置多方块自定义方块问题 - if (CraftEngineBlocks.place(placeLocation, placeBlockState, UpdateOption.UPDATE_ALL_IMMEDIATE, true)) { + if (!blockCheckByKey(blockItemBehavior.block())) continue; + BlockHitResult hitResult = new BlockHitResult( + LocationUtils.toVec3d(blockPos1), + opposite, + blockPos1, + false + ); + PlaceBlockBlockPlaceContext context = new PlaceBlockBlockPlaceContext( + BukkitWorldManager.instance().wrap(level), + InteractionHand.MAIN_HAND, + BukkitItemManager.instance().wrap(FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(itemStack)), + hitResult + ); + InteractionResult result = blockItemBehavior.place(context); + if (result.success()) { return true; } } @@ -130,6 +129,7 @@ public class PlaceBlockBehavior extends FacingTriggerableBlockBehavior { } + @SuppressWarnings("UnusedReturnValue") private static boolean getItemAndDoThings(Object level, BlockPos blockPos, Direction direction, Function function) { for (Object container : getContainersAt(level, blockPos)) { boolean flag = FastNMS.INSTANCE.method$HopperBlockEntity$getSlots(container, DirectionUtils.toNMSDirection(direction)).anyMatch(i -> { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/BlockItemBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/BlockItemBehavior.java index 2e071a68c..0645e706f 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/BlockItemBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/BlockItemBehavior.java @@ -30,10 +30,7 @@ import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext; import net.momirealms.craftengine.core.plugin.context.event.EventTrigger; import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters; import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException; -import net.momirealms.craftengine.core.util.Cancellable; -import net.momirealms.craftengine.core.util.Direction; -import net.momirealms.craftengine.core.util.Key; -import net.momirealms.craftengine.core.util.MiscUtils; +import net.momirealms.craftengine.core.util.*; import net.momirealms.craftengine.core.world.BlockPos; import net.momirealms.craftengine.core.world.WorldPosition; import org.bukkit.Bukkit; @@ -76,11 +73,12 @@ public class BlockItemBehavior extends BlockBoundItemBehavior { return InteractionResult.FAIL; } + Player player = context.getPlayer(); CustomBlock block = optionalBlock.get(); BlockPos pos = context.getClickedPos(); int maxY = context.getLevel().worldHeight().getMaxBuildHeight() - 1; - if (context.getClickedFace() == Direction.UP && pos.y() >= maxY) { - context.getPlayer().sendActionBar(Component.translatable("build.tooHigh").arguments(Component.text(maxY)).color(NamedTextColor.RED)); + if (player != null && context.getClickedFace() == Direction.UP && pos.y() >= maxY) { + player.sendActionBar(Component.translatable("build.tooHigh").arguments(Component.text(maxY)).color(NamedTextColor.RED)); return InteractionResult.FAIL; } @@ -89,15 +87,14 @@ public class BlockItemBehavior extends BlockBoundItemBehavior { return InteractionResult.FAIL; } - Player player = context.getPlayer(); BlockPos againstPos = context.getAgainstPos(); World world = (World) context.getLevel().platformWorld(); Location placeLocation = new Location(world, pos.x(), pos.y(), pos.z()); Block bukkitBlock = world.getBlockAt(placeLocation); Block againstBlock = world.getBlockAt(againstPos.x(), againstPos.y(), againstPos.z()); - org.bukkit.entity.Player bukkitPlayer = (org.bukkit.entity.Player) player.platformPlayer(); + org.bukkit.entity.Player bukkitPlayer = player != null ? (org.bukkit.entity.Player) player.platformPlayer() : null; - if (player.isAdventureMode()) { + if (player != null && player.isAdventureMode()) { Object againstBlockState = BlockStateUtils.blockDataToBlockState(againstBlock.getBlockData()); int stateId = BlockStateUtils.blockStateToId(againstBlockState); if (BlockStateUtils.isVanillaBlock(stateId)) { @@ -113,31 +110,35 @@ public class BlockItemBehavior extends BlockBoundItemBehavior { } } - // trigger event - CustomBlockAttemptPlaceEvent attemptPlaceEvent = new CustomBlockAttemptPlaceEvent(bukkitPlayer, placeLocation.clone(), blockStateToPlace, - DirectionUtils.toBlockFace(context.getClickedFace()), bukkitBlock, context.getHand()); - if (EventUtils.fireAndCheckCancel(attemptPlaceEvent)) { - return InteractionResult.FAIL; + if (player != null) { + // trigger event + CustomBlockAttemptPlaceEvent attemptPlaceEvent = new CustomBlockAttemptPlaceEvent(bukkitPlayer, placeLocation.clone(), blockStateToPlace, + DirectionUtils.toBlockFace(context.getClickedFace()), bukkitBlock, context.getHand()); + if (EventUtils.fireAndCheckCancel(attemptPlaceEvent)) { + return InteractionResult.FAIL; + } } // it's just world + pos BlockState previousState = bukkitBlock.getState(); // place custom block CraftEngineBlocks.place(placeLocation, blockStateToPlace, UpdateOption.UPDATE_ALL_IMMEDIATE, false); - // call bukkit event - BlockPlaceEvent bukkitPlaceEvent = new BlockPlaceEvent(bukkitBlock, previousState, againstBlock, (ItemStack) context.getItem().getItem(), bukkitPlayer, true, context.getHand() == InteractionHand.MAIN_HAND ? EquipmentSlot.HAND : EquipmentSlot.OFF_HAND); - if (EventUtils.fireAndCheckCancel(bukkitPlaceEvent)) { - // revert changes - previousState.update(true, false); - return InteractionResult.FAIL; - } + if (player != null) { + // call bukkit event + BlockPlaceEvent bukkitPlaceEvent = new BlockPlaceEvent(bukkitBlock, previousState, againstBlock, (ItemStack) context.getItem().getItem(), bukkitPlayer, true, context.getHand() == InteractionHand.MAIN_HAND ? EquipmentSlot.HAND : EquipmentSlot.OFF_HAND); + if (EventUtils.fireAndCheckCancel(bukkitPlaceEvent)) { + // revert changes + previousState.update(true, false); + return InteractionResult.FAIL; + } - // call custom event - CustomBlockPlaceEvent customPlaceEvent = new CustomBlockPlaceEvent(bukkitPlayer, placeLocation.clone(), blockStateToPlace, world.getBlockAt(placeLocation), context.getHand()); - if (EventUtils.fireAndCheckCancel(customPlaceEvent)) { - // revert changes - previousState.update(true, false); - return InteractionResult.FAIL; + // call custom event + CustomBlockPlaceEvent customPlaceEvent = new CustomBlockPlaceEvent(bukkitPlayer, placeLocation.clone(), blockStateToPlace, world.getBlockAt(placeLocation), context.getHand()); + if (EventUtils.fireAndCheckCancel(customPlaceEvent)) { + // revert changes + previousState.update(true, false); + return InteractionResult.FAIL; + } } WorldPosition position = new WorldPosition(context.getLevel(), pos.x() + 0.5, pos.y() + 0.5, pos.z() + 0.5); @@ -154,7 +155,7 @@ public class BlockItemBehavior extends BlockBoundItemBehavior { return InteractionResult.SUCCESS_AND_CANCEL; } - if (!player.isCreativeMode()) { + if (player != null && !player.isCreativeMode()) { Item item = context.getItem(); item.count(item.count() - 1); item.load(); @@ -162,7 +163,9 @@ public class BlockItemBehavior extends BlockBoundItemBehavior { block.setPlacedBy(context, blockStateToPlace); - player.swingHand(context.getHand()); + if (player != null) { + player.swingHand(context.getHand()); + } context.getLevel().playBlockSound(position, blockStateToPlace.sounds().placeSound()); world.sendGameEvent(bukkitPlayer, GameEvent.BLOCK_PLACE, new Vector(pos.x(), pos.y(), pos.z())); return InteractionResult.SUCCESS; @@ -179,16 +182,27 @@ public class BlockItemBehavior extends BlockBoundItemBehavior { protected boolean canPlace(BlockPlaceContext context, ImmutableBlockState state) { try { - Object player = context.getPlayer().serverPlayer(); + Player cePlayer = context.getPlayer(); + Object player = cePlayer != null ? cePlayer.serverPlayer() : null; Object blockState = state.customBlockState().handle(); Object blockPos = LocationUtils.toBlockPos(context.getClickedPos()); - Object voxelShape = CoreReflections.method$CollisionContext$of.invoke(null, player); + Object voxelShape; + if (VersionHelper.isOrAbove1_21_6()) { + voxelShape = CoreReflections.method$CollisionContext$placementContext.invoke(null, player); + } else if (player != null) { + voxelShape = CoreReflections.method$CollisionContext$of.invoke(null, player); + } else { + voxelShape = CoreReflections.instance$CollisionContext$empty; + } Object world = FastNMS.INSTANCE.field$CraftWorld$ServerLevel((World) context.getLevel().platformWorld()); boolean defaultReturn = ((!this.checkStatePlacement() || (boolean) CoreReflections.method$BlockStateBase$canSurvive.invoke(blockState, world, blockPos)) && (boolean) CoreReflections.method$ServerLevel$checkEntityCollision.invoke(world, blockState, player, voxelShape, blockPos, true)); Block block = FastNMS.INSTANCE.method$CraftBlock$at(world, blockPos); BlockData blockData = FastNMS.INSTANCE.method$CraftBlockData$fromData(blockState); - BlockCanBuildEvent canBuildEvent = new BlockCanBuildEvent(block, (org.bukkit.entity.Player) context.getPlayer().platformPlayer(), blockData, defaultReturn, context.getHand() == InteractionHand.MAIN_HAND ? EquipmentSlot.HAND : EquipmentSlot.OFF_HAND); + BlockCanBuildEvent canBuildEvent = new BlockCanBuildEvent( + block, cePlayer != null ? (org.bukkit.entity.Player) cePlayer.platformPlayer() : null, blockData, defaultReturn, + context.getHand() == InteractionHand.MAIN_HAND ? EquipmentSlot.HAND : EquipmentSlot.OFF_HAND + ); Bukkit.getPluginManager().callEvent(canBuildEvent); return canBuildEvent.isBuildable(); } catch (ReflectiveOperationException e) { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/CoreReflections.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/CoreReflections.java index ac04131f7..85f4bf223 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/CoreReflections.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/CoreReflections.java @@ -3578,4 +3578,19 @@ public final class CoreReflections { "world.item.BlockItem" ) ); + + public static final Object instance$CollisionContext$empty; + + static { + try { + instance$CollisionContext$empty = requireNonNull(method$CollisionContext$empty.invoke(null)); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + // 1.21.6+ + public static final Method method$CollisionContext$placementContext = ReflectionUtils.getStaticMethod( + clazz$CollisionContext, clazz$CollisionContext, clazz$Player + ); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/LocationUtils.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/LocationUtils.java index 5a103ac24..6e8b09c3b 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/LocationUtils.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/LocationUtils.java @@ -4,6 +4,7 @@ import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.world.BukkitWorld; import net.momirealms.craftengine.core.world.BlockPos; import net.momirealms.craftengine.core.world.Vec3d; +import net.momirealms.craftengine.core.world.Vec3i; import net.momirealms.craftengine.core.world.WorldPosition; import org.bukkit.Location; import org.bukkit.World; @@ -98,4 +99,11 @@ public class LocationUtils { centerLoc.setY(location.getBlockY()); return centerLoc; } + + public static Vec3d atCenterOf(Vec3d vec) { + return atLowerCornerWithOffset(vec, 0.5F, 0.5F, 0.5F); + } + public static Vec3d atLowerCornerWithOffset(Vec3d vec, double deltaX, double deltaY, double deltaZ) { + return new Vec3d(vec.x() + deltaX, vec.y() + deltaY, vec.z() + deltaZ); + } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/BukkitWorldManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/BukkitWorldManager.java index 82931530a..b0b21a005 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/BukkitWorldManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/BukkitWorldManager.java @@ -235,6 +235,8 @@ public class BukkitWorldManager implements WorldManager, Listener { public net.momirealms.craftengine.core.world.World wrap(T world) { if (world instanceof World w) { return new BukkitWorld(w); + } else if (CoreReflections.clazz$Level.isInstance(world)) { + return new BukkitWorld(FastNMS.INSTANCE.method$Level$getCraftWorld(world)); } else { throw new IllegalArgumentException(world.getClass() + " is not a Bukkit World"); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/context/BlockPlaceContext.java b/core/src/main/java/net/momirealms/craftengine/core/item/context/BlockPlaceContext.java index b3cd761f5..be7929b7e 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/context/BlockPlaceContext.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/context/BlockPlaceContext.java @@ -8,6 +8,8 @@ import net.momirealms.craftengine.core.world.BlockHitResult; import net.momirealms.craftengine.core.world.BlockPos; import net.momirealms.craftengine.core.world.World; +import javax.annotation.Nullable; + public class BlockPlaceContext extends UseOnContext { private final BlockPos relativePos; protected boolean replaceClicked; @@ -16,7 +18,7 @@ public class BlockPlaceContext extends UseOnContext { this(context.getLevel(), context.getPlayer(), context.getHand(), context.getItem(), context.getHitResult()); } - public BlockPlaceContext(World world, Player player, InteractionHand hand, Item stack, BlockHitResult hit) { + public BlockPlaceContext(World world, @Nullable Player player, InteractionHand hand, Item stack, BlockHitResult hit) { super(world, player, hand, stack, hit); this.relativePos = hit.getBlockPos().relative(hit.getDirection()); this.replaceClicked = true; diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/context/PlaceBlockBlockPlaceContext.java b/core/src/main/java/net/momirealms/craftengine/core/item/context/PlaceBlockBlockPlaceContext.java new file mode 100644 index 000000000..545362e77 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/item/context/PlaceBlockBlockPlaceContext.java @@ -0,0 +1,18 @@ +package net.momirealms.craftengine.core.item.context; + +import net.momirealms.craftengine.core.entity.player.InteractionHand; +import net.momirealms.craftengine.core.item.Item; +import net.momirealms.craftengine.core.util.Direction; +import net.momirealms.craftengine.core.world.BlockHitResult; +import net.momirealms.craftengine.core.world.World; + +public class PlaceBlockBlockPlaceContext extends BlockPlaceContext { + public PlaceBlockBlockPlaceContext(World world, InteractionHand hand, Item stack, BlockHitResult hit) { + super(world, null, hand, stack, hit); + } + + @Override + public Direction getNearestLookingDirection() { + return this.getHitResult().getDirection(); + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/context/UseOnContext.java b/core/src/main/java/net/momirealms/craftengine/core/item/context/UseOnContext.java index cb65aff39..96af9d3b0 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/context/UseOnContext.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/context/UseOnContext.java @@ -8,8 +8,10 @@ import net.momirealms.craftengine.core.world.BlockHitResult; import net.momirealms.craftengine.core.world.BlockPos; import net.momirealms.craftengine.core.world.Vec3d; import net.momirealms.craftengine.core.world.World; +import org.jetbrains.annotations.Nullable; public class UseOnContext { + @Nullable private final Player player; private final InteractionHand hand; private final BlockHitResult hitResult; @@ -24,7 +26,7 @@ public class UseOnContext { this(player.world(), player, hand, stack, hit); } - public UseOnContext(World world, Player player, InteractionHand hand, Item stack, BlockHitResult hit) { + public UseOnContext(World world, @Nullable Player player, InteractionHand hand, Item stack, BlockHitResult hit) { this.player = player; this.hand = hand; this.hitResult = hit; @@ -56,6 +58,7 @@ public class UseOnContext { return this.itemStack; } + @Nullable public Player getPlayer() { return this.player; } @@ -69,11 +72,11 @@ public class UseOnContext { } public Direction getHorizontalDirection() { - return this.player.getDirection(); + return this.player == null ? Direction.NORTH : this.player.getDirection(); } public boolean isSecondaryUseActive() { - return this.player.isSecondaryUseActive(); + return this.player != null && this.player.isSecondaryUseActive(); } public float getRotation() {