Compare commits

...

2 Commits

Author SHA1 Message Date
itqop 9d68d51e95 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.
2024-11-14 02:21:56 +03:00
itqop 7e622a5761 feat(release): v0.2.0
Added /suicide command with confirmation mechanism, interactive clickable message, and proper chat/console handling on player death.
2024-11-13 15:27:51 +03:00
6 changed files with 178 additions and 2 deletions

View File

@ -4,6 +4,29 @@
Формат основан на [Keep a Changelog](https://keepachangelog.com/ru/1.0.0/), и проект соответствует [Семантическому Версионированию](https://semver.org/lang/ru/). Формат основан на [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 <player>`, доступная администраторам.
- Команда позволяет администраторам тихо убивать выбранного игрока, устанавливая его здоровье на 0.
- Реализовано автодополнение через таб для выбора онлайн-игроков в качестве цели.
## [0.2] - 2024-11-13
### Добавлено
- **PlayerActions**:
- **Команда самоубийства**:
- Добавлена команда `/suicide`, которая запрашивает подтверждение перед выполнением.
- Игроки могут подтвердить действие, нажав на интерактивное сообщение или введя `/suicide confirm`.
- После подтверждения игрок мгновенно умирает, а окно чата или консоли закрывается для предотвращения дальнейшего взаимодействия.
## [0.1] - 2024-11-10 ## [0.1] - 2024-11-10
### Добавлено ### Добавлено

View File

@ -4,6 +4,29 @@ 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/). 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 <player>` 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
- **PlayerActions**:
- **Suicide Command**:
- Added a `/suicide` command that prompts players for confirmation before execution.
- Players can confirm by clicking on the generated clickable message or typing `/suicide confirm`.
- Upon confirmation, the player dies instantly, and the chat window or console is closed to prevent further interaction.
## [0.1] - 2024-11-10 ## [0.1] - 2024-11-10
### Added ### Added

View File

@ -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. # The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default.
mod_license=All Rights Reserved mod_license=All Rights Reserved
# The mod version. See https://semver.org/ # The mod version. See https://semver.org/
mod_version=0.1-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. # 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. # This should match the base package used for the mod sources.
# See https://maven.apache.org/guides/mini/guide-naming-conventions.html # See https://maven.apache.org/guides/mini/guide-naming-conventions.html

View File

@ -2,12 +2,13 @@ package org.itqop.hubmcutils;
import com.mojang.logging.LogUtils; import com.mojang.logging.LogUtils;
import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.entity.player.PlayerEvent;
import net.minecraftforge.event.server.ServerStartingEvent; import net.minecraftforge.event.server.ServerStartingEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.itqop.hubmcutils.command.CommandHandler;
@Mod(HubMcUtils.MODID) @Mod(HubMcUtils.MODID)
public class HubMcUtils { public class HubMcUtils {
@ -16,6 +17,7 @@ public class HubMcUtils {
public HubMcUtils() { public HubMcUtils() {
MinecraftForge.EVENT_BUS.register(this); MinecraftForge.EVENT_BUS.register(this);
MinecraftForge.EVENT_BUS.register(CommandHandler.class);
} }
@SubscribeEvent @SubscribeEvent

View File

@ -0,0 +1,16 @@
package org.itqop.hubmcutils.command;
import com.mojang.brigadier.CommandDispatcher;
import net.minecraft.commands.CommandSourceStack;
import net.minecraftforge.event.RegisterCommandsEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import org.itqop.hubmcutils.command.list.PlayerActions;
public class CommandHandler {
@SubscribeEvent
public static void onRegisterCommands(RegisterCommandsEvent event) {
CommandDispatcher<CommandSourceStack> dispatcher = event.getDispatcher();
PlayerActions.registerCommands(dispatcher);
}
}

View File

@ -0,0 +1,112 @@
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.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<String> pendingConfirmation = new HashSet<>();
private static DamageSources damageSources;
private static final Map<String, Instant> lastConfirmTime = new HashMap<>();
private static final long CONFIRM_COOLDOWN_SECONDS = 120;
public static void registerCommands(CommandDispatcher<CommandSourceStack> dispatcher) {
dispatcher.register(Commands.literal("suicide")
.executes(context -> {
ServerPlayer player = context.getSource().getPlayerOrException();
String playerName = player.getName().getString();
pendingConfirmation.add(playerName);
Component confirmMessage = Component.literal("[Нажмите здесь, чтобы подтвердить]")
.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"))));
player.sendSystemMessage(Component.literal("Вы уверены, что хотите покончить с собой? ").append(confirmMessage));
return Command.SINGLE_SUCCESS;
})
.then(Commands.literal("confirm")
.executes(context -> {
ServerPlayer player = context.getSource().getPlayerOrException();
String playerName = player.getName().getString();
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<Suggestions> suggestOnlinePlayers(CommandSourceStack source, SuggestionsBuilder builder) {
source.getServer().getPlayerList().getPlayers().forEach(player ->
builder.suggest(player.getName().getString())
);
return builder.buildFuture();
}
}