From ef2c26f15f0be8f8d34005801a9dbbfb349a1536 Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Wed, 3 Sep 2025 20:33:30 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E7=BD=AEtick=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bukkit/world/BukkitCEWorld.java | 3 +- .../bukkit/world/BukkitWorldManager.java | 26 ++++---------- common-files/src/main/resources/config.yml | 2 ++ .../core/font/AbstractFontManager.java | 17 +++++---- .../core/plugin/config/Config.java | 6 ++++ .../core/util/AdventureHelper.java | 4 ++- .../craftengine/core/world/CEWorld.java | 35 ++++++++++++++++++- gradle.properties | 2 +- 8 files changed, 64 insertions(+), 31 deletions(-) diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/BukkitCEWorld.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/BukkitCEWorld.java index 8d13cf1b1..136eadb74 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/BukkitCEWorld.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/BukkitCEWorld.java @@ -22,8 +22,7 @@ public class BukkitCEWorld extends CEWorld { } @Override - public void tick() { - super.tick(); + public void updateLight() { HashSet poses; synchronized (super.updatedSectionSet) { poses = new HashSet<>(super.updatedSectionSet); 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 134e2ee7f..c2431e7d9 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,6 +1,7 @@ package net.momirealms.craftengine.bukkit.world; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import net.momirealms.craftengine.bukkit.api.CraftEngineBlocks; import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; import net.momirealms.craftengine.bukkit.plugin.injector.WorldStorageInjector; @@ -33,7 +34,6 @@ import java.io.IOException; import java.util.Map; import java.util.Optional; import java.util.UUID; -import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantReadWriteLock; public class BukkitWorldManager implements WorldManager, Listener { @@ -42,12 +42,10 @@ public class BukkitWorldManager implements WorldManager, Listener { private final Map worlds; private CEWorld[] worldArray = new CEWorld[0]; private final ReentrantReadWriteLock worldMapLock = new ReentrantReadWriteLock(); - private SchedulerTask tickTask; // cache private UUID lastVisitedUUID; private CEWorld lastVisitedWorld; private StorageAdaptor storageAdaptor; - private boolean isTicking = false; private boolean initialized = false; public BukkitWorldManager(BukkitCraftEngine plugin) { @@ -101,20 +99,6 @@ public class BukkitWorldManager implements WorldManager, Listener { } public void delayedInit() { - // events and tasks - this.tickTask = this.plugin.scheduler().asyncRepeating(() -> { - try { - if (this.isTicking) { - return; - } - this.isTicking = true; - for (CEWorld world : this.worldArray) { - world.tick(); - } - } finally { - this.isTicking = false; - } - }, 50, 50, TimeUnit.MILLISECONDS); // load loaded chunks this.worldMapLock.writeLock().lock(); try { @@ -124,6 +108,7 @@ public class BukkitWorldManager implements WorldManager, Listener { for (Chunk chunk : world.getLoadedChunks()) { handleChunkLoad(ceWorld, chunk); } + ceWorld.setTicking(true); } catch (Exception e) { CraftEngine.instance().logger().warn("Error loading world: " + world.getName(), e); } @@ -142,11 +127,9 @@ public class BukkitWorldManager implements WorldManager, Listener { if (this.storageAdaptor instanceof Listener listener) { HandlerList.unregisterAll(listener); } - if (this.tickTask != null && !this.tickTask.cancelled()) { - this.tickTask.cancel(); - } for (World world : Bukkit.getWorlds()) { CEWorld ceWorld = getWorld(world.getUID()); + ceWorld.setTicking(false); for (Chunk chunk : world.getLoadedChunks()) { handleChunkUnload(ceWorld, chunk); } @@ -175,6 +158,7 @@ public class BukkitWorldManager implements WorldManager, Listener { for (Chunk chunk : ((World) world.platformWorld()).getLoadedChunks()) { handleChunkLoad(ceWorld, chunk); } + ceWorld.setTicking(true); } finally { this.worldMapLock.writeLock().unlock(); } @@ -190,6 +174,7 @@ public class BukkitWorldManager implements WorldManager, Listener { for (Chunk chunk : ((World) world.world().platformWorld()).getLoadedChunks()) { handleChunkLoad(world, chunk); } + world.setTicking(true); } finally { this.worldMapLock.writeLock().unlock(); } @@ -229,6 +214,7 @@ public class BukkitWorldManager implements WorldManager, Listener { } finally { this.worldMapLock.writeLock().unlock(); } + ceWorld.setTicking(false); for (Chunk chunk : ((World) world.platformWorld()).getLoadedChunks()) { handleChunkUnload(ceWorld, chunk); } diff --git a/common-files/src/main/resources/config.yml b/common-files/src/main/resources/config.yml index b29463033..5c39b74bf 100644 --- a/common-files/src/main/resources/config.yml +++ b/common-files/src/main/resources/config.yml @@ -361,6 +361,8 @@ gui: light-system: # Required for custom light-emitting blocks enable: true + # Async light update + async-update: true chunk-system: # With cache system, those frequently load/unload chunks would consume fewer resources on serialization diff --git a/core/src/main/java/net/momirealms/craftengine/core/font/AbstractFontManager.java b/core/src/main/java/net/momirealms/craftengine/core/font/AbstractFontManager.java index adfbebdef..cc5c6cdfb 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/font/AbstractFontManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/font/AbstractFontManager.java @@ -40,7 +40,7 @@ public abstract class AbstractFontManager implements FontManager { private final EmojiParser emojiParser; private OffsetFont offsetFont; - protected Trie imageTagTrie; + protected Trie networkTagTrie; protected Trie emojiKeywordTrie; protected Map networkTagMapper; protected Map emojiMapper; @@ -67,9 +67,14 @@ public abstract class AbstractFontManager implements FontManager { this.images.clear(); this.illegalChars.clear(); this.emojis.clear(); + this.networkTagTrie = null; + this.emojiKeywordTrie = null; if (this.networkTagMapper != null) { this.networkTagMapper.clear(); } + if (this.emojiMapper != null) { + this.emojiMapper.clear(); + } } @Override @@ -88,7 +93,7 @@ public abstract class AbstractFontManager implements FontManager { this.registerImageTags(); this.registerShiftTags(); this.registerGlobalTags(); - this.buildImageTagTrie(); + this.buildNetworkTagTrie(); this.buildEmojiKeywordsTrie(); this.emojiList = new ArrayList<>(this.emojis.values()); this.allEmojiSuggestions = this.emojis.values().stream() @@ -131,11 +136,11 @@ public abstract class AbstractFontManager implements FontManager { @Override public Map matchTags(String json) { - if (this.imageTagTrie == null) { + if (this.networkTagTrie == null) { return Collections.emptyMap(); } Map tags = new HashMap<>(); - for (Token token : this.imageTagTrie.tokenize(json)) { + for (Token token : this.networkTagTrie.tokenize(json)) { if (token.isMatch()) { tags.put(token.getFragment(), this.networkTagMapper.get(token.getFragment())); } @@ -305,8 +310,8 @@ public abstract class AbstractFontManager implements FontManager { .build(); } - private void buildImageTagTrie() { - this.imageTagTrie = Trie.builder() + private void buildNetworkTagTrie() { + this.networkTagTrie = Trie.builder() .ignoreOverlaps() .addKeywords(this.networkTagMapper.keySet()) .build(); diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/config/Config.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/config/Config.java index 2a207bb57..f87c745e8 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/config/Config.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/config/Config.java @@ -97,6 +97,7 @@ public class Config { protected Component resource_pack$send$prompt; protected boolean light_system$force_update_light; + protected boolean light_system$async_update; protected boolean light_system$enable; protected int chunk_system$compression_method; @@ -314,6 +315,7 @@ public class Config { // light light_system$force_update_light = config.getBoolean("light-system.force-update-light", false); + light_system$async_update = config.getBoolean("light-system.async-update", true); light_system$enable = config.getBoolean("light-system.enable", true); // chunk @@ -885,6 +887,10 @@ public class Config { return instance.block$chunk_relighter; } + public static boolean asyncLightUpdate() { + return instance.light_system$async_update; + } + public void setObf(boolean enable) { this.resource_pack$protection$obfuscation$enable = enable; } diff --git a/core/src/main/java/net/momirealms/craftengine/core/util/AdventureHelper.java b/core/src/main/java/net/momirealms/craftengine/core/util/AdventureHelper.java index d24d8d4ca..a8ad7ed18 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/util/AdventureHelper.java +++ b/core/src/main/java/net/momirealms/craftengine/core/util/AdventureHelper.java @@ -365,6 +365,8 @@ public class AdventureHelper { return text.replaceText(builder -> builder.match(Pattern.compile(patternString)) .replacement((result, b) -> - replacements.get(result.group()).apply(context))); + Optional.ofNullable(replacements.get(result.group())).orElseThrow(() -> new IllegalStateException("Could not find tag '" + result.group() + "'")).apply(context) + ) + ); } } 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 2807754bd..5feac8921 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 @@ -6,6 +6,8 @@ import net.momirealms.craftengine.core.block.ImmutableBlockState; import net.momirealms.craftengine.core.block.entity.BlockEntity; import net.momirealms.craftengine.core.block.entity.tick.TickingBlockEntity; import net.momirealms.craftengine.core.plugin.CraftEngine; +import net.momirealms.craftengine.core.plugin.config.Config; +import net.momirealms.craftengine.core.plugin.scheduler.SchedulerTask; import net.momirealms.craftengine.core.world.chunk.CEChunk; import net.momirealms.craftengine.core.world.chunk.storage.StorageAdaptor; import net.momirealms.craftengine.core.world.chunk.storage.WorldDataStorage; @@ -25,6 +27,8 @@ public abstract class CEWorld { protected final List tickingBlockEntities = new ArrayList<>(); protected final List pendingTickingBlockEntities = new ArrayList<>(); protected boolean isTickingBlockEntities = false; + protected SchedulerTask syncTickTask; + protected SchedulerTask asyncTickTask; private CEChunk lastChunk; private long lastChunkPos; @@ -45,6 +49,24 @@ public abstract class CEWorld { this.lastChunkPos = ChunkPos.INVALID_CHUNK_POS; } + public void setTicking(boolean ticking) { + if (ticking) { + if (this.syncTickTask == null || this.syncTickTask.cancelled()) { + this.syncTickTask = CraftEngine.instance().scheduler().sync().runRepeating(this::syncTick, 1, 1); + } + if (this.asyncTickTask == null || this.asyncTickTask.cancelled()) { + this.asyncTickTask = CraftEngine.instance().scheduler().sync().runAsyncRepeating(this::asyncTick, 1, 1); + } + } else { + if (this.syncTickTask != null && !this.syncTickTask.cancelled()) { + this.syncTickTask.cancel(); + } + if (this.asyncTickTask != null && !this.asyncTickTask.cancelled()) { + this.asyncTickTask.cancel(); + } + } + } + public String name() { return this.world.name(); } @@ -163,10 +185,21 @@ public abstract class CEWorld { return this.worldHeightAccessor; } - public void tick() { + public void syncTick() { this.tickBlockEntities(); + if (!Config.asyncLightUpdate()) { + this.updateLight(); + } } + public void asyncTick() { + if (Config.asyncLightUpdate()) { + this.updateLight(); + } + } + + public abstract void updateLight(); + protected void tickBlockEntities() { this.isTickingBlockEntities = true; if (!this.pendingTickingBlockEntities.isEmpty()) { diff --git a/gradle.properties b/gradle.properties index a17071ff4..eca3dd45d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,7 +2,7 @@ org.gradle.jvmargs=-Xmx1G # Project settings # Rule: [major update].[feature update].[bug fix] -project_version=0.0.62.8 +project_version=0.0.62.9 config_version=45 lang_version=25 project_group=net.momirealms