Part of block entities

This commit is contained in:
Bjarne Koll
2024-12-13 19:02:07 +01:00
parent 0135513d3d
commit e0fae5ef02
14 changed files with 461 additions and 536 deletions

View File

@@ -0,0 +1,43 @@
--- a/net/minecraft/world/level/block/entity/BarrelBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/BarrelBlockEntity.java
@@ -21,6 +_,40 @@
import net.minecraft.world.level.block.state.BlockState;
public class BarrelBlockEntity extends RandomizableContainerBlockEntity {
+ // CraftBukkit start - add fields and methods
+ public java.util.List<org.bukkit.entity.HumanEntity> transaction = new java.util.ArrayList<>();
+ private int maxStack = MAX_STACK;
+
+ @Override
+ public java.util.List<ItemStack> getContents() {
+ return this.items;
+ }
+
+ @Override
+ public void onOpen(org.bukkit.craftbukkit.entity.CraftHumanEntity who) {
+ this.transaction.add(who);
+ }
+
+ @Override
+ public void onClose(org.bukkit.craftbukkit.entity.CraftHumanEntity who) {
+ this.transaction.remove(who);
+ }
+
+ @Override
+ public java.util.List<org.bukkit.entity.HumanEntity> getViewers() {
+ return this.transaction;
+ }
+
+ @Override
+ public int getMaxStackSize() {
+ return this.maxStack;
+ }
+
+ @Override
+ public void setMaxStackSize(int i) {
+ this.maxStack = i;
+ }
+ // CraftBukkit end
private NonNullList<ItemStack> items = NonNullList.withSize(27, ItemStack.EMPTY);
private final ContainerOpenersCounter openersCounter = new ContainerOpenersCounter() {
@Override

View File

@@ -0,0 +1,62 @@
--- a/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java
@@ -68,17 +_,44 @@
protected abstract Component getDefaultName();
public boolean canOpen(Player player) {
- return canUnlock(player, this.lockKey, this.getDisplayName());
+ return canUnlock(player, this.lockKey, this.getDisplayName(), this); // Paper - Add BlockLockCheckEvent
}
+ @Deprecated @io.papermc.paper.annotation.DoNotUse // Paper - Add BlockLockCheckEvent
public static boolean canUnlock(Player player, LockCode code, Component displayName) {
+ // Paper start - Add BlockLockCheckEvent
+ return canUnlock(player, code, displayName, null);
+ }
+ public static boolean canUnlock(Player player, LockCode code, Component displayName, @Nullable BlockEntity blockEntity) {
+ if (player instanceof net.minecraft.server.level.ServerPlayer serverPlayer && blockEntity != null && blockEntity.getLevel() != null && blockEntity.getLevel().getBlockEntity(blockEntity.getBlockPos()) == blockEntity) {
+ final org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(blockEntity.getLevel(), blockEntity.getBlockPos());
+ net.kyori.adventure.text.Component lockedMessage = net.kyori.adventure.text.Component.translatable("container.isLocked", io.papermc.paper.adventure.PaperAdventure.asAdventure(displayName));
+ net.kyori.adventure.sound.Sound lockedSound = net.kyori.adventure.sound.Sound.sound(org.bukkit.Sound.BLOCK_CHEST_LOCKED, net.kyori.adventure.sound.Sound.Source.BLOCK, 1.0F, 1.0F);
+ final io.papermc.paper.event.block.BlockLockCheckEvent event = new io.papermc.paper.event.block.BlockLockCheckEvent(block, serverPlayer.getBukkitEntity(), lockedMessage, lockedSound);
+ event.callEvent();
+ if (event.getResult() == org.bukkit.event.Event.Result.ALLOW) {
+ return true;
+ } else if (event.getResult() == org.bukkit.event.Event.Result.DENY || (!player.isSpectator() && !code.unlocksWith(event.isUsingCustomKeyItemStack() ? org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getKeyItem()) : player.getMainHandItem()))) {
+ if (event.getLockedMessage() != null) {
+ event.getPlayer().sendActionBar(event.getLockedMessage());
+ }
+ if (event.getLockedSound() != null) {
+ event.getPlayer().playSound(event.getLockedSound());
+ }
+ return false;
+ } else {
+ return true;
+ }
+ } else { // logic below is replaced by logic above
+ // Paper end - Add BlockLockCheckEvent
if (!player.isSpectator() && !code.unlocksWith(player.getMainHandItem())) {
- player.displayClientMessage(Component.translatable("container.isLocked", displayName), true);
+ player.displayClientMessage(Component.translatable("container.isLocked", displayName), true); // Paper - diff on change
player.playNotifySound(SoundEvents.CHEST_LOCKED, SoundSource.BLOCKS, 1.0F, 1.0F);
return false;
} else {
return true;
}
+ } // Paper - Add BlockLockCheckEvent
}
protected abstract NonNullList<ItemStack> getItems();
@@ -166,4 +_,12 @@
tag.remove("lock");
tag.remove("Items");
}
+
+ // CraftBukkit start
+ @Override
+ public org.bukkit.Location getLocation() {
+ if (this.level == null) return null;
+ return new org.bukkit.Location(this.level.getWorld(), this.worldPosition.getX(), this.worldPosition.getY(), this.worldPosition.getZ());
+ }
+ // CraftBukkit end
}

