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

@@ -1,52 +0,0 @@
--- a/net/minecraft/world/level/block/entity/BarrelBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/BarrelBlockEntity.java
@@ -20,9 +20,49 @@
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.BarrelBlock;
import net.minecraft.world.level.block.state.BlockState;
+// CraftBukkit start
+import java.util.ArrayList;
+import java.util.List;
+import org.bukkit.craftbukkit.entity.CraftHumanEntity;
+import org.bukkit.entity.HumanEntity;
+// CraftBukkit end
public class BarrelBlockEntity extends RandomizableContainerBlockEntity {
+ // CraftBukkit start - add fields and methods
+ public List<HumanEntity> transaction = new ArrayList<>();
+ private int maxStack = MAX_STACK;
+
+ @Override
+ public List<ItemStack> getContents() {
+ return this.items;
+ }
+
+ @Override
+ public void onOpen(CraftHumanEntity who) {
+ this.transaction.add(who);
+ }
+
+ @Override
+ public void onClose(CraftHumanEntity who) {
+ this.transaction.remove(who);
+ }
+
+ @Override
+ public List<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;
public final ContainerOpenersCounter openersCounter;

View File

@@ -1,62 +0,0 @@
--- a/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java
@@ -73,17 +73,44 @@
protected abstract Component getDefaultName();
public boolean canOpen(Player player) {
- return BaseContainerBlockEntity.canUnlock(player, this.lockKey, this.getDisplayName());
+ return BaseContainerBlockEntity.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 lock, Component containerName) {
+ // Paper start - Add BlockLockCheckEvent
+ return canUnlock(player, lock, containerName, null);
+ }
+ public static boolean canUnlock(Player player, LockCode lock, Component containerName, @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(containerName));
+ 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() && !lock.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() && !lock.unlocksWith(player.getMainHandItem())) {
- player.displayClientMessage(Component.translatable("container.isLocked", containerName), true);
+ player.displayClientMessage(Component.translatable("container.isLocked", containerName), 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();
@@ -178,4 +205,12 @@
nbt.remove("lock");
nbt.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

@@ -1,65 +0,0 @@
--- a/net/minecraft/world/level/block/entity/BellBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/BellBlockEntity.java
@@ -63,6 +63,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;
}
@@ -76,6 +81,7 @@
++blockEntity.resonationTicks;
} else {
bellEffect.run(world, pos, blockEntity.nearbyEntities);
+ blockEntity.nearbyEntities.clear(); // Paper - Fix bell block entity memory leak
blockEntity.resonating = false;
}
}
@@ -120,11 +126,12 @@
LivingEntity entityliving = (LivingEntity) iterator.next();
if (entityliving.isAlive() && !entityliving.isRemoved() && blockposition.closerToCenterThan(entityliving.position(), 32.0D)) {
- entityliving.getBrain().setMemory(MemoryModuleType.HEARD_BELL_TIME, (Object) this.level.getGameTime());
+ entityliving.getBrain().setMemory(MemoryModuleType.HEARD_BELL_TIME, this.level.getGameTime()); // CraftBukkit - decompile error
}
}
}
+ this.nearbyEntities.removeIf(e -> !e.isAlive()); // Paper - Fix bell block entity memory leak
}
private static boolean areRaidersNearby(BlockPos pos, List<LivingEntity> hearingEntities) {
@@ -144,9 +151,13 @@
}
private static void makeRaidersGlow(Level world, BlockPos pos, List<LivingEntity> hearingEntities) {
+ List<org.bukkit.entity.LivingEntity> entities = // CraftBukkit
hearingEntities.stream().filter((entityliving) -> {
return BellBlockEntity.isRaiderWithinRange(pos, entityliving);
- }).forEach(BellBlockEntity::glow);
+ }).map((entity) -> (org.bukkit.entity.LivingEntity) entity.getBukkitEntity()).collect(java.util.stream.Collectors.toCollection(java.util.ArrayList::new)); // CraftBukkit
+
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBellResonateEvent(world, pos, entities).forEach(entity -> glow(entity, pos)); // Paper - Add BellRevealRaiderEvent
+ // CraftBukkit end
}
private static void showBellParticles(Level world, BlockPos pos, List<LivingEntity> hearingEntities) {
@@ -178,6 +189,13 @@
}
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

