9
0
mirror of https://github.com/Xiao-MoMi/craft-engine.git synced 2025-12-19 15:09:15 +00:00

添加2个debug命令

This commit is contained in:
jhqwqmc
2025-11-20 10:21:18 +08:00
parent 2f4fd9df23
commit 2545ce75b4
13 changed files with 215 additions and 9 deletions

View File

@@ -13,7 +13,6 @@ import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Locale;
import java.util.function.Predicate;
public class CheckItemExpansion extends PlaceholderExpansion {

View File

@@ -115,7 +115,7 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
}
@Override
public Optional<Item<ItemStack>> s2c(Item<ItemStack> item, Player player) {
public Optional<Item<ItemStack>> s2c(Item<ItemStack> item, @Nullable Player player) {
if (item.isEmpty()) return Optional.empty();
return this.networkItemHandler.s2c(item, player);
}

View File

@@ -22,6 +22,7 @@ import net.momirealms.sparrow.nbt.ListTag;
import net.momirealms.sparrow.nbt.StringTag;
import net.momirealms.sparrow.nbt.Tag;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
@@ -119,7 +120,7 @@ public final class LegacyNetworkItemHandler implements NetworkItemHandler<ItemSt
}
@Override
public Optional<Item<ItemStack>> s2c(Item<ItemStack> wrapped, Player player) {
public Optional<Item<ItemStack>> s2c(Item<ItemStack> wrapped, @Nullable Player player) {
boolean forceReturn = false;
// 处理收纳袋

View File

@@ -19,6 +19,7 @@ import net.momirealms.sparrow.nbt.ListTag;
import net.momirealms.sparrow.nbt.StringTag;
import net.momirealms.sparrow.nbt.Tag;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
@@ -110,7 +111,7 @@ public final class ModernNetworkItemHandler implements NetworkItemHandler<ItemSt
}
@Override
public Optional<Item<ItemStack>> s2c(Item<ItemStack> wrapped, Player player) {
public Optional<Item<ItemStack>> s2c(Item<ItemStack> wrapped, @Nullable Player player) {
boolean forceReturn = false;
// 处理收纳袋

View File

@@ -64,8 +64,9 @@ public class BukkitCommandManager extends AbstractCommandManager<CommandSender>
new SendResourcePackCommand(this, plugin),
new DebugSaveDefaultResourcesCommand(this, plugin),
new DebugCleanCacheCommand(this, plugin),
new DebugGenerateInternalAssetsCommand(this, plugin)
// new OverrideGiveCommand(this, plugin)
new DebugGenerateInternalAssetsCommand(this, plugin),
new DebugCustomModelDataCommand(this, plugin),
new DebugImageCommand(this, plugin)
));
final LegacyPaperCommandManager<CommandSender> manager = (LegacyPaperCommandManager<CommandSender>) getCommandManager();
manager.settings().set(ManagerSetting.ALLOW_UNSAFE_REGISTRATION, true);

View File

@@ -0,0 +1,88 @@
package net.momirealms.craftengine.bukkit.plugin.command.feature;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.event.ClickEvent;
import net.kyori.adventure.text.format.NamedTextColor;
import net.momirealms.craftengine.bukkit.api.BukkitAdaptors;
import net.momirealms.craftengine.bukkit.api.CraftEngineItems;
import net.momirealms.craftengine.bukkit.plugin.command.BukkitCommandFeature;
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
import net.momirealms.craftengine.bukkit.util.KeyUtils;
import net.momirealms.craftengine.core.entity.player.InteractionHand;
import net.momirealms.craftengine.core.item.CustomItem;
import net.momirealms.craftengine.core.item.Item;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.plugin.command.CraftEngineCommandManager;
import net.momirealms.craftengine.core.util.Key;
import org.bukkit.NamespacedKey;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.incendo.cloud.Command;
import org.incendo.cloud.CommandManager;
import org.incendo.cloud.bukkit.parser.NamespacedKeyParser;
import org.incendo.cloud.context.CommandContext;
import org.incendo.cloud.context.CommandInput;
import org.incendo.cloud.suggestion.Suggestion;
import org.incendo.cloud.suggestion.SuggestionProvider;
import org.jetbrains.annotations.Nullable;
import java.util.concurrent.CompletableFuture;
public class DebugCustomModelDataCommand extends BukkitCommandFeature<CommandSender> {
public DebugCustomModelDataCommand(CraftEngineCommandManager<CommandSender> commandManager, CraftEngine plugin) {
super(commandManager, plugin);
}
@Override
public Command.Builder<? extends CommandSender> assembleCommand(CommandManager<CommandSender> manager, Command.Builder<CommandSender> builder) {
return builder
.optional("id", NamespacedKeyParser.namespacedKeyComponent().suggestionProvider(new SuggestionProvider<>() {
@Override
public @NonNull CompletableFuture<? extends @NonNull Iterable<? extends @NonNull Suggestion>> suggestionsFuture(@NonNull CommandContext<Object> context, @NonNull CommandInput input) {
return CompletableFuture.completedFuture(plugin().itemManager().cachedCustomItemSuggestions());
}
}))
.handler(this::handleCommand);
}
@Override
public String getFeatureID() {
return "debug_custom_model_data";
}
private void handleCommand(CommandContext<CommandSender> context) {
NamespacedKey namespacedKey = context.getOrDefault("id", null);
@Nullable BukkitServerPlayer player = context.sender() instanceof Player p ? BukkitAdaptors.adapt(p) : null;
if (namespacedKey != null) {
Key itemId = KeyUtils.namespacedKey2Key(namespacedKey);
CustomItem<ItemStack> customItem = CraftEngineItems.byId(itemId);
if (customItem == null) return;
Item<ItemStack> item = customItem.buildItem(player);
sendMessage(context, getCustomModelData(item, player));
return;
}
if (player != null) {
Item<ItemStack> item = player.getItemInHand(InteractionHand.MAIN_HAND).copyWithCount(1);
sendMessage(context, getCustomModelData(item, player));
}
}
private int getCustomModelData(Item<ItemStack> itemStack, BukkitServerPlayer player) {
return plugin().itemManager().s2c(itemStack, player)
.map(Item::customModelData)
.orElse(itemStack.customModelData())
.orElse(0);
}
private void sendMessage(CommandContext<CommandSender> context, int customModelData) {
Component message = Component.text(customModelData)
.hoverEvent(Component.text("Copy", NamedTextColor.YELLOW))
.clickEvent(ClickEvent.suggestCommand(String.valueOf(customModelData)));
plugin().senderFactory().wrap(context.sender()).sendMessage(message);
}
}

View File

@@ -0,0 +1,88 @@
package net.momirealms.craftengine.bukkit.plugin.command.feature;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.event.ClickEvent;
import net.kyori.adventure.text.format.NamedTextColor;
import net.momirealms.craftengine.bukkit.plugin.command.BukkitCommandFeature;
import net.momirealms.craftengine.bukkit.util.KeyUtils;
import net.momirealms.craftengine.core.font.BitmapImage;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.plugin.command.CraftEngineCommandManager;
import net.momirealms.craftengine.core.util.FormatUtils;
import net.momirealms.craftengine.core.util.Key;
import org.bukkit.command.CommandSender;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.incendo.cloud.Command;
import org.incendo.cloud.CommandManager;
import org.incendo.cloud.bukkit.parser.NamespacedKeyParser;
import org.incendo.cloud.context.CommandContext;
import org.incendo.cloud.context.CommandInput;
import org.incendo.cloud.parser.standard.IntegerParser;
import org.incendo.cloud.suggestion.Suggestion;
import org.incendo.cloud.suggestion.SuggestionProvider;
import java.util.concurrent.CompletableFuture;
public class DebugImageCommand extends BukkitCommandFeature<CommandSender> {
public DebugImageCommand(CraftEngineCommandManager<CommandSender> commandManager, CraftEngine plugin) {
super(commandManager, plugin);
}
@Override
public Command.Builder<? extends CommandSender> assembleCommand(CommandManager<CommandSender> manager, Command.Builder<CommandSender> builder) {
return builder
.required("id", NamespacedKeyParser.namespacedKeyComponent().suggestionProvider(new SuggestionProvider<>() {
@Override
public @NonNull CompletableFuture<? extends @NonNull Iterable<? extends @NonNull Suggestion>> suggestionsFuture(@NonNull CommandContext<Object> context, @NonNull CommandInput input) {
return CompletableFuture.completedFuture(plugin().fontManager().cachedImagesSuggestions());
}
}))
.optional("row", IntegerParser.integerParser(0))
.optional("column", IntegerParser.integerParser(0))
.handler(context -> {
Key imageId = KeyUtils.namespacedKey2Key(context.get("id"));
plugin().fontManager().bitmapImageByImageId(imageId).ifPresent(image -> {
int row = context.getOrDefault("row", 0);
int column = context.getOrDefault("column", 0);
String string = image.isValidCoordinate(row, column)
? imageId.asString() + ((row != 0 || column != 0) ? ":" + row + ":" + column : "") // 自动最小化
: imageId.asString() + ":" + (row = 0) + ":" + (column = 0); // 因为是无效的所以说要强调告诉获取的是00
Component component = Component.text()
.append(Component.text(string)
.hoverEvent(image.componentAt(row, column).color(NamedTextColor.WHITE))
.clickEvent(ClickEvent.suggestCommand(string)))
.append(getHelperInfo(image, row, column))
.build();
plugin().senderFactory().wrap(context.sender()).sendMessage(component);
});
});
}
@Override
public String getFeatureID() {
return "debug_image";
}
private static TextComponent.Builder getHelperInfo(BitmapImage image, int row, int column) {
String raw = new String(Character.toChars(image.codepointAt(row, column)));
String font = image.font().toString();
return Component.text()
.append(Component.text(" "))
.append(Component.text("[MM]")
.color(NamedTextColor.YELLOW)
.hoverEvent(Component.text("Copy", NamedTextColor.YELLOW))
.clickEvent(ClickEvent.suggestCommand(FormatUtils.miniMessageFont(raw, font))))
.append(Component.text(" "))
.append(Component.text("[MD]")
.color(NamedTextColor.YELLOW)
.hoverEvent(Component.text("Copy", NamedTextColor.YELLOW))
.clickEvent(ClickEvent.suggestCommand(FormatUtils.mineDownFont(raw, font))))
.append(Component.text(" "))
.append(Component.text("[RAW]")
.color(NamedTextColor.YELLOW)
.hoverEvent(Component.text("Copy", NamedTextColor.YELLOW))
.clickEvent(ClickEvent.suggestCommand(raw)));
}
}

View File

@@ -237,6 +237,20 @@ debug_clean_cache:
- /craftengine debug clean-cache
- /ce debug clean-cache
debug_custom_model_data:
enable: true
permission: ce.command.debug.custom_model_data
usage:
- /craftengine debug custom-model-data
- /ce debug custom-model-data
debug_image:
enable: true
permission: ce.command.debug.image
usage:
- /craftengine debug image
- /ce debug image
debug_generate_internal_assets:
enable: false
permission: ce.command.debug.generate_internal_assets

View File

@@ -17,6 +17,7 @@ import net.momirealms.craftengine.core.plugin.text.component.ComponentProvider;
import net.momirealms.craftengine.core.util.*;
import org.ahocorasick.trie.Token;
import org.ahocorasick.trie.Trie;
import org.incendo.cloud.suggestion.Suggestion;
import org.jetbrains.annotations.NotNull;
import javax.imageio.ImageIO;
@@ -52,6 +53,8 @@ public abstract class AbstractFontManager implements FontManager {
protected Map<String, Emoji> emojiMapper;
protected List<Emoji> emojiList;
protected List<String> allEmojiSuggestions;
// Cached command suggestions
protected final List<Suggestion> cachedImagesSuggestions = new ArrayList<>();
public AbstractFontManager(CraftEngine plugin) {
this.plugin = plugin;
@@ -95,6 +98,7 @@ public abstract class AbstractFontManager implements FontManager {
public void unload() {
this.fonts.clear();
this.images.clear();
this.cachedImagesSuggestions.clear();
this.illegalChars.clear();
this.emojis.clear();
this.networkTagTrie = null;
@@ -415,6 +419,12 @@ public abstract class AbstractFontManager implements FontManager {
return Optional.ofNullable(this.fonts.get(id));
}
@Override
public Collection<Suggestion> cachedImagesSuggestions() {
return Collections.unmodifiableCollection(this.cachedImagesSuggestions);
}
private Font getOrCreateFont(Key key) {
return this.fonts.computeIfAbsent(key, Font::new);
}
@@ -712,6 +722,7 @@ public abstract class AbstractFontManager implements FontManager {
}
AbstractFontManager.this.images.put(id, bitmapImage);
AbstractFontManager.this.cachedImagesSuggestions.add(Suggestion.suggestion(id.asString()));
}, () -> GsonHelper.get().toJson(section)));
}

View File

@@ -8,6 +8,7 @@ import net.momirealms.craftengine.core.plugin.config.ConfigParser;
import net.momirealms.craftengine.core.plugin.text.component.ComponentProvider;
import net.momirealms.craftengine.core.util.*;
import net.momirealms.sparrow.nbt.Tag;
import org.incendo.cloud.suggestion.Suggestion;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -80,6 +81,8 @@ public interface FontManager extends Manageable {
Optional<Font> fontById(Key font);
Collection<Suggestion> cachedImagesSuggestions();
int codepointByImageId(Key imageId, int x, int y);
default int codepointByImageId(Key imageId) {

View File

@@ -113,7 +113,7 @@ public interface ItemManager<T> extends Manageable, ModelGenerator {
Optional<Item<T>> c2s(Item<T> item);
Optional<Item<T>> s2c(Item<T> item, Player player);
Optional<Item<T>> s2c(Item<T> item, @Nullable Player player);
UniqueIdItem<T> uniqueEmptyItem();

View File

@@ -18,7 +18,7 @@ public interface NetworkItemHandler<T> {
String NETWORK_OPERATION = "type";
String NETWORK_VALUE = "value";
Optional<Item<T>> s2c(Item<T> itemStack, Player player);
Optional<Item<T>> s2c(Item<T> itemStack, @Nullable Player player);
Optional<Item<T>> c2s(Item<T> itemStack);

View File

@@ -2,7 +2,7 @@ org.gradle.jvmargs=-Xmx1G
# Project settings
project_version=0.0.65.11
config_version=56
config_version=57
lang_version=39
project_group=net.momirealms
latest_supported_version=1.21.10