View File

@@ -0,0 +1,60 @@
--- a/net/minecraft/world/level/block/entity/BellBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/BellBlockEntity.java
@@ -60,6 +_,11 @@
if (blockEntity.ticks >= 50) {
blockEntity.shaking = false;
+ // Paper start - Fix bell block entity memory leak
+ if (!blockEntity.resonating) {
+ blockEntity.nearbyEntities.clear();
+ }
+ // Paper end - Fix bell block entity memory leak
blockEntity.ticks = 0;
}
@@ -73,6 +_,7 @@
blockEntity.resonationTicks++;
} else {
resonationEndAction.run(level, pos, blockEntity.nearbyEntities);
+ blockEntity.nearbyEntities.clear(); // Paper - Fix bell block entity memory leak
blockEntity.resonating = false;
}
}
@@ -113,6 +_,8 @@
}
}
}
+
+ this.nearbyEntities.removeIf(e -> !e.isAlive()); // Paper - Fix bell block entity memory leak
}
private static boolean areRaidersNearby(BlockPos pos, List<LivingEntity> raiders) {
@@ -129,7 +_,10 @@
}
private static void makeRaidersGlow(Level level, BlockPos pos, List<LivingEntity> raiders) {
- raiders.stream().filter(raider -> isRaiderWithinRange(pos, raider)).forEach(BellBlockEntity::glow);
+ // Paper start - call bell resonate event and bell reveal raider event
+ final List<org.bukkit.entity.LivingEntity> inRangeRaiders = raiders.stream().filter(raider -> isRaiderWithinRange(pos, raider)).map(e -> e.getBukkitEntity()).toList();
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBellResonateEvent(level, pos, inRangeRaiders).forEach(e -> glow(e, pos));
+ // Paper end - call bell resonate event and bell reveal raider event
}
private static void showBellParticles(Level level, BlockPos pos, List<LivingEntity> raiders) {
@@ -159,7 +_,16 @@
return raider.isAlive() && !raider.isRemoved() && pos.closerToCenterThan(raider.position(), 48.0) && raider.getType().is(EntityTypeTags.RAIDERS);
}
+ @io.papermc.paper.annotation.DoNotUse // Paper - Add BellRevealRaiderEvent
private static void glow(LivingEntity entity) {
+ // Paper start - Add BellRevealRaiderEvent
+ glow(entity, null);
+ }
+
+ private static void glow(LivingEntity entity, @javax.annotation.Nullable BlockPos pos) {
+ if (pos != null && !new io.papermc.paper.event.block.BellRevealRaiderEvent(org.bukkit.craftbukkit.block.CraftBlock.at(entity.level(), pos), (org.bukkit.entity.Raider) entity.getBukkitEntity()).callEvent())
+ return;
+ // Paper end - Add BellRevealRaiderEvent
entity.addEffect(new MobEffectInstance(MobEffects.GLOWING, 60));
}

