mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-20 15:39:22 +00:00
refactor we hook
This commit is contained in:
@@ -7,7 +7,8 @@ import com.google.gson.JsonArray;
|
|||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import dev.dejvokep.boostedyaml.YamlDocument;
|
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.BukkitCraftEngine;
|
||||||
import net.momirealms.craftengine.bukkit.plugin.injector.BukkitInjector;
|
import net.momirealms.craftengine.bukkit.plugin.injector.BukkitInjector;
|
||||||
import net.momirealms.craftengine.bukkit.plugin.network.PacketConsumers;
|
import net.momirealms.craftengine.bukkit.plugin.network.PacketConsumers;
|
||||||
@@ -86,11 +87,13 @@ public class BukkitBlockManager extends AbstractBlockManager {
|
|||||||
// Cached command suggestions
|
// Cached command suggestions
|
||||||
private final List<Suggestion> cachedSuggestions = new ArrayList<>();
|
private final List<Suggestion> cachedSuggestions = new ArrayList<>();
|
||||||
// Cached Namespace
|
// Cached Namespace
|
||||||
private final Set<String> cachedNamespaces = new HashSet<>();
|
private final Set<String> namespacesInUse = new HashSet<>();
|
||||||
// Event listeners
|
// Event listeners
|
||||||
private final BlockEventListener blockEventListener;
|
private final BlockEventListener blockEventListener;
|
||||||
private final FallingBlockRemoveListener fallingBlockRemoveListener;
|
private final FallingBlockRemoveListener fallingBlockRemoveListener;
|
||||||
|
|
||||||
|
private WorldEditCommandHelper weCommandHelper;
|
||||||
|
|
||||||
public BukkitBlockManager(BukkitCraftEngine plugin) {
|
public BukkitBlockManager(BukkitCraftEngine plugin) {
|
||||||
super(plugin);
|
super(plugin);
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
@@ -128,6 +131,19 @@ public class BukkitBlockManager extends AbstractBlockManager {
|
|||||||
if (this.fallingBlockRemoveListener != null) {
|
if (this.fallingBlockRemoveListener != null) {
|
||||||
Bukkit.getPluginManager().registerEvents(this.fallingBlockRemoveListener, plugin.bootstrap());
|
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
|
@Override
|
||||||
@@ -148,6 +164,7 @@ public class BukkitBlockManager extends AbstractBlockManager {
|
|||||||
this.unload();
|
this.unload();
|
||||||
HandlerList.unregisterAll(this.blockEventListener);
|
HandlerList.unregisterAll(this.blockEventListener);
|
||||||
if (this.fallingBlockRemoveListener != null) HandlerList.unregisterAll(this.fallingBlockRemoveListener);
|
if (this.fallingBlockRemoveListener != null) HandlerList.unregisterAll(this.fallingBlockRemoveListener);
|
||||||
|
if (this.weCommandHelper != null) this.weCommandHelper.disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -175,7 +192,7 @@ public class BukkitBlockManager extends AbstractBlockManager {
|
|||||||
public void initWorldEditHook() {
|
public void initWorldEditHook() {
|
||||||
try {
|
try {
|
||||||
for (Key newBlockId : this.blockRegisterOrder) {
|
for (Key newBlockId : this.blockRegisterOrder) {
|
||||||
WorldEditHook.register(newBlockId);
|
WorldEditBlockRegister.register(newBlockId);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
this.plugin.logger().warn("Failed to initialize world edit hook", e);
|
this.plugin.logger().warn("Failed to initialize world edit hook", e);
|
||||||
@@ -228,9 +245,11 @@ public class BukkitBlockManager extends AbstractBlockManager {
|
|||||||
@Override
|
@Override
|
||||||
public void initSuggestions() {
|
public void initSuggestions() {
|
||||||
this.cachedSuggestions.clear();
|
this.cachedSuggestions.clear();
|
||||||
|
this.namespacesInUse.clear();
|
||||||
Set<String> states = new HashSet<>();
|
Set<String> states = new HashSet<>();
|
||||||
for (CustomBlock block : this.id2CraftEngineBlocks.values()) {
|
for (CustomBlock block : this.id2CraftEngineBlocks.values()) {
|
||||||
states.add(block.id().toString());
|
states.add(block.id().toString());
|
||||||
|
this.namespacesInUse.add(block.id().namespace());
|
||||||
for (ImmutableBlockState state : block.variantProvider().states()) {
|
for (ImmutableBlockState state : block.variantProvider().states()) {
|
||||||
states.add(state.toString());
|
states.add(state.toString());
|
||||||
}
|
}
|
||||||
@@ -238,22 +257,10 @@ public class BukkitBlockManager extends AbstractBlockManager {
|
|||||||
for (String state : states) {
|
for (String state : states) {
|
||||||
this.cachedSuggestions.add(Suggestion.suggestion(state));
|
this.cachedSuggestions.add(Suggestion.suggestion(state));
|
||||||
}
|
}
|
||||||
this.cachedNamespaces.clear();
|
|
||||||
initCachedNamespaces();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initCachedNamespaces() {
|
public Set<String> namespacesInUse() {
|
||||||
for (Suggestion suggestion : this.cachedSuggestions) {
|
return Collections.unmodifiableSet(namespacesInUse);
|
||||||
String id = suggestion.suggestion();
|
|
||||||
int index = id.indexOf(':');
|
|
||||||
if (index != -1) {
|
|
||||||
cachedNamespaces.add(id.substring(0, index));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Collection<String> cachedNamespaces() {
|
|
||||||
return Collections.unmodifiableSet(cachedNamespaces);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ImmutableMap<Key, List<Integer>> blockAppearanceArranger() {
|
public ImmutableMap<Key, List<Integer>> blockAppearanceArranger() {
|
||||||
|
|||||||
@@ -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<String> matcher;
|
|
||||||
|
|
||||||
private SuggestionHandler(Predicate<String> matcher) {
|
|
||||||
this.matcher = matcher;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean matches(String input) {
|
|
||||||
return matcher.test(input);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SuggestionHandler of(Integer... pos) {
|
|
||||||
Set<Integer> 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<String> matcher) {
|
|
||||||
return new SuggestionHandler(matcher);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<String, SuggestionHandler> 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<Substring> 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<Substring> 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<String> 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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -4,6 +4,7 @@ import net.momirealms.antigrieflib.AntiGriefLib;
|
|||||||
import net.momirealms.craftengine.bukkit.api.event.CraftEngineReloadEvent;
|
import net.momirealms.craftengine.bukkit.api.event.CraftEngineReloadEvent;
|
||||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||||
import net.momirealms.craftengine.bukkit.block.behavior.BukkitBlockBehaviors;
|
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.entity.furniture.BukkitFurnitureManager;
|
||||||
import net.momirealms.craftengine.bukkit.font.BukkitImageManager;
|
import net.momirealms.craftengine.bukkit.font.BukkitImageManager;
|
||||||
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
||||||
@@ -178,12 +179,6 @@ public class BukkitCraftEngine extends CraftEngine {
|
|||||||
new ImageExpansion(this).register();
|
new ImageExpansion(this).register();
|
||||||
this.hasPlaceholderAPI = true;
|
this.hasPlaceholderAPI = true;
|
||||||
}
|
}
|
||||||
// WorldEdit
|
|
||||||
if (this.isPluginEnabled("FastAsyncWorldEdit")) {
|
|
||||||
this.blockManager().initFastAsyncWorldEditHook();
|
|
||||||
} else if (this.isPluginEnabled("WorldEdit")) {
|
|
||||||
this.blockManager().initWorldEditHook();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
Reference in New Issue
Block a user