diff --git a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/worldedit/FastAsyncWorldEditDelegate.java b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/worldedit/FastAsyncWorldEditDelegate.java index e2523d3f1..e464eb263 100644 --- a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/worldedit/FastAsyncWorldEditDelegate.java +++ b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/worldedit/FastAsyncWorldEditDelegate.java @@ -25,7 +25,6 @@ import net.momirealms.craftengine.core.block.EmptyBlock; import net.momirealms.craftengine.core.block.ImmutableBlockState; import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.util.ReflectionUtils; -import net.momirealms.craftengine.core.util.VersionHelper; import net.momirealms.craftengine.core.world.CEWorld; import net.momirealms.craftengine.core.world.ChunkPos; import net.momirealms.craftengine.core.world.SectionPos; @@ -82,6 +81,7 @@ public class FastAsyncWorldEditDelegate extends AbstractDelegateExtent { CESection[] ceSections = ceChunk.sections(); Object worldServer = ceChunk.world().world().serverWorld(); Object chunkSource = FastNMS.INSTANCE.method$ServerLevel$getChunkSource(worldServer); + // TODO THREAD SAFETY? Object levelChunk = FastNMS.INSTANCE.method$ServerChunkCache$getChunkAtIfLoadedMainThread(chunkSource, pos.x, pos.z); Object[] sections = FastNMS.INSTANCE.method$ChunkAccess$getSections(levelChunk); for (int i = 0; i < ceSections.length; i++) { @@ -143,6 +143,7 @@ public class FastAsyncWorldEditDelegate extends AbstractDelegateExtent { @Override protected Operation commitBefore() { + saveAllChunks(); List chunks = new ArrayList<>(BROKEN_CHUNKS); BROKEN_CHUNKS.clear(); for (ChunkPos chunk : chunks) { @@ -163,7 +164,6 @@ public class FastAsyncWorldEditDelegate extends AbstractDelegateExtent { int blockZ = position.z(); this.processBlock(blockX, blockY, blockZ, blockState, oldBlockState); } - saveAllChunks(); } private void processBlock(int blockX, int blockY, int blockZ, BaseBlock newBlock, BaseBlock oldBlock) { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/FurnitureItemBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/FurnitureItemBehavior.java index f61092a23..ff062ebec 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/FurnitureItemBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/FurnitureItemBehavior.java @@ -120,10 +120,6 @@ public class FurnitureItemBehavior extends ItemBehavior { return InteractionResult.FAIL; } - if (!BukkitCraftEngine.instance().antiGrief().canPlace(bukkitPlayer, furnitureLocation)) { - return InteractionResult.FAIL; - } - FurnitureAttemptPlaceEvent attemptPlaceEvent = new FurnitureAttemptPlaceEvent(bukkitPlayer, customFurniture, anchorType, furnitureLocation.clone(), DirectionUtils.toBlockFace(clickedFace), context.getHand(), world.getBlockAt(context.getClickedPos().x(), context.getClickedPos().y(), context.getClickedPos().z())); if (EventUtils.fireAndCheckCancel(attemptPlaceEvent)) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/scheduler/AbstractJavaScheduler.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/scheduler/AbstractJavaScheduler.java index 1198fa6ea..c728459ac 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/scheduler/AbstractJavaScheduler.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/scheduler/AbstractJavaScheduler.java @@ -19,7 +19,6 @@ public abstract class AbstractJavaScheduler implements SchedulerAdapter { public AbstractJavaScheduler(Plugin plugin) { this.plugin = plugin; - this.scheduler = new ScheduledThreadPoolExecutor(4, r -> { Thread thread = Executors.defaultThreadFactory().newThread(r); thread.setName("craft-engine-scheduler"); diff --git a/core/src/main/java/net/momirealms/craftengine/core/world/chunk/storage/DelayedDefaultRegionFileStorage.java b/core/src/main/java/net/momirealms/craftengine/core/world/chunk/storage/DelayedDefaultRegionFileStorage.java index 1df369736..f711fbbb3 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/world/chunk/storage/DelayedDefaultRegionFileStorage.java +++ b/core/src/main/java/net/momirealms/craftengine/core/world/chunk/storage/DelayedDefaultRegionFileStorage.java @@ -10,6 +10,7 @@ import net.momirealms.craftengine.core.world.chunk.CEChunk; import org.jetbrains.annotations.NotNull; import java.io.IOException; +import java.nio.channels.ClosedChannelException; import java.nio.file.Path; import java.util.concurrent.TimeUnit; @@ -28,6 +29,11 @@ public class DelayedDefaultRegionFileStorage extends DefaultRegionFileStorage { if (cause == RemovalCause.EXPIRED || cause == RemovalCause.SIZE) { try { super.writeChunkAt(key, value, true); + } catch (ClosedChannelException e) { + if (this.isClosed) { + return; + } + CraftEngine.instance().logger().warn("Failed to write chunk at " + key, e); } catch (IOException e) { CraftEngine.instance().logger().warn("Failed to write chunk at " + key, e); } @@ -60,9 +66,9 @@ public class DelayedDefaultRegionFileStorage extends DefaultRegionFileStorage { @Override public synchronized void close() throws IOException { + this.isClosed = true; this.saveCache(); this.chunkCache.cleanUp(); - this.isClosed = true; super.close(); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/world/chunk/storage/RegionFile.java b/core/src/main/java/net/momirealms/craftengine/core/world/chunk/storage/RegionFile.java index b2e8ad51b..b50452bae 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/world/chunk/storage/RegionFile.java +++ b/core/src/main/java/net/momirealms/craftengine/core/world/chunk/storage/RegionFile.java @@ -11,6 +11,7 @@ import java.io.*; import java.nio.Buffer; import java.nio.ByteBuffer; import java.nio.IntBuffer; +import java.nio.channels.ClosedChannelException; import java.nio.channels.FileChannel; import java.nio.file.Files; import java.nio.file.Path; @@ -308,6 +309,9 @@ public class RegionFile implements AutoCloseable { } public void clear(ChunkPos pos) throws IOException { + if (!this.fileChannel.isOpen()) { + throw new ClosedChannelException(); + } int chunkLocation = RegionFile.getChunkLocation(pos); int sectorInfo = this.sectorInfo.get(chunkLocation); if (sectorInfo != INFO_NOT_PRESENT) { @@ -321,6 +325,9 @@ public class RegionFile implements AutoCloseable { @SuppressWarnings("ResultOfMethodCallIgnored") protected synchronized void write(ChunkPos pos, ByteBuffer buf) throws IOException { + if (!this.fileChannel.isOpen()) { + throw new ClosedChannelException(); + } // get old offset info int offsetIndex = RegionFile.getChunkLocation(pos); int previousSectorInfo = this.sectorInfo.get(offsetIndex);