mirror of
https://github.com/PaperMC/Paper.git
synced 2025-01-04 10:11:29 +01:00
21ae8ff67e
Developers!: You will need to clean up your work/Minecraft/1.13.2 folder for this Upstream has released updates that appears to apply and compile correctly. This update has not been tested by PaperMC and as with ANY update, please do your own testing Bukkit Changes: b850a822 SPIGOT-4526: Add conversion time API for Zombie & subclasses CraftBukkit Changes:38cf676e
SPIGOT-4534: CreatureSpawnEvent not being called for CHUNK_GENb446cb5d
SPIGOT-4527: Fix sponges with waterlogged blocks6ec8ea5c
SPIGOT-4526: Add conversion time API for Zombie & subclassesc64fe508
Mappings Updatea3c2ec03
Fix missing ServerListPingEvent call for legacy pings Spigot Changes: 1dc156ce Rebuild patches 140f654d Mappings Update
212 lines
No EOL
8.1 KiB
Diff
212 lines
No EOL
8.1 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Colin Godsey <crgodsey@gmail.com>
|
|
Date: Wed, 8 Aug 2018 10:10:06 -0600
|
|
Subject: [PATCH] Cache World Entity Type counts
|
|
|
|
Optimizes mob spawning by keeping a count of entities by type
|
|
|
|
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldEntityList.java b/src/main/java/com/destroystokyo/paper/PaperWorldEntityList.java
|
|
new file mode 100644
|
|
index 000000000..a10a5bc13
|
|
--- /dev/null
|
|
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldEntityList.java
|
|
@@ -0,0 +0,0 @@
|
|
+package com.destroystokyo.paper;
|
|
+
|
|
+import net.minecraft.server.Entity;
|
|
+import net.minecraft.server.EntityInsentient;
|
|
+import net.minecraft.server.EnumCreatureType;
|
|
+import net.minecraft.server.IAnimal;
|
|
+import net.minecraft.server.MinecraftServer;
|
|
+import net.minecraft.server.World;
|
|
+import net.minecraft.server.WorldServer;
|
|
+
|
|
+import java.util.ArrayList;
|
|
+import java.util.Collection;
|
|
+
|
|
+public class PaperWorldEntityList extends ArrayList<Entity> {
|
|
+
|
|
+ private final WorldServer world;
|
|
+ private final int[] entityCounts = new int[EnumCreatureType.values().length];
|
|
+
|
|
+
|
|
+ public PaperWorldEntityList(World world) {
|
|
+ this.world = (WorldServer) world;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean addAll(Collection<? extends Entity> c) {
|
|
+ for (Entity e : c) {
|
|
+ updateEntityCount(e, 1);
|
|
+ }
|
|
+
|
|
+ return super.addAll(c);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean removeAll(Collection<?> c) {
|
|
+ for (Object e : c) {
|
|
+ if (e instanceof Entity && ((Entity) e).getWorld() == world) {
|
|
+ updateEntityCount((Entity) e, -1);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return super.removeAll(c);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean add(Entity e) {
|
|
+ updateEntityCount(e, 1);
|
|
+
|
|
+ return super.add(e);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public Entity remove(int index) {
|
|
+ guard();
|
|
+ Entity entity = super.remove(index);
|
|
+ if (entity != null) updateEntityCount(entity, -1);
|
|
+ return entity;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean remove(Object o) {
|
|
+ guard();
|
|
+ if (super.remove(o)) {
|
|
+ updateEntityCount((Entity) o, -1);
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ private void guard() {
|
|
+ if (world.guardEntityList) {
|
|
+ throw new java.util.ConcurrentModificationException();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public int getCreatureCount(EnumCreatureType type) {
|
|
+ return entityCounts[type.ordinal()];
|
|
+ }
|
|
+
|
|
+ private void updateEntityCount(EnumCreatureType type, int amt) {
|
|
+ int count = entityCounts[type.ordinal()];
|
|
+
|
|
+ count += amt;
|
|
+
|
|
+ if (count < 0) {
|
|
+ MinecraftServer.LOGGER.error("Paper - Entity count cache has gone negative");
|
|
+ count = 0;
|
|
+ }
|
|
+
|
|
+ entityCounts[type.ordinal()] = count;
|
|
+ }
|
|
+
|
|
+ public void updateEntityCount(Entity entity, int amt) {
|
|
+ if (!(entity instanceof IAnimal)) return;
|
|
+
|
|
+ if (entity instanceof EntityInsentient) {
|
|
+ EntityInsentient entityinsentient = (EntityInsentient) entity;
|
|
+ if (amt > 0 && entityinsentient.isTypeNotPersistent() && entityinsentient.isPersistent()) {
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+ if (amt < 0) {
|
|
+ if (!entity.hasBeenCounted) {
|
|
+ return;
|
|
+ }
|
|
+ // Only remove once, we remove from if the entity list is guarded, but may be called later
|
|
+ entity.hasBeenCounted = false;
|
|
+ } else {
|
|
+ if (entity.hasBeenCounted) {
|
|
+ return;
|
|
+ }
|
|
+ entity.hasBeenCounted = true;
|
|
+ }
|
|
+
|
|
+ for (EnumCreatureType type : EnumCreatureType.values()) {
|
|
+ if (type.matches(entity)) {
|
|
+ updateEntityCount(type, amt);
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
|
|
index e9543c06c..c083b2dd3 100644
|
|
--- a/src/main/java/net/minecraft/server/Entity.java
|
|
+++ b/src/main/java/net/minecraft/server/Entity.java
|
|
@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke
|
|
private boolean az;
|
|
public boolean dead;
|
|
public boolean shouldBeRemoved; // Paper
|
|
+ public boolean hasBeenCounted = false; // Paper
|
|
public float width;
|
|
public float length;
|
|
public float J;
|
|
diff --git a/src/main/java/net/minecraft/server/EnumCreatureType.java b/src/main/java/net/minecraft/server/EnumCreatureType.java
|
|
index 8874a05be..0af387c05 100644
|
|
--- a/src/main/java/net/minecraft/server/EnumCreatureType.java
|
|
+++ b/src/main/java/net/minecraft/server/EnumCreatureType.java
|
|
@@ -0,0 +0,0 @@ public enum EnumCreatureType {
|
|
this.h = flag1;
|
|
}
|
|
|
|
+ public boolean matches(Entity entity) { return innerClass().isAssignableFrom(entity.getClass()); } // Paper
|
|
+ public Class<? extends IAnimal> innerClass() { return this.a(); } // Paper - OBFHELPER
|
|
public Class<? extends IAnimal> a() {
|
|
return this.e;
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/server/SpawnerCreature.java b/src/main/java/net/minecraft/server/SpawnerCreature.java
|
|
index 72cd9ba58..35205561b 100644
|
|
--- a/src/main/java/net/minecraft/server/SpawnerCreature.java
|
|
+++ b/src/main/java/net/minecraft/server/SpawnerCreature.java
|
|
@@ -0,0 +0,0 @@ public final class SpawnerCreature {
|
|
|
|
if ((!enumcreaturetype.c() || flag1) && (enumcreaturetype.c() || flag) && (!enumcreaturetype.d() || flag2)) {
|
|
k = limit * i / SpawnerCreature.b; // CraftBukkit - use per-world limits
|
|
- int l1 = worldserver.a(enumcreaturetype.a(), k);
|
|
+ int l1 = worldserver.entityList.getCreatureCount(enumcreaturetype); // Paper - entity count cache
|
|
|
|
if (l1 <= k) {
|
|
BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition();
|
|
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
|
|
index bd6f64e52..67a903a62 100644
|
|
--- a/src/main/java/net/minecraft/server/World.java
|
|
+++ b/src/main/java/net/minecraft/server/World.java
|
|
@@ -0,0 +0,0 @@ public abstract class World implements IEntityAccess, GeneratorAccess, IIBlockAc
|
|
private static final EnumDirection[] a = EnumDirection.values();
|
|
private int b = 63;
|
|
// Spigot start - guard entity list from removals
|
|
- public final List<Entity> entityList = new java.util.ArrayList<Entity>()
|
|
+ public final com.destroystokyo.paper.PaperWorldEntityList entityList = new com.destroystokyo.paper.PaperWorldEntityList(this);
|
|
+ /* // Paper start
|
|
{
|
|
@Override
|
|
public Entity remove(int index)
|
|
@@ -0,0 +0,0 @@ public abstract class World implements IEntityAccess, GeneratorAccess, IIBlockAc
|
|
}
|
|
}
|
|
};
|
|
+ */ // Paper end
|
|
// Spigot end
|
|
protected final Set<Entity> g = com.google.common.collect.Sets.newHashSet(); public Set<Entity> getEntityUnloadQueue() { return g; };// Paper - OBFHELPER
|
|
//public final List<TileEntity> tileEntityList = Lists.newArrayList(); // Paper - remove unused list
|
|
@@ -0,0 +0,0 @@ public abstract class World implements IEntityAccess, GeneratorAccess, IIBlockAc
|
|
public final com.destroystokyo.paper.PaperWorldConfig paperConfig; // Paper
|
|
|
|
public final co.aikar.timings.WorldTimingsHandler timings; // Paper
|
|
- private boolean guardEntityList; // Spigot
|
|
+ public boolean guardEntityList; // Spigot // Paper - public
|
|
public static boolean haveWeSilencedAPhysicsCrash;
|
|
public static String blockLocation;
|
|
private org.spigotmc.TickLimiter entityLimiter;
|
|
@@ -0,0 +0,0 @@ public abstract class World implements IEntityAccess, GeneratorAccess, IIBlockAc
|
|
this.getChunkAt(i, j).b(entity);
|
|
}
|
|
entity.shouldBeRemoved = true; // Paper
|
|
+ entityList.updateEntityCount(entity, -1); // Paper
|
|
|
|
if (!guardEntityList) { // Spigot - It will get removed after the tick if we are ticking // Paper - always remove from current chunk above
|
|
// CraftBukkit start - Decrement loop variable field if we've already ticked this entity
|
|
--
|