@@ -1,51 +0,0 @@
--- a/net/minecraft/world/level/block/entity/ChestBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/ChestBlockEntity.java
@@ -23,6 +23,11 @@
import net.minecraft.world.level.block.ChestBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.ChestType;
+// CraftBukkit start
+import java.util.List;
+import org.bukkit.craftbukkit.entity.CraftHumanEntity;
+import org.bukkit.entity.HumanEntity;
+// CraftBukkit end
public class ChestBlockEntity extends RandomizableContainerBlockEntity implements LidBlockEntity {
@@ -31,6 +36,36 @@
public final ContainerOpenersCounter openersCounter;
private final ChestLidController chestLidController;
+ // CraftBukkit start - add fields and methods
+ public List<HumanEntity> transaction = new java.util.ArrayList<HumanEntity>();
+ private int maxStack = MAX_STACK;
+
+ public List<ItemStack> getContents() {
+ return this.items;
+ }
+
+ public void onOpen(CraftHumanEntity who) {
+ this.transaction.add(who);
+ }
+
+ public void onClose(CraftHumanEntity who) {
+ this.transaction.remove(who);
+ }
+
+ public List<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 state) {
super(type, pos, state);
this.items = NonNullList.withSize(27, ItemStack.EMPTY);

View File

@@ -1,85 +0,0 @@
--- a/net/minecraft/world/level/block/entity/ChiseledBookShelfBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/ChiseledBookShelfBlockEntity.java
@@ -23,13 +23,55 @@
import net.minecraft.world.level.gameevent.GameEvent;
import org.slf4j.Logger;
+// CraftBukkit start
+import java.util.List;
+import org.bukkit.Location;
+import org.bukkit.craftbukkit.entity.CraftHumanEntity;
+import org.bukkit.entity.HumanEntity;
+// CraftBukkit end
+
public class ChiseledBookShelfBlockEntity extends BlockEntity implements Container {
public static final int MAX_BOOKS_IN_STORAGE = 6;
private static final Logger LOGGER = LogUtils.getLogger();
private final NonNullList<ItemStack> items;
public int lastInteractedSlot;
+ // CraftBukkit start - add fields and methods
+ public List<HumanEntity> transaction = new java.util.ArrayList<>();
+ private int maxStack = 1;
+ @Override
+ public List<ItemStack> getContents() {
+ return this.items;
+ }
+
+ @Override
+ public void onOpen(CraftHumanEntity who) {
+ this.transaction.add(who);
+ }
+
+ @Override
+ public void onClose(CraftHumanEntity who) {
+ this.transaction.remove(who);
+ }
+
+ @Override
+ public List<HumanEntity> getViewers() {
+ return this.transaction;
+ }
+
+ @Override
+ public void setMaxStackSize(int size) {
+ this.maxStack = size;
+ }
+
+ @Override
+ public 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
+
public ChiseledBookShelfBlockEntity(BlockPos pos, BlockState state) {
super(BlockEntityType.CHISELED_BOOKSHELF, pos, state);
this.items = NonNullList.withSize(6, ItemStack.EMPTY);
@@ -100,7 +142,7 @@
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;
@@ -115,7 +157,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);
}
@@ -131,7 +173,7 @@
@Override
public int getMaxStackSize() {
- return 1;
+ return this.maxStack; // CraftBukkit
}
@Override

View File

@@ -1,26 +0,0 @@
--- a/net/minecraft/world/level/block/entity/CommandBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/CommandBlockEntity.java
@@ -24,7 +24,14 @@
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);
CommandBlockEntity.this.setChanged();
@@ -51,7 +58,7 @@
public CommandSourceStack createCommandSourceStack() {
Direction enumdirection = (Direction) CommandBlockEntity.this.getBlockState().getValue(CommandBlock.FACING);
- return new CommandSourceStack(this, Vec3.atCenterOf(CommandBlockEntity.this.worldPosition), new Vec2(0.0F, enumdirection.toYRot()), this.getLevel(), 2, this.getName().getString(), this.getName(), this.getLevel().getServer(), (Entity) null);
+ return new CommandSourceStack(this, Vec3.atCenterOf(CommandBlockEntity.this.worldPosition), new Vec2(0.0F, enumdirection.toYRot()), this.getLevel(), this.getLevel().paperConfig().commandBlocks.permissionsLevel, this.getName().getString(), this.getName(), this.getLevel().getServer(), (Entity) null); // Paper - configurable command block perm level
}
@Override

