9
0
mirror of https://github.com/Xiao-MoMi/craft-engine.git synced 2026-01-06 15:52:03 +00:00

提高延迟区域存储的稳定性

This commit is contained in:
XiaoMoMi
2025-05-07 01:54:51 +08:00
parent b01d564e4f
commit daf2ac3e8a
5 changed files with 16 additions and 8 deletions

View File

@@ -25,7 +25,6 @@ import net.momirealms.craftengine.core.block.EmptyBlock;
import net.momirealms.craftengine.core.block.ImmutableBlockState; import net.momirealms.craftengine.core.block.ImmutableBlockState;
import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.util.ReflectionUtils; 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.CEWorld;
import net.momirealms.craftengine.core.world.ChunkPos; import net.momirealms.craftengine.core.world.ChunkPos;
import net.momirealms.craftengine.core.world.SectionPos; import net.momirealms.craftengine.core.world.SectionPos;
@@ -82,6 +81,7 @@ public class FastAsyncWorldEditDelegate extends AbstractDelegateExtent {
CESection[] ceSections = ceChunk.sections(); CESection[] ceSections = ceChunk.sections();
Object worldServer = ceChunk.world().world().serverWorld(); Object worldServer = ceChunk.world().world().serverWorld();
Object chunkSource = FastNMS.INSTANCE.method$ServerLevel$getChunkSource(worldServer); Object chunkSource = FastNMS.INSTANCE.method$ServerLevel$getChunkSource(worldServer);
// TODO THREAD SAFETY?
Object levelChunk = FastNMS.INSTANCE.method$ServerChunkCache$getChunkAtIfLoadedMainThread(chunkSource, pos.x, pos.z); Object levelChunk = FastNMS.INSTANCE.method$ServerChunkCache$getChunkAtIfLoadedMainThread(chunkSource, pos.x, pos.z);
Object[] sections = FastNMS.INSTANCE.method$ChunkAccess$getSections(levelChunk); Object[] sections = FastNMS.INSTANCE.method$ChunkAccess$getSections(levelChunk);
for (int i = 0; i < ceSections.length; i++) { for (int i = 0; i < ceSections.length; i++) {
@@ -143,6 +143,7 @@ public class FastAsyncWorldEditDelegate extends AbstractDelegateExtent {
@Override @Override
protected Operation commitBefore() { protected Operation commitBefore() {
saveAllChunks();
List<ChunkPos> chunks = new ArrayList<>(BROKEN_CHUNKS); List<ChunkPos> chunks = new ArrayList<>(BROKEN_CHUNKS);
BROKEN_CHUNKS.clear(); BROKEN_CHUNKS.clear();
for (ChunkPos chunk : chunks) { for (ChunkPos chunk : chunks) {
@@ -163,7 +164,6 @@ public class FastAsyncWorldEditDelegate extends AbstractDelegateExtent {
int blockZ = position.z(); int blockZ = position.z();
this.processBlock(blockX, blockY, blockZ, blockState, oldBlockState); this.processBlock(blockX, blockY, blockZ, blockState, oldBlockState);
} }
saveAllChunks();
} }
private void processBlock(int blockX, int blockY, int blockZ, BaseBlock newBlock, BaseBlock oldBlock) { private void processBlock(int blockX, int blockY, int blockZ, BaseBlock newBlock, BaseBlock oldBlock) {

View File

@@ -120,10 +120,6 @@ public class FurnitureItemBehavior extends ItemBehavior {
return InteractionResult.FAIL; return InteractionResult.FAIL;
} }
if (!BukkitCraftEngine.instance().antiGrief().canPlace(bukkitPlayer, furnitureLocation)) {
return InteractionResult.FAIL;
}
FurnitureAttemptPlaceEvent attemptPlaceEvent = new FurnitureAttemptPlaceEvent(bukkitPlayer, customFurniture, anchorType, furnitureLocation.clone(), 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())); DirectionUtils.toBlockFace(clickedFace), context.getHand(), world.getBlockAt(context.getClickedPos().x(), context.getClickedPos().y(), context.getClickedPos().z()));
if (EventUtils.fireAndCheckCancel(attemptPlaceEvent)) { if (EventUtils.fireAndCheckCancel(attemptPlaceEvent)) {

View File

@@ -19,7 +19,6 @@ public abstract class AbstractJavaScheduler<T> implements SchedulerAdapter<T> {
public AbstractJavaScheduler(Plugin plugin) { public AbstractJavaScheduler(Plugin plugin) {
this.plugin = plugin; this.plugin = plugin;
this.scheduler = new ScheduledThreadPoolExecutor(4, r -> { this.scheduler = new ScheduledThreadPoolExecutor(4, r -> {
Thread thread = Executors.defaultThreadFactory().newThread(r); Thread thread = Executors.defaultThreadFactory().newThread(r);
thread.setName("craft-engine-scheduler"); thread.setName("craft-engine-scheduler");

View File

@@ -10,6 +10,7 @@ import net.momirealms.craftengine.core.world.chunk.CEChunk;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.io.IOException; import java.io.IOException;
import java.nio.channels.ClosedChannelException;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@@ -28,6 +29,11 @@ public class DelayedDefaultRegionFileStorage extends DefaultRegionFileStorage {
if (cause == RemovalCause.EXPIRED || cause == RemovalCause.SIZE) { if (cause == RemovalCause.EXPIRED || cause == RemovalCause.SIZE) {
try { try {
super.writeChunkAt(key, value, true); 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) { } catch (IOException e) {
CraftEngine.instance().logger().warn("Failed to write chunk at " + key, e); CraftEngine.instance().logger().warn("Failed to write chunk at " + key, e);
} }
@@ -60,9 +66,9 @@ public class DelayedDefaultRegionFileStorage extends DefaultRegionFileStorage {
@Override @Override
public synchronized void close() throws IOException { public synchronized void close() throws IOException {
this.isClosed = true;
this.saveCache(); this.saveCache();
this.chunkCache.cleanUp(); this.chunkCache.cleanUp();
this.isClosed = true;
super.close(); super.close();
} }

View File

@@ -11,6 +11,7 @@ import java.io.*;
import java.nio.Buffer; import java.nio.Buffer;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.IntBuffer; import java.nio.IntBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.FileChannel; import java.nio.channels.FileChannel;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
@@ -308,6 +309,9 @@ public class RegionFile implements AutoCloseable {
} }
public void clear(ChunkPos pos) throws IOException { public void clear(ChunkPos pos) throws IOException {
if (!this.fileChannel.isOpen()) {
throw new ClosedChannelException();
}
int chunkLocation = RegionFile.getChunkLocation(pos); int chunkLocation = RegionFile.getChunkLocation(pos);
int sectorInfo = this.sectorInfo.get(chunkLocation); int sectorInfo = this.sectorInfo.get(chunkLocation);
if (sectorInfo != INFO_NOT_PRESENT) { if (sectorInfo != INFO_NOT_PRESENT) {
@@ -321,6 +325,9 @@ public class RegionFile implements AutoCloseable {
@SuppressWarnings("ResultOfMethodCallIgnored") @SuppressWarnings("ResultOfMethodCallIgnored")
protected synchronized void write(ChunkPos pos, ByteBuffer buf) throws IOException { protected synchronized void write(ChunkPos pos, ByteBuffer buf) throws IOException {
if (!this.fileChannel.isOpen()) {
throw new ClosedChannelException();
}
// get old offset info // get old offset info
int offsetIndex = RegionFile.getChunkLocation(pos); int offsetIndex = RegionFile.getChunkLocation(pos);
int previousSectorInfo = this.sectorInfo.get(offsetIndex); int previousSectorInfo = this.sectorInfo.get(offsetIndex);