9
0
mirror of https://github.com/Xiao-MoMi/craft-engine.git synced 2025-12-23 08:59:27 +00:00

Remove World Thread

This commit is contained in:
XiaoMoMi
2025-02-15 04:43:45 +08:00
parent d657a481f5
commit e67aecbe77
4 changed files with 12 additions and 65 deletions

View File

@@ -5,8 +5,6 @@ import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer; import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
import net.momirealms.craftengine.bukkit.util.*; import net.momirealms.craftengine.bukkit.util.*;
import net.momirealms.craftengine.bukkit.world.BukkitWorld; import net.momirealms.craftengine.bukkit.world.BukkitWorld;
import net.momirealms.craftengine.bukkit.world.BukkitWorldManager;
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.block.PushReaction; import net.momirealms.craftengine.core.block.PushReaction;
import net.momirealms.craftengine.core.block.properties.Property; import net.momirealms.craftengine.core.block.properties.Property;
@@ -18,7 +16,6 @@ import net.momirealms.craftengine.core.plugin.config.ConfigManager;
import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.context.ContextHolder; import net.momirealms.craftengine.core.util.context.ContextHolder;
import net.momirealms.craftengine.core.world.BlockPos; import net.momirealms.craftengine.core.world.BlockPos;
import net.momirealms.craftengine.core.world.CEWorld;
import net.momirealms.craftengine.core.world.Vec3d; import net.momirealms.craftengine.core.world.Vec3d;
import org.bukkit.*; import org.bukkit.*;
import org.bukkit.block.Block; import org.bukkit.block.Block;
@@ -197,27 +194,25 @@ public class BlockEventListener implements Listener {
handlePistonEvent(event.getDirection(), event.getBlocks(), event.getBlock()); handlePistonEvent(event.getDirection(), event.getBlocks(), event.getBlock());
} }
// todo refactor this method
private void handlePistonEvent(BlockFace face, List<Block> blocksList, Block piston) { private void handlePistonEvent(BlockFace face, List<Block> blocksList, Block piston) {
int blocks = blocksList.size(); int blocks = blocksList.size();
CEWorld world = BukkitWorldManager.instance().getWorld(piston.getWorld()); net.momirealms.craftengine.core.world.World world = new BukkitWorld(piston.getWorld());
for (int i = blocks - 1; i >= 0; --i) { for (int i = blocks - 1; i >= 0; --i) {
Location oldLocation = blocksList.get(i).getLocation(); Location oldLocation = blocksList.get(i).getLocation();
BlockPos oldPos = new BlockPos(oldLocation.getBlockX(), oldLocation.getBlockY(), oldLocation.getBlockZ()); BlockPos oldPos = new BlockPos(oldLocation.getBlockX(), oldLocation.getBlockY(), oldLocation.getBlockZ());
ImmutableBlockState blockState = world.getBlockStateAtIfLoaded(oldPos); Block block = blocksList.get(i);
if (blockState.pushReaction() == PushReaction.DESTROY) { ImmutableBlockState blockState = manager.getImmutableBlockState(BlockStateUtils.blockDataToId(block.getBlockData()));
if (blockState != null && blockState.pushReaction() == PushReaction.DESTROY) {
// break actions // break actions
ContextHolder.Builder builder = ContextHolder.builder(); ContextHolder.Builder builder = ContextHolder.builder();
Vec3d vec3d = Vec3d.atCenterOf(oldPos); Vec3d vec3d = Vec3d.atCenterOf(oldPos);
builder.withParameter(LootParameters.LOCATION, vec3d); builder.withParameter(LootParameters.LOCATION, vec3d);
builder.withParameter(LootParameters.WORLD, world.world()); builder.withParameter(LootParameters.WORLD, world);
for (Item<Object> item : blockState.getDrops(builder, world.world())) { for (Item<Object> item : blockState.getDrops(builder, world)) {
world.world().dropItemNaturally(vec3d, item); world.dropItemNaturally(vec3d, item);
} }
world.world().playBlockSound(vec3d, blockState.sounds().breakSound(),1f, 1f); world.playBlockSound(vec3d, blockState.sounds().breakSound(),1f, 1f);
} }
// to prevent duplication in other events
world.setBlockStateAtIfLoaded(oldPos, EmptyBlock.INSTANCE.getDefaultState());
} }
} }

View File

