Skip to content

Commit 37add90

Browse files
committed
fix: synchronize entity removal when needed
1 parent b935a07 commit 37add90

File tree

2 files changed

+25
-11
lines changed

2 files changed

+25
-11
lines changed

worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitEntity.java

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
package com.sk89q.worldedit.bukkit;
2121

22+
import com.fastasyncworldedit.core.util.TaskManager;
2223
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
2324
import com.sk89q.worldedit.entity.BaseEntity;
2425
import com.sk89q.worldedit.entity.Entity;
@@ -110,17 +111,21 @@ public BaseEntity getState() {
110111

111112
@Override
112113
public boolean remove() {
113-
org.bukkit.entity.Entity entity = entityRef.get();
114-
if (entity != null) {
115-
try {
116-
entity.remove();
117-
} catch (UnsupportedOperationException e) {
118-
return false;
114+
// synchronize the whole method, not just the remove operation as we always need to synchronize and
115+
// can make sure the entity reference was not invalidated in the few milliseconds between the next available tick (lol)
116+
return TaskManager.taskManager().sync(() -> {
117+
org.bukkit.entity.Entity entity = entityRef.get();
118+
if (entity != null) {
119+
try {
120+
entity.remove();
121+
} catch (UnsupportedOperationException e) {
122+
return false;
123+
}
124+
return entity.isDead();
125+
} else {
126+
return true;
119127
}
120-
return entity.isDead();
121-
} else {
122-
return true;
123-
}
128+
});
124129
}
125130

126131
@SuppressWarnings("unchecked")

worldedit-core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import com.fastasyncworldedit.core.util.ImgurUtility;
3737
import com.fastasyncworldedit.core.util.MainUtil;
3838
import com.fastasyncworldedit.core.util.MaskTraverser;
39+
import com.fastasyncworldedit.core.util.TaskManager;
3940
import com.fastasyncworldedit.core.util.task.RunnableVal;
4041
import com.google.common.collect.Lists;
4142
import com.sk89q.worldedit.EditSession;
@@ -98,6 +99,7 @@
9899
import java.net.URI;
99100
import java.net.URL;
100101
import java.nio.file.Files;
102+
import java.util.Collection;
101103
import java.util.HashSet;
102104
import java.util.List;
103105
import java.util.Set;
@@ -479,7 +481,14 @@ public void place(
479481
.apply(region.getMaximumPoint().subtract(region.getMinimumPoint()).toVector3())
480482
.toBlockPoint());
481483
if (removeEntities) {
482-
editSession.getEntities(new CuboidRegion(realTo, max)).forEach(Entity::remove);
484+
// Collect entities on the current (command) thread, in case it benefits from asynchronous retrieval (unlikely)
485+
final Collection<? extends Entity> entities = editSession.getEntities(new CuboidRegion(realTo, max));
486+
// BukkitEntity#remove is synchronized, but it makes more sense to synchronize here beforehand in case many
487+
// entities are affected. BukkitEntity will not synchronize if it's already called on the main thread.
488+
TaskManager.taskManager().sync(() -> {
489+
entities.forEach(Entity::remove);
490+
return true;
491+
});
483492
}
484493
if (selectPasted || onlySelect) {
485494
RegionSelector selector = new CuboidRegionSelector(world, realTo, max);

0 commit comments

Comments
 (0)