From a12c0881a098b6e671211ece2fde3955e8284c7d Mon Sep 17 00:00:00 2001 From: Colin Godsey Date: Wed, 8 Aug 2018 15:22:58 -0600 Subject: [PATCH 1/8] add entity count cache #1207 --- .../0333-Add-entity-count-cache.patch | 148 ++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 Spigot-Server-Patches/0333-Add-entity-count-cache.patch diff --git a/Spigot-Server-Patches/0333-Add-entity-count-cache.patch b/Spigot-Server-Patches/0333-Add-entity-count-cache.patch new file mode 100644 index 000000000..98234e4eb --- /dev/null +++ b/Spigot-Server-Patches/0333-Add-entity-count-cache.patch @@ -0,0 +1,148 @@ +From 81259e2cb7b30df39c3d1b23d66ec2c1bdde2a5d Mon Sep 17 00:00:00 2001 +From: Colin Godsey +Date: Wed, 8 Aug 2018 16:10:06 -0600 +Subject: [PATCH] Add entity count cache + + +diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java +index 004c3ec4..09c2bc32 100644 +--- a/src/main/java/net/minecraft/server/World.java ++++ b/src/main/java/net/minecraft/server/World.java +@@ -50,10 +50,41 @@ public abstract class World implements GeneratorAccess, IIBlockAccess, AutoClose + // Spigot start - guard entity list from removals + public final List entityList = new java.util.ArrayList() + { ++ // Paper start - entity count cache ++ @Override ++ public boolean addAll(Collection c) { ++ for(Entity e : c) { ++ updateEntityCount(e, true); ++ } ++ ++ return super.addAll(c); ++ } ++ ++ @Override ++ public boolean removeAll(Collection c) { ++ for(Object e : c) { ++ if(e instanceof Entity) { ++ 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 ); + } + +@@ -61,6 +92,7 @@ public abstract class World implements GeneratorAccess, IIBlockAccess, AutoClose + public boolean remove(Object o) + { + guard(); ++ if(o instanceof Entity) updateEntityCount((Entity)o, false); // Paper + return super.remove( o ); + } + +@@ -82,6 +114,7 @@ public abstract class World implements GeneratorAccess, IIBlockAccess, AutoClose + public final Map playersByName = Maps.newHashMap(); // Paper - World EntityHuman Lookup Optimizations + public final List k = Lists.newArrayList(); + protected final IntHashMap entitiesById = new IntHashMap(); ++ private Map, Integer> countCache = new HashMap(); // Paper + 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(); +@@ -2439,19 +2472,16 @@ public abstract class World implements GeneratorAccess, IIBlockAccess, AutoClose + + } + +- public int a(Class oclass) { ++ // Paper start - entity count cache ++ private int countEntityType(Class oclass) { + int i = 0; + Iterator iterator = this.entityList.iterator(); + + while (iterator.hasNext()) { + Entity entity = (Entity) iterator.next(); +- if (entity.shouldBeRemoved) continue; // Paper + // CraftBukkit start - Split out persistent check, don't apply it to special persistent mobs +- if (entity instanceof EntityInsentient) { +- EntityInsentient entityinsentient = (EntityInsentient) entity; +- if (entityinsentient.isTypeNotPersistent() && entityinsentient.isPersistent()) { +- continue; +- } ++ if (shouldIgnoreForCount(entity)) { ++ continue; + } + + if (oclass.isAssignableFrom(entity.getClass())) { +@@ -2464,6 +2494,52 @@ public abstract class World implements GeneratorAccess, IIBlockAccess, AutoClose + return i; + } + ++ public int getEntityCount(Class oclass) { return a(oclass); } // Paper - OBFHELPER ++ public int a(Class oclass) { ++ if(countCache.containsKey(oclass)) { ++ return countCache.get(oclass); ++ } else { ++ int count = countEntityType(oclass); ++ ++ countCache.put(oclass, count); ++ ++ return count; ++ } ++ } ++ ++ public boolean shouldIgnoreForCount(Entity entity) { ++ if (entity instanceof EntityInsentient) { ++ EntityInsentient entityinsentient = (EntityInsentient) entity; ++ return entityinsentient.isTypeNotPersistent() && entityinsentient.isPersistent(); ++ } ++ ++ return false; ++ } ++ ++ protected void updateEntityCount(Entity entity, boolean incr) { ++ if(entity == null) return; ++ if(shouldIgnoreForCount(entity)) return; ++ ++ countCache.replaceAll((clazz, count) -> { ++ if(clazz.isAssignableFrom(entity.getClass())) { ++ int newCount = count; ++ ++ if(incr) newCount++; ++ else newCount--; ++ ++ if(newCount < 0) { ++ e.warn("Entity count cache has gone negative"); ++ newCount = 0; ++ } ++ ++ return newCount; ++ } else { ++ return count; ++ } ++ }); ++ } ++ // Paper end ++ + public void addChunkEntities(Collection collection) { a(collection); } // Paper - OBFHELPER + public void a(Collection collection) { + org.spigotmc.AsyncCatcher.catchOp( "entity world add"); // Spigot +-- +2.15.2 (Apple Git-101.1) + From c09191b7f97a67777f9fa82e19f21e5916b1b6fe Mon Sep 17 00:00:00 2001 From: Colin Godsey Date: Wed, 8 Aug 2018 15:23:54 -0600 Subject: [PATCH 2/8] Configurable water over lava #1227 --- ...le-speed-for-water-flowing-over-lava.patch | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 Spigot-Server-Patches/0334-Configurable-speed-for-water-flowing-over-lava.patch diff --git a/Spigot-Server-Patches/0334-Configurable-speed-for-water-flowing-over-lava.patch b/Spigot-Server-Patches/0334-Configurable-speed-for-water-flowing-over-lava.patch new file mode 100644 index 000000000..4f10d1173 --- /dev/null +++ b/Spigot-Server-Patches/0334-Configurable-speed-for-water-flowing-over-lava.patch @@ -0,0 +1,65 @@ +From 35c565d267a562633607766e1264ac0cd4c01d87 Mon Sep 17 00:00:00 2001 +From: Colin Godsey +Date: Wed, 8 Aug 2018 16:33:21 -0600 +Subject: [PATCH] Configurable speed for water flowing over lava + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 61c8b58b..ab3f59ad 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -436,6 +436,12 @@ public class PaperWorldConfig { + } + } + ++ public int waterOverLavaFlowSpeed; ++ private void waterOverLavaFlowSpeed() { ++ waterOverLavaFlowSpeed = getInt("water-over-lava-flow-speed", 5); ++ log("Water over lava flow speed: " + waterOverLavaFlowSpeed); ++ } ++ + public enum DuplicateUUIDMode { + SAFE_REGEN, REGEN, DELETE, NOTHING, WARN + } +diff --git a/src/main/java/net/minecraft/server/BlockFluids.java b/src/main/java/net/minecraft/server/BlockFluids.java +index 6ecc1f84..637f6580 100644 +--- a/src/main/java/net/minecraft/server/BlockFluids.java ++++ b/src/main/java/net/minecraft/server/BlockFluids.java +@@ -67,10 +67,24 @@ public class BlockFluids extends Block implements IFluidSource { + + public void onPlace(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1) { + if (this.a(world, blockposition, iblockdata)) { +- world.H().a(blockposition, iblockdata.s().c(), this.a((IWorldReader) world)); ++ world.H().a(blockposition, iblockdata.s().c(), this.getFlowSpeed(world, blockposition)); // Paper + } + + } ++ ++ /** ++ * Paper - Get flow speed. Throttle if its water and flowing adjacent to lava ++ */ ++ public int getFlowSpeed(World world, BlockPosition blockposition) { ++ if (this.material == Material.WATER && ( ++ world.getType(blockposition.north(1)).getBlock().material == Material.LAVA || ++ world.getType(blockposition.south(1)).getBlock().material == Material.LAVA || ++ world.getType(blockposition.west(1)).getBlock().material == Material.LAVA || ++ world.getType(blockposition.east(1)).getBlock().material == Material.LAVA)) { ++ return world.paperConfig.waterOverLavaFlowSpeed; ++ } ++ return this.a(world); ++ } + + public IBlockData updateState(IBlockData iblockdata, EnumDirection enumdirection, IBlockData iblockdata1, GeneratorAccess generatoraccess, BlockPosition blockposition, BlockPosition blockposition1) { + if (iblockdata.s().d() || iblockdata1.s().d()) { +@@ -82,7 +96,7 @@ public class BlockFluids extends Block implements IFluidSource { + + public void doPhysics(IBlockData iblockdata, World world, BlockPosition blockposition, Block block, BlockPosition blockposition1) { + if (this.a(world, blockposition, iblockdata)) { +- world.H().a(blockposition, iblockdata.s().c(), this.a((IWorldReader) world)); ++ world.H().a(blockposition, iblockdata.s().c(), this.getFlowSpeed(world, blockposition)); // Paper + } + + } +-- +2.15.2 (Apple Git-101.1) + From 0753b9271fe6f418907eb580bee86629303f4c76 Mon Sep 17 00:00:00 2001 From: Colin Godsey Date: Wed, 8 Aug 2018 18:07:03 -0600 Subject: [PATCH 3/8] pr fixes --- .../0333-Add-entity-count-cache.patch | 112 +++++++++--------- ...le-speed-for-water-flowing-over-lava.patch | 8 +- 2 files changed, 62 insertions(+), 58 deletions(-) diff --git a/Spigot-Server-Patches/0333-Add-entity-count-cache.patch b/Spigot-Server-Patches/0333-Add-entity-count-cache.patch index 98234e4eb..7fcf3e7a7 100644 --- a/Spigot-Server-Patches/0333-Add-entity-count-cache.patch +++ b/Spigot-Server-Patches/0333-Add-entity-count-cache.patch @@ -1,11 +1,11 @@ -From 81259e2cb7b30df39c3d1b23d66ec2c1bdde2a5d Mon Sep 17 00:00:00 2001 +From 3ac10ee43109b578232e3d127511e761ddc87a1a Mon Sep 17 00:00:00 2001 From: Colin Godsey -Date: Wed, 8 Aug 2018 16:10:06 -0600 +Date: Wed, 8 Aug 2018 10:10:06 -0600 Subject: [PATCH] Add entity count cache diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java -index 004c3ec4..09c2bc32 100644 +index 004c3ec47..c392595c0 100644 --- a/src/main/java/net/minecraft/server/World.java +++ b/src/main/java/net/minecraft/server/World.java @@ -50,10 +50,41 @@ public abstract class World implements GeneratorAccess, IIBlockAccess, AutoClose @@ -15,7 +15,7 @@ index 004c3ec4..09c2bc32 100644 + // Paper start - entity count cache + @Override + public boolean addAll(Collection c) { -+ for(Entity e : c) { ++ for (Entity e : c) { + updateEntityCount(e, true); + } + @@ -24,8 +24,8 @@ index 004c3ec4..09c2bc32 100644 + + @Override + public boolean removeAll(Collection c) { -+ for(Object e : c) { -+ if(e instanceof Entity) { ++ for (Object e : c) { ++ if (e instanceof Entity) { + updateEntityCount((Entity)e, false); + } + } @@ -54,7 +54,7 @@ index 004c3ec4..09c2bc32 100644 public boolean remove(Object o) { guard(); -+ if(o instanceof Entity) updateEntityCount((Entity)o, false); // Paper ++ if (o instanceof Entity) updateEntityCount((Entity)o, false); // Paper return super.remove( o ); } @@ -66,48 +66,49 @@ index 004c3ec4..09c2bc32 100644 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(); -@@ -2439,19 +2472,16 @@ public abstract class World implements GeneratorAccess, IIBlockAccess, AutoClose - +@@ -2440,6 +2473,8 @@ public abstract class World implements GeneratorAccess, IIBlockAccess, AutoClose } -- public int a(Class oclass) { -+ // Paper start - entity count cache -+ private int countEntityType(Class oclass) { + public int a(Class oclass) { ++ if (true) return getEntityCount(oclass); //Paper - short circuit to cached method ++ int i = 0; Iterator iterator = this.entityList.iterator(); - while (iterator.hasNext()) { - Entity entity = (Entity) iterator.next(); -- if (entity.shouldBeRemoved) continue; // Paper - // CraftBukkit start - Split out persistent check, don't apply it to special persistent mobs -- if (entity instanceof EntityInsentient) { -- EntityInsentient entityinsentient = (EntityInsentient) entity; -- if (entityinsentient.isTypeNotPersistent() && entityinsentient.isPersistent()) { -- continue; -- } -+ if (shouldIgnoreForCount(entity)) { -+ continue; - } - - if (oclass.isAssignableFrom(entity.getClass())) { -@@ -2464,6 +2494,52 @@ public abstract class World implements GeneratorAccess, IIBlockAccess, AutoClose +@@ -2464,6 +2499,71 @@ public abstract class World implements GeneratorAccess, IIBlockAccess, AutoClose return i; } -+ public int getEntityCount(Class oclass) { return a(oclass); } // Paper - OBFHELPER -+ public int a(Class oclass) { -+ if(countCache.containsKey(oclass)) { -+ return countCache.get(oclass); -+ } else { -+ int count = countEntityType(oclass); ++ // Paper start - entity count cache ++ private int countEntityType(Class oclass) { ++ int i = 0; ++ Iterator iterator = this.entityList.iterator(); + -+ countCache.put(oclass, count); ++ while (iterator.hasNext()) { ++ Entity entity = (Entity) iterator.next(); + -+ return count; ++ if (shouldIgnoreForCount(entity)) continue; ++ if (oclass.isAssignableFrom(entity.getClass())) i++; + } ++ ++ return i; ++ } ++ ++ public int getEntityCount(Class oclass) { ++ Integer count = countCache.get(oclass); ++ ++ if (count != null) return count; ++ ++ count = countEntityType(oclass); ++ ++ countCache.put(oclass, count); ++ ++ return count; + } + + public boolean shouldIgnoreForCount(Entity entity) { ++ if (entity == null) return true; ++ + if (entity instanceof EntityInsentient) { + EntityInsentient entityinsentient = (EntityInsentient) entity; + return entityinsentient.isTypeNotPersistent() && entityinsentient.isPersistent(); @@ -116,27 +117,30 @@ index 004c3ec4..09c2bc32 100644 + return false; + } + ++ protected void updateEntityCount(Class clazz, boolean incr) { ++ Integer countObject = countCache.get(clazz); ++ ++ if (countObject == null) return; ++ ++ int count = countObject; ++ ++ if (incr) count++; ++ else count--; ++ ++ if(count < 0) { ++ e.warn("Entity count cache has gone negative"); ++ count = 0; ++ } ++ ++ countCache.put(clazz, count); ++ } ++ + protected void updateEntityCount(Entity entity, boolean incr) { -+ if(entity == null) return; -+ if(shouldIgnoreForCount(entity)) return; ++ if (shouldIgnoreForCount(entity)) return; + -+ countCache.replaceAll((clazz, count) -> { -+ if(clazz.isAssignableFrom(entity.getClass())) { -+ int newCount = count; -+ -+ if(incr) newCount++; -+ else newCount--; -+ -+ if(newCount < 0) { -+ e.warn("Entity count cache has gone negative"); -+ newCount = 0; -+ } -+ -+ return newCount; -+ } else { -+ return count; -+ } -+ }); ++ for (Class clazz = entity.getClass() ; !clazz.equals(Object.class) ; clazz = clazz.getSuperclass()) { ++ updateEntityCount(clazz, incr); ++ } + } + // Paper end + diff --git a/Spigot-Server-Patches/0334-Configurable-speed-for-water-flowing-over-lava.patch b/Spigot-Server-Patches/0334-Configurable-speed-for-water-flowing-over-lava.patch index 4f10d1173..d7f5d993b 100644 --- a/Spigot-Server-Patches/0334-Configurable-speed-for-water-flowing-over-lava.patch +++ b/Spigot-Server-Patches/0334-Configurable-speed-for-water-flowing-over-lava.patch @@ -1,11 +1,11 @@ -From 35c565d267a562633607766e1264ac0cd4c01d87 Mon Sep 17 00:00:00 2001 +From b9f0b43802d049d91f4db3cf26bce5f2084de76e Mon Sep 17 00:00:00 2001 From: Colin Godsey -Date: Wed, 8 Aug 2018 16:33:21 -0600 +Date: Wed, 8 Aug 2018 11:33:21 -0600 Subject: [PATCH] Configurable speed for water flowing over lava diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 61c8b58b..ab3f59ad 100644 +index 61c8b58b1..ab3f59ad7 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java @@ -436,6 +436,12 @@ public class PaperWorldConfig { @@ -22,7 +22,7 @@ index 61c8b58b..ab3f59ad 100644 SAFE_REGEN, REGEN, DELETE, NOTHING, WARN } diff --git a/src/main/java/net/minecraft/server/BlockFluids.java b/src/main/java/net/minecraft/server/BlockFluids.java -index 6ecc1f84..637f6580 100644 +index 6ecc1f84e..637f6580b 100644 --- a/src/main/java/net/minecraft/server/BlockFluids.java +++ b/src/main/java/net/minecraft/server/BlockFluids.java @@ -67,10 +67,24 @@ public class BlockFluids extends Block implements IFluidSource { From 40e32744ddcbcb0a26e27f51d6c01f3c6c5043b1 Mon Sep 17 00:00:00 2001 From: Colin Godsey Date: Wed, 8 Aug 2018 20:49:02 -0600 Subject: [PATCH 4/8] reduced down to EnumCreatureType --- .../0333-Add-entity-count-cache.patch | 161 +++++++++++++----- ...le-speed-for-water-flowing-over-lava.patch | 65 ------- 2 files changed, 115 insertions(+), 111 deletions(-) delete mode 100644 Spigot-Server-Patches/0334-Configurable-speed-for-water-flowing-over-lava.patch diff --git a/Spigot-Server-Patches/0333-Add-entity-count-cache.patch b/Spigot-Server-Patches/0333-Add-entity-count-cache.patch index 7fcf3e7a7..ddccbd1bb 100644 --- a/Spigot-Server-Patches/0333-Add-entity-count-cache.patch +++ b/Spigot-Server-Patches/0333-Add-entity-count-cache.patch @@ -1,14 +1,94 @@ -From 3ac10ee43109b578232e3d127511e761ddc87a1a Mon Sep 17 00:00:00 2001 +From 5b101db469123c2f92ff82fc04a8b77274296bcf Mon Sep 17 00:00:00 2001 From: Colin Godsey Date: Wed, 8 Aug 2018 10:10:06 -0600 Subject: [PATCH] Add entity count cache +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) { diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java -index 004c3ec47..c392595c0 100644 +index 004c3ec47..baf73a411 100644 --- a/src/main/java/net/minecraft/server/World.java +++ b/src/main/java/net/minecraft/server/World.java -@@ -50,10 +50,41 @@ public abstract class World implements GeneratorAccess, IIBlockAccess, AutoClose +@@ -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 // Spigot start - guard entity list from removals public final List entityList = new java.util.ArrayList() { @@ -50,7 +130,7 @@ index 004c3ec47..c392595c0 100644 return super.remove( index ); } -@@ -61,6 +92,7 @@ public abstract class World implements GeneratorAccess, IIBlockAccess, AutoClose +@@ -61,6 +79,7 @@ public abstract class World implements GeneratorAccess, IIBlockAccess, AutoClose public boolean remove(Object o) { guard(); @@ -58,67 +138,45 @@ index 004c3ec47..c392595c0 100644 return super.remove( o ); } -@@ -82,6 +114,7 @@ public abstract class World implements GeneratorAccess, IIBlockAccess, AutoClose +@@ -82,6 +101,7 @@ public abstract class World implements GeneratorAccess, IIBlockAccess, AutoClose public final Map playersByName = Maps.newHashMap(); // Paper - World EntityHuman Lookup Optimizations public final List k = Lists.newArrayList(); protected final IntHashMap entitiesById = new IntHashMap(); -+ private Map, Integer> countCache = new HashMap(); // Paper ++ private Map countCache = new EnumMap(EnumCreatureType.class); // Paper - entity count cache 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(); -@@ -2440,6 +2473,8 @@ public abstract class World implements GeneratorAccess, IIBlockAccess, AutoClose +@@ -2439,6 +2459,7 @@ public abstract class World implements GeneratorAccess, IIBlockAccess, AutoClose + } ++ public int getEntityCount(Class oclass) { return a(oclass); } // Paper - OBFHELPER public int a(Class oclass) { -+ if (true) return getEntityCount(oclass); //Paper - short circuit to cached method -+ int i = 0; Iterator iterator = this.entityList.iterator(); - -@@ -2464,6 +2499,71 @@ public abstract class World implements GeneratorAccess, IIBlockAccess, AutoClose +@@ -2464,6 +2485,61 @@ public abstract class World implements GeneratorAccess, IIBlockAccess, AutoClose return i; } + // Paper start - entity count cache -+ private int countEntityType(Class oclass) { -+ int i = 0; -+ Iterator iterator = this.entityList.iterator(); ++ public int getCreatureCount(EnumCreatureType typ) { ++ Integer count = countCache.get(typ); + -+ while (iterator.hasNext()) { -+ Entity entity = (Entity) iterator.next(); ++ if (count == null) { ++ count = getEntityCount(typ.a()); + -+ if (shouldIgnoreForCount(entity)) continue; -+ if (oclass.isAssignableFrom(entity.getClass())) i++; ++ countCache.put(typ, count); + } + -+ return i; -+ } -+ -+ public int getEntityCount(Class oclass) { -+ Integer count = countCache.get(oclass); -+ -+ if (count != null) return count; -+ -+ count = countEntityType(oclass); -+ -+ countCache.put(oclass, count); -+ + return count; + } + -+ public boolean shouldIgnoreForCount(Entity entity) { -+ if (entity == null) return true; -+ -+ if (entity instanceof EntityInsentient) { -+ EntityInsentient entityinsentient = (EntityInsentient) entity; -+ return entityinsentient.isTypeNotPersistent() && entityinsentient.isPersistent(); -+ } -+ -+ return false; ++ void clearEntityCountCache() { ++ countCache.clear(); + } + -+ protected void updateEntityCount(Class clazz, boolean incr) { -+ Integer countObject = countCache.get(clazz); ++ protected void updateEntityCount(EnumCreatureType typ, boolean incr) { ++ Integer countObject = countCache.get(typ); + + if (countObject == null) return; + @@ -127,19 +185,30 @@ index 004c3ec47..c392595c0 100644 + if (incr) count++; + else count--; + -+ if(count < 0) { ++ if (count < 0) { + e.warn("Entity count cache has gone negative"); + count = 0; + } + -+ countCache.put(clazz, count); ++ countCache.put(typ, count); + } + + protected void updateEntityCount(Entity entity, boolean incr) { -+ if (shouldIgnoreForCount(entity)) return; ++ if (entity == null || !(entity instanceof IAnimal)) return; + -+ for (Class clazz = entity.getClass() ; !clazz.equals(Object.class) ; clazz = clazz.getSuperclass()) { -+ updateEntityCount(clazz, incr); ++ 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); ++ } + } + } + // Paper end diff --git a/Spigot-Server-Patches/0334-Configurable-speed-for-water-flowing-over-lava.patch b/Spigot-Server-Patches/0334-Configurable-speed-for-water-flowing-over-lava.patch deleted file mode 100644 index d7f5d993b..000000000 --- a/Spigot-Server-Patches/0334-Configurable-speed-for-water-flowing-over-lava.patch +++ /dev/null @@ -1,65 +0,0 @@ -From b9f0b43802d049d91f4db3cf26bce5f2084de76e Mon Sep 17 00:00:00 2001 -From: Colin Godsey -Date: Wed, 8 Aug 2018 11:33:21 -0600 -Subject: [PATCH] Configurable speed for water flowing over lava - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 61c8b58b1..ab3f59ad7 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -436,6 +436,12 @@ public class PaperWorldConfig { - } - } - -+ public int waterOverLavaFlowSpeed; -+ private void waterOverLavaFlowSpeed() { -+ waterOverLavaFlowSpeed = getInt("water-over-lava-flow-speed", 5); -+ log("Water over lava flow speed: " + waterOverLavaFlowSpeed); -+ } -+ - public enum DuplicateUUIDMode { - SAFE_REGEN, REGEN, DELETE, NOTHING, WARN - } -diff --git a/src/main/java/net/minecraft/server/BlockFluids.java b/src/main/java/net/minecraft/server/BlockFluids.java -index 6ecc1f84e..637f6580b 100644 ---- a/src/main/java/net/minecraft/server/BlockFluids.java -+++ b/src/main/java/net/minecraft/server/BlockFluids.java -@@ -67,10 +67,24 @@ public class BlockFluids extends Block implements IFluidSource { - - public void onPlace(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1) { - if (this.a(world, blockposition, iblockdata)) { -- world.H().a(blockposition, iblockdata.s().c(), this.a((IWorldReader) world)); -+ world.H().a(blockposition, iblockdata.s().c(), this.getFlowSpeed(world, blockposition)); // Paper - } - - } -+ -+ /** -+ * Paper - Get flow speed. Throttle if its water and flowing adjacent to lava -+ */ -+ public int getFlowSpeed(World world, BlockPosition blockposition) { -+ if (this.material == Material.WATER && ( -+ world.getType(blockposition.north(1)).getBlock().material == Material.LAVA || -+ world.getType(blockposition.south(1)).getBlock().material == Material.LAVA || -+ world.getType(blockposition.west(1)).getBlock().material == Material.LAVA || -+ world.getType(blockposition.east(1)).getBlock().material == Material.LAVA)) { -+ return world.paperConfig.waterOverLavaFlowSpeed; -+ } -+ return this.a(world); -+ } - - public IBlockData updateState(IBlockData iblockdata, EnumDirection enumdirection, IBlockData iblockdata1, GeneratorAccess generatoraccess, BlockPosition blockposition, BlockPosition blockposition1) { - if (iblockdata.s().d() || iblockdata1.s().d()) { -@@ -82,7 +96,7 @@ public class BlockFluids extends Block implements IFluidSource { - - public void doPhysics(IBlockData iblockdata, World world, BlockPosition blockposition, Block block, BlockPosition blockposition1) { - if (this.a(world, blockposition, iblockdata)) { -- world.H().a(blockposition, iblockdata.s().c(), this.a((IWorldReader) world)); -+ world.H().a(blockposition, iblockdata.s().c(), this.getFlowSpeed(world, blockposition)); // Paper - } - - } --- -2.15.2 (Apple Git-101.1) - From 65a71d18c4af105e7431cb105acaa3e2258b705c Mon Sep 17 00:00:00 2001 From: Colin Godsey Date: Thu, 9 Aug 2018 06:35:13 -0600 Subject: [PATCH 5/8] clean up, pr fixes --- .../0333-Add-entity-count-cache.patch | 167 +++++++----------- 1 file changed, 59 insertions(+), 108 deletions(-) diff --git a/Spigot-Server-Patches/0333-Add-entity-count-cache.patch b/Spigot-Server-Patches/0333-Add-entity-count-cache.patch index ddccbd1bb..25efed0a3 100644 --- a/Spigot-Server-Patches/0333-Add-entity-count-cache.patch +++ b/Spigot-Server-Patches/0333-Add-entity-count-cache.patch @@ -1,28 +1,43 @@ -From 5b101db469123c2f92ff82fc04a8b77274296bcf Mon Sep 17 00:00:00 2001 +From 4f16c3445f22654d43ca5b2006f45fac0e17203b Mon Sep 17 00:00:00 2001 From: Colin Godsey Date: Wed, 8 Aug 2018 10:10:06 -0600 Subject: [PATCH] Add entity count cache -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 */ +diff --git a/src/main/java/net/minecraft/server/EntityInsentient.java b/src/main/java/net/minecraft/server/EntityInsentient.java +index 7b64ec27c..55606756e 100644 +--- a/src/main/java/net/minecraft/server/EntityInsentient.java ++++ b/src/main/java/net/minecraft/server/EntityInsentient.java +@@ -42,6 +42,7 @@ public abstract class EntityInsentient extends EntityLiving { + public float[] dropChanceArmor; + // public boolean canPickUpLoot; // CraftBukkit - moved up to EntityLiving + public boolean persistent; ++ public boolean countsAgainstSpawnLimit = true; // Paper + private final Map bH; + private MinecraftKey bI; + private long bJ; +diff --git a/src/main/java/net/minecraft/server/EnumCreatureType.java b/src/main/java/net/minecraft/server/EnumCreatureType.java +index 79e52f7ba..288f59ed3 100644 +--- a/src/main/java/net/minecraft/server/EnumCreatureType.java ++++ b/src/main/java/net/minecraft/server/EnumCreatureType.java +@@ -16,10 +16,17 @@ public enum EnumCreatureType { + this.h = flag1; + } -+ /* -+ * 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(); ++ public Class innerClass() { return this.a(); } // Paper - OBFHELPER + public Class a() { + return this.e; + } + ++ // Paper start ++ public boolean matches(Entity entity) { ++ return innerClass().isAssignableFrom(entity.getClass()); ++ } ++ // Paper end + - this.methodProfiler.a("tick"); - - CrashReport crashreport; + public int b() { + return this.f; + } 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 @@ -37,58 +52,18 @@ index f525fd1b4..494759a1c 100644 if (k <= l1) { diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java -index 004c3ec47..baf73a411 100644 +index 004c3ec47..dc301c6f4 100644 --- a/src/main/java/net/minecraft/server/World.java +++ b/src/main/java/net/minecraft/server/World.java -@@ -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.*; +@@ -11,6 +11,7 @@ import java.util.Iterator; + import java.util.List; + import java.util.Random; + import java.util.UUID; ++import java.util.EnumMap; // Paper 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 +@@ -50,10 +51,41 @@ public abstract class World implements GeneratorAccess, IIBlockAccess, AutoClose // Spigot start - guard entity list from removals public final List entityList = new java.util.ArrayList() { @@ -130,7 +105,7 @@ index 004c3ec47..baf73a411 100644 return super.remove( index ); } -@@ -61,6 +79,7 @@ public abstract class World implements GeneratorAccess, IIBlockAccess, AutoClose +@@ -61,6 +93,7 @@ public abstract class World implements GeneratorAccess, IIBlockAccess, AutoClose public boolean remove(Object o) { guard(); @@ -138,59 +113,33 @@ index 004c3ec47..baf73a411 100644 return super.remove( o ); } -@@ -82,6 +101,7 @@ public abstract class World implements GeneratorAccess, IIBlockAccess, AutoClose - public final Map playersByName = Maps.newHashMap(); // Paper - World EntityHuman Lookup Optimizations - public final List k = Lists.newArrayList(); - protected final IntHashMap entitiesById = new IntHashMap(); -+ private Map countCache = new EnumMap(EnumCreatureType.class); // Paper - entity count cache - 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(); -@@ -2439,6 +2459,7 @@ public abstract class World implements GeneratorAccess, IIBlockAccess, AutoClose - - } - -+ public int getEntityCount(Class oclass) { return a(oclass); } // Paper - OBFHELPER - public int a(Class oclass) { - int i = 0; - Iterator iterator = this.entityList.iterator(); -@@ -2464,6 +2485,61 @@ public abstract class World implements GeneratorAccess, IIBlockAccess, AutoClose +@@ -2464,6 +2497,53 @@ public abstract class World implements GeneratorAccess, IIBlockAccess, AutoClose return i; } + // Paper start - entity count cache -+ public int getCreatureCount(EnumCreatureType typ) { -+ Integer count = countCache.get(typ); ++ private Map countCache = new EnumMap(EnumCreatureType.class); + -+ if (count == null) { -+ count = getEntityCount(typ.a()); ++ public int getCreatureCount(EnumCreatureType type) { ++ Integer count = countCache.get(type); + -+ countCache.put(typ, count); -+ } -+ -+ return count; ++ return count == null ? 0 : count; + } + -+ void clearEntityCountCache() { -+ countCache.clear(); -+ } ++ protected void updateEntityCount(EnumCreatureType type, boolean incr) { ++ Integer countObject = countCache.get(type); + -+ protected void updateEntityCount(EnumCreatureType typ, boolean incr) { -+ Integer countObject = countCache.get(typ); -+ -+ if (countObject == null) return; -+ -+ int count = countObject; ++ int count = countObject == null ? 0 : countObject; + + if (incr) count++; + else count--; + + if (count < 0) { -+ e.warn("Entity count cache has gone negative"); ++ e.warn("Paper - Entity count cache has gone negative"); + count = 0; + } + -+ countCache.put(typ, count); ++ countCache.put(type, count); + } + + protected void updateEntityCount(Entity entity, boolean incr) { @@ -198,16 +147,18 @@ index 004c3ec47..baf73a411 100644 + + if (entity instanceof EntityInsentient) { + EntityInsentient entityinsentient = (EntityInsentient) entity; -+ if (entityinsentient.isTypeNotPersistent() && entityinsentient.isPersistent()) { ++ if (incr && entityinsentient.isTypeNotPersistent() && entityinsentient.isPersistent()) { ++ entityinsentient.countsAgainstSpawnLimit = false; ++ ++ return; ++ } else if (!incr && !entityinsentient.countsAgainstSpawnLimit) { + return; + } + } + -+ Class clazz = entity.getClass(); -+ -+ for (EnumCreatureType typ : EnumCreatureType.values()) { -+ if (typ.a().isAssignableFrom(clazz)) { -+ updateEntityCount(typ, incr); ++ for (EnumCreatureType type : EnumCreatureType.values()) { ++ if (type.matches(entity)) { ++ updateEntityCount(type, incr); + } + } + } From cec8b211d5ee90475fc14762788871bbf5253a7b Mon Sep 17 00:00:00 2001 From: Colin Godsey Date: Thu, 9 Aug 2018 06:52:41 -0600 Subject: [PATCH 6/8] Trigger From 064a3dc73196b07324ad21c00e5a7a6b5fd722f2 Mon Sep 17 00:00:00 2001 From: Colin Godsey Date: Thu, 9 Aug 2018 17:21:12 -0600 Subject: [PATCH 7/8] Trigger From 6656d07bd277fcd9d73c686766d2b68dc7b19634 Mon Sep 17 00:00:00 2001 From: Colin Godsey Date: Wed, 15 Aug 2018 15:07:30 -0600 Subject: [PATCH 8/8] pr changes, flat array --- .../0333-Add-entity-count-cache.patch | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/Spigot-Server-Patches/0333-Add-entity-count-cache.patch b/Spigot-Server-Patches/0333-Add-entity-count-cache.patch index 25efed0a3..e671dd45a 100644 --- a/Spigot-Server-Patches/0333-Add-entity-count-cache.patch +++ b/Spigot-Server-Patches/0333-Add-entity-count-cache.patch @@ -1,4 +1,4 @@ -From 4f16c3445f22654d43ca5b2006f45fac0e17203b Mon Sep 17 00:00:00 2001 +From 7077ffc2e14e2b759174392e773d65ee8ba303a5 Mon Sep 17 00:00:00 2001 From: Colin Godsey Date: Wed, 8 Aug 2018 10:10:06 -0600 Subject: [PATCH] Add entity count cache @@ -52,7 +52,7 @@ index f525fd1b4..494759a1c 100644 if (k <= l1) { diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java -index 004c3ec47..dc301c6f4 100644 +index 004c3ec47..e2d591f8f 100644 --- a/src/main/java/net/minecraft/server/World.java +++ b/src/main/java/net/minecraft/server/World.java @@ -11,6 +11,7 @@ import java.util.Iterator; @@ -113,23 +113,19 @@ index 004c3ec47..dc301c6f4 100644 return super.remove( o ); } -@@ -2464,6 +2497,53 @@ public abstract class World implements GeneratorAccess, IIBlockAccess, AutoClose +@@ -2464,6 +2497,49 @@ public abstract class World implements GeneratorAccess, IIBlockAccess, AutoClose return i; } + // Paper start - entity count cache -+ private Map countCache = new EnumMap(EnumCreatureType.class); ++ private final int[] countCache = new int[EnumCreatureType.values().length]; + + public int getCreatureCount(EnumCreatureType type) { -+ Integer count = countCache.get(type); -+ -+ return count == null ? 0 : count; ++ return countCache[type.ordinal()]; + } + + protected void updateEntityCount(EnumCreatureType type, boolean incr) { -+ Integer countObject = countCache.get(type); -+ -+ int count = countObject == null ? 0 : countObject; ++ int count = countCache[type.ordinal()]; + + if (incr) count++; + else count--; @@ -139,7 +135,7 @@ index 004c3ec47..dc301c6f4 100644 + count = 0; + } + -+ countCache.put(type, count); ++ countCache[type.ordinal()] = count; + } + + protected void updateEntityCount(Entity entity, boolean incr) {