mirror of
https://github.com/BX-Team/DivineMC.git
synced 2025-12-21 15:59:23 +00:00
Upstream has released updates that appear to apply and compile correctly Purpur Changes: PurpurMC/Purpur@4a3b139f Updated Upstream (Paper)
683 lines
37 KiB
Diff
683 lines
37 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
|
|
Date: Sat, 1 Feb 2025 00:55:34 +0300
|
|
Subject: [PATCH] Optimize hoppers
|
|
|
|
|
|
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
|
index 3002ed51a579e81c3266da79a5dd38bac0b4a39c..9fdd4bbbe0e4c75880e9f24741fea7c60c57d09a 100644
|
|
--- a/net/minecraft/server/MinecraftServer.java
|
|
+++ b/net/minecraft/server/MinecraftServer.java
|
|
@@ -1789,7 +1789,6 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
|
serverLevel.hasPhysicsEvent = org.bukkit.event.block.BlockPhysicsEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - BlockPhysicsEvent
|
|
serverLevel.hasEntityMoveEvent = io.papermc.paper.event.entity.EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - Add EntityMoveEvent
|
|
serverLevel.updateLagCompensationTick(); // Paper - lag compensation
|
|
- net.minecraft.world.level.block.entity.HopperBlockEntity.skipHopperEvents = serverLevel.paperConfig().hopper.disableMoveEvent || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper - Perf: Optimize Hoppers
|
|
serverLevel.hasRidableMoveEvent = org.purpurmc.purpur.event.entity.RidableMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Purpur - Ridables
|
|
profilerFiller.push(() -> serverLevel + " " + serverLevel.dimension().location());
|
|
|
|
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
|
index a3f363d0c86142e03edc7fc6e2ff6ed81de8ed65..0de0570397a6c6de43b1143b0d722af7a6093c8e 100644
|
|
--- a/net/minecraft/server/level/ServerLevel.java
|
|
+++ b/net/minecraft/server/level/ServerLevel.java
|
|
@@ -195,7 +195,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
|
private final LevelTicks<Fluid> fluidTicks = new LevelTicks<>(this::isPositionTickingWithEntitiesLoaded);
|
|
private final PathTypeCache pathTypesByPosCache = new PathTypeCache();
|
|
final Set<Mob> navigatingMobs = new ObjectOpenHashSet<>();
|
|
- volatile boolean isUpdatingNavigations;
|
|
+ final java.util.concurrent.atomic.AtomicBoolean isUpdatingNavigations = new java.util.concurrent.atomic.AtomicBoolean(false); // DivineMC - Optimize Hoppers
|
|
protected final Raids raids;
|
|
private final ObjectLinkedOpenHashSet<BlockEventData> blockEvents = new ObjectLinkedOpenHashSet<>();
|
|
private final List<BlockEventData> blockEventsToReschedule = new ArrayList<>(64);
|
|
@@ -1770,7 +1770,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
|
|
|
@Override
|
|
public void sendBlockUpdated(BlockPos pos, BlockState oldState, BlockState newState, int flags) {
|
|
- if (this.isUpdatingNavigations) {
|
|
+ if (this.isUpdatingNavigations.get() && false) { // DivineMC
|
|
String string = "recursive call to sendBlockUpdated";
|
|
Util.logAndPauseIfInIde("recursive call to sendBlockUpdated", new IllegalStateException("recursive call to sendBlockUpdated"));
|
|
}
|
|
@@ -1801,13 +1801,13 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
|
// Paper end - catch CME see below why
|
|
|
|
try {
|
|
- this.isUpdatingNavigations = true;
|
|
+ this.isUpdatingNavigations.set(true); // DivineMC
|
|
|
|
for (PathNavigation pathNavigation : list) {
|
|
pathNavigation.recomputePath();
|
|
}
|
|
} finally {
|
|
- this.isUpdatingNavigations = false;
|
|
+ this.isUpdatingNavigations.set(false); // DivineMC
|
|
}
|
|
}
|
|
} // Paper - option to disable pathfinding updates
|
|
@@ -2699,7 +2699,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
|
}
|
|
|
|
if (entity instanceof Mob mob) {
|
|
- if (false && ServerLevel.this.isUpdatingNavigations) { // Paper - Remove unnecessary onTrackingStart during navigation warning
|
|
+ if (false && ServerLevel.this.isUpdatingNavigations.get()) { // Paper - Remove unnecessary onTrackingStart during navigation warning // DivineMC
|
|
String string = "onTrackingStart called during navigation iteration";
|
|
Util.logAndPauseIfInIde(
|
|
"onTrackingStart called during navigation iteration", new IllegalStateException("onTrackingStart called during navigation iteration")
|
|
@@ -2769,7 +2769,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
|
}
|
|
|
|
if (entity instanceof Mob mob) {
|
|
- if (false && ServerLevel.this.isUpdatingNavigations) { // Paper - Remove unnecessary onTrackingStart during navigation warning
|
|
+ if (false && ServerLevel.this.isUpdatingNavigations.get()) { // Paper - Remove unnecessary onTrackingStart during navigation warning // DivineMC
|
|
String string = "onTrackingStart called during navigation iteration";
|
|
Util.logAndPauseIfInIde(
|
|
"onTrackingStart called during navigation iteration", new IllegalStateException("onTrackingStart called during navigation iteration")
|
|
diff --git a/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
|
index 5cd1326ad5d046c88b2b3449d610a78fa880b4cd..a0ee6ad6e7a6791605191d20d742e16cc9857a60 100644
|
|
--- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
|
+++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
|
@@ -139,56 +139,18 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
|
}
|
|
}
|
|
|
|
- // Paper start - Perf: Optimize Hoppers
|
|
- private static final int HOPPER_EMPTY = 0;
|
|
- private static final int HOPPER_HAS_ITEMS = 1;
|
|
- private static final int HOPPER_IS_FULL = 2;
|
|
-
|
|
- private static int getFullState(final HopperBlockEntity hopper) {
|
|
- hopper.unpackLootTable(null);
|
|
-
|
|
- final List<ItemStack> hopperItems = hopper.items;
|
|
-
|
|
- boolean empty = true;
|
|
- boolean full = true;
|
|
-
|
|
- for (int i = 0, len = hopperItems.size(); i < len; ++i) {
|
|
- final ItemStack stack = hopperItems.get(i);
|
|
- if (stack.isEmpty()) {
|
|
- full = false;
|
|
- continue;
|
|
- }
|
|
-
|
|
- if (!full) {
|
|
- // can't be full
|
|
- return HOPPER_HAS_ITEMS;
|
|
- }
|
|
-
|
|
- empty = false;
|
|
-
|
|
- if (stack.getCount() != stack.getMaxStackSize()) {
|
|
- // can't be full or empty
|
|
- return HOPPER_HAS_ITEMS;
|
|
- }
|
|
- }
|
|
-
|
|
- return empty ? HOPPER_EMPTY : (full ? HOPPER_IS_FULL : HOPPER_HAS_ITEMS);
|
|
- }
|
|
- // Paper end - Perf: Optimize Hoppers
|
|
-
|
|
private static boolean tryMoveItems(Level level, BlockPos pos, BlockState state, HopperBlockEntity blockEntity, BooleanSupplier validator) {
|
|
if (level.isClientSide) {
|
|
return false;
|
|
} else {
|
|
if (!blockEntity.isOnCooldown() && state.getValue(HopperBlock.ENABLED)) {
|
|
boolean flag = false;
|
|
- final int fullState = getFullState(blockEntity); // Paper - Perf: Optimize Hoppers
|
|
- if (fullState != HOPPER_EMPTY) { // Paper - Perf: Optimize Hoppers
|
|
+ if (!blockEntity.isEmpty()) { // DivineMC - Optimize hoppers
|
|
flag = ejectItems(level, pos, blockEntity);
|
|
}
|
|
|
|
- if (fullState != HOPPER_IS_FULL || flag) { // Paper - Perf: Optimize Hoppers
|
|
- flag |= validator.getAsBoolean(); // Paper - note: this is not a validator, it's what adds/sucks in items
|
|
+ if (!blockEntity.inventoryFull()) { // DivineMC - Optimize hoppers
|
|
+ flag |= validator.getAsBoolean(); // DivineMC - Optimize hoppers
|
|
}
|
|
|
|
if (flag) {
|
|
@@ -212,206 +174,6 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
|
return true;
|
|
}
|
|
|
|
- // Paper start - Perf: Optimize Hoppers
|
|
- public static boolean skipHopperEvents;
|
|
- private static boolean skipPullModeEventFire;
|
|
- private static boolean skipPushModeEventFire;
|
|
-
|
|
- private static boolean hopperPush(final Level level, final Container destination, final Direction direction, final HopperBlockEntity hopper) {
|
|
- skipPushModeEventFire = skipHopperEvents;
|
|
- boolean foundItem = false;
|
|
- for (int i = 0; i < hopper.getContainerSize(); ++i) {
|
|
- final ItemStack item = hopper.getItem(i);
|
|
- if (!item.isEmpty()) {
|
|
- foundItem = true;
|
|
- ItemStack origItemStack = item;
|
|
- ItemStack movedItem = origItemStack;
|
|
-
|
|
- final int originalItemCount = origItemStack.getCount();
|
|
- final int movedItemCount = Math.min(level.spigotConfig.hopperAmount, originalItemCount);
|
|
- origItemStack.setCount(movedItemCount);
|
|
-
|
|
- // We only need to fire the event once to give protection plugins a chance to cancel this event
|
|
- // Because nothing uses getItem, every event call should end up the same result.
|
|
- if (!skipPushModeEventFire) {
|
|
- movedItem = callPushMoveEvent(destination, movedItem, hopper);
|
|
- if (movedItem == null) { // cancelled
|
|
- origItemStack.setCount(originalItemCount);
|
|
- return false;
|
|
- }
|
|
- }
|
|
-
|
|
- final ItemStack remainingItem = addItem(hopper, destination, movedItem, direction);
|
|
- final int remainingItemCount = remainingItem.getCount();
|
|
- if (remainingItemCount != movedItemCount) {
|
|
- origItemStack = origItemStack.copy(true);
|
|
- origItemStack.setCount(originalItemCount);
|
|
- if (!origItemStack.isEmpty()) {
|
|
- origItemStack.setCount(originalItemCount - movedItemCount + remainingItemCount);
|
|
- }
|
|
- hopper.setItem(i, origItemStack);
|
|
- destination.setChanged();
|
|
- return true;
|
|
- }
|
|
- origItemStack.setCount(originalItemCount);
|
|
- }
|
|
- }
|
|
- if (foundItem && level.paperConfig().hopper.cooldownWhenFull) { // Inventory was full - cooldown
|
|
- hopper.setCooldown(level.spigotConfig.hopperTransfer);
|
|
- }
|
|
- return false;
|
|
- }
|
|
-
|
|
- private static boolean hopperPull(final Level level, final Hopper hopper, final Container container, ItemStack origItemStack, final int i) {
|
|
- ItemStack movedItem = origItemStack;
|
|
- final int originalItemCount = origItemStack.getCount();
|
|
- final int movedItemCount = Math.min(level.spigotConfig.hopperAmount, originalItemCount);
|
|
- container.setChanged(); // original logic always marks source inv as changed even if no move happens.
|
|
- movedItem.setCount(movedItemCount);
|
|
-
|
|
- if (!skipPullModeEventFire) {
|
|
- movedItem = callPullMoveEvent(hopper, container, movedItem);
|
|
- if (movedItem == null) { // cancelled
|
|
- origItemStack.setCount(originalItemCount);
|
|
- // Drastically improve performance by returning true.
|
|
- // No plugin could have relied on the behavior of false as the other call
|
|
- // site for IMIE did not exhibit the same behavior
|
|
- return true;
|
|
- }
|
|
- }
|
|
-
|
|
- final ItemStack remainingItem = addItem(container, hopper, movedItem, null);
|
|
- final int remainingItemCount = remainingItem.getCount();
|
|
- if (remainingItemCount != movedItemCount) {
|
|
- origItemStack = origItemStack.copy(true);
|
|
- origItemStack.setCount(originalItemCount);
|
|
- if (!origItemStack.isEmpty()) {
|
|
- origItemStack.setCount(originalItemCount - movedItemCount + remainingItemCount);
|
|
- }
|
|
-
|
|
- ignoreBlockEntityUpdates = true;
|
|
- container.setItem(i, origItemStack);
|
|
- ignoreBlockEntityUpdates = false;
|
|
- container.setChanged();
|
|
- return true;
|
|
- }
|
|
- origItemStack.setCount(originalItemCount);
|
|
-
|
|
- if (level.paperConfig().hopper.cooldownWhenFull) {
|
|
- applyCooldown(hopper);
|
|
- }
|
|
-
|
|
- return false;
|
|
- }
|
|
-
|
|
- @Nullable
|
|
- private static ItemStack callPushMoveEvent(Container destination, ItemStack itemStack, HopperBlockEntity hopper) {
|
|
- final org.bukkit.inventory.Inventory destinationInventory = getInventory(destination);
|
|
- final io.papermc.paper.event.inventory.PaperInventoryMoveItemEvent event = new io.papermc.paper.event.inventory.PaperInventoryMoveItemEvent(
|
|
- hopper.getOwner(false).getInventory(),
|
|
- org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack),
|
|
- destinationInventory,
|
|
- true
|
|
- );
|
|
- final boolean result = event.callEvent();
|
|
- if (!event.calledGetItem && !event.calledSetItem) {
|
|
- skipPushModeEventFire = true;
|
|
- }
|
|
- if (!result) {
|
|
- applyCooldown(hopper);
|
|
- return null;
|
|
- }
|
|
-
|
|
- if (event.calledSetItem) {
|
|
- return org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
|
|
- } else {
|
|
- return itemStack;
|
|
- }
|
|
- }
|
|
-
|
|
- @Nullable
|
|
- private static ItemStack callPullMoveEvent(final Hopper hopper, final Container container, final ItemStack itemstack) {
|
|
- final org.bukkit.inventory.Inventory sourceInventory = getInventory(container);
|
|
- final org.bukkit.inventory.Inventory destination = getInventory(hopper);
|
|
-
|
|
- // Mirror is safe as no plugins ever use this item
|
|
- final io.papermc.paper.event.inventory.PaperInventoryMoveItemEvent event = new io.papermc.paper.event.inventory.PaperInventoryMoveItemEvent(sourceInventory, org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), destination, false);
|
|
- final boolean result = event.callEvent();
|
|
- if (!event.calledGetItem && !event.calledSetItem) {
|
|
- skipPullModeEventFire = true;
|
|
- }
|
|
- if (!result) {
|
|
- applyCooldown(hopper);
|
|
- return null;
|
|
- }
|
|
-
|
|
- if (event.calledSetItem) {
|
|
- return org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
|
|
- } else {
|
|
- return itemstack;
|
|
- }
|
|
- }
|
|
-
|
|
- private static org.bukkit.inventory.Inventory getInventory(final Container container) {
|
|
- final org.bukkit.inventory.Inventory sourceInventory;
|
|
- if (container instanceof net.minecraft.world.CompoundContainer compoundContainer) {
|
|
- // Have to special-case large chests as they work oddly
|
|
- sourceInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest(compoundContainer);
|
|
- } else if (container instanceof BlockEntity blockEntity) {
|
|
- sourceInventory = blockEntity.getOwner(false).getInventory();
|
|
- } else if (container.getOwner() != null) {
|
|
- sourceInventory = container.getOwner().getInventory();
|
|
- } else {
|
|
- sourceInventory = new org.bukkit.craftbukkit.inventory.CraftInventory(container);
|
|
- }
|
|
- return sourceInventory;
|
|
- }
|
|
-
|
|
- private static void applyCooldown(final Hopper hopper) {
|
|
- if (hopper instanceof HopperBlockEntity blockEntity && blockEntity.getLevel() != null) {
|
|
- blockEntity.setCooldown(blockEntity.getLevel().spigotConfig.hopperTransfer);
|
|
- }
|
|
- }
|
|
-
|
|
- private static boolean allMatch(Container container, Direction direction, java.util.function.BiPredicate<ItemStack, Integer> test) {
|
|
- if (container instanceof WorldlyContainer) {
|
|
- for (int slot : ((WorldlyContainer) container).getSlotsForFace(direction)) {
|
|
- if (!test.test(container.getItem(slot), slot)) {
|
|
- return false;
|
|
- }
|
|
- }
|
|
- } else {
|
|
- int size = container.getContainerSize();
|
|
- for (int slot = 0; slot < size; slot++) {
|
|
- if (!test.test(container.getItem(slot), slot)) {
|
|
- return false;
|
|
- }
|
|
- }
|
|
- }
|
|
- return true;
|
|
- }
|
|
-
|
|
- private static boolean anyMatch(Container container, Direction direction, java.util.function.BiPredicate<ItemStack, Integer> test) {
|
|
- if (container instanceof WorldlyContainer) {
|
|
- for (int slot : ((WorldlyContainer) container).getSlotsForFace(direction)) {
|
|
- if (test.test(container.getItem(slot), slot)) {
|
|
- return true;
|
|
- }
|
|
- }
|
|
- } else {
|
|
- int size = container.getContainerSize();
|
|
- for (int slot = 0; slot < size; slot++) {
|
|
- if (test.test(container.getItem(slot), slot)) {
|
|
- return true;
|
|
- }
|
|
- }
|
|
- }
|
|
- return true;
|
|
- }
|
|
- private static final java.util.function.BiPredicate<ItemStack, Integer> STACK_SIZE_TEST = (itemStack, i) -> itemStack.getCount() >= itemStack.getMaxStackSize();
|
|
- private static final java.util.function.BiPredicate<ItemStack, Integer> IS_EMPTY_TEST = (itemStack, i) -> itemStack.isEmpty();
|
|
- // Paper end - Perf: Optimize Hoppers
|
|
-
|
|
private static boolean ejectItems(Level level, BlockPos pos, HopperBlockEntity blockEntity) {
|
|
Container attachedContainer = getAttachedContainer(level, pos, blockEntity);
|
|
if (attachedContainer == null) {
|
|
@@ -421,60 +183,59 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
|
if (isFullContainer(attachedContainer, opposite)) {
|
|
return false;
|
|
} else {
|
|
- // Paper start - Perf: Optimize Hoppers
|
|
- return hopperPush(level, attachedContainer, opposite, blockEntity);
|
|
- //for (int i = 0; i < blockEntity.getContainerSize(); i++) {
|
|
- // ItemStack item = blockEntity.getItem(i);
|
|
- // if (!item.isEmpty()) {
|
|
- // int count = item.getCount();
|
|
- // // 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 net.minecraft.world.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);
|
|
- // // Spigot start
|
|
- // item.shrink(origCount - itemStack.getCount());
|
|
- // if (count <= level.spigotConfig.hopperAmount) {
|
|
- // // Spigot end
|
|
- // blockEntity.setItem(i, item);
|
|
- // }
|
|
- // }
|
|
- //}
|
|
-
|
|
- //return false;
|
|
- // Paper end - Perf: Optimize Hoppers
|
|
+ // DivineMC start - Optimize hoppers
|
|
+ for (int i = 0; i < blockEntity.getContainerSize(); i++) {
|
|
+ ItemStack item = blockEntity.getItem(i);
|
|
+ if (!item.isEmpty()) {
|
|
+ int count = item.getCount();
|
|
+ // 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 net.minecraft.world.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);
|
|
+ // Spigot start
|
|
+ item.shrink(origCount - itemStack.getCount());
|
|
+ if (count <= level.spigotConfig.hopperAmount) {
|
|
+ // Spigot end
|
|
+ blockEntity.setItem(i, item);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return false;
|
|
+ // DivineMC end - Optimize hoppers
|
|
}
|
|
}
|
|
}
|
|
@@ -529,7 +290,6 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
|
Container sourceContainer = getSourceContainer(level, hopper, blockPos, blockState);
|
|
if (sourceContainer != null) {
|
|
Direction direction = Direction.DOWN;
|
|
- skipPullModeEventFire = skipHopperEvents; // Paper - Perf: Optimize Hoppers
|
|
|
|
for (int i : getSlots(sourceContainer, direction)) {
|
|
if (tryTakeInItemFromSlot(hopper, sourceContainer, i, direction, level)) { // Spigot
|
|
@@ -555,59 +315,58 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
|
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)) {
|
|
- // Paper start - Perf: Optimize Hoppers
|
|
- return hopperPull(level, hopper, container, item, slot);
|
|
- //int count = item.getCount();
|
|
- //// 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 net.minecraft.world.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);
|
|
- //// Spigot start
|
|
- //item.shrink(origCount - itemStack.getCount());
|
|
- //if (count <= level.spigotConfig.hopperAmount) {
|
|
- // // Spigot end
|
|
- // container.setItem(slot, item);
|
|
- //}
|
|
- // Paper end - Perf: Optimize Hoppers
|
|
+ // DivineMC start - Optimize hoppers
|
|
+ int count = item.getCount();
|
|
+ // 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 net.minecraft.world.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);
|
|
+ // Spigot start
|
|
+ item.shrink(origCount - itemStack.getCount());
|
|
+ if (count <= level.spigotConfig.hopperAmount) {
|
|
+ // Spigot end
|
|
+ container.setItem(slot, item);
|
|
+ }
|
|
}
|
|
+ // DivineMC end - Optimize hoppers
|
|
|
|
return false;
|
|
}
|
|
@@ -615,15 +374,13 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
|
public static boolean addItem(Container container, ItemEntity item) {
|
|
boolean flag = false;
|
|
// CraftBukkit start
|
|
- if (org.bukkit.event.inventory.InventoryPickupItemEvent.getHandlerList().getRegisteredListeners().length > 0) { // Paper - optimize hoppers
|
|
org.bukkit.event.inventory.InventoryPickupItemEvent event = new org.bukkit.event.inventory.InventoryPickupItemEvent(
|
|
- getInventory(container), (org.bukkit.entity.Item) item.getBukkitEntity() // Paper - Perf: Optimize Hoppers; use getInventory() to avoid snapshot creation
|
|
+ container.getOwner().getInventory(), (org.bukkit.entity.Item) item.getBukkitEntity() // DivineMC - Optimize hoppers
|
|
);
|
|
if (!event.callEvent()) {
|
|
return false;
|
|
}
|
|
// CraftBukkit end
|
|
- } // Paper - Perf: Optimize Hoppers
|
|
ItemStack itemStack = item.getItem().copy();
|
|
ItemStack itemStack1 = addItem(null, container, itemStack, null);
|
|
if (itemStack1.isEmpty()) {
|
|
@@ -678,9 +435,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
|
stack = stack.split(destination.getMaxStackSize());
|
|
}
|
|
// Spigot end
|
|
- ignoreBlockEntityUpdates = true; // Paper - Perf: Optimize Hoppers
|
|
destination.setItem(slot, stack);
|
|
- ignoreBlockEntityUpdates = false; // Paper - Perf: Optimize Hoppers
|
|
stack = leftover; // Paper - Make hoppers respect inventory max stack size
|
|
flag = true;
|
|
} else if (canMergeItems(item, stack)) {
|
|
@@ -768,19 +523,13 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
|
|
|
@Nullable
|
|
public static Container getContainerAt(Level level, BlockPos pos) {
|
|
- return getContainerAt(level, pos, level.getBlockState(pos), pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, true); // Paper - Optimize hoppers
|
|
+ return getContainerAt(level, pos, level.getBlockState(pos), pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5); // DivineMC - Optimize hoppers
|
|
}
|
|
|
|
@Nullable
|
|
private static Container getContainerAt(Level level, BlockPos pos, BlockState state, double x, double y, double z) {
|
|
- // Paper start - Perf: Optimize Hoppers
|
|
- return HopperBlockEntity.getContainerAt(level, pos, state, x, y, z, false);
|
|
- }
|
|
- @Nullable
|
|
- private static Container getContainerAt(Level level, BlockPos pos, BlockState state, double x, double y, double z, final boolean optimizeEntities) {
|
|
- // Paper end - Perf: Optimize Hoppers
|
|
Container blockContainer = getBlockContainer(level, pos, state);
|
|
- if (blockContainer == null && (!optimizeEntities || !level.paperConfig().hopper.ignoreOccludingBlocks || !state.getBukkitMaterial().isOccluding())) { // Paper - Perf: Optimize Hoppers
|
|
+ if (blockContainer == null) { // DivineMC - Optimize hoppers
|
|
blockContainer = getEntityContainer(level, x, y, z);
|
|
}
|
|
|
|
@@ -806,14 +555,14 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
|
|
|
@Nullable
|
|
private static Container getEntityContainer(Level level, double x, double y, double z) {
|
|
- List<Entity> entities = level.getEntitiesOfClass(
|
|
- (Class) Container.class, new AABB(x - 0.5, y - 0.5, z - 0.5, x + 0.5, y + 0.5, z + 0.5), EntitySelector.CONTAINER_ENTITY_SELECTOR // Paper - Perf: Optimize hoppers
|
|
- );
|
|
+ List<Entity> entities = level.getEntities(
|
|
+ (Entity)null, new AABB(x - 0.5, y - 0.5, z - 0.5, x + 0.5, y + 0.5, z + 0.5), EntitySelector.CONTAINER_ENTITY_SELECTOR
|
|
+ ); // DivineMC - Optimize hoppers
|
|
return !entities.isEmpty() ? (Container)entities.get(level.random.nextInt(entities.size())) : null;
|
|
}
|
|
|
|
private static boolean canMergeItems(ItemStack stack1, ItemStack stack2) {
|
|
- return stack1.getCount() < stack1.getMaxStackSize() && ItemStack.isSameItemSameComponents(stack1, stack2); // Paper - Perf: Optimize Hoppers; used to return true for full itemstacks?!
|
|
+ return stack1.getCount() <= stack1.getMaxStackSize() && ItemStack.isSameItemSameComponents(stack1, stack2); // DivineMC - Optimize hoppers
|
|
}
|
|
|
|
@Override
|
|
diff --git a/net/minecraft/world/ticks/LevelChunkTicks.java b/net/minecraft/world/ticks/LevelChunkTicks.java
|
|
index faf45ac459f7c25309d6ef6dce371d484a0dae7b..6f0d1b28a45b93c51c5476283f1629a86e3420d1 100644
|
|
--- a/net/minecraft/world/ticks/LevelChunkTicks.java
|
|
+++ b/net/minecraft/world/ticks/LevelChunkTicks.java
|
|
@@ -17,7 +17,8 @@ import net.minecraft.core.BlockPos;
|
|
import net.minecraft.nbt.ListTag;
|
|
import net.minecraft.world.level.ChunkPos;
|
|
|
|
-public class LevelChunkTicks<T> implements SerializableTickContainer<T>, TickContainerAccess<T>, ca.spottedleaf.moonrise.patches.chunk_system.ticks.ChunkSystemLevelChunkTicks { // Paper - rewrite chunk system
|
|
+public class LevelChunkTicks<T> implements SerializableTickContainer<T>, TickContainerAccess<T>, ca.spottedleaf.moonrise.patches.chunk_system.ticks.ChunkSystemLevelChunkTicks { // DivineMC
|
|
+ private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.LogManager.getLogger(LevelChunkTicks.class); // Paper - rewrite chunk system
|
|
private final Queue<ScheduledTick<T>> tickQueue = new PriorityQueue<>(ScheduledTick.DRAIN_ORDER);
|
|
@Nullable
|
|
private List<SavedTick<T>> pendingTicks;
|
|
@@ -71,10 +72,18 @@ public class LevelChunkTicks<T> implements SerializableTickContainer<T>, TickCon
|
|
|
|
@Nullable
|
|
public ScheduledTick<T> poll() {
|
|
- ScheduledTick<T> scheduledTick = this.tickQueue.poll();
|
|
- if (scheduledTick != null) {
|
|
- this.ticksPerPosition.remove(scheduledTick); this.dirty = true; // Paper - rewrite chunk system
|
|
+ // DivineMC start - catch exceptions when polling chunk ticks
|
|
+ ScheduledTick<T> scheduledTick = null;
|
|
+ try {
|
|
+ scheduledTick = this.tickQueue.poll();
|
|
+ if (scheduledTick != null) {
|
|
+ this.ticksPerPosition.remove(scheduledTick); this.dirty = true; // Paper - rewrite chunk system
|
|
+ }
|
|
+ } catch (Exception e) {
|
|
+ log.error("Encountered caught exception when polling chunk ticks, blocking and returning null.", e);
|
|
+ return null;
|
|
}
|
|
+ // DivineMC end - catch exceptions when polling chunk ticks
|
|
|
|
return scheduledTick;
|
|
}
|