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

添加clear指令

This commit is contained in:
XiaoMoMi
2025-11-18 17:59:24 +08:00
parent 691aed86dd
commit fca6090918
7 changed files with 126 additions and 4 deletions

View File

@@ -33,6 +33,7 @@ public class BukkitCommandManager extends AbstractCommandManager<CommandSender>
new ReloadCommand(this, plugin),
new GetItemCommand(this, plugin),
new GiveItemCommand(this, plugin),
new ClearItemCommand(this, plugin),
new ItemBrowserPlayerCommand(this, plugin),
new ItemBrowserAdminCommand(this, plugin),
new SearchRecipePlayerCommand(this, plugin),

View File

@@ -0,0 +1,98 @@
package net.momirealms.craftengine.bukkit.plugin.command.feature;
import net.kyori.adventure.text.Component;
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
import net.momirealms.craftengine.bukkit.nms.FastNMS;
import net.momirealms.craftengine.bukkit.plugin.command.BukkitCommandFeature;
import net.momirealms.craftengine.bukkit.util.ItemStackUtils;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.plugin.command.CraftEngineCommandManager;
import net.momirealms.craftengine.core.plugin.command.FlagKeys;
import net.momirealms.craftengine.core.plugin.locale.MessageConstants;
import net.momirealms.craftengine.core.util.Key;
import org.bukkit.NamespacedKey;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.incendo.cloud.Command;
import org.incendo.cloud.CommandManager;
import org.incendo.cloud.bukkit.data.MultiplePlayerSelector;
import org.incendo.cloud.bukkit.parser.NamespacedKeyParser;
import org.incendo.cloud.bukkit.parser.selector.MultiplePlayerSelectorParser;
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.Collection;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.function.Predicate;
public class ClearItemCommand extends BukkitCommandFeature<CommandSender> {
public ClearItemCommand(CraftEngineCommandManager<CommandSender> commandManager, CraftEngine plugin) {
super(commandManager, plugin);
}
@Override
public Command.Builder<? extends CommandSender> assembleCommand(CommandManager<CommandSender> manager, Command.Builder<CommandSender> builder) {
return builder
.flag(FlagKeys.SILENT_FLAG)
.required("player", MultiplePlayerSelectorParser.multiplePlayerSelectorParser(true))
.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().itemManager().cachedCustomItemSuggestions());
}
}))
.optional("amount", IntegerParser.integerParser(0))
.handler(context -> {
MultiplePlayerSelector selector = context.get("player");
int amount = context.getOrDefault("amount", -1);
NamespacedKey namespacedKey = context.get("id");
Key itemId = Key.of(namespacedKey.namespace(), namespacedKey.value());
Predicate<Object> predicate = nmsStack -> {
Optional<Key> id = BukkitItemManager.instance().wrap(ItemStackUtils.asCraftMirror(nmsStack)).customId();
return id.isPresent() && id.get().equals(itemId);
};
int totalCount = 0;
Collection<Player> players = selector.values();
for (Player player : players) {
Object serverPlayer = FastNMS.INSTANCE.method$CraftPlayer$getHandle(player);
Object inventory = FastNMS.INSTANCE.method$Player$getInventory(serverPlayer);
Object inventoryMenu = FastNMS.INSTANCE.field$Player$inventoryMenu(serverPlayer);
totalCount += FastNMS.INSTANCE.method$Inventory$clearOrCountMatchingItems(inventory, predicate, amount, FastNMS.INSTANCE.method$InventoryMenu$getCraftSlots(inventoryMenu));
FastNMS.INSTANCE.method$AbstractContainerMenu$broadcastChanges(FastNMS.INSTANCE.field$Player$containerMenu(serverPlayer));
FastNMS.INSTANCE.method$InventoryMenu$slotsChanged(inventoryMenu, inventory);
}
if (totalCount == 0) {
if (players.size() == 1) {
handleFeedback(context, MessageConstants.COMMAND_ITEM_CLEAR_FAILED_SINGLE, Component.text(players.iterator().next().getName()));
} else {
handleFeedback(context, MessageConstants.COMMAND_ITEM_CLEAR_FAILED_MULTIPLE, Component.text(players.size()));
}
} else {
if (amount == 0) {
if (players.size() == 1) {
handleFeedback(context, MessageConstants.COMMAND_ITEM_CLEAR_TEST_SINGLE, Component.text(totalCount), Component.text(players.iterator().next().getName()));
} else {
handleFeedback(context, MessageConstants.COMMAND_ITEM_CLEAR_TEST_MULTIPLE, Component.text(totalCount), Component.text(players.size()));
}
} else {
if (players.size() == 1) {
handleFeedback(context, MessageConstants.COMMAND_ITEM_CLEAR_SUCCESS_SINGLE, Component.text(totalCount), Component.text(players.iterator().next().getName()));
} else {
handleFeedback(context, MessageConstants.COMMAND_ITEM_CLEAR_SUCCESS_MULTIPLE, Component.text(totalCount), Component.text(players.size()));
}
}
}
});
}
@Override
public String getFeatureID() {
return "clear_item";
}
}

