9
0
mirror of https://github.com/Xiao-MoMi/craft-engine.git synced 2025-12-31 04:46:37 +00:00

feat: Re-implement WorldEdit command and suggestion support in a proper way

This commit is contained in:
iqtester
2025-04-14 18:08:14 +08:00
parent b5505ec06d
commit 71fbf7f7b9
3 changed files with 110 additions and 99 deletions

View File

@@ -87,7 +87,8 @@ public class BukkitBlockManager extends AbstractBlockManager {
// Event listeners
private final BlockEventListener blockEventListener;
private final FallingBlockRemoveListener fallingBlockRemoveListener;
private WorldEditCommandHelper weCommandHelper;
// WE support
private WorldEditBlockRegister weBlockRegister;
public BukkitBlockManager(BukkitCraftEngine plugin) {
super(plugin);
@@ -128,18 +129,11 @@ 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();
}
}
@@ -152,6 +146,8 @@ public class BukkitBlockManager extends AbstractBlockManager {
this.modBlockStates.clear();
if (EmptyBlock.INSTANCE != null)
Arrays.fill(this.stateId2ImmutableBlockStates, EmptyBlock.INSTANCE.defaultState());
if (weBlockRegister != null)
weBlockRegister.unload();
}
@Override
@@ -159,7 +155,6 @@ 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
@@ -172,6 +167,7 @@ public class BukkitBlockManager extends AbstractBlockManager {
initSuggestions();
resetPacketConsumers();
clearCache();
loadWorldEditRegister();
}
private void clearCache() {
@@ -181,19 +177,27 @@ public class BukkitBlockManager extends AbstractBlockManager {
}
public void initFastAsyncWorldEditHook() {
// do nothing
this.weBlockRegister = new WorldEditBlockRegister(this);
this.weBlockRegister.enable();
}
public void initWorldEditHook() {
this.weBlockRegister = new WorldEditBlockRegister(this);
this.weBlockRegister.enable();
try {
for (Key newBlockId : this.blockRegisterOrder) {
WorldEditBlockRegister.register(newBlockId);
weBlockRegister.register(newBlockId);
}
} catch (Exception e) {
this.plugin.logger().warn("Failed to initialize world edit hook", e);
}
}
public void loadWorldEditRegister() {
if (this.weBlockRegister != null)
this.weBlockRegister.load();
}
@Nullable
public Object getMinecraftBlockHolder(int stateId) {
return stateId2BlockHolder.get(stateId);

View File

@@ -1,85 +0,0 @@
package net.momirealms.craftengine.bukkit.block;
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.ArrayList;
import java.util.List;
import java.util.Set;
// 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<String> cachedNamespaces = manager.namespacesInUse();
String[] args = message.split(" ");
boolean modified = false;
for (int i = 1; i < args.length; i++) {
String[] parts = args[i].split(",");
List<String> 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<String> 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;
}
}
}