From 9d68d51e952407841b62f5fc004986beab85c3d2 Mon Sep 17 00:00:00 2001 From: itqop Date: Thu, 14 Nov 2024 02:21:56 +0300 Subject: [PATCH] chore(release): update to version 0.2.1 ### Added - Updated the `/suicide` command to ensure instant death via maximum magic damage. - Introduced a 120-second cooldown for the `/suicide confirm` command. - Added the `/silenceKill` command for administrators to silently kill players by setting their health to 0. - Added tab-completion support for selecting online players in the `/silenceKill` command. --- CHANGELOG.RU.MD | 13 +++ CHANGELOG.md | 13 +++ gradle.properties | 2 +- .../java/org/itqop/hubmcutils/HubMcUtils.java | 1 - .../command/list/PlayerActions.java | 80 ++++++++++++++++--- 5 files changed, 95 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.RU.MD b/CHANGELOG.RU.MD index f6e246b..0475cf7 100644 --- a/CHANGELOG.RU.MD +++ b/CHANGELOG.RU.MD @@ -4,6 +4,19 @@ Формат основан на [Keep a Changelog](https://keepachangelog.com/ru/1.0.0/), и проект соответствует [Семантическому Версионированию](https://semver.org/lang/ru/). +### [0.2.1] - 2024-11-14 + +#### Добавлено + +- **PlayerActions**: + - **Команда Suicide**: + - Обновлен метод выполнения команды `/suicide` для мгновенной смерти через максимальный магический урон. + - Добавлено ограничение в 120 секунд на выполнение команды `/suicide confirm`, чтобы предотвратить спам и случайные повторные действия. + - **Команда SilenceKill**: + - Добавлена новая команда `/silenceKill `, доступная администраторам. + - Команда позволяет администраторам тихо убивать выбранного игрока, устанавливая его здоровье на 0. + - Реализовано автодополнение через таб для выбора онлайн-игроков в качестве цели. + ## [0.2] - 2024-11-13 ### Добавлено diff --git a/CHANGELOG.md b/CHANGELOG.md index e82882f..2b09a32 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,19 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/). +### [0.2.1] - 2024-11-14 + +#### Added + +- **PlayerActions**: + - **Suicide Command**: + - Updated the method of execution for the `/suicide` command to ensure instant death via maximum magic damage. + - Introduced a 120-second cooldown for the `/suicide confirm` command to prevent spam and accidental multiple executions. + - **SilenceKill Command**: + - Added a new `/silenceKill ` command for administrators. + - The command allows administrators to silently kill a specified player by setting their health to 0. + - Added tab-completion support for selecting online players as targets. + ## [0.2] - 2024-11-13 ### Added diff --git a/gradle.properties b/gradle.properties index 5217303..bfc8d69 100644 --- a/gradle.properties +++ b/gradle.properties @@ -38,7 +38,7 @@ mod_name=HubMcUtils # The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default. mod_license=All Rights Reserved # The mod version. See https://semver.org/ -mod_version=0.2.0-BETA +mod_version=0.2.1-BETA # The group ID for the mod. It is only important when publishing as an artifact to a Maven repository. # This should match the base package used for the mod sources. # See https://maven.apache.org/guides/mini/guide-naming-conventions.html diff --git a/src/main/java/org/itqop/hubmcutils/HubMcUtils.java b/src/main/java/org/itqop/hubmcutils/HubMcUtils.java index 7411c94..bd9d033 100644 --- a/src/main/java/org/itqop/hubmcutils/HubMcUtils.java +++ b/src/main/java/org/itqop/hubmcutils/HubMcUtils.java @@ -2,7 +2,6 @@ package org.itqop.hubmcutils; import com.mojang.logging.LogUtils; import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.event.entity.player.PlayerEvent; import net.minecraftforge.event.server.ServerStartingEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; diff --git a/src/main/java/org/itqop/hubmcutils/command/list/PlayerActions.java b/src/main/java/org/itqop/hubmcutils/command/list/PlayerActions.java index f68ebf2..d0fc50b 100644 --- a/src/main/java/org/itqop/hubmcutils/command/list/PlayerActions.java +++ b/src/main/java/org/itqop/hubmcutils/command/list/PlayerActions.java @@ -2,20 +2,31 @@ package org.itqop.hubmcutils.command.list; import com.mojang.brigadier.Command; import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.suggestion.Suggestions; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; +import net.minecraft.ChatFormatting; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; import net.minecraft.network.chat.ClickEvent; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.HoverEvent; -import net.minecraft.network.chat.Style; import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.damagesource.DamageSources; +import java.time.Instant; +import java.util.HashMap; import java.util.HashSet; +import java.util.Map; import java.util.Set; +import java.util.concurrent.CompletableFuture; public class PlayerActions { private static final Set pendingConfirmation = new HashSet<>(); + private static DamageSources damageSources; + private static final Map lastConfirmTime = new HashMap<>(); + private static final long CONFIRM_COOLDOWN_SECONDS = 120; public static void registerCommands(CommandDispatcher dispatcher) { dispatcher.register(Commands.literal("suicide") @@ -26,8 +37,8 @@ public class PlayerActions { pendingConfirmation.add(playerName); Component confirmMessage = Component.literal("[Нажмите здесь, чтобы подтвердить]") - .withStyle(Style.EMPTY - .withColor(0xFF5555) // Красный цвет + .withStyle(style -> style + .withColor(ChatFormatting.RED) // Красный цвет .withClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/suicide confirm")) .withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.literal("Подтвердите команду /suicide confirm")))); @@ -39,18 +50,63 @@ public class PlayerActions { ServerPlayer player = context.getSource().getPlayerOrException(); String playerName = player.getName().getString(); - if (pendingConfirmation.contains(playerName)) { - pendingConfirmation.remove(playerName); - player.sendSystemMessage(Component.literal("Вы приняли решение покончить с собой.").withStyle(Style.EMPTY.withColor(0xFF5555))); - player.setHealth(0.0F); // Устанавливаем здоровье игрока на 0 для мгновенной смерти - player.closeContainer(); // Закрываем окно чата или инвентаря - return Command.SINGLE_SUCCESS; - } else { - player.sendSystemMessage(Component.literal("Сначала используйте команду /suicide, чтобы запросить подтверждение.").withStyle(Style.EMPTY.withColor(0xFFFF55))); // Желтый цвет - return Command.SINGLE_SUCCESS; + Instant now = Instant.now(); + if (lastConfirmTime.containsKey(playerName)) { + Instant lastTime = lastConfirmTime.get(playerName); + long secondsSinceLastConfirm = now.getEpochSecond() - lastTime.getEpochSecond(); + + if (secondsSinceLastConfirm < CONFIRM_COOLDOWN_SECONDS) { + long secondsLeft = CONFIRM_COOLDOWN_SECONDS - secondsSinceLastConfirm; + player.sendSystemMessage(Component.literal("Вы не можете использовать команду /suicide confirm прямо сейчас. Подождите еще " + secondsLeft + " секунд.") + .withStyle(ChatFormatting.YELLOW)); + return Command.SINGLE_SUCCESS; + } } + + if (pendingConfirmation.contains(playerName)) { + if (damageSources == null) { + damageSources = new DamageSources(player.server.registryAccess()); + } + pendingConfirmation.remove(playerName); + player.sendSystemMessage(Component.literal("Вы приняли решение покончить с собой.").withStyle(ChatFormatting.RED)); + player.hurt(damageSources.indirectMagic(player, null), Float.MAX_VALUE); + player.closeContainer(); + lastConfirmTime.put(playerName, now); + } else { + player.sendSystemMessage(Component.literal("Сначала используйте команду /suicide, чтобы запросить подтверждение.") + .withStyle(ChatFormatting.YELLOW)); + } + return Command.SINGLE_SUCCESS; + }) + ) + ); + + dispatcher.register(Commands.literal("silenceKill") + .requires(source -> source.hasPermission(2)) + .then(Commands.argument("target", StringArgumentType.string()) + .suggests((context, builder) -> suggestOnlinePlayers(context.getSource(), builder)) // Автодополнение игроков + .executes(context -> { + String targetName = StringArgumentType.getString(context, "target"); + ServerPlayer targetPlayer = context.getSource().getServer().getPlayerList().getPlayerByName(targetName); + + if (targetPlayer != null) { + targetPlayer.setHealth(0); + context.getSource().sendSuccess( + () -> Component.literal("Игрок " + targetName + " беззвучно исчез.").withStyle(ChatFormatting.GREEN), true); + } else { + context.getSource().sendFailure( + Component.literal("Игрок с ником " + targetName + " не найден.").withStyle(ChatFormatting.RED)); + } + return Command.SINGLE_SUCCESS; }) ) ); } + + private static CompletableFuture suggestOnlinePlayers(CommandSourceStack source, SuggestionsBuilder builder) { + source.getServer().getPlayerList().getPlayers().forEach(player -> + builder.suggest(player.getName().getString()) + ); + return builder.buildFuture(); + } }