View File

@@ -1,322 +0,0 @@
--- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
@@ -11,6 +11,7 @@
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.tags.BlockTags;
+import net.minecraft.world.CompoundContainer;
import net.minecraft.world.Container;
import net.minecraft.world.ContainerHelper;
import net.minecraft.world.WorldlyContainer;
@@ -18,7 +19,6 @@
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntitySelector;
import net.minecraft.world.entity.item.ItemEntity;
-import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.HopperMenu;
@@ -29,6 +29,18 @@
import net.minecraft.world.level.block.HopperBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.AABB;
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.block.CraftBlock;
+import org.bukkit.craftbukkit.entity.CraftHumanEntity;
+import org.bukkit.craftbukkit.inventory.CraftInventory;
+import org.bukkit.craftbukkit.inventory.CraftItemStack;
+import org.bukkit.entity.HumanEntity;
+import org.bukkit.event.entity.EntityRemoveEvent;
+import org.bukkit.event.inventory.HopperInventorySearchEvent;
+import org.bukkit.event.inventory.InventoryMoveItemEvent;
+import org.bukkit.event.inventory.InventoryPickupItemEvent;
+import org.bukkit.inventory.Inventory;
+// CraftBukkit end
public class HopperBlockEntity extends RandomizableContainerBlockEntity implements Hopper {
@@ -40,6 +52,36 @@
private long tickedGameTime;
private Direction facing;
+ // CraftBukkit start - add fields and methods
+ public List<HumanEntity> transaction = new java.util.ArrayList<HumanEntity>();
+ private int maxStack = MAX_STACK;
+
+ public List<ItemStack> getContents() {
+ return this.items;
+ }
+
+ public void onOpen(CraftHumanEntity who) {
+ this.transaction.add(who);
+ }
+
+ public void onClose(CraftHumanEntity who) {
+ this.transaction.remove(who);
+ }
+
+ public List<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 state) {
super(BlockEntityType.HOPPER, pos, state);
this.items = NonNullList.withSize(5, ItemStack.EMPTY);
@@ -102,9 +144,14 @@
blockEntity.tickedGameTime = world.getGameTime();
if (!blockEntity.isOnCooldown()) {
blockEntity.setCooldown(0);
- HopperBlockEntity.tryMoveItems(world, pos, state, blockEntity, () -> {
+ // Spigot start
+ boolean result = HopperBlockEntity.tryMoveItems(world, pos, state, blockEntity, () -> {
return HopperBlockEntity.suckInItems(world, blockEntity);
});
+ if (!result && blockEntity.level.spigotConfig.hopperCheck > 1) {
+ blockEntity.setCooldown(blockEntity.level.spigotConfig.hopperCheck);
+ }
+ // Spigot end
}
}
@@ -125,7 +172,7 @@
}
if (flag) {
- blockEntity.setCooldown(8);
+ blockEntity.setCooldown(world.spigotConfig.hopperTransfer); // Spigot
setChanged(world, pos, state);
return true;
}
@@ -167,15 +214,41 @@
if (!itemstack.isEmpty()) {
int j = itemstack.getCount();
- ItemStack itemstack1 = HopperBlockEntity.addItem(blockEntity, iinventory, blockEntity.removeItem(i, 1), enumdirection);
+ // CraftBukkit start - Call event when pushing items into other inventories
+ ItemStack original = itemstack.copy();
+ CraftItemStack oitemstack = CraftItemStack.asCraftMirror(blockEntity.removeItem(i, world.spigotConfig.hopperAmount)); // Spigot
+ Inventory destinationInventory;
+ // Have to special case large chests as they work oddly
+ if (iinventory instanceof CompoundContainer) {
+ destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((CompoundContainer) iinventory);
+ } else if (iinventory.getOwner() != null) {
+ destinationInventory = iinventory.getOwner().getInventory();
+ } else {
+ destinationInventory = new CraftInventory(iinventory);
+ }
+
+ InventoryMoveItemEvent event = new InventoryMoveItemEvent(blockEntity.getOwner().getInventory(), oitemstack, destinationInventory, true);
+ world.getCraftServer().getPluginManager().callEvent(event);
+ if (event.isCancelled()) {
+ blockEntity.setItem(i, original);
+ blockEntity.setCooldown(world.spigotConfig.hopperTransfer); // Delay hopper checks // Spigot
+ return false;
+ }
+ int origCount = event.getItem().getAmount(); // Spigot
+ ItemStack itemstack1 = HopperBlockEntity.addItem(blockEntity, iinventory, CraftItemStack.asNMSCopy(event.getItem()), enumdirection);
+ // CraftBukkit end
+
if (itemstack1.isEmpty()) {
iinventory.setChanged();
return true;
}
itemstack.setCount(j);
- if (j == 1) {
+ // Spigot start
+ itemstack.shrink(origCount - itemstack1.getCount());
+ if (j <= world.spigotConfig.hopperAmount) {
+ // Spigot end
blockEntity.setItem(i, itemstack);
}
}
@@ -249,7 +322,7 @@
for (int j = 0; j < i; ++j) {
int k = aint[j];
- if (HopperBlockEntity.tryTakeInItemFromSlot(hopper, iinventory, k, enumdirection)) {
+ if (HopperBlockEntity.tryTakeInItemFromSlot(hopper, iinventory, k, enumdirection, world)) { // Spigot
return true;
}
}
@@ -274,21 +347,52 @@
}
}
- private static boolean tryTakeInItemFromSlot(Hopper hopper, Container inventory, int slot, Direction side) {
- ItemStack itemstack = inventory.getItem(slot);
+ private static boolean tryTakeInItemFromSlot(Hopper ihopper, Container iinventory, int i, Direction enumdirection, Level world) { // Spigot
+ ItemStack itemstack = iinventory.getItem(i);
- if (!itemstack.isEmpty() && HopperBlockEntity.canTakeItemFromContainer(hopper, inventory, itemstack, slot, side)) {
+ if (!itemstack.isEmpty() && HopperBlockEntity.canTakeItemFromContainer(ihopper, iinventory, itemstack, i, enumdirection)) {
int j = itemstack.getCount();
- ItemStack itemstack1 = HopperBlockEntity.addItem(inventory, hopper, inventory.removeItem(slot, 1), (Direction) null);
+ // CraftBukkit start - Call event on collection of items from inventories into the hopper
+ ItemStack original = itemstack.copy();
+ CraftItemStack oitemstack = CraftItemStack.asCraftMirror(iinventory.removeItem(i, world.spigotConfig.hopperAmount)); // Spigot
+ Inventory sourceInventory;
+ // Have to special case large chests as they work oddly
+ if (iinventory instanceof CompoundContainer) {
+ sourceInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((CompoundContainer) iinventory);
+ } else if (iinventory.getOwner() != null) {
+ sourceInventory = iinventory.getOwner().getInventory();
+ } else {
+ sourceInventory = new CraftInventory(iinventory);
+ }
+
+ InventoryMoveItemEvent event = new InventoryMoveItemEvent(sourceInventory, oitemstack, ihopper.getOwner().getInventory(), false);
+
+ Bukkit.getServer().getPluginManager().callEvent(event);
+ if (event.isCancelled()) {
+ iinventory.setItem(i, original);
+
+ if (ihopper instanceof HopperBlockEntity) {
+ ((HopperBlockEntity) ihopper).setCooldown(world.spigotConfig.hopperTransfer); // Spigot
+ }
+
+ return false;
+ }
+ int origCount = event.getItem().getAmount(); // Spigot
+ ItemStack itemstack1 = HopperBlockEntity.addItem(iinventory, ihopper, CraftItemStack.asNMSCopy(event.getItem()), null);
+ // CraftBukkit end
+
if (itemstack1.isEmpty()) {
- inventory.setChanged();
+ iinventory.setChanged();
return true;
}
itemstack.setCount(j);
- if (j == 1) {
- inventory.setItem(slot, itemstack);
+ // Spigot start
+ itemstack.shrink(origCount - itemstack1.getCount());
+ if (j <= world.spigotConfig.hopperAmount) {
+ // Spigot end
+ iinventory.setItem(i, itemstack);
}
}
@@ -297,13 +401,20 @@
public static boolean addItem(Container inventory, ItemEntity itemEntity) {
boolean flag = false;
+ // CraftBukkit start
+ InventoryPickupItemEvent event = new InventoryPickupItemEvent(inventory.getOwner().getInventory(), (org.bukkit.entity.Item) itemEntity.getBukkitEntity());
+ itemEntity.level().getCraftServer().getPluginManager().callEvent(event);
+ if (event.isCancelled()) {
+ return false;
+ }
+ // CraftBukkit end
ItemStack itemstack = itemEntity.getItem().copy();
ItemStack itemstack1 = HopperBlockEntity.addItem((Container) null, inventory, itemstack, (Direction) null);
if (itemstack1.isEmpty()) {
flag = true;
itemEntity.setItem(ItemStack.EMPTY);
- itemEntity.discard();
+ itemEntity.discard(EntityRemoveEvent.Cause.PICKUP); // CraftBukkit - add Bukkit remove cause
} else {
itemEntity.setItem(itemstack1);
}
@@ -383,11 +494,18 @@
boolean flag1 = to.isEmpty();
if (itemstack1.isEmpty()) {
+ // Spigot start - SPIGOT-6693, InventorySubcontainer#setItem
+ ItemStack leftover = ItemStack.EMPTY; // Paper - Make hoppers respect inventory max stack size
+ if (!stack.isEmpty() && stack.getCount() > to.getMaxStackSize()) {
+ leftover = stack; // Paper - Make hoppers respect inventory max stack size
+ stack = stack.split(to.getMaxStackSize());
+ }
+ // Spigot end
to.setItem(slot, stack);
- stack = ItemStack.EMPTY;
+ stack = leftover; // Paper - Make hoppers respect inventory max stack size
flag = true;
} else if (HopperBlockEntity.canMergeItems(itemstack1, stack)) {
- int j = stack.getMaxStackSize() - itemstack1.getCount();
+ int j = Math.min(stack.getMaxStackSize(), to.getMaxStackSize()) - itemstack1.getCount(); // Paper - Make hoppers respect inventory max stack size
int k = Math.min(stack.getCount(), j);
stack.shrink(k);
@@ -410,7 +528,7 @@
}
}
- tileentityhopper.setCooldown(8 - b0);
+ tileentityhopper.setCooldown(tileentityhopper.level.spigotConfig.hopperTransfer - b0); // Spigot
}
}
@@ -421,14 +539,38 @@
return stack;
}
+ // CraftBukkit start
@Nullable
+ private static Container runHopperInventorySearchEvent(Container inventory, CraftBlock hopper, CraftBlock searchLocation, HopperInventorySearchEvent.ContainerType containerType) {
+ HopperInventorySearchEvent event = new HopperInventorySearchEvent((inventory != null) ? new CraftInventory(inventory) : null, containerType, hopper, searchLocation);
+ Bukkit.getServer().getPluginManager().callEvent(event);
+ CraftInventory craftInventory = (CraftInventory) event.getInventory();
+ return (craftInventory != null) ? craftInventory.getInventory() : null;
+ }
+ // CraftBukkit end
+
+ @Nullable
private static Container getAttachedContainer(Level world, BlockPos pos, HopperBlockEntity blockEntity) {
- return HopperBlockEntity.getContainerAt(world, pos.relative(blockEntity.facing));
+ // CraftBukkit start
+ BlockPos searchPosition = pos.relative(blockEntity.facing);
+ Container inventory = HopperBlockEntity.getContainerAt(world, searchPosition);
+
+ CraftBlock hopper = CraftBlock.at(world, pos);
+ CraftBlock searchBlock = CraftBlock.at(world, searchPosition);
+ return HopperBlockEntity.runHopperInventorySearchEvent(inventory, hopper, searchBlock, HopperInventorySearchEvent.ContainerType.DESTINATION);
+ // CraftBukkit end
}
@Nullable
private static Container getSourceContainer(Level world, Hopper hopper, BlockPos pos, BlockState state) {
- return HopperBlockEntity.getContainerAt(world, pos, state, hopper.getLevelX(), hopper.getLevelY() + 1.0D, hopper.getLevelZ());
+ // CraftBukkit start
+ Container inventory = HopperBlockEntity.getContainerAt(world, pos, state, hopper.getLevelX(), hopper.getLevelY() + 1.0D, hopper.getLevelZ());
+
+ BlockPos blockPosition = BlockPos.containing(hopper.getLevelX(), hopper.getLevelY(), hopper.getLevelZ());
+ CraftBlock hopper1 = CraftBlock.at(world, blockPosition);
+ CraftBlock container = CraftBlock.at(world, blockPosition.above());
+ return HopperBlockEntity.runHopperInventorySearchEvent(inventory, hopper1, container, HopperInventorySearchEvent.ContainerType.SOURCE);
+ // CraftBukkit end
}
public static List<ItemEntity> getItemsAtAndAbove(Level world, Hopper hopper) {
@@ -455,6 +597,7 @@
@Nullable
private static Container getBlockContainer(Level world, BlockPos pos, BlockState state) {
+ if ( !world.spigotConfig.hopperCanLoadChunks && !world.hasChunkAt( pos ) ) return null; // Spigot
Block block = state.getBlock();
if (block instanceof WorldlyContainerHolder) {
@@ -543,7 +686,7 @@
}
@Override
- protected AbstractContainerMenu createMenu(int syncId, Inventory playerInventory) {
+ protected AbstractContainerMenu createMenu(int syncId, net.minecraft.world.entity.player.Inventory playerInventory) {
return new HopperMenu(syncId, playerInventory, this);
}
}

View File

@@ -1,29 +0,0 @@
--- a/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java
@@ -37,8 +37,18 @@
this.catalystListener = new SculkCatalystBlockEntity.CatalystListener(state, 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 world, BlockPos pos, BlockState state, SculkCatalystBlockEntity blockEntity) {
+ org.bukkit.craftbukkit.event.CraftEventFactory.sourceBlockOverride = blockEntity.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.
blockEntity.catalystListener.getSculkSpreader().updateCursors(world, pos, world.getRandom(), true);
+ org.bukkit.craftbukkit.event.CraftEventFactory.sourceBlockOverride = null; // CraftBukkit
}
@Override
@@ -69,6 +79,7 @@
this.blockState = state;
this.positionSource = positionSource;
this.sculkSpreader = SculkSpreader.createLevelSpreader();
+ // this.sculkSpreader.level = this.level; // CraftBukkit // Paper - Fix NPE in SculkBloomEvent world access
}
@Override

View File

@@ -1,19 +0,0 @@
--- a/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java
@@ -21,6 +21,7 @@
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.LevelChunk;
+import net.minecraft.world.level.dimension.LevelStem;
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.level.levelgen.feature.configurations.EndGatewayConfiguration;
@@ -143,7 +144,7 @@
public Vec3 getPortalPosition(ServerLevel world, BlockPos pos) {
BlockPos blockposition1;
- if (this.exitPortal == null && world.dimension() == Level.END) {
+ if (this.exitPortal == null && world.getTypeKey() == LevelStem.END) { // CraftBukkit - work in alternate worlds
blockposition1 = TheEndGatewayBlockEntity.findOrCreateValidTeleportPos(world, pos);
blockposition1 = blockposition1.above(10);
TheEndGatewayBlockEntity.LOGGER.debug("Creating portal at {}", blockposition1);