diff --git a/src/main/java/de/dafuqs/spectrum/blocks/redstone/BlockPlacerBlock.java b/src/main/java/de/dafuqs/spectrum/blocks/redstone/BlockPlacerBlock.java index dba2febd57..9743543a49 100644 --- a/src/main/java/de/dafuqs/spectrum/blocks/redstone/BlockPlacerBlock.java +++ b/src/main/java/de/dafuqs/spectrum/blocks/redstone/BlockPlacerBlock.java @@ -2,6 +2,7 @@ import de.dafuqs.spectrum.*; import de.dafuqs.spectrum.compat.claims.*; +import de.dafuqs.spectrum.registries.*; import net.minecraft.block.*; import net.minecraft.block.entity.*; import net.minecraft.entity.*; @@ -9,6 +10,7 @@ import net.minecraft.item.*; import net.minecraft.registry.*; import net.minecraft.screen.*; +import net.minecraft.server.network.*; import net.minecraft.server.world.*; import net.minecraft.util.*; import net.minecraft.util.hit.*; @@ -51,25 +53,28 @@ protected void dispense(ServerWorld world, BlockPos pos) { world.emitGameEvent(null, GameEvent.BLOCK_ACTIVATE, pos); } else { ItemStack stack = blockEntity.getStack(slot); - tryPlace(stack, pointer); + PlayerEntity cause = blockEntity.getOwnerIfOnline(); + tryPlace(stack, pointer, cause); } } // We can't reuse the vanilla BlockPlacementDispenserBehavior, since we are using a different orientation for our block: // BlockPlacerBlock.ORIENTATION instead of DispenserBlock.FACING - protected void tryPlace(@NotNull ItemStack stack, BlockPointer pointer) { + protected void tryPlace(@NotNull ItemStack stack, BlockPointer pointer, PlayerEntity cause) { World world = pointer.getWorld(); if (stack.getItem() instanceof BlockItem blockItem) { Direction facing = pointer.getBlockState().get(BlockPlacerBlock.ORIENTATION).getFacing(); BlockPos placementPos = pointer.getPos().offset(facing); Direction placementDirection = world.isAir(placementPos.down()) ? facing : Direction.UP; - if (!GenericClaimModsCompat.canPlaceBlock(world, placementPos, null)) { + if (!GenericClaimModsCompat.canPlaceBlock(world, placementPos, cause)) { return; } try { - blockItem.place(new BlockPlacerPlacementContext(world, placementPos, facing, stack, placementDirection)); + if(blockItem.place(new BlockPlacerPlacementContext(world, placementPos, facing, stack, placementDirection, cause)).isAccepted()) { + if(cause != null && cause.getAbilities().creativeMode) { stack.decrement(1); } + } world.syncWorldEvent(WorldEvents.DISPENSER_DISPENSES, pointer.getPos(), 0); world.syncWorldEvent(WorldEvents.DISPENSER_ACTIVATED, pointer.getPos(), pointer.getBlockState().get(BlockPlacerBlock.ORIENTATION).getFacing().getId()); world.emitGameEvent(null, GameEvent.BLOCK_PLACE, placementPos); @@ -83,6 +88,10 @@ protected void tryPlace(@NotNull ItemStack stack, BlockPointer pointer) { } } + protected void tryPlace(@NotNull ItemStack itemStack, BlockPointer pointer) { + this.tryPlace(itemStack, pointer, null); + } + @Override public void neighborUpdate(BlockState state, World world, BlockPos pos, Block sourceBlock, BlockPos sourcePos, boolean notify) { boolean bl = world.isReceivingRedstonePower(pos) || world.isReceivingRedstonePower(pos.up()); @@ -102,10 +111,13 @@ public void scheduledTick(BlockState state, ServerWorld world, BlockPos pos, Ran @Override public void onPlaced(World world, BlockPos pos, BlockState state, LivingEntity placer, ItemStack itemStack) { - if (itemStack.hasCustomName()) { - if (world.getBlockEntity(pos) instanceof BlockPlacerBlockEntity blockPlacerBlockEntity) { + if (world.getBlockEntity(pos) instanceof BlockPlacerBlockEntity blockPlacerBlockEntity) { + if (itemStack.hasCustomName()) { blockPlacerBlockEntity.setCustomName(itemStack.getName()); } + if (placer instanceof ServerPlayerEntity serverPlayerEntity) { + blockPlacerBlockEntity.setOwner(serverPlayerEntity); + } } } @@ -133,9 +145,28 @@ public int getComparatorOutput(BlockState state, World world, BlockPos pos) { } public static final class BlockPlacerPlacementContext extends AutomaticItemPlacementContext { + // Shadows the variable facing in the superclass. + private final Direction facing; + private final PlayerEntity cause; - public BlockPlacerPlacementContext(World world, BlockPos pos, Direction facing, ItemStack stack, Direction side) { + public BlockPlacerPlacementContext(World world, BlockPos pos, Direction facing, ItemStack stack, Direction side, PlayerEntity cause) { super(world, pos, facing, stack, side); + this.facing = facing; + this.cause = cause; + } + + public BlockPlacerPlacementContext(World world, BlockPos pos, Direction facing, ItemStack stack, Direction side) { + this(world, pos, facing, stack, side, null); + } + + // Not global, as to avoid any exploits where Ender Droppers et al. can be placed without player consent. + @Nullable @Override + public PlayerEntity getPlayer() { + return this.getStack().isIn(SpectrumItemTags.PLAYER_ATTRIBUTED_PLACEMENT) ? this.cause : null; + } + + public Direction getPlayerLookDirection() { + return facing.getOpposite(); } // SlabBlocks cause a non-funny StackOverflowError diff --git a/src/main/java/de/dafuqs/spectrum/blocks/redstone/BlockPlacerBlockEntity.java b/src/main/java/de/dafuqs/spectrum/blocks/redstone/BlockPlacerBlockEntity.java index 244ba043dc..25bcb94226 100644 --- a/src/main/java/de/dafuqs/spectrum/blocks/redstone/BlockPlacerBlockEntity.java +++ b/src/main/java/de/dafuqs/spectrum/blocks/redstone/BlockPlacerBlockEntity.java @@ -1,15 +1,21 @@ package de.dafuqs.spectrum.blocks.redstone; +import de.dafuqs.spectrum.api.block.*; import de.dafuqs.spectrum.inventories.*; import de.dafuqs.spectrum.registries.*; import net.minecraft.block.*; import net.minecraft.block.entity.*; import net.minecraft.entity.player.*; +import net.minecraft.nbt.*; import net.minecraft.screen.*; import net.minecraft.text.*; import net.minecraft.util.math.*; -public class BlockPlacerBlockEntity extends DispenserBlockEntity { +import java.util.*; + +public class BlockPlacerBlockEntity extends DispenserBlockEntity implements PlayerOwned { + + private UUID ownerUUID; public BlockPlacerBlockEntity(BlockPos pos, BlockState state) { super(SpectrumBlockEntities.BLOCK_PLACER, pos, state); @@ -25,4 +31,26 @@ protected ScreenHandler createScreenHandler(int syncId, PlayerInventory playerIn return Spectrum3x3ContainerScreenHandler.createTier1(syncId, playerInventory, this); } + @Override + public UUID getOwnerUUID() { + return this.ownerUUID; + } + + @Override + public void setOwner(PlayerEntity playerEntity) { + this.ownerUUID = playerEntity.getUuid(); + this.markDirty(); + } + + @Override + public void writeNbt(NbtCompound nbt) { + super.writeNbt(nbt); + PlayerOwned.writeOwnerUUID(nbt, this.ownerUUID); + } + + @Override + public void readNbt(NbtCompound nbt) { + super.readNbt(nbt); + this.ownerUUID = PlayerOwned.readOwnerUUID(nbt); + } } diff --git a/src/main/java/de/dafuqs/spectrum/blocks/redstone/RedstoneInteractionBlock.java b/src/main/java/de/dafuqs/spectrum/blocks/redstone/RedstoneInteractionBlock.java index 0271d5170b..bd6759b43b 100644 --- a/src/main/java/de/dafuqs/spectrum/blocks/redstone/RedstoneInteractionBlock.java +++ b/src/main/java/de/dafuqs/spectrum/blocks/redstone/RedstoneInteractionBlock.java @@ -42,8 +42,8 @@ protected void appendProperties(StateManager.Builder builder) public BlockState getPlacementState(ItemPlacementContext ctx) { Direction direction = ctx.getPlayerLookDirection().getOpposite(); Direction direction2 = switch (direction) { - case DOWN -> ctx.getPlayer().getHorizontalFacing().getOpposite(); - case UP -> ctx.getPlayer().getHorizontalFacing(); + case DOWN -> ctx.getHorizontalPlayerFacing().getOpposite(); + case UP -> ctx.getHorizontalPlayerFacing(); case NORTH, SOUTH, WEST, EAST -> Direction.UP; }; diff --git a/src/main/java/de/dafuqs/spectrum/registries/SpectrumItemTags.java b/src/main/java/de/dafuqs/spectrum/registries/SpectrumItemTags.java index d0a5f51ac0..6454fdea33 100644 --- a/src/main/java/de/dafuqs/spectrum/registries/SpectrumItemTags.java +++ b/src/main/java/de/dafuqs/spectrum/registries/SpectrumItemTags.java @@ -31,6 +31,7 @@ public class SpectrumItemTags { public static final TagKey PASTEL_NODE_UPGRADES = of("pastel_node_upgrades"); public static final TagKey TAG_FILTERING_ITEMS = of("tag_filtering_items"); public static final TagKey WEEPING_GALA_LOGS = of("weeping_gala_logs"); + public static final TagKey PLAYER_ATTRIBUTED_PLACEMENT = of("player_attributed_placement"); private static TagKey of(String id) { return TagKey.of(RegistryKeys.ITEM, SpectrumCommon.locate(id)); diff --git a/src/main/resources/data/spectrum/tags/items/player_attributed_placement.json b/src/main/resources/data/spectrum/tags/items/player_attributed_placement.json new file mode 100644 index 0000000000..fb9ef54498 --- /dev/null +++ b/src/main/resources/data/spectrum/tags/items/player_attributed_placement.json @@ -0,0 +1,6 @@ +{ + "values": [ + "spectrum:block_breaker", + "spectrum:block_placer" + ] +} \ No newline at end of file