mirror of
https://github.com/Winds-Studio/Leaf.git
synced 2025-12-27 02:49:19 +00:00
565 lines
24 KiB
Diff
565 lines
24 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: wangxyper <wangxyper@163.com>
|
|
Date: Thu, 12 Jan 2023 19:43:48 +0800
|
|
Subject: [PATCH] Hearse: Move player ticking to main thread and add lock in
|
|
ChunkEntitySlices
|
|
|
|
Original license: MIT
|
|
Original project: https://github.com/NaturalCodeClub/HearseRewrite
|
|
|
|
diff --git a/src/main/java/io/papermc/paper/world/ChunkEntitySlices.java b/src/main/java/io/papermc/paper/world/ChunkEntitySlices.java
|
|
index ae22ca9ea5fd3d78d8c5bf9f1ab96f1129fddc11..1012b8d1d192a946b0982c88c12a0fc0e6051972 100644
|
|
--- a/src/main/java/io/papermc/paper/world/ChunkEntitySlices.java
|
|
+++ b/src/main/java/io/papermc/paper/world/ChunkEntitySlices.java
|
|
@@ -33,7 +33,7 @@ public final class ChunkEntitySlices {
|
|
public final int chunkX;
|
|
public final int chunkZ;
|
|
protected final ServerLevel world;
|
|
-
|
|
+ protected final StampedLock accessLock = new StampedLock(); //Hearse -- fix some entity can't be removed
|
|
protected final EntityCollectionBySection allEntities;
|
|
protected final EntityCollectionBySection hardCollidingEntities;
|
|
protected final Reference2ObjectMap<Class<? extends Entity>, EntityCollectionBySection> entitiesByClass;
|
|
@@ -70,68 +70,82 @@ public final class ChunkEntitySlices {
|
|
|
|
// Paper start - optimise CraftChunk#getEntities
|
|
public org.bukkit.entity.Entity[] getChunkEntities() {
|
|
- List<org.bukkit.entity.Entity> ret = new java.util.ArrayList<>();
|
|
- final Entity[] entities = this.entities.getRawData();
|
|
- for (int i = 0, size = Math.min(entities.length, this.entities.size()); i < size; ++i) {
|
|
- final Entity entity = entities[i];
|
|
- if (entity == null) {
|
|
- continue;
|
|
- }
|
|
- final org.bukkit.entity.Entity bukkit = entity.getBukkitEntity();
|
|
- if (bukkit != null && bukkit.isValid()) {
|
|
- ret.add(bukkit);
|
|
+ final long id = this.accessLock.readLock();
|
|
+ try {
|
|
+ List<org.bukkit.entity.Entity> ret = new java.util.ArrayList<>();
|
|
+ final Entity[] entities = this.entities.getRawData();
|
|
+ for (int i = 0, size = Math.min(entities.length, this.entities.size()); i < size; ++i) {
|
|
+ final Entity entity = entities[i];
|
|
+ if (entity == null) {
|
|
+ continue;
|
|
+ }
|
|
+ final org.bukkit.entity.Entity bukkit = entity.getBukkitEntity();
|
|
+ if (bukkit != null && bukkit.isValid()) {
|
|
+ ret.add(bukkit);
|
|
+ }
|
|
}
|
|
+ return ret.toArray(new org.bukkit.entity.Entity[0]);
|
|
+ } finally {
|
|
+ this.accessLock.unlockRead(id);
|
|
}
|
|
-
|
|
- return ret.toArray(new org.bukkit.entity.Entity[0]);
|
|
}
|
|
|
|
public CompoundTag save() {
|
|
- final int len = this.entities.size();
|
|
- if (len == 0) {
|
|
- return null;
|
|
- }
|
|
+ final long id = this.accessLock.readLock();
|
|
+ try {
|
|
+ final int len = this.entities.size();
|
|
+ if (len == 0) {
|
|
+ return null;
|
|
+ }
|
|
|
|
- final Entity[] rawData = this.entities.getRawData();
|
|
- final List<Entity> collectedEntities = new ArrayList<>(len);
|
|
- for (int i = 0; i < len; ++i) {
|
|
- final Entity entity = rawData[i];
|
|
- if (entity.shouldBeSaved()) {
|
|
- collectedEntities.add(entity);
|
|
+ final Entity[] rawData = this.entities.getRawData();
|
|
+ final List<Entity> collectedEntities = new ArrayList<>(len);
|
|
+ for (int i = 0; i < len; ++i) {
|
|
+ final Entity entity = rawData[i];
|
|
+ if (entity.shouldBeSaved()) {
|
|
+ collectedEntities.add(entity);
|
|
+ }
|
|
}
|
|
- }
|
|
|
|
- if (collectedEntities.isEmpty()) {
|
|
- return null;
|
|
- }
|
|
+ if (collectedEntities.isEmpty()) {
|
|
+ return null;
|
|
+ }
|
|
|
|
- return EntityStorage.saveEntityChunk(collectedEntities, new ChunkPos(this.chunkX, this.chunkZ), this.world);
|
|
+ return EntityStorage.saveEntityChunk(collectedEntities, new ChunkPos(this.chunkX, this.chunkZ), this.world);
|
|
+ } finally {
|
|
+ this.accessLock.unlockRead(id);
|
|
+ }
|
|
}
|
|
|
|
// returns true if this chunk has transient entities remaining
|
|
public boolean unload() {
|
|
- final int len = this.entities.size();
|
|
- final Entity[] collectedEntities = Arrays.copyOf(this.entities.getRawData(), len);
|
|
-
|
|
- for (int i = 0; i < len; ++i) {
|
|
- final Entity entity = collectedEntities[i];
|
|
- if (entity.isRemoved()) {
|
|
- // removed by us below
|
|
- continue;
|
|
- }
|
|
- if (entity.shouldBeSaved()) {
|
|
- entity.setRemoved(Entity.RemovalReason.UNLOADED_TO_CHUNK);
|
|
- if (entity.isVehicle()) {
|
|
- // we cannot assume that these entities are contained within this chunk, because entities can
|
|
- // desync - so we need to remove them all
|
|
- for (final Entity passenger : entity.getIndirectPassengers()) {
|
|
- passenger.setRemoved(Entity.RemovalReason.UNLOADED_TO_CHUNK);
|
|
+ long id = this.accessLock.readLock();
|
|
+ try {
|
|
+ final int len = this.entities.size();
|
|
+ final Entity[] collectedEntities = Arrays.copyOf(this.entities.getRawData(), len);
|
|
+
|
|
+ for (int i = 0; i < len; ++i) {
|
|
+ final Entity entity = collectedEntities[i];
|
|
+ if (entity.isRemoved()) {
|
|
+ // removed by us below
|
|
+ continue;
|
|
+ }
|
|
+ if (entity.shouldBeSaved()) {
|
|
+ entity.setRemoved(Entity.RemovalReason.UNLOADED_TO_CHUNK);
|
|
+ if (entity.isVehicle()) {
|
|
+ // we cannot assume that these entities are contained within this chunk, because entities can
|
|
+ // desync - so we need to remove them all
|
|
+ for (final Entity passenger : entity.getIndirectPassengers()) {
|
|
+ passenger.setRemoved(Entity.RemovalReason.UNLOADED_TO_CHUNK);
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
- }
|
|
|
|
- return this.entities.size() != 0;
|
|
+ return this.entities.size() != 0;
|
|
+ } finally {
|
|
+ this.accessLock.unlockRead(id);
|
|
+ }
|
|
}
|
|
|
|
private List<Entity> getAllEntities() {
|
|
@@ -142,42 +156,65 @@ public final class ChunkEntitySlices {
|
|
|
|
final Entity[] rawData = this.entities.getRawData();
|
|
final List<Entity> collectedEntities = new ArrayList<>(len);
|
|
- for (int i = 0; i < len; ++i) {
|
|
- collectedEntities.add(rawData[i]);
|
|
- }
|
|
+ collectedEntities.addAll(Arrays.asList(rawData).subList(0, len));
|
|
|
|
return collectedEntities;
|
|
}
|
|
|
|
public void callEntitiesLoadEvent() {
|
|
- CraftEventFactory.callEntitiesLoadEvent(this.world, new ChunkPos(this.chunkX, this.chunkZ), this.getAllEntities());
|
|
+ final long id = this.accessLock.readLock();
|
|
+ try {
|
|
+ CraftEventFactory.callEntitiesLoadEvent(this.world, new ChunkPos(this.chunkX, this.chunkZ), this.getAllEntities());
|
|
+ } finally {
|
|
+ this.accessLock.unlockRead(id);
|
|
+ }
|
|
}
|
|
|
|
public void callEntitiesUnloadEvent() {
|
|
- CraftEventFactory.callEntitiesUnloadEvent(this.world, new ChunkPos(this.chunkX, this.chunkZ), this.getAllEntities());
|
|
+ final long id = this.accessLock.readLock();
|
|
+ try {
|
|
+ CraftEventFactory.callEntitiesUnloadEvent(this.world, new ChunkPos(this.chunkX, this.chunkZ), this.getAllEntities());
|
|
+ } finally {
|
|
+ this.accessLock.unlockRead(id);
|
|
+ }
|
|
}
|
|
// Paper end - optimise CraftChunk#getEntities
|
|
|
|
public boolean isEmpty() {
|
|
- return this.entities.size() == 0;
|
|
+ final long id = this.accessLock.readLock();
|
|
+ try {
|
|
+ return this.entities.size() == 0;
|
|
+ } finally {
|
|
+ this.accessLock.unlockRead(id);
|
|
+ }
|
|
}
|
|
|
|
public void mergeInto(final ChunkEntitySlices slices) {
|
|
- final Entity[] entities = this.entities.getRawData();
|
|
- for (int i = 0, size = Math.min(entities.length, this.entities.size()); i < size; ++i) {
|
|
- final Entity entity = entities[i];
|
|
- slices.addEntity(entity, entity.sectionY);
|
|
+ final long id = this.accessLock.readLock();
|
|
+ try {
|
|
+ final Entity[] entities = this.entities.getRawData();
|
|
+ for (int i = 0, size = Math.min(entities.length, this.entities.size()); i < size; ++i) {
|
|
+ final Entity entity = entities[i];
|
|
+ slices.addEntity(entity, entity.sectionY);
|
|
+ }
|
|
+ } finally {
|
|
+ this.accessLock.unlockRead(id);
|
|
}
|
|
}
|
|
|
|
public void updateStatus(final ChunkHolder.FullChunkStatus status, final EntityLookup lookup) {
|
|
this.status = status;
|
|
|
|
- final Entity[] entities = this.entities.getRawData();
|
|
+ Entity[] entities;
|
|
|
|
- for (int i = 0, size = this.entities.size(); i < size; ++i) {
|
|
- final Entity entity = entities[i];
|
|
+ final long id = this.accessLock.readLock();
|
|
+ try {
|
|
+ entities = Arrays.copyOf(this.entities.getRawData(), this.entities.getRawData().length);
|
|
+ } finally {
|
|
+ this.accessLock.unlockRead(id);
|
|
+ }
|
|
|
|
+ for (final Entity entity : entities) {
|
|
final Visibility oldVisibility = EntityLookup.getEntityStatus(entity);
|
|
entity.chunkStatus = status;
|
|
final Visibility newVisibility = EntityLookup.getEntityStatus(entity);
|
|
@@ -187,70 +224,95 @@ public final class ChunkEntitySlices {
|
|
}
|
|
|
|
public boolean addEntity(final Entity entity, final int chunkSection) {
|
|
- if (!this.entities.add(entity)) {
|
|
- return false;
|
|
- }
|
|
- entity.chunkStatus = this.status;
|
|
- final int sectionIndex = chunkSection - this.minSection;
|
|
-
|
|
- this.allEntities.addEntity(entity, sectionIndex);
|
|
+ long id = this.accessLock.writeLock();
|
|
+ try {
|
|
+ if (!this.entities.add(entity)) {
|
|
+ return false;
|
|
+ }
|
|
+ entity.chunkStatus = this.status;
|
|
+ final int sectionIndex = chunkSection - this.minSection;
|
|
|
|
- if (entity.hardCollides()) {
|
|
- this.hardCollidingEntities.addEntity(entity, sectionIndex);
|
|
- }
|
|
+ this.allEntities.addEntity(entity, sectionIndex);
|
|
|
|
- for (final Iterator<Reference2ObjectMap.Entry<Class<? extends Entity>, EntityCollectionBySection>> iterator =
|
|
- this.entitiesByClass.reference2ObjectEntrySet().iterator(); iterator.hasNext();) {
|
|
- final Reference2ObjectMap.Entry<Class<? extends Entity>, EntityCollectionBySection> entry = iterator.next();
|
|
+ if (entity.hardCollides()) {
|
|
+ this.hardCollidingEntities.addEntity(entity, sectionIndex);
|
|
+ }
|
|
|
|
- if (entry.getKey().isInstance(entity)) {
|
|
- entry.getValue().addEntity(entity, sectionIndex);
|
|
+ for (final Reference2ObjectMap.Entry<Class<? extends Entity>, EntityCollectionBySection> entry : this.entitiesByClass.reference2ObjectEntrySet()) {
|
|
+ if (entry.getKey().isInstance(entity)) {
|
|
+ entry.getValue().addEntity(entity, sectionIndex);
|
|
+ }
|
|
}
|
|
+ } finally {
|
|
+ this.accessLock.unlockWrite(id);
|
|
}
|
|
-
|
|
return true;
|
|
}
|
|
|
|
public boolean removeEntity(final Entity entity, final int chunkSection) {
|
|
- if (!this.entities.remove(entity)) {
|
|
- return false;
|
|
- }
|
|
- entity.chunkStatus = null;
|
|
- final int sectionIndex = chunkSection - this.minSection;
|
|
-
|
|
- this.allEntities.removeEntity(entity, sectionIndex);
|
|
+ long id = this.accessLock.writeLock();
|
|
+ try {
|
|
+ if (!this.entities.remove(entity)) {
|
|
+ return false;
|
|
+ }
|
|
+ entity.chunkStatus = null;
|
|
+ final int sectionIndex = chunkSection - this.minSection;
|
|
|
|
- if (entity.hardCollides()) {
|
|
- this.hardCollidingEntities.removeEntity(entity, sectionIndex);
|
|
- }
|
|
+ this.allEntities.removeEntity(entity, sectionIndex);
|
|
|
|
- for (final Iterator<Reference2ObjectMap.Entry<Class<? extends Entity>, EntityCollectionBySection>> iterator =
|
|
- this.entitiesByClass.reference2ObjectEntrySet().iterator(); iterator.hasNext();) {
|
|
- final Reference2ObjectMap.Entry<Class<? extends Entity>, EntityCollectionBySection> entry = iterator.next();
|
|
+ if (entity.hardCollides()) {
|
|
+ this.hardCollidingEntities.removeEntity(entity, sectionIndex);
|
|
+ }
|
|
|
|
- if (entry.getKey().isInstance(entity)) {
|
|
- entry.getValue().removeEntity(entity, sectionIndex);
|
|
+ for (final Reference2ObjectMap.Entry<Class<? extends Entity>, EntityCollectionBySection> entry : this.entitiesByClass.reference2ObjectEntrySet()) {
|
|
+ if (entry.getKey().isInstance(entity)) {
|
|
+ entry.getValue().removeEntity(entity, sectionIndex);
|
|
+ }
|
|
}
|
|
+ } finally {
|
|
+ this.accessLock.unlockWrite(id);
|
|
}
|
|
-
|
|
return true;
|
|
}
|
|
|
|
public void getHardCollidingEntities(final Entity except, final AABB box, final List<Entity> into, final Predicate<? super Entity> predicate) {
|
|
- this.hardCollidingEntities.getEntities(except, box, into, predicate);
|
|
+ final long id = this.accessLock.readLock();
|
|
+ try {
|
|
+ this.hardCollidingEntities.getEntities(except, box, into, predicate);
|
|
+ } finally {
|
|
+ this.accessLock.unlockRead(id);
|
|
+ }
|
|
}
|
|
|
|
public void getEntities(final Entity except, final AABB box, final List<Entity> into, final Predicate<? super Entity> predicate) {
|
|
- this.allEntities.getEntitiesWithEnderDragonParts(except, box, into, predicate);
|
|
+ final long id = this.accessLock.readLock();
|
|
+ try {
|
|
+ this.allEntities.getEntitiesWithEnderDragonParts(except, box, into, predicate);
|
|
+ } finally {
|
|
+ this.accessLock.unlockRead(id);
|
|
+ }
|
|
+
|
|
}
|
|
|
|
public void getEntitiesWithoutDragonParts(final Entity except, final AABB box, final List<Entity> into, final Predicate<? super Entity> predicate) {
|
|
- this.allEntities.getEntities(except, box, into, predicate);
|
|
+ final long id = this.accessLock.readLock();
|
|
+ try {
|
|
+ this.allEntities.getEntities(except, box, into, predicate);
|
|
+ } finally {
|
|
+ this.accessLock.unlockRead(id);
|
|
+ }
|
|
+
|
|
}
|
|
|
|
public <T extends Entity> void getEntities(final EntityType<?> type, final AABB box, final List<? super T> into,
|
|
final Predicate<? super T> predicate) {
|
|
- this.allEntities.getEntities(type, box, (List)into, (Predicate)predicate);
|
|
+ final long id = this.accessLock.readLock();
|
|
+ try {
|
|
+ this.allEntities.getEntities(type, box, (List) into, (Predicate) predicate);
|
|
+ } finally {
|
|
+ this.accessLock.unlockRead(id);
|
|
+ }
|
|
+
|
|
}
|
|
|
|
protected EntityCollectionBySection initClass(final Class<? extends Entity> clazz) {
|
|
@@ -278,12 +340,17 @@ public final class ChunkEntitySlices {
|
|
|
|
public <T extends Entity> void getEntities(final Class<? extends T> clazz, final Entity except, final AABB box, final List<? super T> into,
|
|
final Predicate<? super T> predicate) {
|
|
- EntityCollectionBySection collection = this.entitiesByClass.get(clazz);
|
|
- if (collection != null) {
|
|
- collection.getEntitiesWithEnderDragonParts(except, clazz, box, (List)into, (Predicate)predicate);
|
|
- } else {
|
|
- this.entitiesByClass.putIfAbsent(clazz, collection = this.initClass(clazz));
|
|
- collection.getEntitiesWithEnderDragonParts(except, clazz, box, (List)into, (Predicate)predicate);
|
|
+ final long id = this.accessLock.readLock();
|
|
+ try {
|
|
+ EntityCollectionBySection collection = this.entitiesByClass.get(clazz);
|
|
+ if (collection != null) {
|
|
+ collection.getEntitiesWithEnderDragonParts(except, clazz, box, (List) into, (Predicate) predicate);
|
|
+ } else {
|
|
+ this.entitiesByClass.putIfAbsent(clazz, collection = this.initClass(clazz));
|
|
+ collection.getEntitiesWithEnderDragonParts(except, clazz, box, (List) into, (Predicate) predicate);
|
|
+ }
|
|
+ } finally {
|
|
+ this.accessLock.unlockRead(id);
|
|
}
|
|
}
|
|
|
|
@@ -300,7 +367,7 @@ public final class ChunkEntitySlices {
|
|
}
|
|
|
|
public BasicEntityList(final int cap) {
|
|
- this.storage = (E[])(cap <= 0 ? EMPTY : new Entity[cap]);
|
|
+ this.storage = (E[]) (cap <= 0 ? EMPTY : new Entity[cap]);
|
|
}
|
|
|
|
public synchronized boolean isEmpty() {
|
|
@@ -313,7 +380,7 @@ public final class ChunkEntitySlices {
|
|
|
|
private void resize() {
|
|
if (this.storage == EMPTY) {
|
|
- this.storage = (E[])new Entity[DEFAULT_CAPACITY];
|
|
+ this.storage = (E[]) new Entity[DEFAULT_CAPACITY];
|
|
} else {
|
|
this.storage = Arrays.copyOf(this.storage, this.storage.length * 2);
|
|
}
|
|
@@ -396,7 +463,7 @@ public final class ChunkEntitySlices {
|
|
|
|
list.add(entity);
|
|
++this.count;
|
|
- }finally {
|
|
+ } finally {
|
|
this.listLock.unlockWrite(id);
|
|
}
|
|
}
|
|
@@ -416,7 +483,7 @@ public final class ChunkEntitySlices {
|
|
this.entitiesBySection[sectionIndex] = null;
|
|
this.nonEmptyBitset[sectionIndex >>> 6] ^= (1L << (sectionIndex & (Long.SIZE - 1)));
|
|
}
|
|
- }finally {
|
|
+ } finally {
|
|
this.listLock.unlockWrite(id);
|
|
}
|
|
}
|
|
@@ -459,65 +526,65 @@ public final class ChunkEntitySlices {
|
|
into.add(entity);
|
|
}
|
|
}
|
|
- }finally {
|
|
+ } finally {
|
|
this.listLock.unlockRead(id);
|
|
}
|
|
}
|
|
|
|
public void getEntitiesWithEnderDragonParts(final Entity except, final AABB box, final List<Entity> into,
|
|
final Predicate<? super Entity> predicate) {
|
|
- final long id = this.listLock.readLock();
|
|
- try {
|
|
- if (this.count == 0) {
|
|
- return;
|
|
- }
|
|
+ final long id = this.listLock.readLock();
|
|
+ try {
|
|
+ if (this.count == 0) {
|
|
+ return;
|
|
+ }
|
|
|
|
- final int minSection = this.manager.minSection;
|
|
- final int maxSection = this.manager.maxSection;
|
|
+ final int minSection = this.manager.minSection;
|
|
+ final int maxSection = this.manager.maxSection;
|
|
|
|
- final int min = Mth.clamp(Mth.floor(box.minY - 2.0) >> 4, minSection, maxSection);
|
|
- final int max = Mth.clamp(Mth.floor(box.maxY + 2.0) >> 4, minSection, maxSection);
|
|
+ final int min = Mth.clamp(Mth.floor(box.minY - 2.0) >> 4, minSection, maxSection);
|
|
+ final int max = Mth.clamp(Mth.floor(box.maxY + 2.0) >> 4, minSection, maxSection);
|
|
|
|
- final BasicEntityList<Entity>[] entitiesBySection = this.entitiesBySection;
|
|
+ final BasicEntityList<Entity>[] entitiesBySection = this.entitiesBySection;
|
|
|
|
- for (int section = min; section <= max; ++section) {
|
|
- final BasicEntityList<Entity> list = entitiesBySection[section - minSection];
|
|
+ for (int section = min; section <= max; ++section) {
|
|
+ final BasicEntityList<Entity> list = entitiesBySection[section - minSection];
|
|
|
|
- if (list == null) {
|
|
- continue;
|
|
- }
|
|
+ if (list == null) {
|
|
+ continue;
|
|
+ }
|
|
|
|
- final Entity[] storage = list.storage;
|
|
+ final Entity[] storage = list.storage;
|
|
|
|
- for (int i = 0, len = Math.min(storage.length, list.size()); i < len; ++i) {
|
|
- final Entity entity = storage[i];
|
|
+ for (int i = 0, len = Math.min(storage.length, list.size()); i < len; ++i) {
|
|
+ final Entity entity = storage[i];
|
|
|
|
- if (entity == null || entity == except || !entity.getBoundingBox().intersects(box)) {
|
|
- continue;
|
|
- }
|
|
+ if (entity == null || entity == except || !entity.getBoundingBox().intersects(box)) {
|
|
+ continue;
|
|
+ }
|
|
|
|
- if (predicate == null || predicate.test(entity)) {
|
|
- into.add(entity);
|
|
- } // else: continue to test the ender dragon parts
|
|
+ if (predicate == null || predicate.test(entity)) {
|
|
+ into.add(entity);
|
|
+ } // else: continue to test the ender dragon parts
|
|
|
|
- if (entity instanceof EnderDragon) {
|
|
- for (final EnderDragonPart part : ((EnderDragon)entity).subEntities) {
|
|
- if (part == except || !part.getBoundingBox().intersects(box)) {
|
|
- continue;
|
|
- }
|
|
+ if (entity instanceof EnderDragon) {
|
|
+ for (final EnderDragonPart part : ((EnderDragon) entity).subEntities) {
|
|
+ if (part == except || !part.getBoundingBox().intersects(box)) {
|
|
+ continue;
|
|
+ }
|
|
|
|
- if (predicate != null && !predicate.test(part)) {
|
|
- continue;
|
|
- }
|
|
+ if (predicate != null && !predicate.test(part)) {
|
|
+ continue;
|
|
+ }
|
|
|
|
- into.add(part);
|
|
- }
|
|
- }
|
|
- }
|
|
- }
|
|
- }finally {
|
|
- this.listLock.unlockRead(id);
|
|
- }
|
|
+ into.add(part);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ } finally {
|
|
+ this.listLock.unlockRead(id);
|
|
+ }
|
|
}
|
|
|
|
public void getEntitiesWithEnderDragonParts(final Entity except, final Class<?> clazz, final AABB box, final List<Entity> into,
|
|
@@ -557,7 +624,7 @@ public final class ChunkEntitySlices {
|
|
} // else: continue to test the ender dragon parts
|
|
|
|
if (entity instanceof EnderDragon) {
|
|
- for (final EnderDragonPart part : ((EnderDragon)entity).subEntities) {
|
|
+ for (final EnderDragonPart part : ((EnderDragon) entity).subEntities) {
|
|
if (part == except || !part.getBoundingBox().intersects(box) || !clazz.isInstance(part)) {
|
|
continue;
|
|
}
|
|
@@ -571,7 +638,7 @@ public final class ChunkEntitySlices {
|
|
}
|
|
}
|
|
}
|
|
- }finally {
|
|
+ } finally {
|
|
this.listLock.unlockRead(id);
|
|
}
|
|
}
|
|
@@ -608,14 +675,14 @@ public final class ChunkEntitySlices {
|
|
continue;
|
|
}
|
|
|
|
- if (predicate != null && !predicate.test((T)entity)) {
|
|
+ if (predicate != null && !predicate.test((T) entity)) {
|
|
continue;
|
|
}
|
|
|
|
- into.add((T)entity);
|
|
+ into.add((T) entity);
|
|
}
|
|
}
|
|
- }finally {
|
|
+ } finally {
|
|
this.listLock.unlockRead(id);
|
|
}
|
|
}
|