View File

@@ -0,0 +1,39 @@
--- a/net/minecraft/world/level/block/entity/ChestBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/ChestBlockEntity.java
@@ -56,6 +_,36 @@
};
private final ChestLidController chestLidController = new ChestLidController();
+ // CraftBukkit start - add fields and methods
+ public java.util.List<org.bukkit.entity.HumanEntity> transaction = new java.util.ArrayList<>();
+ private int maxStack = MAX_STACK;
+
+ public java.util.List<net.minecraft.world.item.ItemStack> getContents() {
+ return this.items;
+ }
+
+ public void onOpen(org.bukkit.craftbukkit.entity.CraftHumanEntity who) {
+ this.transaction.add(who);
+ }
+
+ public void onClose(org.bukkit.craftbukkit.entity.CraftHumanEntity who) {
+ this.transaction.remove(who);
+ }
+
+ public java.util.List<org.bukkit.entity.HumanEntity> getViewers() {
+ return this.transaction;
+ }
+
+ @Override
+ public int getMaxStackSize() {
+ return this.maxStack;
+ }
+
+ public void setMaxStackSize(int size) {
+ this.maxStack = size;
+ }
+ // CraftBukkit end
+
protected ChestBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState blockState) {
super(type, pos, blockState);
}

View File

@@ -0,0 +1,72 @@
--- a/net/minecraft/world/level/block/entity/ChiseledBookShelfBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/ChiseledBookShelfBlockEntity.java
@@ -27,6 +_,42 @@
private final NonNullList<ItemStack> items = NonNullList.withSize(6, ItemStack.EMPTY);
private int lastInteractedSlot = -1;
+ // CraftBukkit start - add fields and methods
+ public java.util.List<org.bukkit.entity.HumanEntity> transaction = new java.util.ArrayList<>();
+ private int maxStack = 1;
+
+ @Override
+ public java.util.List<net.minecraft.world.item.ItemStack> getContents() {
+ return this.items;
+ }
+
+ @Override
+ public void onOpen(org.bukkit.craftbukkit.entity.CraftHumanEntity who) {
+ this.transaction.add(who);
+ }
+
+ @Override
+ public void onClose(org.bukkit.craftbukkit.entity.CraftHumanEntity who) {
+ this.transaction.remove(who);
+ }
+
+ @Override
+ public List<org.bukkit.entity.HumanEntity> getViewers() {
+ return this.transaction;
+ }
+
+ @Override
+ public void setMaxStackSize(int size) {
+ this.maxStack = size;
+ }
+
+ @Override
+ public org.bukkit.Location getLocation() {
+ if (this.level == null) return null;
+ return io.papermc.paper.util.MCUtil.toLocation(this.level, this.worldPosition);
+ }
+ // CraftBukkit end
+
public ChiseledBookShelfBlockEntity(BlockPos pos, BlockState state) {
super(BlockEntityType.CHISELED_BOOKSHELF, pos, state);
}
@@ -93,7 +_,7 @@
ItemStack itemStack = Objects.requireNonNullElse(this.items.get(slot), ItemStack.EMPTY);
this.items.set(slot, ItemStack.EMPTY);
if (!itemStack.isEmpty()) {
- this.updateState(slot);
+ if (this.level != null) this.updateState(slot); // CraftBukkit - SPIGOT-7381: check for null world
}
return itemStack;
@@ -108,7 +_,7 @@
public void setItem(int slot, ItemStack stack) {
if (stack.is(ItemTags.BOOKSHELF_BOOKS)) {
this.items.set(slot, stack);
- this.updateState(slot);
+ if (this.level != null) this.updateState(slot); // CraftBukkit - SPIGOT-7381: check for null world
} else if (stack.isEmpty()) {
this.removeItem(slot, 1);
}
@@ -124,7 +_,7 @@
@Override
public int getMaxStackSize() {
- return 1;
+ return this.maxStack; // CraftBukkit
}
@Override

View File

@@ -0,0 +1,25 @@
--- a/net/minecraft/world/level/block/entity/CommandBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/CommandBlockEntity.java
@@ -21,6 +_,13 @@
private boolean auto;
private boolean conditionMet;
private final BaseCommandBlock commandBlock = new BaseCommandBlock() {
+ // CraftBukkit start
+ @Override
+ public org.bukkit.command.CommandSender getBukkitSender(CommandSourceStack wrapper) {
+ return new org.bukkit.craftbukkit.command.CraftBlockCommandSender(wrapper, CommandBlockEntity.this);
+ }
+ // CraftBukkit end
+
@Override
public void setCommand(String command) {
super.setCommand(command);
@@ -51,7 +_,7 @@
Vec3.atCenterOf(CommandBlockEntity.this.worldPosition),
new Vec2(0.0F, direction.toYRot()),
this.getLevel(),
- 2,
+ this.getLevel().paperConfig().commandBlocks.permissionsLevel, // Paper - configurable command block perm level
this.getName().getString(),
this.getName(),
this.getLevel().getServer(),

View File

@@ -0,0 +1,303 @@
--- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
@@ -37,6 +_,37 @@
private long tickedGameTime;
private Direction facing;
+ // CraftBukkit start - add fields and methods
+ public List<org.bukkit.entity.HumanEntity> transaction = new java.util.ArrayList<>();
+ private int maxStack = MAX_STACK;
+
+ public List<ItemStack> getContents() {
+ return this.items;
+ }
+
+ public void onOpen(org.bukkit.craftbukkit.entity.CraftHumanEntity who) {
+ this.transaction.add(who);
+ }
+
+ public void onClose(org.bukkit.craftbukkit.entity.CraftHumanEntity who) {
+ this.transaction.remove(who);
+ }
+
+ public List<org.bukkit.entity.HumanEntity> getViewers() {
+ return this.transaction;
+ }
+
+ @Override
+ public int getMaxStackSize() {
+ return this.maxStack;
+ }
+
+ public void setMaxStackSize(int size) {
+ this.maxStack = size;
+ }
+ // CraftBukkit end
+
+
public HopperBlockEntity(BlockPos pos, BlockState blockState) {
super(BlockEntityType.HOPPER, pos, blockState);
this.facing = blockState.getValue(HopperBlock.FACING);
@@ -97,7 +_,14 @@
blockEntity.tickedGameTime = level.getGameTime();
if (!blockEntity.isOnCooldown()) {
blockEntity.setCooldown(0);
- tryMoveItems(level, pos, state, blockEntity, () -> suckInItems(level, blockEntity));
+ // Spigot start
+ boolean result = tryMoveItems(level, pos, state, blockEntity, () -> {
+ return suckInItems(level, blockEntity);
+ });
+ if (!result && blockEntity.level.spigotConfig.hopperCheck > 1) {
+ blockEntity.setCooldown(blockEntity.level.spigotConfig.hopperCheck);
+ }
+ // Spigot end
}
}
@@ -116,7 +_,7 @@
}
if (flag) {
- blockEntity.setCooldown(8);
+ blockEntity.setCooldown(level.spigotConfig.hopperTransfer); // Spigot
setChanged(level, pos, state);
return true;
}
@@ -149,14 +_,47 @@
ItemStack item = blockEntity.getItem(i);
if (!item.isEmpty()) {
int count = item.getCount();
- ItemStack itemStack = addItem(blockEntity, attachedContainer, blockEntity.removeItem(i, 1), opposite);
+ // CraftBukkit start - Call event when pushing items into other inventories
+ ItemStack original = item.copy();
+ org.bukkit.craftbukkit.inventory.CraftItemStack oitemstack = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(
+ blockEntity.removeItem(i, level.spigotConfig.hopperAmount)
+ ); // Spigot
+
+ org.bukkit.inventory.Inventory destinationInventory;
+ // Have to special case large chests as they work oddly
+ if (attachedContainer instanceof final CompoundContainer compoundContainer) {
+ destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest(compoundContainer);
+ } else if (attachedContainer.getOwner() != null) {
+ destinationInventory = attachedContainer.getOwner().getInventory();
+ } else {
+ destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventory(attachedContainer);
+ }
+
+ org.bukkit.event.inventory.InventoryMoveItemEvent event = new org.bukkit.event.inventory.InventoryMoveItemEvent(
+ blockEntity.getOwner().getInventory(),
+ oitemstack,
+ destinationInventory,
+ true
+ );
+ if (!event.callEvent()) {
+ blockEntity.setItem(i, original);
+ blockEntity.setCooldown(level.spigotConfig.hopperTransfer); // Delay hopper checks // Spigot
+ return false;
+ }
+ int origCount = event.getItem().getAmount(); // Spigot
+ ItemStack itemStack = HopperBlockEntity.addItem(blockEntity, attachedContainer, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem()), opposite);
+ // CraftBukkit end
+
if (itemStack.isEmpty()) {
attachedContainer.setChanged();
return true;
}
item.setCount(count);
- if (count == 1) {
+ // Spigot start
+ item.shrink(origCount - itemStack.getCount());
+ if (count <= level.spigotConfig.hopperAmount) {
+ // Spigot end
blockEntity.setItem(i, item);
}
}
@@ -219,7 +_,7 @@
Direction direction = Direction.DOWN;
for (int i : getSlots(sourceContainer, direction)) {
- if (tryTakeInItemFromSlot(hopper, sourceContainer, i, direction)) {
+ if (tryTakeInItemFromSlot(hopper, sourceContainer, i, direction, level)) { // Spigot
return true;
}
}
@@ -239,18 +_,54 @@
}
}
- private static boolean tryTakeInItemFromSlot(Hopper hopper, Container container, int slot, Direction direction) {
+ private static boolean tryTakeInItemFromSlot(Hopper hopper, Container container, int slot, Direction direction, Level level) { // Spigot
ItemStack item = container.getItem(slot);
if (!item.isEmpty() && canTakeItemFromContainer(hopper, container, item, slot, direction)) {
int count = item.getCount();
- ItemStack itemStack = addItem(container, hopper, container.removeItem(slot, 1), null);
+ // CraftBukkit start - Call event on collection of items from inventories into the hopper
+ ItemStack original = item.copy();
+ org.bukkit.craftbukkit.inventory.CraftItemStack oitemstack = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(
+ container.removeItem(slot, level.spigotConfig.hopperAmount) // Spigot
+ );
+
+ org.bukkit.inventory.Inventory sourceInventory;
+ // Have to special case large chests as they work oddly
+ if (container instanceof final CompoundContainer compoundContainer) {
+ sourceInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest(compoundContainer);
+ } else if (container.getOwner() != null) {
+ sourceInventory = container.getOwner().getInventory();
+ } else {
+ sourceInventory = new org.bukkit.craftbukkit.inventory.CraftInventory(container);
+ }
+
+ org.bukkit.event.inventory.InventoryMoveItemEvent event = new org.bukkit.event.inventory.InventoryMoveItemEvent(
+ sourceInventory,
+ oitemstack,
+ hopper.getOwner().getInventory(),
+ false
+ );
+
+ if (!event.callEvent()) {
+ container.setItem(slot, original);
+
+ if (hopper instanceof final HopperBlockEntity hopperBlockEntity) {
+ hopperBlockEntity.setCooldown(level.spigotConfig.hopperTransfer); // Spigot
+ }
+
+ return false;
+ }
+ int origCount = event.getItem().getAmount(); // Spigot
+ ItemStack itemStack = HopperBlockEntity.addItem(container, hopper, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem()), null);
+ // CraftBukkit end
+
if (itemStack.isEmpty()) {
container.setChanged();
return true;
}
item.setCount(count);
- if (count == 1) {
+ item.shrink(origCount - itemStack.getCount());
+ if (count <= level.spigotConfig.hopperAmount) {
container.setItem(slot, item);
}
}
@@ -260,12 +_,21 @@
public static boolean addItem(Container container, ItemEntity item) {
boolean flag = false;
+ // CraftBukkit start
+ org.bukkit.event.inventory.InventoryPickupItemEvent event = new org.bukkit.event.inventory.InventoryPickupItemEvent(
+ container.getOwner().getInventory(), (org.bukkit.entity.Item) item.getBukkitEntity()
+ );
+ item.level().getCraftServer().getPluginManager().callEvent(event);
+ if (event.isCancelled()) {
+ return false;
+ }
+ // CraftBukkit end
ItemStack itemStack = item.getItem().copy();
ItemStack itemStack1 = addItem(null, container, itemStack, null);
if (itemStack1.isEmpty()) {
flag = true;
item.setItem(ItemStack.EMPTY);
- item.discard();
+ item.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.PICKUP); // CraftBukkit - add Bukkit remove cause
} else {
item.setItem(itemStack1);
}
@@ -307,11 +_,18 @@
boolean flag = false;
boolean isEmpty = destination.isEmpty();
if (item.isEmpty()) {
+ // Spigot start - SPIGOT-6693, InventorySubcontainer#setItem
+ ItemStack leftover = ItemStack.EMPTY; // Paper - Make hoppers respect inventory max stack size
+ if (!stack.isEmpty() && stack.getCount() > destination.getMaxStackSize()) {
+ leftover = stack; // Paper - Make hoppers respect inventory max stack size
+ stack = stack.split(destination.getMaxStackSize());
+ }
+ // Spigot end
destination.setItem(slot, stack);
- stack = ItemStack.EMPTY;
+ stack = leftover; // Paper - Make hoppers respect inventory max stack size
flag = true;
} else if (canMergeItems(item, stack)) {
- int i = stack.getMaxStackSize() - item.getCount();
+ int i = Math.min(stack.getMaxStackSize(), destination.getMaxStackSize()) - item.getCount(); // Paper - Make hoppers respect inventory max stack size
int min = Math.min(stack.getCount(), i);
stack.shrink(min);
item.grow(min);
@@ -325,7 +_,7 @@
min = 1;
}
- hopperBlockEntity.setCooldown(8 - min);
+ hopperBlockEntity.setCooldown(hopperBlockEntity.level.spigotConfig.hopperTransfer - min); // Spigot
}
destination.setChanged();
@@ -335,14 +_,57 @@
return stack;
}
+ // CraftBukkit start
+ @Nullable
+ private static Container runHopperInventorySearchEvent(
+ Container container,
+ org.bukkit.craftbukkit.block.CraftBlock hopper,
+ org.bukkit.craftbukkit.block.CraftBlock searchLocation,
+ org.bukkit.event.inventory.HopperInventorySearchEvent.ContainerType containerType
+ ) {
+ org.bukkit.event.inventory.HopperInventorySearchEvent event = new org.bukkit.event.inventory.HopperInventorySearchEvent(
+ (container != null) ? new org.bukkit.craftbukkit.inventory.CraftInventory(container) : null,
+ containerType,
+ hopper,
+ searchLocation
+ );
+ event.callEvent();
+ return (event.getInventory() != null) ? ((org.bukkit.craftbukkit.inventory.CraftInventory) event.getInventory()).getInventory() : null;
+ }
+ // CraftBukkit end
+
@Nullable
private static Container getAttachedContainer(Level level, BlockPos pos, HopperBlockEntity blockEntity) {
- return getContainerAt(level, pos.relative(blockEntity.facing));
+ // CraftBukkit start
+ BlockPos searchPosition = pos.relative(blockEntity.facing);
+ Container inventory = getContainerAt(level, searchPosition);
+
+ org.bukkit.craftbukkit.block.CraftBlock hopper = org.bukkit.craftbukkit.block.CraftBlock.at(level, pos);
+ org.bukkit.craftbukkit.block.CraftBlock searchBlock = org.bukkit.craftbukkit.block.CraftBlock.at(level, searchPosition);
+ return HopperBlockEntity.runHopperInventorySearchEvent(
+ inventory,
+ hopper,
+ searchBlock,
+ org.bukkit.event.inventory.HopperInventorySearchEvent.ContainerType.DESTINATION
+ );
+ // CraftBukkit end
}
@Nullable
private static Container getSourceContainer(Level level, Hopper hopper, BlockPos pos, BlockState state) {
- return getContainerAt(level, pos, state, hopper.getLevelX(), hopper.getLevelY() + 1.0, hopper.getLevelZ());
+ // CraftBukkit start
+ final Container inventory = HopperBlockEntity.getContainerAt(level, pos, state, hopper.getLevelX(), hopper.getLevelY() + 1.0D, hopper.getLevelZ());
+
+ final BlockPos blockPosition = BlockPos.containing(hopper.getLevelX(), hopper.getLevelY(), hopper.getLevelZ());
+ org.bukkit.craftbukkit.block.CraftBlock hopperBlock = org.bukkit.craftbukkit.block.CraftBlock.at(level, blockPosition);
+ org.bukkit.craftbukkit.block.CraftBlock containerBlock = org.bukkit.craftbukkit.block.CraftBlock.at(level, blockPosition.above());
+ return HopperBlockEntity.runHopperInventorySearchEvent(
+ inventory,
+ hopperBlock,
+ containerBlock,
+ org.bukkit.event.inventory.HopperInventorySearchEvent.ContainerType.SOURCE
+ );
+ // CraftBukkit end
}
public static List<ItemEntity> getItemsAtAndAbove(Level level, Hopper hopper) {
@@ -367,6 +_,7 @@
@Nullable
private static Container getBlockContainer(Level level, BlockPos pos, BlockState state) {
+ if (!level.spigotConfig.hopperCanLoadChunks && !level.hasChunkAt(pos)) return null; // Spigot
Block block = state.getBlock();
if (block instanceof WorldlyContainerHolder) {
return ((WorldlyContainerHolder)block).getContainer(state, level, pos);

View File

@@ -0,0 +1,21 @@
--- a/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java
@@ -34,8 +_,18 @@
this.catalystListener = new SculkCatalystBlockEntity.CatalystListener(blockState, new BlockPositionSource(pos));
}
+ // Paper start - Fix NPE in SculkBloomEvent world access
+ @Override
+ public void setLevel(Level level) {
+ super.setLevel(level);
+ this.catalystListener.sculkSpreader.level = level;
+ }
+ // Paper end - Fix NPE in SculkBloomEvent world access
+
public static void serverTick(Level level, BlockPos pos, BlockState state, SculkCatalystBlockEntity sculkCatalyst) {
+ org.bukkit.craftbukkit.event.CraftEventFactory.sourceBlockOverride = sculkCatalyst.getBlockPos(); // CraftBukkit - SPIGOT-7068: Add source block override, not the most elegant way but better than passing down a BlockPosition up to five methods deep.
sculkCatalyst.catalystListener.getSculkSpreader().updateCursors(level, pos, level.getRandom(), true);
+ org.bukkit.craftbukkit.event.CraftEventFactory.sourceBlockOverride = null; // CraftBukkit
}
@Override

View File

@@ -0,0 +1,11 @@
--- a/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java
@@ -131,7 +_,7 @@
@Nullable
public Vec3 getPortalPosition(ServerLevel level, BlockPos pos) {
- if (this.exitPortal == null && level.dimension() == Level.END) {
+ if (this.exitPortal == null && level.getTypeKey() == net.minecraft.world.level.dimension.LevelStem.END) { // CraftBukkit - work in alternate worlds
BlockPos blockPos = findOrCreateValidTeleportPos(level, pos);
blockPos = blockPos.above(10);
LOGGER.debug("Creating portal at {}", blockPos);