mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-25 09:59:20 +00:00
refactor(item): 重构使用物品上下文以支持玩家为null的情况
This commit is contained in:
@@ -2,6 +2,7 @@ package net.momirealms.craftengine.bukkit.item.behavior;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.block.behavior.StrippableBlockBehavior;
|
||||
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
import net.momirealms.craftengine.bukkit.util.*;
|
||||
@@ -54,7 +55,7 @@ public class AxeItemBehavior extends ItemBehavior {
|
||||
public InteractionResult useOnBlock(UseOnContext context) {
|
||||
Player player = context.getPlayer();
|
||||
// no adventure mode for the moment
|
||||
if (player.isAdventureMode()) {
|
||||
if (player != null && player.isAdventureMode()) {
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
|
||||
@@ -66,9 +67,9 @@ public class AxeItemBehavior extends ItemBehavior {
|
||||
Optional<StrippableBlockBehavior> behaviorOptional = customState.behavior().getAs(StrippableBlockBehavior.class);
|
||||
if (behaviorOptional.isEmpty()) return InteractionResult.PASS;
|
||||
Key stripped = behaviorOptional.get().stripped();
|
||||
Item<ItemStack> offHandItem = (Item<ItemStack>) player.getItemInHand(InteractionHand.OFF_HAND);
|
||||
Item<ItemStack> offHandItem = player != null ? (Item<ItemStack>) player.getItemInHand(InteractionHand.OFF_HAND) : BukkitItemManager.instance().wrap(new ItemStack(Material.AIR));
|
||||
// is using a shield
|
||||
if (context.getHand() == InteractionHand.MAIN_HAND && !ItemUtils.isEmpty(offHandItem) && canBlockAttack(offHandItem) && !player.isSecondaryUseActive()) {
|
||||
if (context.getHand() == InteractionHand.MAIN_HAND && !ItemUtils.isEmpty(offHandItem) && canBlockAttack(offHandItem) && player != null && !player.isSecondaryUseActive()) {
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
|
||||
@@ -81,13 +82,15 @@ public class AxeItemBehavior extends ItemBehavior {
|
||||
CompoundTag compoundTag = customState.propertiesNbt();
|
||||
ImmutableBlockState newState = newCustomBlock.getBlockState(compoundTag);
|
||||
|
||||
org.bukkit.entity.Player bukkitPlayer = ((org.bukkit.entity.Player) player.platformPlayer());
|
||||
|
||||
BukkitBlockInWorld clicked = (BukkitBlockInWorld) context.getLevel().getBlockAt(context.getClickedPos());
|
||||
// Call bukkit event
|
||||
EntityChangeBlockEvent event = new EntityChangeBlockEvent(bukkitPlayer, clicked.block(), BlockStateUtils.fromBlockData(newState.customBlockState().handle()));
|
||||
if (EventUtils.fireAndCheckCancel(event)) {
|
||||
return InteractionResult.FAIL;
|
||||
org.bukkit.entity.Player bukkitPlayer = null;
|
||||
if (player != null) {
|
||||
bukkitPlayer = ((org.bukkit.entity.Player) player.platformPlayer());
|
||||
// Call bukkit event
|
||||
EntityChangeBlockEvent event = new EntityChangeBlockEvent(bukkitPlayer, clicked.block(), BlockStateUtils.fromBlockData(newState.customBlockState().handle()));
|
||||
if (EventUtils.fireAndCheckCancel(event)) {
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
Item<ItemStack> item = (Item<ItemStack>) context.getItem();
|
||||
@@ -98,28 +101,30 @@ public class AxeItemBehavior extends ItemBehavior {
|
||||
FastNMS.INSTANCE.method$LevelWriter$setBlock(context.getLevel().serverWorld(), LocationUtils.toBlockPos(pos), newState.customBlockState().handle(), UpdateOption.UPDATE_ALL_IMMEDIATE.flags());
|
||||
clicked.block().getWorld().sendGameEvent(bukkitPlayer, GameEvent.BLOCK_CHANGE, new Vector(pos.x(), pos.y(), pos.z()));
|
||||
Material material = MaterialUtils.getMaterial(item.vanillaId());
|
||||
bukkitPlayer.setStatistic(Statistic.USE_ITEM, material, bukkitPlayer.getStatistic(Statistic.USE_ITEM, material) + 1);
|
||||
if (bukkitPlayer != null) {
|
||||
bukkitPlayer.setStatistic(Statistic.USE_ITEM, material, bukkitPlayer.getStatistic(Statistic.USE_ITEM, material) + 1);
|
||||
|
||||
// resend swing if it's not interactable on client side
|
||||
if (!InteractUtils.isInteractable(
|
||||
bukkitPlayer, BlockStateUtils.fromBlockData(customState.vanillaBlockState().handle()),
|
||||
context.getHitResult(), item
|
||||
) || player.isSecondaryUseActive()) {
|
||||
player.swingHand(context.getHand());
|
||||
}
|
||||
// shrink item amount
|
||||
if (VersionHelper.isOrAbove1_20_5()) {
|
||||
Object itemStack = item.getLiteralObject();
|
||||
Object serverPlayer = player.serverPlayer();
|
||||
Object equipmentSlot = context.getHand() == InteractionHand.MAIN_HAND ? CoreReflections.instance$EquipmentSlot$MAINHAND : CoreReflections.instance$EquipmentSlot$OFFHAND;
|
||||
try {
|
||||
CoreReflections.method$ItemStack$hurtAndBreak.invoke(itemStack, 1, serverPlayer, equipmentSlot);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
CraftEngine.instance().logger().warn("Failed to hurt itemStack", e);
|
||||
// resend swing if it's not interactable on client side
|
||||
if (!InteractUtils.isInteractable(
|
||||
bukkitPlayer, BlockStateUtils.fromBlockData(customState.vanillaBlockState().handle()),
|
||||
context.getHitResult(), item
|
||||
) || player.isSecondaryUseActive()) {
|
||||
player.swingHand(context.getHand());
|
||||
}
|
||||
// shrink item amount
|
||||
if (VersionHelper.isOrAbove1_20_5()) {
|
||||
Object itemStack = item.getLiteralObject();
|
||||
Object serverPlayer = player.serverPlayer();
|
||||
Object equipmentSlot = context.getHand() == InteractionHand.MAIN_HAND ? CoreReflections.instance$EquipmentSlot$MAINHAND : CoreReflections.instance$EquipmentSlot$OFFHAND;
|
||||
try {
|
||||
CoreReflections.method$ItemStack$hurtAndBreak.invoke(itemStack, 1, serverPlayer, equipmentSlot);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
CraftEngine.instance().logger().warn("Failed to hurt itemStack", e);
|
||||
}
|
||||
} else {
|
||||
ItemStack itemStack = item.getItem();
|
||||
itemStack.damage(1, bukkitPlayer);
|
||||
}
|
||||
} else {
|
||||
ItemStack itemStack = item.getItem();
|
||||
itemStack.damage(1, bukkitPlayer);
|
||||
}
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(againstBlockState);
|
||||
if (optionalCustomState.isEmpty()) {
|
||||
@@ -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,14 +155,16 @@ 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);
|
||||
}
|
||||
|
||||
block.setPlacedBy(context, blockStateToPlace);
|
||||
|
||||
player.swingHand(context.getHand());
|
||||
if (player != null) {
|
||||
player.swingHand(context.getHand());
|
||||
}
|
||||
context.getLevel().playBlockSound(position, blockStateToPlace.settings().sounds().placeSound());
|
||||
world.sendGameEvent(bukkitPlayer, GameEvent.BLOCK_PLACE, new Vector(pos.x(), pos.y(), pos.z()));
|
||||
return InteractionResult.SUCCESS;
|
||||
@@ -178,16 +181,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) {
|
||||
|
||||
@@ -51,15 +51,17 @@ public class CompostableItemBehavior extends ItemBehavior {
|
||||
|
||||
if (willRaise) {
|
||||
levelled.setLevel(currentLevel + 1);
|
||||
EntityChangeBlockEvent event = new EntityChangeBlockEvent((Entity) context.getPlayer().platformPlayer(), block.block(), levelled);
|
||||
if (EventUtils.fireAndCheckCancel(event)) {
|
||||
return InteractionResult.FAIL;
|
||||
if (context.getPlayer() != null) {
|
||||
EntityChangeBlockEvent event = new EntityChangeBlockEvent((Entity) context.getPlayer().platformPlayer(), block.block(), levelled);
|
||||
if (EventUtils.fireAndCheckCancel(event)) {
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
}
|
||||
block.block().setBlockData(levelled);
|
||||
}
|
||||
|
||||
context.getLevel().levelEvent(WorldEvents.COMPOSTER_COMPOSTS, context.getClickedPos(), willRaise ? 1 : 0);
|
||||
((World) context.getLevel().platformWorld()).sendGameEvent((Entity) context.getPlayer().platformPlayer(), GameEvent.BLOCK_CHANGE, new Vector(block.x() + 0.5, block.y() + 0.5, block.z() + 0.5));
|
||||
((World) context.getLevel().platformWorld()).sendGameEvent(context.getPlayer() != null ? (Entity) context.getPlayer().platformPlayer() : null, GameEvent.BLOCK_CHANGE, new Vector(block.x() + 0.5, block.y() + 0.5, block.z() + 0.5));
|
||||
if (currentLevel + 1 == 7) {
|
||||
FastNMS.INSTANCE.method$ScheduledTickAccess$scheduleBlockTick(context.getLevel().serverWorld(), LocationUtils.toBlockPos(context.getClickedPos()), blockOwner, 20);
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ public class FlintAndSteelItemBehavior extends ItemBehavior {
|
||||
}
|
||||
BlockData vanillaBlockState = BlockStateUtils.fromBlockData(immutableBlockState.vanillaBlockState().handle());
|
||||
// 点击的是方块上面,则只需要判断shift和可交互
|
||||
if (direction == Direction.UP) {
|
||||
if (player != null && direction == Direction.UP) {
|
||||
// 客户端层面必须可交互
|
||||
if (!InteractUtils.isInteractable((Player) player.platformPlayer(), vanillaBlockState,
|
||||
context.getHitResult(), (Item<ItemStack>) context.getItem())) {
|
||||
@@ -106,7 +106,7 @@ public class FlintAndSteelItemBehavior extends ItemBehavior {
|
||||
}
|
||||
|
||||
// 客户端觉得这玩意可交互,就会忽略声音
|
||||
if (InteractUtils.isInteractable((Player) player.platformPlayer(), vanillaBlockState, context.getHitResult(), (Item<ItemStack>) context.getItem())) {
|
||||
if (player != null && InteractUtils.isInteractable((Player) player.platformPlayer(), vanillaBlockState, context.getHitResult(), (Item<ItemStack>) context.getItem())) {
|
||||
// 如果按住了shift,则代表尝试对侧面方块点火
|
||||
if (player.isSecondaryUseActive()) {
|
||||
// 如果底部不能燃烧,则燃烧点位为侧面,需要补发
|
||||
@@ -119,7 +119,7 @@ public class FlintAndSteelItemBehavior extends ItemBehavior {
|
||||
}
|
||||
} else {
|
||||
// 如果底部方块不可燃烧才补发
|
||||
if (!belowCanBurn) {
|
||||
if (player != null && !belowCanBurn) {
|
||||
player.playSound(FLINT_SOUND, firePos, SoundSource.BLOCK, 1f, RandomUtils.generateRandomFloat(0.8f, 1.2f));
|
||||
player.swingHand(context.getHand());
|
||||
}
|
||||
@@ -151,8 +151,10 @@ public class FlintAndSteelItemBehavior extends ItemBehavior {
|
||||
}
|
||||
}
|
||||
}
|
||||
player.playSound(FLINT_SOUND, firePos, SoundSource.BLOCK, 1f, RandomUtils.generateRandomFloat(0.8f, 1.2f));
|
||||
player.swingHand(context.getHand());
|
||||
if (player != null) {
|
||||
player.playSound(FLINT_SOUND, firePos, SoundSource.BLOCK, 1f, RandomUtils.generateRandomFloat(0.8f, 1.2f));
|
||||
player.swingHand(context.getHand());
|
||||
}
|
||||
}
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
|
||||
@@ -77,14 +77,14 @@ public class FurnitureItemBehavior extends ItemBehavior {
|
||||
|
||||
Player player = context.getPlayer();
|
||||
// todo adventure check
|
||||
if (player.isAdventureMode()) {
|
||||
if (player != null && player.isAdventureMode()) {
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
|
||||
Vec3d clickedPosition = context.getClickLocation();
|
||||
|
||||
// trigger event
|
||||
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;
|
||||
World world = (World) context.getLevel().platformWorld();
|
||||
|
||||
// get position and rotation for placement
|
||||
@@ -100,7 +100,7 @@ public class FurnitureItemBehavior extends ItemBehavior {
|
||||
finalPlacePosition = new Vec3d(xz.left(), xz.right(), clickedPosition.z());
|
||||
}
|
||||
} else {
|
||||
furnitureYaw = placement.rotationRule().apply(180 + player.xRot());
|
||||
furnitureYaw = placement.rotationRule().apply(180 + (player != null ? player.xRot() : 0));
|
||||
Pair<Double, Double> xz = placement.alignmentRule().apply(Pair.of(clickedPosition.x(), clickedPosition.z()));
|
||||
finalPlacePosition = new Vec3d(xz.left(), clickedPosition.y(), xz.right());
|
||||
}
|
||||
@@ -121,10 +121,12 @@ public class FurnitureItemBehavior extends ItemBehavior {
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
|
||||
FurnitureAttemptPlaceEvent attemptPlaceEvent = new FurnitureAttemptPlaceEvent(bukkitPlayer, customFurniture, anchorType, furnitureLocation.clone(),
|
||||
DirectionUtils.toBlockFace(clickedFace), context.getHand(), world.getBlockAt(context.getClickedPos().x(), context.getClickedPos().y(), context.getClickedPos().z()));
|
||||
if (EventUtils.fireAndCheckCancel(attemptPlaceEvent)) {
|
||||
return InteractionResult.FAIL;
|
||||
if (player != null) {
|
||||
FurnitureAttemptPlaceEvent attemptPlaceEvent = new FurnitureAttemptPlaceEvent(bukkitPlayer, customFurniture, anchorType, furnitureLocation.clone(),
|
||||
DirectionUtils.toBlockFace(clickedFace), context.getHand(), world.getBlockAt(context.getClickedPos().x(), context.getClickedPos().y(), context.getClickedPos().z()));
|
||||
if (EventUtils.fireAndCheckCancel(attemptPlaceEvent)) {
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
Item<?> item = context.getItem();
|
||||
@@ -140,10 +142,12 @@ public class FurnitureItemBehavior extends ItemBehavior {
|
||||
.fireworkExplosionColors(item.fireworkExplosion().map(explosion -> explosion.colors().toIntArray()).orElse(null))
|
||||
.build(), false);
|
||||
|
||||
FurniturePlaceEvent placeEvent = new FurniturePlaceEvent(bukkitPlayer, bukkitFurniture, furnitureLocation, context.getHand());
|
||||
if (EventUtils.fireAndCheckCancel(placeEvent)) {
|
||||
bukkitFurniture.destroy();
|
||||
return InteractionResult.FAIL;
|
||||
if (player != null) {
|
||||
FurniturePlaceEvent placeEvent = new FurniturePlaceEvent(bukkitPlayer, bukkitFurniture, furnitureLocation, context.getHand());
|
||||
if (EventUtils.fireAndCheckCancel(placeEvent)) {
|
||||
bukkitFurniture.destroy();
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
Cancellable dummy = Cancellable.dummy();
|
||||
@@ -159,12 +163,14 @@ public class FurnitureItemBehavior extends ItemBehavior {
|
||||
return InteractionResult.SUCCESS_AND_CANCEL;
|
||||
}
|
||||
|
||||
if (!player.isCreativeMode()) {
|
||||
if (player != null && !player.isCreativeMode()) {
|
||||
item.count(item.count() - 1);
|
||||
}
|
||||
|
||||
context.getLevel().playBlockSound(finalPlacePosition, customFurniture.settings().sounds().placeSound());
|
||||
player.swingHand(context.getHand());
|
||||
if (player != null) {
|
||||
player.swingHand(context.getHand());
|
||||
}
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package net.momirealms.craftengine.bukkit.item.behavior;
|
||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
import net.momirealms.craftengine.bukkit.util.DirectionUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.LocationUtils;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionHand;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionResult;
|
||||
@@ -21,6 +22,7 @@ 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;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Map;
|
||||
@@ -36,13 +38,26 @@ public class LiquidCollisionBlockItemBehavior extends BlockItemBehavior {
|
||||
|
||||
@Override
|
||||
public InteractionResult useOnBlock(UseOnContext context) {
|
||||
return use(context.getLevel(), context.getPlayer(), context.getHand());
|
||||
return use(context.getLevel(), context.getPlayer(), context.getHand(), context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult use(World world, Player player, InteractionHand hand) {
|
||||
public InteractionResult use(World world, @Nullable Player player, InteractionHand hand, @Nullable UseOnContext context) {
|
||||
try {
|
||||
Object blockHitResult = CoreReflections.method$Item$getPlayerPOVHitResult.invoke(null, world.serverWorld(), player.serverPlayer(), CoreReflections.instance$ClipContext$Fluid$SOURCE_ONLY);
|
||||
Object blockHitResult;
|
||||
if (player != null) {
|
||||
blockHitResult = CoreReflections.method$Item$getPlayerPOVHitResult.invoke(null, world.serverWorld(), player.serverPlayer(), CoreReflections.instance$ClipContext$Fluid$SOURCE_ONLY);
|
||||
} else if (context != null) {
|
||||
BlockPos clickedPos = context.getClickedPos();
|
||||
blockHitResult = CoreReflections.constructor$BlockHitResult.newInstance(
|
||||
CoreReflections.constructor$Vec3.newInstance(clickedPos.x() + 0.5, clickedPos.y() + 0.5, clickedPos.z() + 0.5),
|
||||
DirectionUtils.toNMSDirection(context.getHorizontalDirection()),
|
||||
LocationUtils.toBlockPos(clickedPos),
|
||||
false
|
||||
);
|
||||
} else {
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
Object blockPos = CoreReflections.field$BlockHitResul$blockPos.get(blockHitResult);
|
||||
BlockPos above = new BlockPos(FastNMS.INSTANCE.field$Vec3i$x(blockPos), FastNMS.INSTANCE.field$Vec3i$y(blockPos) + offsetY, FastNMS.INSTANCE.field$Vec3i$z(blockPos));
|
||||
Direction direction = Direction.values()[(int) CoreReflections.method$Direction$ordinal.invoke(CoreReflections.field$BlockHitResul$direction.get(blockHitResult))];
|
||||
|
||||
@@ -365,7 +365,7 @@ public class ItemEventListener implements Listener {
|
||||
Optional<List<ItemBehavior>> optionalItemBehaviors = itemInHand.getItemBehavior();
|
||||
if (optionalItemBehaviors.isPresent()) {
|
||||
for (ItemBehavior itemBehavior : optionalItemBehaviors.get()) {
|
||||
InteractionResult result = itemBehavior.use(serverPlayer.world(), serverPlayer, hand);
|
||||
InteractionResult result = itemBehavior.use(serverPlayer.world(), serverPlayer, hand, null);
|
||||
if (result.success()) {
|
||||
serverPlayer.updateLastSuccessfulInteractionTick(serverPlayer.gameTicks());
|
||||
}
|
||||
|
||||
@@ -3830,4 +3830,24 @@ public final class CoreReflections {
|
||||
),
|
||||
!VersionHelper.isOrAbove1_21_5()
|
||||
);
|
||||
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
|
||||
);
|
||||
|
||||
public static final Constructor<?> constructor$BlockHitResult = requireNonNull(
|
||||
ReflectionUtils.getConstructor(
|
||||
CoreReflections.clazz$BlockHitResult, CoreReflections.clazz$Vec3, CoreReflections.clazz$Direction, CoreReflections.clazz$BlockPos, boolean.class
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,9 @@ import net.momirealms.craftengine.core.entity.player.InteractionHand;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionResult;
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
import net.momirealms.craftengine.core.item.context.UseOnContext;
|
||||
import net.momirealms.craftengine.core.world.BlockPos;
|
||||
import net.momirealms.craftengine.core.world.World;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public abstract class ItemBehavior {
|
||||
|
||||
@@ -12,7 +14,7 @@ public abstract class ItemBehavior {
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
|
||||
public InteractionResult use(World world, Player player, InteractionHand hand) {
|
||||
public InteractionResult use(World world, @Nullable Player player, InteractionHand hand, @Nullable UseOnContext context) {
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import net.momirealms.craftengine.core.util.Direction;
|
||||
import net.momirealms.craftengine.core.world.BlockHitResult;
|
||||
import net.momirealms.craftengine.core.world.BlockPos;
|
||||
import net.momirealms.craftengine.core.world.World;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class BlockPlaceContext extends UseOnContext {
|
||||
private final BlockPos relativePos;
|
||||
@@ -16,7 +17,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;
|
||||
|
||||
@@ -9,8 +9,10 @@ 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.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class UseOnContext {
|
||||
@Nullable
|
||||
private final Player player;
|
||||
private final InteractionHand hand;
|
||||
private final BlockHitResult hitResult;
|
||||
@@ -25,7 +27,7 @@ public class UseOnContext {
|
||||
this(player.world(), player, hand, stack, hit);
|
||||
}
|
||||
|
||||
public UseOnContext(@NotNull World world, Player player, InteractionHand hand, @NotNull Item<?> stack, BlockHitResult hit) {
|
||||
public UseOnContext(@NotNull World world, @Nullable Player player, InteractionHand hand, @NotNull Item<?> stack, BlockHitResult hit) {
|
||||
this.player = player;
|
||||
this.hand = hand;
|
||||
this.hitResult = hit;
|
||||
@@ -58,6 +60,7 @@ public class UseOnContext {
|
||||
return this.itemStack;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Player getPlayer() {
|
||||
return this.player;
|
||||
}
|
||||
@@ -71,11 +74,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() {
|
||||
|
||||
Reference in New Issue
Block a user