From 70677f1956d29d2da6cc4754c674a983d7279891 Mon Sep 17 00:00:00 2001 From: daoge_cmd <3523206925@qq.com> Date: Wed, 16 Oct 2024 17:07:11 +0800 Subject: [PATCH] feat: add /kill command --- .../attribute/EntityAttributeComponent.java | 4 ++ .../server/command/defaults/ClearCommand.java | 21 ++++--- .../server/command/defaults/KillCommand.java | 61 +++++++++++++++++++ .../component/EntityBaseComponentImpl.java | 1 + .../player/EntityPlayerBaseComponentImpl.java | 5 -- .../server/registry/AllayCommandRegistry.java | 1 + 6 files changed, 81 insertions(+), 12 deletions(-) create mode 100644 server/src/main/java/org/allaymc/server/command/defaults/KillCommand.java diff --git a/api/src/main/java/org/allaymc/api/entity/component/attribute/EntityAttributeComponent.java b/api/src/main/java/org/allaymc/api/entity/component/attribute/EntityAttributeComponent.java index a7612140a..6f170c021 100644 --- a/api/src/main/java/org/allaymc/api/entity/component/attribute/EntityAttributeComponent.java +++ b/api/src/main/java/org/allaymc/api/entity/component/attribute/EntityAttributeComponent.java @@ -1,5 +1,6 @@ package org.allaymc.api.entity.component.attribute; +import org.allaymc.api.entity.component.EntityBaseComponent; import org.allaymc.api.entity.component.EntityComponent; import org.cloudburstmc.nbt.NbtMap; @@ -134,6 +135,9 @@ default void resetHealth() { /** * Kill the entity. + *

+ * Compared to {@link EntityBaseComponent#despawn()} method, this method will set the health + * of this entity to zero, rather than remove the entity directly. */ default void kill() { setHealth(0); diff --git a/server/src/main/java/org/allaymc/server/command/defaults/ClearCommand.java b/server/src/main/java/org/allaymc/server/command/defaults/ClearCommand.java index e4058c83a..8fd11125f 100644 --- a/server/src/main/java/org/allaymc/server/command/defaults/ClearCommand.java +++ b/server/src/main/java/org/allaymc/server/command/defaults/ClearCommand.java @@ -10,7 +10,6 @@ import org.allaymc.api.item.type.ItemType; import org.allaymc.api.item.type.ItemTypes; -import java.util.ArrayList; import java.util.List; import java.util.stream.Stream; @@ -36,8 +35,13 @@ public void prepareCommandTree(CommandTree tree) { .intNum("maxCount", -1) .optional() .exec((context, sender) -> { - var targets = new ArrayList(); - targets.addAll(context.getResult(0) != null ? context.getResult(0) : List.of(sender)); + List targets = context.getResult(0); + if (targets != null && targets.isEmpty()) { + context.addNoTargetMatchError(); + return context.fail(); + } else if (targets == null) { + targets = List.of(sender); + } ItemType itemType = context.getResult(1); int data = context.getResult(2); @@ -46,6 +50,8 @@ public void prepareCommandTree(CommandTree tree) { maxCount = Integer.MAX_VALUE; } + boolean success = true; + int status = 0; for (var target : targets) { var containers = Stream.of(FullContainerType.PLAYER_INVENTORY, FullContainerType.OFFHAND, FullContainerType.ARMOR).map(target::getContainer).toList(); if (maxCount == 0) { @@ -58,7 +64,7 @@ public void prepareCommandTree(CommandTree tree) { .sum()) .sum(); context.addOutput(TrKeys.M_COMMANDS_CLEAR_TESTING, target.getOriginName(), count); - return context.success(count); + status = count; } else { int c = maxCount; for (var container : containers) { @@ -81,13 +87,14 @@ public void prepareCommandTree(CommandTree tree) { if (maxCount != c) { context.addOutput(TrKeys.M_COMMANDS_CLEAR_SUCCESS, target.getOriginName(), maxCount - c); } else { - context.addOutput(TrKeys.M_COMMANDS_CLEAR_FAILURE_NO_ITEMS, target.getOriginName()); + context.addError("%" + TrKeys.M_COMMANDS_CLEAR_FAILURE_NO_ITEMS, target.getOriginName()); + success = false; } } } - return context.success(); + return success ? context.success(status) : context.fail(); }, SenderType.PLAYER); } -} +} \ No newline at end of file diff --git a/server/src/main/java/org/allaymc/server/command/defaults/KillCommand.java b/server/src/main/java/org/allaymc/server/command/defaults/KillCommand.java new file mode 100644 index 000000000..a18de4a91 --- /dev/null +++ b/server/src/main/java/org/allaymc/server/command/defaults/KillCommand.java @@ -0,0 +1,61 @@ +package org.allaymc.server.command.defaults; + +import org.allaymc.api.command.SenderType; +import org.allaymc.api.command.SimpleCommand; +import org.allaymc.api.command.tree.CommandTree; +import org.allaymc.api.entity.Entity; +import org.allaymc.api.entity.component.attribute.EntityAttributeComponent; +import org.allaymc.api.entity.interfaces.EntityPlayer; +import org.allaymc.api.i18n.TrKeys; +import org.cloudburstmc.protocol.bedrock.data.GameType; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @author daoge_cmd + */ +public class KillCommand extends SimpleCommand { + + public KillCommand() { + super("kill", TrKeys.M_COMMANDS_KILL_DESCRIPTION); + } + + @Override + public void prepareCommandTree(CommandTree tree) { + tree.getRoot() + // Set default value to null to + // mark that the sender want to suicide + .target("targets", null) + .optional() + .exec((context, sender) -> { + List targets = context.getResult(0); + if (targets == null) { + targets = List.of(sender); + } + + if (targets.stream().allMatch(target -> target instanceof EntityPlayer player && player.getGameType() == GameType.CREATIVE)) { + context.addError("%" + TrKeys.M_COMMANDS_KILL_ATTEMPTKILLPLAYERCREATIVE); + return context.fail(); + } + + Map killedEntities = new HashMap<>(); + for (var target : targets) { + if (target instanceof EntityPlayer player && (player.getGameType() == GameType.CREATIVE || player.getGameType() == GameType.SPECTATOR)) { + continue; + } + if (target instanceof EntityAttributeComponent damageComponent) { + damageComponent.kill(); + } else { + target.despawn(); + } + killedEntities.compute(target.getCommandSenderName(), (k ,v) -> v != null ? ++v : 1); + } + context.addOutput(TrKeys.M_COMMANDS_KILL_SUCCESSFUL, killedEntities.entrySet().stream().map(entry -> entry.getKey() + " * " + entry.getValue()).collect(Collectors.joining(", "))); + return context.success(); + }, SenderType.ENTITY); + } +} diff --git a/server/src/main/java/org/allaymc/server/entity/component/EntityBaseComponentImpl.java b/server/src/main/java/org/allaymc/server/entity/component/EntityBaseComponentImpl.java index 2f3dd1014..d83c4e056 100644 --- a/server/src/main/java/org/allaymc/server/entity/component/EntityBaseComponentImpl.java +++ b/server/src/main/java/org/allaymc/server/entity/component/EntityBaseComponentImpl.java @@ -203,6 +203,7 @@ protected void tickEffects() { } protected void checkDead() { + // TODO: move these code to EntityAttributeComponentImpl if (attributeComponent == null || !attributeComponent.supportHealth()) return; if (attributeComponent.getHealth() == 0 && !dead) { onDie(); diff --git a/server/src/main/java/org/allaymc/server/entity/component/player/EntityPlayerBaseComponentImpl.java b/server/src/main/java/org/allaymc/server/entity/component/player/EntityPlayerBaseComponentImpl.java index af8b728d1..097a293a2 100644 --- a/server/src/main/java/org/allaymc/server/entity/component/player/EntityPlayerBaseComponentImpl.java +++ b/server/src/main/java/org/allaymc/server/entity/component/player/EntityPlayerBaseComponentImpl.java @@ -640,11 +640,6 @@ public void sendTr(String key, boolean forceTranslatedByClient, String... args) } else sendText(I18n.get().tr(thisPlayer.getLangCode(), key, args)); } - @Override - public String getCommandSenderName() { - return thisPlayer.getDisplayName(); - } - @Override public void applyEntityEvent(EntityEventType event, int data) { var packet = new EntityEventPacket(); diff --git a/server/src/main/java/org/allaymc/server/registry/AllayCommandRegistry.java b/server/src/main/java/org/allaymc/server/registry/AllayCommandRegistry.java index 90edc7164..32203f374 100644 --- a/server/src/main/java/org/allaymc/server/registry/AllayCommandRegistry.java +++ b/server/src/main/java/org/allaymc/server/registry/AllayCommandRegistry.java @@ -67,6 +67,7 @@ private void registerDefaultCommands() { register(new SetBlockCommand()); register(new WeatherCommand()); register(new ClearCommand()); + register(new KillCommand()); } @Override