View File

@@ -51,4 +51,8 @@ public final class ItemStackUtils {
Item<ItemStack> wrappedItem = BukkitItemManager.instance().wrap(itemStack);
return UniqueIdItem.of(wrappedItem);
}
public static ItemStack asCraftMirror(Object itemStack) {
return FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(itemStack);
}
}

View File

@@ -43,6 +43,13 @@ give_item:
- /craftengine item give
- /ce item give
clear_item:
enable: true
permission: ce.command.admin.clear_item
usage:
- /craftengine item clear
- /ce item clear
item_browser_player:
enable: true
permission: ce.command.player.item_browser

View File

@@ -49,6 +49,12 @@ command.item.get.failure.not_exist: "<red><lang:argument.item.id.invalid:'<arg:0
command.item.give.success.single: "<lang:commands.give.success.single:'<arg:0>':'<arg:1>':'<arg:2>'>"
command.item.give.success.multiple: "<lang:commands.give.success.multiple:'<arg:0>':'<arg:1>':'<arg:2>'>"
command.item.give.failure.not_exist: "<red><lang:argument.item.id.invalid:'<arg:0>'></red>"
command.item.clear.failed.single: "<red>No items were found on player <arg:0></red>"
command.item.clear.failed.multiple: "<red>No items were found on <arg:0> players</red>"
command.item.clear.success.single: "<white>Removed <arg:0> item(s) from player <arg:1></white>"
command.item.clear.success.multiple: "<white>Removed <arg:0> item(s) from <arg:1> players</white>"
command.item.clear.test.single: "<white>Found <arg:0> matching item(s) on player <arg:1></white>"
command.item.clear.test.multiple: "<white>Found <arg:0> matching item(s) on <arg:1> players</white>"
command.search_recipe.not_found: "<red>No recipe found for this item</red>"
command.search_usage.not_found: "<red>No usage found for this item</red>"
command.search_recipe.no_item: "<red>Please hold an item before running this command</red>"

View File

@@ -35,4 +35,10 @@ public interface MessageConstants {
TranslatableComponent.Builder COMMAND_LOCALE_SET_FAILURE = Component.translatable().key("command.locale.set.failure");
TranslatableComponent.Builder COMMAND_LOCALE_SET_SUCCESS = Component.translatable().key("command.locale.set.success");
TranslatableComponent.Builder COMMAND_LOCALE_UNSET_SUCCESS = Component.translatable().key("command.locale.unset.success");
TranslatableComponent.Builder COMMAND_ITEM_CLEAR_SUCCESS_SINGLE = Component.translatable().key("command.item.clear.success.single");
TranslatableComponent.Builder COMMAND_ITEM_CLEAR_SUCCESS_MULTIPLE = Component.translatable().key("command.item.clear.success.multiple");
TranslatableComponent.Builder COMMAND_ITEM_CLEAR_FAILED_SINGLE = Component.translatable().key("command.item.clear.failed.single");
TranslatableComponent.Builder COMMAND_ITEM_CLEAR_FAILED_MULTIPLE = Component.translatable().key("command.item.clear.failed.multiple");
TranslatableComponent.Builder COMMAND_ITEM_CLEAR_TEST_SINGLE = Component.translatable().key("command.item.clear.test.single");
TranslatableComponent.Builder COMMAND_ITEM_CLEAR_TEST_MULTIPLE = Component.translatable().key("command.item.clear.test.multiple");
}

View File

@@ -1,9 +1,9 @@
org.gradle.jvmargs=-Xmx1G
# Project settings
project_version=0.0.65.8
config_version=55
lang_version=38
project_version=0.0.65.9
config_version=56
lang_version=39
project_group=net.momirealms
latest_supported_version=1.21.10
@@ -48,7 +48,7 @@ byte_buddy_version=1.17.8
ahocorasick_version=0.6.3
snake_yaml_version=2.5
anti_grief_version=1.0.4
nms_helper_version=1.0.134
nms_helper_version=1.0.135
evalex_version=3.5.0
reactive_streams_version=1.0.4
amazon_awssdk_version=2.34.5