2021-06-15 10:29:12 +02:00
|
|
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
|
|
From: CullanP <cullanpage@gmail.com>
|
|
|
|
Date: Thu, 3 Mar 2016 02:13:38 -0600
|
|
|
|
Subject: [PATCH] Avoid hopper searches if there are no items
|
|
|
|
|
|
|
|
Hoppers searching for items and minecarts is the most expensive part of hopper ticking.
|
|
|
|
We keep track of the number of minecarts and items in a chunk.
|
|
|
|
If there are no items in the chunk, we skip searching for items.
|
|
|
|
If there are no minecarts in the chunk, we skip searching for them.
|
|
|
|
|
|
|
|
Usually hoppers aren't near items, so we can skip most item searches.
|
|
|
|
And since minecart hoppers are used _very_ rarely near we can avoid alot of searching there.
|
|
|
|
|
|
|
|
Combined, this adds up a lot.
|
|
|
|
|
|
|
|
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
|
2021-07-07 08:52:40 +02:00
|
|
|
index fa8cf70d7d24a82757326ff8f7f240cff3dcbe73..fd23c7913b7a426443515e14be0ac9814a5e934e 100644
|
2021-06-15 10:29:12 +02:00
|
|
|
--- a/src/main/java/net/minecraft/world/level/Level.java
|
|
|
|
+++ b/src/main/java/net/minecraft/world/level/Level.java
|
2021-07-07 08:52:40 +02:00
|
|
|
@@ -994,7 +994,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
2021-06-15 10:29:12 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
- });
|
|
|
|
+ }, predicate == net.minecraft.world.entity.EntitySelector.CONTAINER_ENTITY_SELECTOR); // Paper
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
|
|
|
diff --git a/src/main/java/net/minecraft/world/level/entity/EntitySection.java b/src/main/java/net/minecraft/world/level/entity/EntitySection.java
|
|
|
|
index 9a7b2602c2549dd03ad097c4a922a10a5e869645..5342eafe25614d262eeb39fa517a242e27d998f6 100644
|
|
|
|
--- a/src/main/java/net/minecraft/world/level/entity/EntitySection.java
|
|
|
|
+++ b/src/main/java/net/minecraft/world/level/entity/EntitySection.java
|
|
|
|
@@ -12,6 +12,10 @@ public class EntitySection<T> {
|
|
|
|
protected static final Logger LOGGER = LogManager.getLogger();
|
|
|
|
private final ClassInstanceMultiMap<T> storage;
|
|
|
|
private Visibility chunkStatus;
|
|
|
|
+ // Paper start - track number of items and minecarts
|
|
|
|
+ public int itemCount;
|
|
|
|
+ public int inventoryEntityCount;
|
|
|
|
+ // Paper end
|
|
|
|
|
|
|
|
public EntitySection(Class<T> entityClass, Visibility status) {
|
|
|
|
this.chunkStatus = status;
|
|
|
|
@@ -19,10 +23,24 @@ public class EntitySection<T> {
|
|
|
|
}
|
|
|
|
|
|
|
|
public void add(T obj) {
|
|
|
|
+ // Paper start
|
|
|
|
+ if (obj instanceof net.minecraft.world.entity.item.ItemEntity) {
|
|
|
|
+ this.itemCount++;
|
|
|
|
+ } else if (obj instanceof net.minecraft.world.Container) {
|
|
|
|
+ this.inventoryEntityCount++;
|
|
|
|
+ }
|
|
|
|
+ // Paper end
|
|
|
|
this.storage.add(obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean remove(T obj) {
|
|
|
|
+ // Paper start
|
|
|
|
+ if (obj instanceof net.minecraft.world.entity.item.ItemEntity) {
|
|
|
|
+ this.itemCount--;
|
|
|
|
+ } else if (obj instanceof net.minecraft.world.Container) {
|
|
|
|
+ this.inventoryEntityCount--;
|
|
|
|
+ }
|
|
|
|
+ // Paper end
|
|
|
|
return this.storage.remove(obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
@@ -39,7 +57,7 @@ public class EntitySection<T> {
|
|
|
|
for(T object : this.storage.find(type.getBaseClass())) {
|
|
|
|
U object2 = (U)type.tryCast(object);
|
|
|
|
if (object2 != null && filter.test(object2)) {
|
|
|
|
- action.accept((T)object2);
|
|
|
|
+ action.accept(object2); // Paper - decompile fix
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
diff --git a/src/main/java/net/minecraft/world/level/entity/EntitySectionStorage.java b/src/main/java/net/minecraft/world/level/entity/EntitySectionStorage.java
|
|
|
|
index 067138e3983959347d19754e668bb7a1f702bad0..24552500307c42f9f3dc5c4d9ba73a84a787423a 100644
|
|
|
|
--- a/src/main/java/net/minecraft/world/level/entity/EntitySectionStorage.java
|
|
|
|
+++ b/src/main/java/net/minecraft/world/level/entity/EntitySectionStorage.java
|
|
|
|
@@ -105,7 +105,7 @@ public class EntitySectionStorage<T extends EntityAccess> {
|
|
|
|
|
|
|
|
public LongSet getAllChunksWithExistingSections() {
|
|
|
|
LongSet longSet = new LongOpenHashSet();
|
|
|
|
- this.sections.keySet().forEach((sectionPos) -> {
|
|
|
|
+ this.sections.keySet().forEach((java.util.function.LongConsumer) (sectionPos) -> { // Paper - decompile fix
|
|
|
|
longSet.add(getChunkKeyFromSectionKey(sectionPos));
|
|
|
|
});
|
|
|
|
return longSet;
|
|
|
|
@@ -118,13 +118,20 @@ public class EntitySectionStorage<T extends EntityAccess> {
|
|
|
|
}
|
|
|
|
|
|
|
|
public void getEntities(AABB box, Consumer<T> action) {
|
|
|
|
+ // Paper start
|
|
|
|
+ this.getEntities(box, action, false);
|
|
|
|
+ }
|
|
|
|
+ public void getEntities(AABB box, Consumer<T> action, boolean isContainerSearch) {
|
|
|
|
+ // Paper end
|
|
|
|
this.forEachAccessibleSection(box, (entitySection) -> {
|
|
|
|
+ if (isContainerSearch && entitySection.inventoryEntityCount <= 0) return; // Paper
|
|
|
|
entitySection.getEntities(createBoundingBoxCheck(box), action);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
public <U extends T> void getEntities(EntityTypeTest<T, U> filter, AABB box, Consumer<U> action) {
|
|
|
|
this.forEachAccessibleSection(box, (entitySection) -> {
|
|
|
|
+ if (filter.getBaseClass() == net.minecraft.world.entity.item.ItemEntity.class && entitySection.itemCount <= 0) return; // Paper
|
|
|
|
entitySection.getEntities(filter, createBoundingBoxCheck(box), action);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
diff --git a/src/main/java/net/minecraft/world/level/entity/LevelEntityGetter.java b/src/main/java/net/minecraft/world/level/entity/LevelEntityGetter.java
|
|
|
|
index 9723a0ad61548c8c6c4c5ef20a150d5b17d80afd..da1ad0b2679e392ed81b50c15f012c63cb5c939e 100644
|
|
|
|
--- a/src/main/java/net/minecraft/world/level/entity/LevelEntityGetter.java
|
|
|
|
+++ b/src/main/java/net/minecraft/world/level/entity/LevelEntityGetter.java
|
|
|
|
@@ -17,6 +17,7 @@ public interface LevelEntityGetter<T extends EntityAccess> {
|
|
|
|
<U extends T> void get(EntityTypeTest<T, U> filter, Consumer<U> action);
|
|
|
|
|
|
|
|
void get(AABB box, Consumer<T> action);
|
|
|
|
+ void get(AABB box, Consumer<T> action, boolean isContainerSearch); // Paper
|
|
|
|
|
|
|
|
<U extends T> void get(EntityTypeTest<T, U> filter, AABB box, Consumer<U> action);
|
|
|
|
}
|
|
|
|
diff --git a/src/main/java/net/minecraft/world/level/entity/LevelEntityGetterAdapter.java b/src/main/java/net/minecraft/world/level/entity/LevelEntityGetterAdapter.java
|
|
|
|
index d5129c12c79eb6fe6b7e5f8eed4d24226423f5fd..3b13f6ea36a3bfecabe09221eb5c48dddab119db 100644
|
|
|
|
--- a/src/main/java/net/minecraft/world/level/entity/LevelEntityGetterAdapter.java
|
|
|
|
+++ b/src/main/java/net/minecraft/world/level/entity/LevelEntityGetterAdapter.java
|
|
|
|
@@ -38,7 +38,13 @@ public class LevelEntityGetterAdapter<T extends EntityAccess> implements LevelEn
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void get(AABB box, Consumer<T> action) {
|
|
|
|
- this.sectionStorage.getEntities(box, action);
|
|
|
|
+ // Paper start
|
|
|
|
+ this.get(box, action, false);
|
|
|
|
+ }
|
|
|
|
+ @Override
|
|
|
|
+ public void get(AABB box, Consumer<T> action, boolean isContainerSearch) {
|
|
|
|
+ this.sectionStorage.getEntities(box, action, isContainerSearch);
|
|
|
|
+ // Paper end
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|