diff --git a/bukkit/build.gradle.kts b/bukkit/build.gradle.kts index c9bf92f91..7519028f8 100644 --- a/bukkit/build.gradle.kts +++ b/bukkit/build.gradle.kts @@ -4,11 +4,11 @@ plugins { } repositories { + mavenCentral() maven("https://jitpack.io/") maven("https://repo.momirealms.net/releases/") maven("https://libraries.minecraft.net/") maven("https://repo.papermc.io/repository/maven-public/") - mavenCentral() } dependencies { @@ -60,6 +60,8 @@ dependencies { compileOnly("org.ahocorasick:ahocorasick:${rootProject.properties["ahocorasick_version"]}") // authlib compileOnly("com.mojang:authlib:${rootProject.properties["authlib_version"]}") + // concurrentutil + compileOnly("ca.spottedleaf:concurrentutil:${rootProject.properties["concurrent_util_version"]}") } java { diff --git a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/item/ZaphkielSource.java b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/item/ZaphkielSource.java index 25cb5917b..3c9329b11 100644 --- a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/item/ZaphkielSource.java +++ b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/item/ZaphkielSource.java @@ -30,5 +30,4 @@ public class ZaphkielSource implements ExternalItemSource { public String id(ItemStack item) { return Zaphkiel.INSTANCE.api().getItemHandler().getItemId(item); } - } diff --git a/bukkit/loader/build.gradle.kts b/bukkit/loader/build.gradle.kts index c7ef218b6..53736c927 100644 --- a/bukkit/loader/build.gradle.kts +++ b/bukkit/loader/build.gradle.kts @@ -21,6 +21,9 @@ dependencies { implementation(project(":bukkit:compatibility:legacy")) implementation(project(":common-files")) + // concurrentutil + implementation(files("${rootProject.rootDir}/libs/concurrentutil-${rootProject.properties["concurrent_util_version"]}.jar")) + implementation("net.momirealms:sparrow-util:${rootProject.properties["sparrow_util_version"]}") implementation("net.momirealms:antigrieflib:${rootProject.properties["anti_grief_version"]}") implementation("net.momirealms:craft-engine-nms-helper:${rootProject.properties["nms_helper_version"]}") @@ -77,5 +80,6 @@ tasks { relocate("com.google.common.jimfs", "net.momirealms.craftengine.libraries.jimfs") relocate("org.apache.commons", "net.momirealms.craftengine.libraries.commons") relocate("io.leangen.geantyref", "net.momirealms.craftengine.libraries.geantyref") + relocate("ca.spottedleaf.concurrentutil", "net.momirealms.craftengine.libraries.concurrentutil") } } diff --git a/bukkit/paper-loader/build.gradle.kts b/bukkit/paper-loader/build.gradle.kts index 16a4caf37..8929b281f 100644 --- a/bukkit/paper-loader/build.gradle.kts +++ b/bukkit/paper-loader/build.gradle.kts @@ -23,6 +23,9 @@ dependencies { implementation(project(":bukkit:compatibility:legacy")) implementation(project(":common-files")) + // concurrentutil + implementation(files("${rootProject.rootDir}/libs/concurrentutil-${rootProject.properties["concurrent_util_version"]}.jar")) + implementation("net.momirealms:sparrow-util:${rootProject.properties["sparrow_util_version"]}") implementation("net.momirealms:antigrieflib:${rootProject.properties["anti_grief_version"]}") implementation("net.momirealms:craft-engine-nms-helper-mojmap:${rootProject.properties["nms_helper_version"]}") @@ -150,5 +153,6 @@ tasks { relocate("com.google.common.jimfs", "net.momirealms.craftengine.libraries.jimfs") relocate("org.apache.commons", "net.momirealms.craftengine.libraries.commons") relocate("io.leangen.geantyref", "net.momirealms.craftengine.libraries.geantyref") + relocate("ca.spottedleaf.concurrentutil", "net.momirealms.craftengine.libraries.concurrentutil") } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java index e98de26d8..8a3f5d23f 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java @@ -11,8 +11,8 @@ import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; import net.momirealms.craftengine.bukkit.plugin.network.id.PacketIdFinder; import net.momirealms.craftengine.bukkit.plugin.network.id.PacketIds1_20; import net.momirealms.craftengine.bukkit.plugin.network.id.PacketIds1_20_5; +import net.momirealms.craftengine.bukkit.plugin.reflection.leaves.LeavesReflections; import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections; -import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.LeavesReflections; import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.LibraryReflections; import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.NetworkReflections; import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer; @@ -213,6 +213,7 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes registerNMSPacketConsumer(PacketConsumers.LOGIN_FINISHED, NetworkReflections.clazz$ClientboundLoginFinishedPacket); registerNMSPacketConsumer(PacketConsumers.UPDATE_TAGS, NetworkReflections.clazz$ClientboundUpdateTagsPacket); registerNMSPacketConsumer(PacketConsumers.CONTAINER_CLICK_1_21_5, VersionHelper.isOrAbove1_21_5() ? NetworkReflections.clazz$ServerboundContainerClickPacket : null); + registerS2CByteBufPacketConsumer(PacketConsumers.FORGET_LEVEL_CHUNK, this.packetIds.clientboundForgetLevelChunkPacket()); registerS2CByteBufPacketConsumer(PacketConsumers.LEVEL_CHUNK_WITH_LIGHT, this.packetIds.clientboundLevelChunkWithLightPacket()); registerS2CByteBufPacketConsumer(PacketConsumers.SECTION_BLOCK_UPDATE, this.packetIds.clientboundSectionBlocksUpdatePacket()); registerS2CByteBufPacketConsumer(PacketConsumers.BLOCK_UPDATE, this.packetIds.clientboundBlockUpdatePacket()); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java index cda262388..f3897953b 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java @@ -64,10 +64,7 @@ import net.momirealms.craftengine.core.plugin.logger.Debugger; import net.momirealms.craftengine.core.plugin.network.*; import net.momirealms.craftengine.core.plugin.text.component.ComponentProvider; import net.momirealms.craftengine.core.util.*; -import net.momirealms.craftengine.core.world.BlockHitResult; -import net.momirealms.craftengine.core.world.BlockPos; -import net.momirealms.craftengine.core.world.EntityHitResult; -import net.momirealms.craftengine.core.world.WorldEvents; +import net.momirealms.craftengine.core.world.*; import net.momirealms.craftengine.core.world.chunk.Palette; import net.momirealms.craftengine.core.world.chunk.PalettedContainer; import net.momirealms.craftengine.core.world.chunk.packet.BlockEntityData; @@ -75,6 +72,7 @@ import net.momirealms.craftengine.core.world.chunk.packet.MCSection; import net.momirealms.craftengine.core.world.collision.AABB; import net.momirealms.sparrow.nbt.Tag; import org.bukkit.*; +import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; @@ -261,12 +259,29 @@ public class PacketConsumers { return MOD_BLOCK_STATE_MAPPINGS[stateId]; } + public static final BiConsumer FORGET_LEVEL_CHUNK = (user, event) -> { + try { + FriendlyByteBuf buf = event.getBuffer(); + if (VersionHelper.isOrAbove1_20_2()) { + long chunkPos = buf.readLong(); + user.setChunkTrackStatus(new ChunkPos(chunkPos), false); + } else { + int x = buf.readInt(); + int y = buf.readInt(); + user.setChunkTrackStatus(ChunkPos.of(x, y), false); + } + } catch (Exception e) { + CraftEngine.instance().logger().warn("Failed to handle ClientboundForgetLevelChunkPacket", e); + } + }; + public static final BiConsumer LEVEL_CHUNK_WITH_LIGHT = (user, event) -> { try { BukkitServerPlayer player = (BukkitServerPlayer) user; FriendlyByteBuf buf = event.getBuffer(); int chunkX = buf.readInt(); int chunkZ = buf.readInt(); + player.setChunkTrackStatus(ChunkPos.of(chunkX, chunkZ), true); boolean named = !VersionHelper.isOrAbove1_20_2(); // ClientboundLevelChunkPacketData int heightmapsCount = 0; @@ -1262,6 +1277,7 @@ public class PacketConsumers { int sectionCount = (world.getMaxHeight() - world.getMinHeight()) / 16; player.setClientSideSectionCount(sectionCount); player.setClientSideDimension(Key.of(location.toString())); + player.clearTrackedChunks(); } else { CraftEngine.instance().logger().warn("Failed to handle ClientboundRespawnPacket: World " + location + " does not exist"); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketIds.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketIds.java index bef170327..dd41cb280 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketIds.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketIds.java @@ -67,4 +67,6 @@ public interface PacketIds { int serverboundInteractPacket(); int clientboundUpdateRecipesPacket(); + + int clientboundForgetLevelChunkPacket(); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/id/PacketIds1_20.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/id/PacketIds1_20.java index 34981a06b..7a3b81947 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/id/PacketIds1_20.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/id/PacketIds1_20.java @@ -169,4 +169,9 @@ public class PacketIds1_20 implements PacketIds { public int clientboundUpdateAdvancementsPacket() { return PacketIdFinder.clientboundByClazz(NetworkReflections.clazz$ClientboundUpdateAdvancementsPacket); } + + @Override + public int clientboundForgetLevelChunkPacket() { + return PacketIdFinder.clientboundByClazz(NetworkReflections.clazz$ClientboundForgetLevelChunkPacket); + } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/id/PacketIds1_20_5.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/id/PacketIds1_20_5.java index 216b11d56..b3a9b624a 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/id/PacketIds1_20_5.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/id/PacketIds1_20_5.java @@ -168,4 +168,9 @@ public class PacketIds1_20_5 implements PacketIds { public int serverboundInteractPacket() { return PacketIdFinder.serverboundByName("minecraft:interact"); } + + @Override + public int clientboundForgetLevelChunkPacket() { + return PacketIdFinder.clientboundByName("minecraft:forget_level_chunk"); + } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/LeavesReflections.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/leaves/LeavesReflections.java similarity index 97% rename from bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/LeavesReflections.java rename to bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/leaves/LeavesReflections.java index b7b89995c..dd5522890 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/LeavesReflections.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/leaves/LeavesReflections.java @@ -1,4 +1,4 @@ -package net.momirealms.craftengine.bukkit.plugin.reflection.minecraft; +package net.momirealms.craftengine.bukkit.plugin.reflection.leaves; //import net.momirealms.craftengine.core.util.MiscUtils; //import net.momirealms.craftengine.core.util.ReflectionUtils; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/NetworkReflections.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/NetworkReflections.java index 48bb2b8cd..4e421cff8 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/NetworkReflections.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/NetworkReflections.java @@ -1665,4 +1665,11 @@ public final class NetworkReflections { ), VersionHelper.isOrAbove1_21_5() ); + + public static final Class clazz$ClientboundForgetLevelChunkPacket = requireNonNull( + BukkitReflectionUtils.findReobfOrMojmapClass( + "network.protocol.game.PacketPlayOutUnloadChunk", + "network.protocol.game.ClientboundForgetLevelChunkPacket" + ) + ); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java index 2d13134ce..9d4ebc8ee 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java @@ -34,6 +34,7 @@ import net.momirealms.craftengine.core.util.Direction; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.VersionHelper; import net.momirealms.craftengine.core.world.BlockPos; +import net.momirealms.craftengine.core.world.ChunkPos; import net.momirealms.craftengine.core.world.World; import net.momirealms.craftengine.core.world.WorldEvents; import org.bukkit.*; @@ -109,7 +110,11 @@ public class BukkitServerPlayer extends Player { private double cachedInteractionRange; // cooldown data private CooldownData cooldownData; - + // tracked chunks + private final Set trackedChunks = Collections.synchronizedSet(new HashSet<>()); + // relighted chunks + private final Set relightedChunks = Collections.synchronizedSet(new HashSet<>()); + // entity view private final Map entityTypeView = new ConcurrentHashMap<>(); public BukkitServerPlayer(BukkitCraftEngine plugin, @Nullable Channel channel) { @@ -497,9 +502,6 @@ public class BukkitServerPlayer extends Player { Item tool = getItemInHand(InteractionHand.MAIN_HAND); boolean isCorrectTool = FastNMS.INSTANCE.method$ItemStack$isCorrectToolForDrops(tool.getLiteralObject(), blockState); // 如果自定义方块在服务端侧未使用正确的工具,那么需要还原挖掘速度 - if (!isCorrectTool) { - progress *= (10f / 3f); - } if (!BlockStateUtils.isCorrectTool(customState, tool)) { progress *= customState.settings().incorrectToolSpeed(); } @@ -1032,4 +1034,23 @@ public class BukkitServerPlayer extends Player { public CooldownData cooldown() { return this.cooldownData; } + + @Override + public boolean isChunkTracked(ChunkPos chunkPos) { + return this.trackedChunks.contains(chunkPos); + } + + @Override + public void setChunkTrackStatus(ChunkPos chunkPos, boolean tracked) { + if (tracked) { + this.trackedChunks.add(chunkPos); + } else { + this.trackedChunks.remove(chunkPos); + } + } + + @Override + public void clearTrackedChunks() { + this.trackedChunks.clear(); + } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/BukkitWorldManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/BukkitWorldManager.java index 6f2c47628..134e2ee7f 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/BukkitWorldManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/BukkitWorldManager.java @@ -1,5 +1,6 @@ package net.momirealms.craftengine.bukkit.world; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; import net.momirealms.craftengine.bukkit.plugin.injector.WorldStorageInjector; @@ -29,7 +30,6 @@ import org.bukkit.event.world.*; import org.jetbrains.annotations.NotNull; import java.io.IOException; -import java.util.HashMap; import java.util.Map; import java.util.Optional; import java.util.UUID; @@ -53,7 +53,7 @@ public class BukkitWorldManager implements WorldManager, Listener { public BukkitWorldManager(BukkitCraftEngine plugin) { instance = this; this.plugin = plugin; - this.worlds = new HashMap<>(); + this.worlds = new Object2ObjectOpenHashMap<>(32, 0.5f); this.storageAdaptor = new DefaultStorageAdaptor(); for (World world : Bukkit.getWorlds()) { this.worlds.put(world.getUID(), new BukkitCEWorld(new BukkitWorld(world), this.storageAdaptor)); diff --git a/core/build.gradle.kts b/core/build.gradle.kts index df535d1cd..6a172d1c3 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -65,6 +65,8 @@ dependencies { compileOnly("com.mojang:brigadier:${rootProject.properties["mojang_brigadier_version"]}") // authlib compileOnly("com.mojang:authlib:${rootProject.properties["authlib_version"]}") + // concurrentutil + compileOnly("ca.spottedleaf:concurrentutil:${rootProject.properties["concurrent_util_version"]}") } java { diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/player/Player.java b/core/src/main/java/net/momirealms/craftengine/core/entity/player/Player.java index b0adb4685..6675659ba 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/player/Player.java +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/player/Player.java @@ -10,8 +10,6 @@ import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.world.BlockPos; import org.jetbrains.annotations.NotNull; -import java.util.List; - public abstract class Player extends AbstractEntity implements NetWorkUser { private static final Key TYPE = Key.of("minecraft:player"); @@ -26,10 +24,6 @@ public abstract class Player extends AbstractEntity implements NetWorkUser { @Override public abstract Object serverPlayer(); - public abstract void sendPackets(List packet, boolean immediately); - - public abstract void sendPackets(List packet, boolean immediately, Runnable sendListener); - public abstract float getDestroyProgress(Object blockState, BlockPos pos); public abstract void setClientSideCanBreakBlock(boolean canBreak); diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/network/NetWorkUser.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/network/NetWorkUser.java index 453b8e055..83661fd2f 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/network/NetWorkUser.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/network/NetWorkUser.java @@ -5,9 +5,11 @@ import io.netty.channel.ChannelHandler; import net.kyori.adventure.text.Component; import net.momirealms.craftengine.core.plugin.Plugin; import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.world.ChunkPos; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; +import java.util.List; import java.util.Map; import java.util.UUID; @@ -38,6 +40,10 @@ public interface NetWorkUser { void sendPacket(Object packet, boolean immediately, Runnable sendListener); + void sendPackets(List packet, boolean immediately); + + void sendPackets(List packet, boolean immediately, Runnable sendListener); + void sendCustomPayload(Key channel, byte[] data); void kick(Component message); @@ -71,4 +77,10 @@ public interface NetWorkUser { void setShouldProcessFinishConfiguration(boolean shouldProcess); boolean shouldProcessFinishConfiguration(); + + boolean isChunkTracked(ChunkPos chunkPos); + + void setChunkTrackStatus(ChunkPos chunkPos, boolean tracked); + + void clearTrackedChunks(); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/world/CEWorld.java b/core/src/main/java/net/momirealms/craftengine/core/world/CEWorld.java index 2a636bd69..62dfa77da 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/world/CEWorld.java +++ b/core/src/main/java/net/momirealms/craftengine/core/world/CEWorld.java @@ -1,6 +1,6 @@ package net.momirealms.craftengine.core.world; -import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import ca.spottedleaf.concurrentutil.map.ConcurrentLong2ReferenceChainedHashTable; import net.momirealms.craftengine.core.block.ImmutableBlockState; import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.world.chunk.CEChunk; @@ -10,17 +10,14 @@ import org.jetbrains.annotations.Nullable; import java.io.IOException; import java.util.Collection; -import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.locks.ReentrantReadWriteLock; public abstract class CEWorld { public static final String REGION_DIRECTORY = "craftengine"; protected final World world; - protected final Map loadedChunkMap; + protected final ConcurrentLong2ReferenceChainedHashTable loadedChunkMap; protected final WorldDataStorage worldDataStorage; - protected final ReentrantReadWriteLock loadedChunkMapLock = new ReentrantReadWriteLock(); protected final WorldHeight worldHeightAccessor; protected final Set updatedSectionSet = ConcurrentHashMap.newKeySet(128); @@ -29,7 +26,7 @@ public abstract class CEWorld { public CEWorld(World world, StorageAdaptor adaptor) { this.world = world; - this.loadedChunkMap = new Long2ObjectOpenHashMap<>(1024, 0.5f); + this.loadedChunkMap = ConcurrentLong2ReferenceChainedHashTable.createWithCapacity(1024, 0.5f); this.worldDataStorage = adaptor.adapt(world); this.worldHeightAccessor = world.worldHeight(); this.lastChunkPos = ChunkPos.INVALID_CHUNK_POS; @@ -37,16 +34,15 @@ public abstract class CEWorld { public CEWorld(World world, WorldDataStorage dataStorage) { this.world = world; - this.loadedChunkMap = new Long2ObjectOpenHashMap<>(1024, 0.5f); + this.loadedChunkMap = ConcurrentLong2ReferenceChainedHashTable.createWithCapacity(1024, 0.5f); this.worldDataStorage = dataStorage; this.worldHeightAccessor = world.worldHeight(); this.lastChunkPos = ChunkPos.INVALID_CHUNK_POS; } public void save() { - this.loadedChunkMapLock.readLock().lock(); try { - for (Map.Entry entry : this.loadedChunkMap.entrySet()) { + for (ConcurrentLong2ReferenceChainedHashTable.TableEntry entry : this.loadedChunkMap.entrySet()) { CEChunk chunk = entry.getValue(); if (chunk.dirty()) { worldDataStorage.writeChunkAt(new ChunkPos(entry.getKey()), chunk); @@ -55,8 +51,6 @@ public abstract class CEWorld { } } catch (IOException e) { CraftEngine.instance().logger().warn("Failed to save world chunks", e); - } finally { - this.loadedChunkMapLock.readLock().unlock(); } } @@ -65,44 +59,24 @@ public abstract class CEWorld { } public boolean isChunkLoaded(final long chunkPos) { - this.loadedChunkMapLock.readLock().lock(); - try { - return loadedChunkMap.containsKey(chunkPos); - } finally { - this.loadedChunkMapLock.readLock().unlock(); - } + return loadedChunkMap.containsKey(chunkPos); } public void addLoadedChunk(CEChunk chunk) { - this.loadedChunkMapLock.writeLock().lock(); - try { - this.loadedChunkMap.put(chunk.chunkPos().longKey(), chunk); - } finally { - this.loadedChunkMapLock.writeLock().unlock(); - } + this.loadedChunkMap.put(chunk.chunkPos().longKey(), chunk); } public void removeLoadedChunk(CEChunk chunk) { - this.loadedChunkMapLock.writeLock().lock(); - try { - this.loadedChunkMap.remove(chunk.chunkPos().longKey()); - if (this.lastChunk == chunk) { - this.lastChunk = null; - this.lastChunkPos = ChunkPos.INVALID_CHUNK_POS; - } - } finally { - this.loadedChunkMapLock.writeLock().unlock(); + this.loadedChunkMap.remove(chunk.chunkPos().longKey()); + if (this.lastChunk == chunk) { + this.lastChunk = null; + this.lastChunkPos = ChunkPos.INVALID_CHUNK_POS; } } @Nullable public CEChunk getChunkAtIfLoaded(long chunkPos) { - this.loadedChunkMapLock.readLock().lock(); - try { - return getChunkAtIfLoadedMainThread(chunkPos); - } finally { - this.loadedChunkMapLock.readLock().unlock(); - } + return getChunkAtIfLoadedMainThread(chunkPos); } @Nullable diff --git a/gradle.properties b/gradle.properties index a99f6d22e..2bc460d2f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -57,6 +57,7 @@ amazon_awssdk_version=2.31.23 amazon_awssdk_eventstream_version=1.0.1 jimfs_version=1.3.0 authlib_version=6.0.58 +concurrent_util_version=0.0.3 # Proxy settings #systemProp.socks.proxyHost=127.0.0.1 diff --git a/libs/boosted-yaml-1.3.7.jar b/libs/boosted-yaml-1.3.7.jar index ea489cb34..b6481f3fa 100644 Binary files a/libs/boosted-yaml-1.3.7.jar and b/libs/boosted-yaml-1.3.7.jar differ diff --git a/libs/concurrentutil-0.0.3.jar b/libs/concurrentutil-0.0.3.jar new file mode 100644 index 000000000..27b20749b Binary files /dev/null and b/libs/concurrentutil-0.0.3.jar differ