@@ -11,7 +11,6 @@ import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock;
public abstract class CEWorld { public abstract class CEWorld {
@@ -20,7 +19,6 @@ public abstract class CEWorld {
protected final Map<Long, CEChunk> loadedChunkMap; protected final Map<Long, CEChunk> loadedChunkMap;
protected final WorldDataStorage worldDataStorage; protected final WorldDataStorage worldDataStorage;
protected final ReentrantReadWriteLock loadedChunkMapLock = new ReentrantReadWriteLock(); protected final ReentrantReadWriteLock loadedChunkMapLock = new ReentrantReadWriteLock();
protected final WorldExecutor executor;
protected final WorldHeight worldHeightAccessor; protected final WorldHeight worldHeightAccessor;
protected final Set<SectionPos> updatedSectionPositions = Collections.synchronizedSet(new HashSet<>()); protected final Set<SectionPos> updatedSectionPositions = Collections.synchronizedSet(new HashSet<>());
@@ -31,7 +29,6 @@ public abstract class CEWorld {
this.world = world; this.world = world;
this.loadedChunkMap = new Long2ObjectOpenHashMap<>(1024, 0.5f); this.loadedChunkMap = new Long2ObjectOpenHashMap<>(1024, 0.5f);
this.worldDataStorage = new DefaultRegionFileStorage(world.directory().resolve(REGION_DIRECTORY)); this.worldDataStorage = new DefaultRegionFileStorage(world.directory().resolve(REGION_DIRECTORY));
this.executor = new WorldExecutor(this);
this.worldHeightAccessor = world.worldHeight(); this.worldHeightAccessor = world.worldHeight();
this.lastChunkPos = ChunkPos.INVALID_CHUNK_POS; this.lastChunkPos = ChunkPos.INVALID_CHUNK_POS;
} }
@@ -73,9 +70,6 @@ public abstract class CEWorld {
@Nullable @Nullable
public CEChunk getLoadedChunkImmediately(int x, int z) { public CEChunk getLoadedChunkImmediately(int x, int z) {
if (WorldThread.isWorldThreadFor(this)) {
return this.getChunkAtIfLoadedWorldThread(x, z);
}
long longKey = ChunkPos.asLong(x, z); long longKey = ChunkPos.asLong(x, z);
this.loadedChunkMapLock.readLock().lock(); this.loadedChunkMapLock.readLock().lock();
try { try {
@@ -86,7 +80,7 @@ public abstract class CEWorld {
} }
@Nullable @Nullable
public CEChunk getChunkAtIfLoadedWorldThread(long chunkPos) { public CEChunk getChunkAtIfLoadedMainThread(long chunkPos) {
if (chunkPos == this.lastChunkPos) { if (chunkPos == this.lastChunkPos) {
return this.lastChunk; return this.lastChunk;
} }
@@ -99,17 +93,14 @@ public abstract class CEWorld {
} }
@Nullable @Nullable
public CEChunk getChunkAtIfLoadedWorldThread(int x, int z) { public CEChunk getChunkAtIfLoadedMainThread(int x, int z) {
return getChunkAtIfLoadedWorldThread(ChunkPos.asLong(x, z)); return getChunkAtIfLoadedMainThread(ChunkPos.asLong(x, z));
} }
@Nullable @Nullable
public CEChunk getChunkAtIfLoaded(int x, int z) { public CEChunk getChunkAtIfLoaded(int x, int z) {
if (!WorldThread.isWorldThreadFor(this)) {
return CompletableFuture.supplyAsync(() -> this.getChunkAtIfLoaded(x, z), this.executor).join();
}
long chunkPos = ChunkPos.asLong(x, z); long chunkPos = ChunkPos.asLong(x, z);
return this.getChunkAtIfLoadedWorldThread(chunkPos); return this.getChunkAtIfLoadedMainThread(chunkPos);
} }
public WorldHeight worldHeight() { public WorldHeight worldHeight() {

View File

@@ -1,21 +0,0 @@
package net.momirealms.craftengine.core.world;
import org.jetbrains.annotations.NotNull;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class WorldExecutor implements Executor {
private final ExecutorService threadPool;
public WorldExecutor(CEWorld world) {
this.threadPool = Executors.newSingleThreadExecutor(r -> new WorldThread(r, "CEWorld-Thread-" + world.world().name(), world));
}
@Override
public void execute(@NotNull Runnable command) {
this.threadPool.execute(command);
}
}

View File

@@ -1,18 +0,0 @@
package net.momirealms.craftengine.core.world;
public class WorldThread extends Thread {
private final CEWorld world;
public WorldThread(Runnable target, String name, CEWorld world) {
super(target, name);
this.world = world;
}
public static boolean isWorldThreadFor(CEWorld world) {
if (Thread.currentThread() instanceof WorldThread worldThread) {
return worldThread.world == world;
}
return false;
}
}