Paper/Spigot-Server-Patches/0333-Add-entity-count-cache.patch

222 lines
8.1 KiB
Diff
Raw Normal View History

2018-08-09 04:49:02 +02:00
From 5b101db469123c2f92ff82fc04a8b77274296bcf Mon Sep 17 00:00:00 2001
2018-08-08 23:22:58 +02:00
From: Colin Godsey <crgodsey@gmail.com>
2018-08-09 02:07:03 +02:00
Date: Wed, 8 Aug 2018 10:10:06 -0600
2018-08-08 23:22:58 +02:00
Subject: [PATCH] Add entity count cache
2018-08-09 04:49:02 +02:00
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index d6b56d685..3d973deb7 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -1034,6 +1034,14 @@ public abstract class MinecraftServer implements IAsyncTaskHandler, IMojangStati
}
// CraftBukkit end */
+ /*
+ * Paper - clear count cache every once in a while.
+ * Cache can never be entirely trusted because
+ * an entity may become persistent or not
+ * during its lifetime.
+ */
+ if (this.ticks % 600 == 0) worldserver.clearEntityCountCache();
+
this.methodProfiler.a("tick");
CrashReport crashreport;
diff --git a/src/main/java/net/minecraft/server/SpawnerCreature.java b/src/main/java/net/minecraft/server/SpawnerCreature.java
index f525fd1b4..494759a1c 100644
--- a/src/main/java/net/minecraft/server/SpawnerCreature.java
+++ b/src/main/java/net/minecraft/server/SpawnerCreature.java
@@ -113,7 +113,7 @@ public final class SpawnerCreature {
// CraftBukkit end
if ((!enumcreaturetype.c() || flag1) && (enumcreaturetype.c() || flag) && (!enumcreaturetype.d() || flag2)) {
- k = worldserver.a(enumcreaturetype.a());
+ k = worldserver.getCreatureCount(enumcreaturetype); // Paper - entity count cache
int l1 = limit * i / b; // CraftBukkit - use per-world limits
if (k <= l1) {
2018-08-08 23:22:58 +02:00
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
2018-08-09 04:49:02 +02:00
index 004c3ec47..baf73a411 100644
2018-08-08 23:22:58 +02:00
--- a/src/main/java/net/minecraft/server/World.java
+++ b/src/main/java/net/minecraft/server/World.java
2018-08-09 04:49:02 +02:00
@@ -1,28 +1,20 @@
package net.minecraft.server;
-import co.aikar.timings.Timings;
import com.destroystokyo.paper.event.server.ServerExceptionEvent;
import com.destroystokyo.paper.exception.ServerInternalException;
import com.google.common.base.MoreObjects;
import com.google.common.collect.Lists;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Random;
-import java.util.UUID;
+
+import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
-import java.util.function.Supplier;
import javax.annotation.Nullable;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
// CraftBukkit start
import com.google.common.collect.Maps;
-import java.util.HashMap; // Paper
-import java.util.Map;
import org.bukkit.Bukkit;
import org.bukkit.block.BlockState;
import org.bukkit.craftbukkit.CraftServer;
@@ -30,16 +22,11 @@ import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.craftbukkit.block.CraftBlockState;
import org.bukkit.craftbukkit.block.data.CraftBlockData;
import org.bukkit.craftbukkit.event.CraftEventFactory;
-import org.bukkit.craftbukkit.util.CraftMagicNumbers;
-import org.bukkit.craftbukkit.util.LongHashSet; // Paper
-import org.bukkit.entity.Player;
-import org.bukkit.event.block.BlockCanBuildEvent;
import org.bukkit.event.block.BlockPhysicsEvent;
import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
import org.bukkit.generator.ChunkGenerator;
// CraftBukkit end
// Paper start
-import java.util.Set;
import com.google.common.collect.Sets;
// Paper end
public abstract class World implements GeneratorAccess, IIBlockAccess, AutoCloseable {
@@ -50,10 +37,41 @@ public abstract class World implements GeneratorAccess, IIBlockAccess, AutoClose
2018-08-08 23:22:58 +02:00
// Spigot start - guard entity list from removals
public final List<Entity> entityList = new java.util.ArrayList<Entity>()
{
+ // Paper start - entity count cache
+ @Override
+ public boolean addAll(Collection<? extends Entity> c) {
2018-08-09 02:07:03 +02:00
+ for (Entity e : c) {
2018-08-08 23:22:58 +02:00
+ updateEntityCount(e, true);
+ }
+
+ return super.addAll(c);
+ }
+
+ @Override
+ public boolean removeAll(Collection<?> c) {
2018-08-09 02:07:03 +02:00
+ for (Object e : c) {
+ if (e instanceof Entity) {
2018-08-08 23:22:58 +02:00
+ updateEntityCount((Entity)e, false);
+ }
+ }
+
+ return super.removeAll(c);
+ }
+
+ @Override
+ public boolean add(Entity e) {
+ updateEntityCount(e, true);
+
+ return super.add(e);
+ }
+
+ // Paper end
+
@Override
public Entity remove(int index)
{
guard();
+ updateEntityCount(get(index), false); // Paper
return super.remove( index );
}
2018-08-09 04:49:02 +02:00
@@ -61,6 +79,7 @@ public abstract class World implements GeneratorAccess, IIBlockAccess, AutoClose
2018-08-08 23:22:58 +02:00
public boolean remove(Object o)
{
guard();
2018-08-09 02:07:03 +02:00
+ if (o instanceof Entity) updateEntityCount((Entity)o, false); // Paper
2018-08-08 23:22:58 +02:00
return super.remove( o );
}
2018-08-09 04:49:02 +02:00
@@ -82,6 +101,7 @@ public abstract class World implements GeneratorAccess, IIBlockAccess, AutoClose
2018-08-08 23:22:58 +02:00
public final Map<String, EntityHuman> playersByName = Maps.newHashMap(); // Paper - World EntityHuman Lookup Optimizations
public final List<Entity> k = Lists.newArrayList();
protected final IntHashMap<Entity> entitiesById = new IntHashMap();
2018-08-09 04:49:02 +02:00
+ private Map<EnumCreatureType, Integer> countCache = new EnumMap(EnumCreatureType.class); // Paper - entity count cache
2018-08-08 23:22:58 +02:00
private final long G = 16777215L;
private int H; public int getSkylightSubtracted() { return this.H; } public void setSkylightSubtracted(int value) { this.H = value;} // Paper - OBFHELPER
protected int m = (new Random()).nextInt();
2018-08-09 04:49:02 +02:00
@@ -2439,6 +2459,7 @@ public abstract class World implements GeneratorAccess, IIBlockAccess, AutoClose
2018-08-08 23:22:58 +02:00
}
2018-08-09 04:49:02 +02:00
+ public int getEntityCount(Class<?> oclass) { return a(oclass); } // Paper - OBFHELPER
2018-08-09 02:07:03 +02:00
public int a(Class<?> oclass) {
2018-08-08 23:22:58 +02:00
int i = 0;
Iterator iterator = this.entityList.iterator();
2018-08-09 04:49:02 +02:00
@@ -2464,6 +2485,61 @@ public abstract class World implements GeneratorAccess, IIBlockAccess, AutoClose
2018-08-08 23:22:58 +02:00
return i;
}
2018-08-09 02:07:03 +02:00
+ // Paper start - entity count cache
2018-08-09 04:49:02 +02:00
+ public int getCreatureCount(EnumCreatureType typ) {
+ Integer count = countCache.get(typ);
2018-08-08 23:22:58 +02:00
+
2018-08-09 04:49:02 +02:00
+ if (count == null) {
+ count = getEntityCount(typ.a());
2018-08-08 23:22:58 +02:00
+
2018-08-09 04:49:02 +02:00
+ countCache.put(typ, count);
2018-08-08 23:22:58 +02:00
+ }
2018-08-09 02:07:03 +02:00
+
+ return count;
2018-08-08 23:22:58 +02:00
+ }
+
2018-08-09 04:49:02 +02:00
+ void clearEntityCountCache() {
+ countCache.clear();
2018-08-08 23:22:58 +02:00
+ }
+
2018-08-09 04:49:02 +02:00
+ protected void updateEntityCount(EnumCreatureType typ, boolean incr) {
+ Integer countObject = countCache.get(typ);
2018-08-08 23:22:58 +02:00
+
2018-08-09 02:07:03 +02:00
+ if (countObject == null) return;
2018-08-08 23:22:58 +02:00
+
2018-08-09 02:07:03 +02:00
+ int count = countObject;
2018-08-08 23:22:58 +02:00
+
2018-08-09 02:07:03 +02:00
+ if (incr) count++;
+ else count--;
2018-08-08 23:22:58 +02:00
+
2018-08-09 04:49:02 +02:00
+ if (count < 0) {
2018-08-09 02:07:03 +02:00
+ e.warn("Entity count cache has gone negative");
+ count = 0;
+ }
+
2018-08-09 04:49:02 +02:00
+ countCache.put(typ, count);
2018-08-09 02:07:03 +02:00
+ }
+
+ protected void updateEntityCount(Entity entity, boolean incr) {
2018-08-09 04:49:02 +02:00
+ if (entity == null || !(entity instanceof IAnimal)) return;
2018-08-09 02:07:03 +02:00
+
2018-08-09 04:49:02 +02:00
+ if (entity instanceof EntityInsentient) {
+ EntityInsentient entityinsentient = (EntityInsentient) entity;
+ if (entityinsentient.isTypeNotPersistent() && entityinsentient.isPersistent()) {
+ return;
+ }
+ }
+
+ Class<?> clazz = entity.getClass();
+
+ for (EnumCreatureType typ : EnumCreatureType.values()) {
+ if (typ.a().isAssignableFrom(clazz)) {
+ updateEntityCount(typ, incr);
+ }
2018-08-09 02:07:03 +02:00
+ }
2018-08-08 23:22:58 +02:00
+ }
+ // Paper end
+
public void addChunkEntities(Collection<Entity> collection) { a(collection); } // Paper - OBFHELPER
public void a(Collection<Entity> collection) {
org.spigotmc.AsyncCatcher.catchOp( "entity world add"); // Spigot
--
2.15.2 (Apple Git-101.1)