From 10b675ae5d6c0d66ebbb738d43eeb3ccb568f590 Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Tue, 25 Mar 2025 17:11:18 +0800 Subject: [PATCH 1/5] added hide base entity option --- bukkit/loader/src/main/resources/config.yml | 2 ++ .../craftengine/bukkit/plugin/network/PacketConsumers.java | 3 +++ .../craftengine/core/plugin/config/ConfigManager.java | 6 ++++++ 3 files changed, 11 insertions(+) diff --git a/bukkit/loader/src/main/resources/config.yml b/bukkit/loader/src/main/resources/config.yml index e4aa5638c..d0d39a52e 100644 --- a/bukkit/loader/src/main/resources/config.yml +++ b/bukkit/loader/src/main/resources/config.yml @@ -136,6 +136,8 @@ furniture: # If you want to remove all invalid furniture, please set this list to empty, otherwise only furniture in the list will be removed. list: - "xxx:invalid_furniture" + # Whether to hide the entity containing metadata + hide-base-entity: true image: # Prevent players from using images set in minecraft:default font 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 8e315fc3a..d588863b8 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 @@ -598,6 +598,9 @@ public class PacketConsumers { if (furniture != null) { user.furnitureView().computeIfAbsent(furniture.baseEntityId(), k -> new ArrayList<>()).addAll(furniture.subEntityIds()); user.sendPacket(furniture.spawnPacket(), false); + if (ConfigManager.hideBaseEntity()) { + event.setCancelled(true); + } } } } catch (Exception e) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/config/ConfigManager.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/config/ConfigManager.java index 746769d83..c61e8ccec 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/config/ConfigManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/config/ConfigManager.java @@ -99,6 +99,7 @@ public class ConfigManager implements Reloadable { protected boolean furniture$remove_invalid_furniture_on_chunk_load$enable; protected Set furniture$remove_invalid_furniture_on_chunk_load$list; + protected boolean furniture$hide_base_entity; protected boolean block$sound_system$enable; protected boolean recipe$enable; @@ -248,6 +249,7 @@ public class ConfigManager implements Reloadable { // furniture furniture$remove_invalid_furniture_on_chunk_load$enable = config.getBoolean("furniture.remove-invalid-furniture-on-chunk-load.enable", false); furniture$remove_invalid_furniture_on_chunk_load$list = new HashSet<>(config.getStringList("furniture.remove-invalid-furniture-on-chunk-load.list")); + furniture$hide_base_entity = config.getBoolean("furniture.hide-base-entity", true); // block block$sound_system$enable = config.getBoolean("block.sound-system.enable", true); @@ -533,6 +535,10 @@ public class ConfigManager implements Reloadable { return instance().image$illegal_characters_filter$sign; } + public static boolean hideBaseEntity() { + return instance().furniture$hide_base_entity; + } + public YamlDocument loadOrCreateYamlData(String fileName) { File file = new File(this.plugin.dataFolderFile(), fileName); if (!file.exists()) { From 08b6b352e10ed9c5fa297973e61c807fe94c36a6 Mon Sep 17 00:00:00 2001 From: iqtester Date: Tue, 25 Mar 2025 22:28:29 +0800 Subject: [PATCH 2/5] Support CE block display names in WorldEdit --- .../bukkit/block/BukkitBlockManager.java | 19 +++ .../bukkit/block/WorldEditHook.java | 24 ---- .../block/worldedit/SuggestionHandler.java | 31 +++++ .../bukkit/block/worldedit/WorldEditHook.java | 116 ++++++++++++++++++ 4 files changed, 166 insertions(+), 24 deletions(-) delete mode 100644 bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/WorldEditHook.java create mode 100644 bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/worldedit/SuggestionHandler.java create mode 100644 bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/worldedit/WorldEditHook.java diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java index 3eae94443..330f9fb6e 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java @@ -7,6 +7,7 @@ import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import dev.dejvokep.boostedyaml.YamlDocument; +import net.momirealms.craftengine.bukkit.block.worldedit.WorldEditHook; import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; import net.momirealms.craftengine.bukkit.plugin.injector.BukkitInjector; import net.momirealms.craftengine.bukkit.plugin.network.PacketConsumers; @@ -84,6 +85,8 @@ public class BukkitBlockManager extends AbstractBlockManager { private final Map modBlockStates = new HashMap<>(); // Cached command suggestions private final List cachedSuggestions = new ArrayList<>(); + // Cached Namespace + private final Set cachedNamespaces = new HashSet<>(); // Event listeners private final BlockEventListener blockEventListener; private final FallingBlockRemoveListener fallingBlockRemoveListener; @@ -235,6 +238,22 @@ public class BukkitBlockManager extends AbstractBlockManager { for (String state : states) { this.cachedSuggestions.add(Suggestion.suggestion(state)); } + this.cachedNamespaces.clear(); + initCachedNamespaces(); + } + + private void initCachedNamespaces() { + for (Suggestion suggestion : this.cachedSuggestions) { + String id = suggestion.suggestion(); + int index = id.indexOf(':'); + if (index != -1) { + cachedNamespaces.add(id.substring(0, index)); + } + } + } + + public Collection cachedNamespaces() { + return Collections.unmodifiableSet(cachedNamespaces); } public ImmutableMap> blockAppearanceArranger() { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/WorldEditHook.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/WorldEditHook.java deleted file mode 100644 index f4992949e..000000000 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/WorldEditHook.java +++ /dev/null @@ -1,24 +0,0 @@ -package net.momirealms.craftengine.bukkit.block; - -import com.sk89q.worldedit.bukkit.BukkitBlockRegistry; -import com.sk89q.worldedit.util.concurrency.LazyReference; -import com.sk89q.worldedit.world.block.BlockType; -import net.momirealms.craftengine.core.util.Key; -import net.momirealms.craftengine.core.util.ReflectionUtils; -import org.bukkit.Material; - -import java.lang.reflect.Field; - -public class WorldEditHook { - private static final Field field$BlockType$blockMaterial; - - static { - field$BlockType$blockMaterial = ReflectionUtils.getDeclaredField(BlockType.class, "blockMaterial"); - } - - public static void register(Key id) throws ReflectiveOperationException { - BlockType blockType = new BlockType(id.toString(), blockState -> blockState); - field$BlockType$blockMaterial.set(blockType, LazyReference.from(() -> new BukkitBlockRegistry.BukkitBlockMaterial(null, Material.STONE))); - BlockType.REGISTRY.register(id.toString(), blockType); - } -} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/worldedit/SuggestionHandler.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/worldedit/SuggestionHandler.java new file mode 100644 index 000000000..da6cb7da2 --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/worldedit/SuggestionHandler.java @@ -0,0 +1,31 @@ +package net.momirealms.craftengine.bukkit.block.worldedit; + +import java.util.Set; +import java.util.function.Predicate; + +public class SuggestionHandler { + private final Predicate matcher; + + private SuggestionHandler(Predicate matcher) { + this.matcher = matcher; + } + + public boolean matches(String input) { + return matcher.test(input); + } + + public static SuggestionHandler of(Integer... pos) { + Set valid = Set.of(pos); + return new SuggestionHandler(input -> { + if (input.contains(" ")) return false; + + String[] args = input.split(" "); + int index = input.endsWith(" ") ? args.length : args.length - 1; + return valid.contains(index); + }); + } + + public static SuggestionHandler custom(Predicate matcher) { + return new SuggestionHandler(matcher); + } +} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/worldedit/WorldEditHook.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/worldedit/WorldEditHook.java new file mode 100644 index 000000000..ae2f3198f --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/worldedit/WorldEditHook.java @@ -0,0 +1,116 @@ +package net.momirealms.craftengine.bukkit.block.worldedit; + +import com.google.common.collect.ImmutableMap; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.bukkit.BukkitBlockRegistry; +import com.sk89q.worldedit.event.platform.CommandSuggestionEvent; +import com.sk89q.worldedit.internal.util.Substring; +import com.sk89q.worldedit.util.concurrency.LazyReference; +import com.sk89q.worldedit.util.eventbus.Subscribe; +import com.sk89q.worldedit.world.block.BlockType; +import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; +import net.momirealms.craftengine.bukkit.util.BlockStateUtils; +import net.momirealms.craftengine.core.block.BlockStateParser; +import net.momirealms.craftengine.core.block.ImmutableBlockState; +import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.util.ReflectionUtils; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerCommandPreprocessEvent; +import org.incendo.cloud.suggestion.Suggestion; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class WorldEditHook implements Listener { + private static final Field field$BlockType$blockMaterial; + private final Map handlers = ImmutableMap.of( + "//set", SuggestionHandler.of(1), + "//replace", SuggestionHandler.of(1, 2) + ); + + static { + WorldEdit.getInstance().getEventBus().register(new WorldEditHook()); + field$BlockType$blockMaterial = ReflectionUtils.getDeclaredField(BlockType.class, "blockMaterial"); + } + + public static void register(Key id) throws ReflectiveOperationException { + BlockType blockType = new BlockType(id.toString(), blockState -> blockState); + field$BlockType$blockMaterial.set(blockType, LazyReference.from(() -> new BukkitBlockRegistry.BukkitBlockMaterial(null, Material.STONE))); + BlockType.REGISTRY.register(id.toString(), blockType); + } + + public WorldEditHook() { + Bukkit.getPluginManager().registerEvents(this, BukkitCraftEngine.instance().bootstrap()); + } + + @Subscribe + public void onSuggestion(CommandSuggestionEvent event) { + String input = event.getArguments(); + String command = input.substring(0, input.indexOf(" ")); + + SuggestionHandler handler = handlers.get(command); + if (handler == null || !handler.matches(input)) return; + int start = input.lastIndexOf(" ") + 1; + int end = input.length(); + + if (start == end) { + List suggestions = BukkitCraftEngine.instance().blockManager().cachedNamespaces() + .stream() + .map(ns -> Substring.wrap(ns + ":", start, end)) + .collect(Collectors.toList()); + suggestions.addAll(event.getSuggestions()); + event.setSuggestions(suggestions); + return; + } + + String last = input.substring(start, end); + List suggestions = new ArrayList<>(); + for (Suggestion s : BukkitCraftEngine.instance().blockManager().cachedSuggestions()) { + String id = s.suggestion(); + if (id.startsWith(last)) + suggestions.add(Substring.wrap(id, start, end)); + } + suggestions.addAll(event.getSuggestions()); + event.setSuggestions(suggestions); + } + + @EventHandler(priority = EventPriority.HIGH) + public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event) { + String message = event.getMessage(); + if (!message.startsWith("//")) return; + + Collection cachedNamespaces = BukkitCraftEngine.instance().blockManager().cachedNamespaces(); + + String[] args = message.split(" "); + boolean modified = false; + + for (int i = 1; i < args.length; i++) { + String token = args[i]; + + int colon = token.indexOf(':'); + if (colon == -1) continue; + + String namespace = token.substring(0, colon); + if (!cachedNamespaces.contains(namespace)) continue; + + ImmutableBlockState state = BlockStateParser.deserialize(token); + if (state == null) continue; + + String internalId = BlockStateUtils.getBlockOwnerIdFromState(state.customBlockState().handle()).toString(); + args[i] = internalId; + modified = true; + } + + if (modified) { + event.setMessage(String.join(" ", args)); + } + } +} From 511d1fd09e1c306d32f183f1d818f00ccc26e9cf Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Wed, 26 Mar 2025 02:09:57 +0800 Subject: [PATCH 3/5] fix template --- .../resources/resources/internal/configuration/gui.yml | 9 ++++++++- .../craftengine/bukkit/item/BukkitItemManager.java | 10 ---------- .../plugin/config/template/TemplateManagerImpl.java | 6 ++++-- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/bukkit/loader/src/main/resources/resources/internal/configuration/gui.yml b/bukkit/loader/src/main/resources/resources/internal/configuration/gui.yml index 827a861ed..9c32bd009 100644 --- a/bukkit/loader/src/main/resources/resources/internal/configuration/gui.yml +++ b/bukkit/loader/src/main/resources/resources/internal/configuration/gui.yml @@ -74,9 +74,16 @@ templates: item-name: "{name}" lore: "{lore}" model: - template: "default:model/simplified_generated" + template: "internal:model/simplified_generated" arguments: path: "minecraft:item/custom/gui/{texture}" + internal:model/simplified_generated: + type: "minecraft:model" + path: "{path}" + generation: + parent: "minecraft:item/generated" + textures: + "layer0": "{path}" items: internal:next_page_0: diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java index 16a7458ad..0f965dbc8 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java @@ -111,16 +111,6 @@ public class BukkitItemManager extends AbstractItemManager { return getCustomItem(id).map(it -> it.settings().fuelTime()).orElse(0); } - @Override - public void load() { - super.load(); - } - - @Override - public void unload() { - super.unload(); - } - @Override public void disable() { this.unload(); diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/config/template/TemplateManagerImpl.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/config/template/TemplateManagerImpl.java index e50fe5837..7afd0daf1 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/config/template/TemplateManagerImpl.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/config/template/TemplateManagerImpl.java @@ -76,7 +76,9 @@ public class TemplateManagerImpl implements TemplateManager { for (Object template : templates) { processUnknownTypeMember(template, processingResult.arguments(), processedTemplates::add); } - + if (processedTemplates.isEmpty()) { + return; + } Object firstTemplate = processedTemplates.get(0); // 对于map和list,应当对多模板合并 if (firstTemplate instanceof Map) { @@ -187,7 +189,7 @@ public class TemplateManagerImpl implements TemplateManager { // 合并参数 private Map mergeArguments(@NotNull Map rawChildArguments, @NotNull Map parentArguments) { - Map result = new HashMap<>(); + Map result = new HashMap<>(parentArguments); // 我们遍历一下当前节点下的所有参数,这些参数可能含有内嵌参数。所以需要对参数map先处理一次后再合并 // arguments: // argument_1: "{parent_argument}" From 7a24edf8073f42bdf120e85586b00ea4b076efcc Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Wed, 26 Mar 2025 02:48:50 +0800 Subject: [PATCH 4/5] refactor we hook --- .../bukkit/block/BukkitBlockManager.java | 41 ++++--- .../block/worldedit/SuggestionHandler.java | 31 ----- .../worldedit/WorldEditBlockRegister.java | 24 ++++ .../worldedit/WorldEditCommandHelper.java | 84 +++++++++++++ .../bukkit/block/worldedit/WorldEditHook.java | 116 ------------------ .../bukkit/plugin/BukkitCraftEngine.java | 7 +- 6 files changed, 133 insertions(+), 170 deletions(-) delete mode 100644 bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/worldedit/SuggestionHandler.java create mode 100644 bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/worldedit/WorldEditBlockRegister.java create mode 100644 bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/worldedit/WorldEditCommandHelper.java delete mode 100644 bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/worldedit/WorldEditHook.java diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java index 330f9fb6e..46b5e204e 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java @@ -7,7 +7,8 @@ import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import dev.dejvokep.boostedyaml.YamlDocument; -import net.momirealms.craftengine.bukkit.block.worldedit.WorldEditHook; +import net.momirealms.craftengine.bukkit.block.worldedit.WorldEditCommandHelper; +import net.momirealms.craftengine.bukkit.block.worldedit.WorldEditBlockRegister; import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; import net.momirealms.craftengine.bukkit.plugin.injector.BukkitInjector; import net.momirealms.craftengine.bukkit.plugin.network.PacketConsumers; @@ -86,11 +87,13 @@ public class BukkitBlockManager extends AbstractBlockManager { // Cached command suggestions private final List cachedSuggestions = new ArrayList<>(); // Cached Namespace - private final Set cachedNamespaces = new HashSet<>(); + private final Set namespacesInUse = new HashSet<>(); // Event listeners private final BlockEventListener blockEventListener; private final FallingBlockRemoveListener fallingBlockRemoveListener; + private WorldEditCommandHelper weCommandHelper; + public BukkitBlockManager(BukkitCraftEngine plugin) { super(plugin); this.plugin = plugin; @@ -128,6 +131,19 @@ public class BukkitBlockManager extends AbstractBlockManager { if (this.fallingBlockRemoveListener != null) { Bukkit.getPluginManager().registerEvents(this.fallingBlockRemoveListener, plugin.bootstrap()); } + boolean hasWE = false; + // WorldEdit + if (this.plugin.isPluginEnabled("FastAsyncWorldEdit")) { + this.initFastAsyncWorldEditHook(); + hasWE = true; + } else if (this.plugin.isPluginEnabled("WorldEdit")) { + this.initWorldEditHook(); + hasWE = true; + } + if (hasWE) { + this.weCommandHelper = new WorldEditCommandHelper(this.plugin, this); + this.weCommandHelper.enable(); + } } @Override @@ -148,6 +164,7 @@ public class BukkitBlockManager extends AbstractBlockManager { this.unload(); HandlerList.unregisterAll(this.blockEventListener); if (this.fallingBlockRemoveListener != null) HandlerList.unregisterAll(this.fallingBlockRemoveListener); + if (this.weCommandHelper != null) this.weCommandHelper.disable(); } @Override @@ -175,7 +192,7 @@ public class BukkitBlockManager extends AbstractBlockManager { public void initWorldEditHook() { try { for (Key newBlockId : this.blockRegisterOrder) { - WorldEditHook.register(newBlockId); + WorldEditBlockRegister.register(newBlockId); } } catch (Exception e) { this.plugin.logger().warn("Failed to initialize world edit hook", e); @@ -228,9 +245,11 @@ public class BukkitBlockManager extends AbstractBlockManager { @Override public void initSuggestions() { this.cachedSuggestions.clear(); + this.namespacesInUse.clear(); Set states = new HashSet<>(); for (CustomBlock block : this.id2CraftEngineBlocks.values()) { states.add(block.id().toString()); + this.namespacesInUse.add(block.id().namespace()); for (ImmutableBlockState state : block.variantProvider().states()) { states.add(state.toString()); } @@ -238,22 +257,10 @@ public class BukkitBlockManager extends AbstractBlockManager { for (String state : states) { this.cachedSuggestions.add(Suggestion.suggestion(state)); } - this.cachedNamespaces.clear(); - initCachedNamespaces(); } - private void initCachedNamespaces() { - for (Suggestion suggestion : this.cachedSuggestions) { - String id = suggestion.suggestion(); - int index = id.indexOf(':'); - if (index != -1) { - cachedNamespaces.add(id.substring(0, index)); - } - } - } - - public Collection cachedNamespaces() { - return Collections.unmodifiableSet(cachedNamespaces); + public Set namespacesInUse() { + return Collections.unmodifiableSet(namespacesInUse); } public ImmutableMap> blockAppearanceArranger() { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/worldedit/SuggestionHandler.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/worldedit/SuggestionHandler.java deleted file mode 100644 index da6cb7da2..000000000 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/worldedit/SuggestionHandler.java +++ /dev/null @@ -1,31 +0,0 @@ -package net.momirealms.craftengine.bukkit.block.worldedit; - -import java.util.Set; -import java.util.function.Predicate; - -public class SuggestionHandler { - private final Predicate matcher; - - private SuggestionHandler(Predicate matcher) { - this.matcher = matcher; - } - - public boolean matches(String input) { - return matcher.test(input); - } - - public static SuggestionHandler of(Integer... pos) { - Set valid = Set.of(pos); - return new SuggestionHandler(input -> { - if (input.contains(" ")) return false; - - String[] args = input.split(" "); - int index = input.endsWith(" ") ? args.length : args.length - 1; - return valid.contains(index); - }); - } - - public static SuggestionHandler custom(Predicate matcher) { - return new SuggestionHandler(matcher); - } -} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/worldedit/WorldEditBlockRegister.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/worldedit/WorldEditBlockRegister.java new file mode 100644 index 000000000..279ada1c2 --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/worldedit/WorldEditBlockRegister.java @@ -0,0 +1,24 @@ +package net.momirealms.craftengine.bukkit.block.worldedit; + +import com.sk89q.worldedit.bukkit.BukkitBlockRegistry; +import com.sk89q.worldedit.util.concurrency.LazyReference; +import com.sk89q.worldedit.world.block.BlockType; +import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.util.ReflectionUtils; +import org.bukkit.Material; + +import java.lang.reflect.Field; + +public class WorldEditBlockRegister { + private static final Field field$BlockType$blockMaterial; + + static { + field$BlockType$blockMaterial = ReflectionUtils.getDeclaredField(BlockType.class, "blockMaterial"); + } + + public static void register(Key id) throws ReflectiveOperationException { + BlockType blockType = new BlockType(id.toString(), blockState -> blockState); + field$BlockType$blockMaterial.set(blockType, LazyReference.from(() -> new BukkitBlockRegistry.BukkitBlockMaterial(null, Material.STONE))); + BlockType.REGISTRY.register(id.toString(), blockType); + } +} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/worldedit/WorldEditCommandHelper.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/worldedit/WorldEditCommandHelper.java new file mode 100644 index 000000000..31d3f331d --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/worldedit/WorldEditCommandHelper.java @@ -0,0 +1,84 @@ +package net.momirealms.craftengine.bukkit.block.worldedit; + +import net.momirealms.craftengine.bukkit.block.BukkitBlockManager; +import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; +import net.momirealms.craftengine.bukkit.util.BlockStateUtils; +import net.momirealms.craftengine.core.block.BlockStateParser; +import net.momirealms.craftengine.core.block.ImmutableBlockState; +import org.bukkit.Bukkit; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerCommandPreprocessEvent; + +import java.util.*; + +// TODO A better command suggestion system +public class WorldEditCommandHelper implements Listener { + private final BukkitBlockManager manager; + private final BukkitCraftEngine plugin; + + public WorldEditCommandHelper(BukkitCraftEngine plugin, BukkitBlockManager manager) { + this.plugin = plugin; + this.manager = manager; + } + + public void enable() { + Bukkit.getPluginManager().registerEvents(this, plugin.bootstrap()); + } + + public void disable() { + HandlerList.unregisterAll(this); + } + + @EventHandler(priority = EventPriority.HIGH) + public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event) { + String message = event.getMessage(); + if (!message.startsWith("//")) return; + + Set cachedNamespaces = manager.namespacesInUse(); + String[] args = message.split(" "); + boolean modified = false; + + for (int i = 1; i < args.length; i++) { + String[] parts = args[i].split(","); + List processedParts = new ArrayList<>(parts.length); + boolean partModified = false; + + for (String part : parts) { + String processed = processIdentifier(part, cachedNamespaces); + partModified |= !part.equals(processed); + processedParts.add(processed); + } + + if (partModified) { + args[i] = String.join(",", processedParts); + modified = true; + } + } + + if (modified) { + event.setMessage(String.join(" ", args)); + } + } + + private String processIdentifier(String identifier, Set cachedNamespaces) { + int colonIndex = identifier.indexOf(':'); + if (colonIndex == -1) return identifier; + + String namespace = identifier.substring(0, colonIndex); + if (!cachedNamespaces.contains(namespace)) return identifier; + + ImmutableBlockState state = BlockStateParser.deserialize(identifier); + if (state == null) return identifier; + + try { + return BlockStateUtils.getBlockOwnerIdFromState( + state.customBlockState().handle() + ).toString(); + } catch (NullPointerException e) { + return identifier; + } + } +} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/worldedit/WorldEditHook.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/worldedit/WorldEditHook.java deleted file mode 100644 index ae2f3198f..000000000 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/worldedit/WorldEditHook.java +++ /dev/null @@ -1,116 +0,0 @@ -package net.momirealms.craftengine.bukkit.block.worldedit; - -import com.google.common.collect.ImmutableMap; -import com.sk89q.worldedit.WorldEdit; -import com.sk89q.worldedit.bukkit.BukkitBlockRegistry; -import com.sk89q.worldedit.event.platform.CommandSuggestionEvent; -import com.sk89q.worldedit.internal.util.Substring; -import com.sk89q.worldedit.util.concurrency.LazyReference; -import com.sk89q.worldedit.util.eventbus.Subscribe; -import com.sk89q.worldedit.world.block.BlockType; -import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; -import net.momirealms.craftengine.bukkit.util.BlockStateUtils; -import net.momirealms.craftengine.core.block.BlockStateParser; -import net.momirealms.craftengine.core.block.ImmutableBlockState; -import net.momirealms.craftengine.core.util.Key; -import net.momirealms.craftengine.core.util.ReflectionUtils; -import org.bukkit.Bukkit; -import org.bukkit.Material; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; -import org.bukkit.event.player.PlayerCommandPreprocessEvent; -import org.incendo.cloud.suggestion.Suggestion; - -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -public class WorldEditHook implements Listener { - private static final Field field$BlockType$blockMaterial; - private final Map handlers = ImmutableMap.of( - "//set", SuggestionHandler.of(1), - "//replace", SuggestionHandler.of(1, 2) - ); - - static { - WorldEdit.getInstance().getEventBus().register(new WorldEditHook()); - field$BlockType$blockMaterial = ReflectionUtils.getDeclaredField(BlockType.class, "blockMaterial"); - } - - public static void register(Key id) throws ReflectiveOperationException { - BlockType blockType = new BlockType(id.toString(), blockState -> blockState); - field$BlockType$blockMaterial.set(blockType, LazyReference.from(() -> new BukkitBlockRegistry.BukkitBlockMaterial(null, Material.STONE))); - BlockType.REGISTRY.register(id.toString(), blockType); - } - - public WorldEditHook() { - Bukkit.getPluginManager().registerEvents(this, BukkitCraftEngine.instance().bootstrap()); - } - - @Subscribe - public void onSuggestion(CommandSuggestionEvent event) { - String input = event.getArguments(); - String command = input.substring(0, input.indexOf(" ")); - - SuggestionHandler handler = handlers.get(command); - if (handler == null || !handler.matches(input)) return; - int start = input.lastIndexOf(" ") + 1; - int end = input.length(); - - if (start == end) { - List suggestions = BukkitCraftEngine.instance().blockManager().cachedNamespaces() - .stream() - .map(ns -> Substring.wrap(ns + ":", start, end)) - .collect(Collectors.toList()); - suggestions.addAll(event.getSuggestions()); - event.setSuggestions(suggestions); - return; - } - - String last = input.substring(start, end); - List suggestions = new ArrayList<>(); - for (Suggestion s : BukkitCraftEngine.instance().blockManager().cachedSuggestions()) { - String id = s.suggestion(); - if (id.startsWith(last)) - suggestions.add(Substring.wrap(id, start, end)); - } - suggestions.addAll(event.getSuggestions()); - event.setSuggestions(suggestions); - } - - @EventHandler(priority = EventPriority.HIGH) - public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event) { - String message = event.getMessage(); - if (!message.startsWith("//")) return; - - Collection cachedNamespaces = BukkitCraftEngine.instance().blockManager().cachedNamespaces(); - - String[] args = message.split(" "); - boolean modified = false; - - for (int i = 1; i < args.length; i++) { - String token = args[i]; - - int colon = token.indexOf(':'); - if (colon == -1) continue; - - String namespace = token.substring(0, colon); - if (!cachedNamespaces.contains(namespace)) continue; - - ImmutableBlockState state = BlockStateParser.deserialize(token); - if (state == null) continue; - - String internalId = BlockStateUtils.getBlockOwnerIdFromState(state.customBlockState().handle()).toString(); - args[i] = internalId; - modified = true; - } - - if (modified) { - event.setMessage(String.join(" ", args)); - } - } -} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/BukkitCraftEngine.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/BukkitCraftEngine.java index 423bdd269..fc5b6b2a5 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/BukkitCraftEngine.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/BukkitCraftEngine.java @@ -4,6 +4,7 @@ import net.momirealms.antigrieflib.AntiGriefLib; import net.momirealms.craftengine.bukkit.api.event.CraftEngineReloadEvent; import net.momirealms.craftengine.bukkit.block.BukkitBlockManager; import net.momirealms.craftengine.bukkit.block.behavior.BukkitBlockBehaviors; +import net.momirealms.craftengine.bukkit.block.worldedit.WorldEditCommandHelper; import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurnitureManager; import net.momirealms.craftengine.bukkit.font.BukkitImageManager; import net.momirealms.craftengine.bukkit.item.BukkitItemManager; @@ -178,12 +179,6 @@ public class BukkitCraftEngine extends CraftEngine { new ImageExpansion(this).register(); this.hasPlaceholderAPI = true; } - // WorldEdit - if (this.isPluginEnabled("FastAsyncWorldEdit")) { - this.blockManager().initFastAsyncWorldEditHook(); - } else if (this.isPluginEnabled("WorldEdit")) { - this.blockManager().initWorldEditHook(); - } } @Override From c625aad284dd4f2b170a6a6d5e5d8830dcb36f73 Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Wed, 26 Mar 2025 03:15:59 +0800 Subject: [PATCH 5/5] split config section --- bukkit/loader/src/main/resources/config.yml | 30 ++++++++-------- .../core/plugin/config/ConfigManager.java | 36 +++++++++++-------- gradle.properties | 4 +-- 3 files changed, 39 insertions(+), 31 deletions(-) diff --git a/bukkit/loader/src/main/resources/config.yml b/bukkit/loader/src/main/resources/config.yml index d0d39a52e..2a1105a77 100644 --- a/bukkit/loader/src/main/resources/config.yml +++ b/bukkit/loader/src/main/resources/config.yml @@ -211,20 +211,22 @@ gui: performance: # Maximum chain update depth when fixing client visuals max-block-chain-update-limit: 64 - light-system: - enable: true - # Turning this option on will reduce lighting system issues to some extent, but will increase server bandwidth consumption - force-update-light: false - chunk-system: - # Disabling this option prevents the plugin from converting custom blocks to vanilla states when chunks are unloaded. - # While this can improve performance, custom blocks will turn into air if the plugin is uninstalled. - restore-vanilla-blocks-on-chunk-unload: true - # When you edit a map locally using CraftEngine fabric mod, the custom block data is not immediately synchronized with the - # server's CraftEngine internal data. Enabling this option will synchronize the data when the chunk is loaded. - # (This option only slightly impacts performance, which has been fully optimized, so you don't need to worry too much.) - sync-custom-blocks-on-chunk-load: false - # If you disable this, it's a must to disable the above option. - restore-custom-blocks-on-chunk-load: true + +light-system: + enable: true + # Turning this option on will reduce lighting system issues to some extent, but will increase server bandwidth consumption + force-update-light: false + +chunk-system: + # Disabling this option prevents the plugin from converting custom blocks to vanilla states when chunks are unloaded. + # While this can improve performance, custom blocks will turn into air if the plugin is uninstalled. + restore-vanilla-blocks-on-chunk-unload: true + # When you edit a map locally using CraftEngine fabric mod, the custom block data is not immediately synchronized with the + # server's CraftEngine internal data. Enabling this option will synchronize the data when the chunk is loaded. + # (This option only slightly impacts performance, which has been fully optimized, so you don't need to worry too much.) + sync-custom-blocks-on-chunk-load: false + # If you disable this, it's a must to disable the above option. + restore-custom-blocks-on-chunk-load: true offset-characters: font: minecraft:default diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/config/ConfigManager.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/config/ConfigManager.java index c61e8ccec..1914dbb78 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/config/ConfigManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/config/ConfigManager.java @@ -90,12 +90,14 @@ public class ConfigManager implements Reloadable { protected String resource_pack$external_host$sha1; protected UUID resource_pack$external_host$uuid; - protected boolean performance$light_system$force_update_light; - protected boolean performance$light_system$enable; protected int performance$max_block_chain_update_limit; - protected boolean performance$chunk_system$restore_vanilla_blocks_on_chunk_unload; - protected boolean performance$chunk_system$restore_custom_blocks_on_chunk_load; - protected boolean performance$chunk_system$sync_custom_blocks_on_chunk_load; + + protected boolean light_system$force_update_light; + protected boolean light_system$enable; + + protected boolean chunk_system$restore_vanilla_blocks_on_chunk_unload; + protected boolean chunk_system$restore_custom_blocks_on_chunk_load; + protected boolean chunk_system$sync_custom_blocks_on_chunk_load; protected boolean furniture$remove_invalid_furniture_on_chunk_load$enable; protected Set furniture$remove_invalid_furniture_on_chunk_load$list; @@ -240,11 +242,15 @@ public class ConfigManager implements Reloadable { // performance performance$max_block_chain_update_limit = config.getInt("performance.max-block-chain-update-limit", 64); - performance$light_system$force_update_light = config.getBoolean("performance.light-system.force-update-light", false); - performance$light_system$enable = config.getBoolean("performance.light-system.enable", true); - performance$chunk_system$restore_vanilla_blocks_on_chunk_unload = config.getBoolean("performance.chunk-system.restore-vanilla-blocks-on-chunk-unload", true); - performance$chunk_system$restore_custom_blocks_on_chunk_load = config.getBoolean("performance.chunk-system.restore-custom-blocks-on-chunk-load", true); - performance$chunk_system$sync_custom_blocks_on_chunk_load = config.getBoolean("performance.chunk-system.sync-custom-blocks-on-chunk-load", false); + + // light + light_system$force_update_light = config.getBoolean("light-system.force-update-light", false); + light_system$enable = config.getBoolean("light-system.enable", true); + + // chunk + chunk_system$restore_vanilla_blocks_on_chunk_unload = config.getBoolean("chunk-system.restore-vanilla-blocks-on-chunk-unload", true); + chunk_system$restore_custom_blocks_on_chunk_load = config.getBoolean("chunk-system.restore-custom-blocks-on-chunk-load", true); + chunk_system$sync_custom_blocks_on_chunk_load = config.getBoolean("chunk-system.sync-custom-blocks-on-chunk-load", false); // furniture furniture$remove_invalid_furniture_on_chunk_load$enable = config.getBoolean("furniture.remove-invalid-furniture-on-chunk-load.enable", false); @@ -320,11 +326,11 @@ public class ConfigManager implements Reloadable { } public static boolean forceUpdateLight() { - return instance.performance$light_system$force_update_light; + return instance.light_system$force_update_light; } public static boolean enableLightSystem() { - return instance.performance$light_system$enable; + return instance.light_system$enable; } public static float packMinVersion() { @@ -348,7 +354,7 @@ public class ConfigManager implements Reloadable { } public static boolean restoreVanillaBlocks() { - return instance.performance$chunk_system$restore_vanilla_blocks_on_chunk_unload && instance.performance$chunk_system$restore_custom_blocks_on_chunk_load; + return instance.chunk_system$restore_vanilla_blocks_on_chunk_unload && instance.chunk_system$restore_custom_blocks_on_chunk_load; } public static boolean denyNonMinecraftRequest() { @@ -356,11 +362,11 @@ public class ConfigManager implements Reloadable { } public static boolean restoreCustomBlocks() { - return instance.performance$chunk_system$restore_custom_blocks_on_chunk_load; + return instance.chunk_system$restore_custom_blocks_on_chunk_load; } public static boolean syncCustomBlocks() { - return instance.performance$chunk_system$sync_custom_blocks_on_chunk_load; + return instance.chunk_system$sync_custom_blocks_on_chunk_load; } public static List foldersToMerge() { diff --git a/gradle.properties b/gradle.properties index 3375f61ce..3f90eae1f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,8 +2,8 @@ org.gradle.jvmargs=-Xmx1G # Project settings # Rule: [major update].[feature update].[bug fix] -project_version=0.0.38 -config_version=16 +project_version=0.0.39 +config_version=17 lang_version=3 project_group=net.momirealms latest_minecraft_version=1.21.4