Backup before major refactor of AdminMode based on user feedback
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -3,15 +3,23 @@ package org.blz.adminmode;
|
|||||||
import org.blz.adminmode.commands.AdminModeCommand;
|
import org.blz.adminmode.commands.AdminModeCommand;
|
||||||
import org.blz.adminmode.config.ConfigManager;
|
import org.blz.adminmode.config.ConfigManager;
|
||||||
import org.blz.adminmode.dialog.AdminDialogService;
|
import org.blz.adminmode.dialog.AdminDialogService;
|
||||||
|
import org.blz.adminmode.integrations.CoreProtectIntegration;
|
||||||
|
import org.blz.adminmode.integrations.LuckPermsIntegration;
|
||||||
import org.blz.adminmode.listeners.AdminModeListener;
|
import org.blz.adminmode.listeners.AdminModeListener;
|
||||||
import org.blz.adminmode.listeners.GameModeChangeListener;
|
import org.blz.adminmode.listeners.GameModeChangeListener;
|
||||||
import org.blz.adminmode.listeners.MobTargetListener;
|
import org.blz.adminmode.listeners.MobTargetListener;
|
||||||
|
import org.blz.adminmode.listeners.PlayerDeathListener;
|
||||||
|
import org.blz.adminmode.listeners.PlayerSessionListener;
|
||||||
|
import org.blz.adminmode.moderation.ModeManager;
|
||||||
|
import org.blz.adminmode.moderation.ModeSessionLogger;
|
||||||
|
import org.blz.adminmode.session.SessionStorage;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
public class AdminMode extends JavaPlugin {
|
public class AdminMode extends JavaPlugin {
|
||||||
|
|
||||||
private static AdminMode instance;
|
private static AdminMode instance;
|
||||||
private ConfigManager configManager;
|
private ConfigManager configManager;
|
||||||
|
private ModeManager modeManager;
|
||||||
private AdminModeCommand adminModeCommand;
|
private AdminModeCommand adminModeCommand;
|
||||||
private AdminDialogService dialogService;
|
private AdminDialogService dialogService;
|
||||||
|
|
||||||
@@ -21,29 +29,40 @@ public class AdminMode extends JavaPlugin {
|
|||||||
saveDefaultConfig();
|
saveDefaultConfig();
|
||||||
|
|
||||||
configManager = new ConfigManager(this);
|
configManager = new ConfigManager(this);
|
||||||
adminModeCommand = new AdminModeCommand(this, configManager);
|
SessionStorage sessionStorage = new SessionStorage(this);
|
||||||
|
LuckPermsIntegration luckPermsIntegration = new LuckPermsIntegration(this, configManager);
|
||||||
|
CoreProtectIntegration coreProtectIntegration = new CoreProtectIntegration(this, configManager);
|
||||||
|
ModeSessionLogger sessionLogger = new ModeSessionLogger(this, configManager);
|
||||||
|
modeManager = new ModeManager(this, configManager, luckPermsIntegration, sessionStorage, sessionLogger);
|
||||||
|
adminModeCommand = new AdminModeCommand(configManager, modeManager, coreProtectIntegration);
|
||||||
dialogService = new AdminDialogService(this, configManager, adminModeCommand);
|
dialogService = new AdminDialogService(this, configManager, adminModeCommand);
|
||||||
adminModeCommand.setDialogService(dialogService);
|
adminModeCommand.setDialogService(dialogService);
|
||||||
getCommand("adminmode").setExecutor(adminModeCommand);
|
getCommand("adminmode").setExecutor(adminModeCommand);
|
||||||
getCommand("admfix").setExecutor(new org.blz.adminmode.commands.AdminFixCommand(adminModeCommand));
|
getCommand("admfix").setExecutor(new org.blz.adminmode.commands.AdminFixCommand(adminModeCommand));
|
||||||
|
|
||||||
getServer().getPluginManager().registerEvents(new AdminModeListener(this, adminModeCommand, configManager),
|
getServer().getPluginManager().registerEvents(new AdminModeListener(adminModeCommand, configManager, modeManager, dialogService),
|
||||||
this);
|
this);
|
||||||
getServer().getPluginManager().registerEvents(new MobTargetListener(adminModeCommand, configManager), this);
|
getServer().getPluginManager().registerEvents(new MobTargetListener(adminModeCommand, configManager), this);
|
||||||
getServer().getPluginManager().registerEvents(new GameModeChangeListener(adminModeCommand, configManager),
|
getServer().getPluginManager().registerEvents(new GameModeChangeListener(adminModeCommand, configManager),
|
||||||
this);
|
this);
|
||||||
|
getServer().getPluginManager().registerEvents(new PlayerSessionListener(adminModeCommand, modeManager), this);
|
||||||
|
getServer().getPluginManager().registerEvents(new PlayerDeathListener(modeManager), this);
|
||||||
|
|
||||||
|
for (org.bukkit.entity.Player onlinePlayer : getServer().getOnlinePlayers()) {
|
||||||
|
if (modeManager.hasSession(onlinePlayer.getUniqueId())) {
|
||||||
|
getServer().getScheduler().runTaskLater(this, () -> adminModeCommand.recoverSession(onlinePlayer), 1L);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Load Pocket Dimension World
|
// Load Pocket Dimension World
|
||||||
new org.blz.adminmode.utils.WorldLoader(this, "pocket_dimension").loadWorld();
|
new org.blz.adminmode.utils.WorldLoader(this, "pocket_dimension").loadWorld();
|
||||||
|
|
||||||
// Register Abilities
|
// Register Abilities
|
||||||
belzeManager = new org.blz.adminmode.managers.BelzeBoolManager(this);
|
new org.blz.adminmode.managers.BelzeBoolManager(this);
|
||||||
|
|
||||||
getLogger().info("AdminMode успешно включен!");
|
getLogger().info("AdminMode успешно включен!");
|
||||||
}
|
}
|
||||||
|
|
||||||
private org.blz.adminmode.managers.BelzeBoolManager belzeManager; // Field to store manager
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDisable() {
|
public void onDisable() {
|
||||||
getLogger().info("AdminMode отключен!");
|
getLogger().info("AdminMode отключен!");
|
||||||
@@ -57,6 +76,10 @@ public class AdminMode extends JavaPlugin {
|
|||||||
return configManager;
|
return configManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ModeManager getModeManager() {
|
||||||
|
return modeManager;
|
||||||
|
}
|
||||||
|
|
||||||
public AdminModeCommand getAdminModeCommand() {
|
public AdminModeCommand getAdminModeCommand() {
|
||||||
return adminModeCommand;
|
return adminModeCommand;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,47 +1,36 @@
|
|||||||
package org.blz.adminmode.commands;
|
package org.blz.adminmode.commands;
|
||||||
|
|
||||||
import net.luckperms.api.LuckPerms;
|
import java.util.List;
|
||||||
import net.luckperms.api.LuckPermsProvider;
|
import java.util.UUID;
|
||||||
import net.luckperms.api.model.user.User;
|
|
||||||
import net.luckperms.api.node.Node;
|
import org.blz.adminmode.config.ConfigManager;
|
||||||
|
import org.blz.adminmode.dialog.AdminDialogService;
|
||||||
|
import org.blz.adminmode.integrations.CoreProtectIntegration;
|
||||||
|
import org.blz.adminmode.moderation.ModeManager;
|
||||||
|
import org.blz.adminmode.moderation.ModeratorProfile;
|
||||||
|
import org.blz.adminmode.moderation.PlayerListAction;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.ChatColor;
|
|
||||||
import org.bukkit.GameMode;
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.Material;
|
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
import org.bukkit.command.CommandExecutor;
|
import org.bukkit.command.CommandExecutor;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
import org.bukkit.plugin.Plugin;
|
|
||||||
import org.bukkit.potion.PotionEffect;
|
|
||||||
import org.blz.adminmode.dialog.AdminDialogService;
|
|
||||||
import org.blz.adminmode.config.ConfigManager;
|
|
||||||
import org.blz.adminmode.data.AdminModeDataManager;
|
|
||||||
import org.blz.adminmode.data.AdminModeDataManager.PlayerStateData;
|
|
||||||
import org.blz.adminmode.moderation.ModeratorProfile;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
import net.kyori.adventure.text.Component;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public class AdminModeCommand implements CommandExecutor {
|
public class AdminModeCommand implements CommandExecutor {
|
||||||
|
|
||||||
private final Plugin plugin;
|
|
||||||
private final ConfigManager configManager;
|
private final ConfigManager configManager;
|
||||||
private final Map<UUID, PlayerState> savedStates = new HashMap<>();
|
private final ModeManager modeManager;
|
||||||
private final Map<UUID, ModeratorProfile> activeProfiles = new HashMap<>();
|
private final CoreProtectIntegration coreProtectIntegration;
|
||||||
private final AdminModeDataManager dataManager;
|
|
||||||
private AdminDialogService dialogService;
|
private AdminDialogService dialogService;
|
||||||
|
|
||||||
public AdminModeCommand(Plugin plugin, ConfigManager configManager) {
|
public AdminModeCommand(
|
||||||
this.plugin = plugin;
|
ConfigManager configManager,
|
||||||
|
ModeManager modeManager,
|
||||||
|
CoreProtectIntegration coreProtectIntegration) {
|
||||||
this.configManager = configManager;
|
this.configManager = configManager;
|
||||||
this.dataManager = new AdminModeDataManager(plugin);
|
this.modeManager = modeManager;
|
||||||
loadAllStates();
|
this.coreProtectIntegration = coreProtectIntegration;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDialogService(AdminDialogService dialogService) {
|
public void setDialogService(AdminDialogService dialogService) {
|
||||||
@@ -52,23 +41,22 @@ public class AdminModeCommand implements CommandExecutor {
|
|||||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||||
if (args.length > 0 && args[0].equalsIgnoreCase("reload")) {
|
if (args.length > 0 && args[0].equalsIgnoreCase("reload")) {
|
||||||
if (!sender.hasPermission("adminmode.reload")) {
|
if (!sender.hasPermission("adminmode.reload")) {
|
||||||
sender.sendMessage(ChatColor.RED + configManager.getMsgNoPermission());
|
sender.sendMessage(configManager.getPrefixedMessage(configManager.getMsgNoPermission()));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
configManager.loadConfig();
|
configManager.loadConfig();
|
||||||
sender.sendMessage(ChatColor.GREEN + configManager.getMsgReloaded());
|
sender.sendMessage(configManager.getPrefixedMessage(configManager.getMsgReloaded()));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Команда disable <игрок> - принудительно отключить способности
|
|
||||||
if (args.length > 0 && args[0].equalsIgnoreCase("disable")) {
|
if (args.length > 0 && args[0].equalsIgnoreCase("disable")) {
|
||||||
if (!canUseHardActions(sender)) {
|
if (!canUseHardActions(sender)) {
|
||||||
sender.sendMessage(ChatColor.RED + configManager.getMsgNoPermission());
|
sender.sendMessage(configManager.getPrefixedMessage(configManager.getMsgNoPermission()));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args.length < 2) {
|
if (args.length < 2) {
|
||||||
sender.sendMessage(ChatColor.RED + "Использование: /adminmode disable <игрок>");
|
sender.sendMessage(configManager.getPrefixedMessage("§cИспользование: /adminmode disable <игрок>"));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,132 +64,121 @@ public class AdminModeCommand implements CommandExecutor {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(sender instanceof Player)) {
|
if (!(sender instanceof Player player)) {
|
||||||
sender.sendMessage(ChatColor.RED + "Эта команда доступна только игрокам!");
|
sender.sendMessage("Эта команда доступна только игрокам!");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Player player = (Player) sender;
|
|
||||||
|
|
||||||
if (!configManager.isEnabled()) {
|
if (!configManager.isEnabled()) {
|
||||||
player.sendMessage(ChatColor.RED + "Режим администратора отключен!");
|
player.sendMessage(configManager.getPrefixedMessage("§cРежим администратора отключен!"));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args.length > 0 && args[0].equalsIgnoreCase("dialog")) {
|
if (args.length > 0 && args[0].equalsIgnoreCase("dialog")) {
|
||||||
if (!openRelevantDialog(player)) {
|
if (!openRelevantDialog(player)) {
|
||||||
player.sendMessage(ChatColor.YELLOW + "Dialog-панель недоступна. Используйте /adminmode enable <soft|hard>.");
|
player.sendMessage(configManager.getPrefixedMessage("§eDialog-панель сейчас недоступна."));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args.length > 0 && (args[0].equalsIgnoreCase("enable") || args[0].equalsIgnoreCase("profile"))) {
|
if (args.length > 0 && (args[0].equalsIgnoreCase("enable") || args[0].equalsIgnoreCase("profile"))) {
|
||||||
if (args.length < 2) {
|
if (args.length < 2) {
|
||||||
if (!openRelevantDialog(player)) {
|
openRelevantDialog(player);
|
||||||
player.sendMessage(ChatColor.YELLOW + "Использование: /adminmode enable <soft|hard>");
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ModeratorProfile profile = ModeratorProfile.fromInput(args[1]).orElse(null);
|
ModeratorProfile profile = ModeratorProfile.fromInput(args[1]).orElse(null);
|
||||||
if (profile == null) {
|
if (profile == null) {
|
||||||
player.sendMessage(ChatColor.RED + "Неизвестный профиль. Доступно: soft, hard.");
|
player.sendMessage(configManager.getPrefixedMessage("§cНеизвестный профиль. Доступно: soft, hard."));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleAdminMode(player, profile);
|
activateProfile(player, profile);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isInAdminMode(player.getUniqueId()) && getAvailableProfiles(player).isEmpty()) {
|
if (!isInAdminMode(player.getUniqueId()) && getAvailableProfiles(player).isEmpty()) {
|
||||||
player.sendMessage(ChatColor.RED + configManager.getMsgNoPermission());
|
player.sendMessage(configManager.getPrefixedMessage(configManager.getMsgNoPermission()));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleAdminMode(player);
|
openRelevantDialog(player);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void toggleAdminMode(Player player) {
|
public boolean activateProfile(Player player, ModeratorProfile profile) {
|
||||||
if (isInAdminMode(player.getUniqueId())) {
|
|
||||||
disableAdminMode(player);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<ModeratorProfile> availableProfiles = getAvailableProfiles(player);
|
|
||||||
if (availableProfiles.isEmpty()) {
|
|
||||||
player.sendMessage(ChatColor.RED + configManager.getMsgNoPermission());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (availableProfiles.size() == 1) {
|
|
||||||
enableAdminMode(player, availableProfiles.get(0));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!openRelevantDialog(player)) {
|
|
||||||
player.sendMessage(ChatColor.YELLOW + "Доступно несколько профилей. Используйте /adminmode enable <soft|hard>.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void toggleAdminMode(Player player, ModeratorProfile profile) {
|
|
||||||
if (profile == null) {
|
if (profile == null) {
|
||||||
toggleAdminMode(player);
|
return openRelevantDialog(player);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isInAdminMode(player.getUniqueId())) {
|
|
||||||
ModeratorProfile activeProfile = getActiveProfile(player.getUniqueId());
|
|
||||||
if (activeProfile == profile) {
|
|
||||||
disableAdminMode(player);
|
|
||||||
} else {
|
|
||||||
player.sendMessage(ChatColor.YELLOW + "Сначала выключите текущий режим модерации, затем включите новый профиль.");
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!profile.isAvailableFor(player)) {
|
if (!profile.isAvailableFor(player)) {
|
||||||
player.sendMessage(ChatColor.RED + configManager.getMsgNoPermission());
|
player.sendMessage(configManager.getPrefixedMessage(configManager.getMsgNoPermission()));
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
enableAdminMode(player, profile);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<ModeratorProfile> getAvailableProfiles(Player player) {
|
|
||||||
return ModeratorProfile.availableFor(player);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ModeratorProfile getActiveProfile(UUID playerId) {
|
|
||||||
return activeProfiles.get(playerId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void applyAdminSettings(Player player, float flySpeed, float walkSpeed, boolean godMode) {
|
|
||||||
if (!isInAdminMode(player.getUniqueId())) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
player.setAllowFlight(true);
|
|
||||||
player.setFlying(true);
|
|
||||||
player.setFlySpeed(clampSpeed(flySpeed, 0.1f));
|
|
||||||
player.setWalkSpeed(clampSpeed(walkSpeed, 0.1f));
|
|
||||||
player.setInvulnerable(godMode);
|
|
||||||
player.sendMessage(ChatColor.GREEN + "✓ Настройки admin mode обновлены.");
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean teleportToPlayer(Player moderator, String targetName) {
|
|
||||||
if (!validateHardActionPlayer(moderator)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Player target = resolveOnlinePlayer(targetName, moderator);
|
if (modeManager.hasSession(player.getUniqueId())) {
|
||||||
|
ModeratorProfile activeProfile = getActiveProfile(player.getUniqueId());
|
||||||
|
if (activeProfile == profile) {
|
||||||
|
return openRelevantDialog(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
player.sendMessage(configManager.getPrefixedMessage(
|
||||||
|
"§eУ вас уже активен профиль §f" + activeProfile.getDisplayName() + "§e. Сначала выйдите из режима."));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return modeManager.enterMode(player, profile);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean exitMode(Player player) {
|
||||||
|
return modeManager.exitMode(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean recoverSession(Player player) {
|
||||||
|
return modeManager.recoverSession(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ModeratorProfile> getAvailableProfiles(Player player) {
|
||||||
|
return modeManager.getAvailableProfiles(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ModeratorProfile getActiveProfile(UUID playerId) {
|
||||||
|
return modeManager.getProfile(playerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isInAdminMode(UUID playerId) {
|
||||||
|
return modeManager.hasSession(playerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Component> getOnlineSummary(Player player) {
|
||||||
|
return modeManager.buildOnlineSummary(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void applyAdminSettings(Player player, float flySpeed, float walkSpeed, boolean godMode) {
|
||||||
|
if (!modeManager.hasSession(player.getUniqueId())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
modeManager.applyAdminSettings(player, flySpeed, walkSpeed, godMode);
|
||||||
|
player.sendMessage(configManager.getPrefixedMessage("§aНастройки режима обновлены."));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean performPlayerListAction(Player moderator, PlayerListAction action, String targetName) {
|
||||||
|
Player target = validateActiveTarget(moderator, targetName);
|
||||||
if (target == null) {
|
if (target == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
moderator.teleport(target.getLocation());
|
return switch (action) {
|
||||||
moderator.sendMessage(ChatColor.GREEN + "✓ Вы телепортированы к игроку " + target.getName());
|
case SPECTATE -> modeManager.spectatePlayer(moderator, target);
|
||||||
return true;
|
case TELEPORT -> modeManager.teleportToPlayer(moderator, target);
|
||||||
|
case INVSEE -> modeManager.openInvsee(moderator, target);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean teleportToPlayer(Player moderator, String targetName) {
|
||||||
|
Player target = validateActiveTarget(moderator, targetName);
|
||||||
|
return target != null && modeManager.teleportToPlayer(moderator, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean teleportPlayerHere(Player moderator, String targetName) {
|
public boolean teleportPlayerHere(Player moderator, String targetName) {
|
||||||
@@ -210,19 +187,12 @@ public class AdminModeCommand implements CommandExecutor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Player target = resolveOnlinePlayer(targetName, moderator);
|
Player target = resolveOnlinePlayer(targetName, moderator);
|
||||||
if (target == null) {
|
return target != null && modeManager.teleportPlayerHere(moderator, target);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
target.teleport(moderator.getLocation());
|
|
||||||
moderator.sendMessage(ChatColor.GREEN + "✓ Игрок " + target.getName() + " телепортирован к вам.");
|
|
||||||
target.sendMessage(ChatColor.YELLOW + "⚠ Вас телепортировал модератор " + moderator.getName());
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean forceDisableTarget(CommandSender sender, String targetName) {
|
public boolean forceDisableTarget(CommandSender sender, String targetName) {
|
||||||
if (!canUseHardActions(sender)) {
|
if (!canUseHardActions(sender)) {
|
||||||
sender.sendMessage(ChatColor.RED + configManager.getMsgNoPermission());
|
sender.sendMessage(configManager.getPrefixedMessage(configManager.getMsgNoPermission()));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,296 +202,81 @@ public class AdminModeCommand implements CommandExecutor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
forceDisableAbilities(target);
|
forceDisableAbilities(target);
|
||||||
sender.sendMessage(ChatColor.GREEN + "✓ Все способности отключены для игрока " + target.getName());
|
sender.sendMessage(configManager.getPrefixedMessage("§aРежим и способности игрока §f" + target.getName() + "§a сброшены."));
|
||||||
target.sendMessage(ChatColor.YELLOW + "⚠ Ваши способности были сброшены модератором");
|
target.sendMessage(configManager.getPrefixedMessage("§eВаш режим модерации был принудительно отключен."));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean executeCPLookup(Player player, String targetPlayer, int radius, String time) {
|
||||||
|
if (!validateHardActionPlayer(player)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return coreProtectIntegration.lookup(player, targetPlayer, radius, time);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean executeCPRollback(Player player, int radius, String time, String targetPlayer) {
|
||||||
|
if (!validateHardActionPlayer(player)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return coreProtectIntegration.rollback(player, radius, time, targetPlayer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean toggleInspector(Player player) {
|
||||||
|
if (!validateHardActionPlayer(player)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return coreProtectIntegration.toggleInspector(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void forceDisableAbilities(Player player) {
|
||||||
|
if (modeManager.hasSession(player.getUniqueId())) {
|
||||||
|
modeManager.exitMode(player);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
player.setInvulnerable(false);
|
||||||
|
player.setFlying(false);
|
||||||
|
player.setAllowFlight(false);
|
||||||
|
player.setFlySpeed(0.1f);
|
||||||
|
player.setWalkSpeed(0.2f);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean canUseHardActions(CommandSender sender) {
|
||||||
|
return modeManager.canUseHardActions(sender);
|
||||||
|
}
|
||||||
|
|
||||||
private boolean openRelevantDialog(Player player) {
|
private boolean openRelevantDialog(Player player) {
|
||||||
if (dialogService == null || !configManager.isDialogsEnabled()) {
|
if (dialogService == null || !configManager.isDialogsEnabled()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isInAdminMode(player.getUniqueId())) {
|
if (modeManager.hasSession(player.getUniqueId())) {
|
||||||
return dialogService.openModerationPanel(player);
|
return dialogService.openCurrentPanel(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
return dialogService.openProfileSelectionDialog(player);
|
return dialogService.openModeSelectDialog(player);
|
||||||
}
|
|
||||||
|
|
||||||
private void enableAdminMode(Player player, ModeratorProfile profile) {
|
|
||||||
savePlayerState(player, profile);
|
|
||||||
activeProfiles.put(player.getUniqueId(), profile);
|
|
||||||
clearPlayerState(player);
|
|
||||||
givePresetBlocks(player);
|
|
||||||
setAdminGameMode(player);
|
|
||||||
savePlayerStateToFile(player);
|
|
||||||
grantLuckPermsPermissions(player, profile);
|
|
||||||
|
|
||||||
player.sendMessage(ChatColor.AQUA + configManager.getMsgEnabled());
|
|
||||||
player.sendMessage(ChatColor.GRAY + configManager.getMsgEnabledSubtitle());
|
|
||||||
player.sendMessage(ChatColor.YELLOW + configManager.getMsgPermissionsGranted());
|
|
||||||
player.sendMessage(ChatColor.GRAY + "Профиль: " + profile.getDisplayName());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void disableAdminMode(Player player) {
|
|
||||||
UUID playerId = player.getUniqueId();
|
|
||||||
ModeratorProfile profile = activeProfiles.getOrDefault(playerId, ModeratorProfile.SOFT_MODER);
|
|
||||||
|
|
||||||
removeLuckPermsPermissions(player, profile);
|
|
||||||
restorePlayerState(player);
|
|
||||||
dataManager.deletePlayerState(playerId);
|
|
||||||
|
|
||||||
player.sendMessage(ChatColor.GREEN + configManager.getMsgDisabled());
|
|
||||||
player.sendMessage(ChatColor.GRAY + configManager.getMsgDisabledSubtitle());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void savePlayerState(Player player, ModeratorProfile profile) {
|
|
||||||
PlayerState state = new PlayerState();
|
|
||||||
|
|
||||||
state.inventory = player.getInventory().getContents().clone();
|
|
||||||
state.armorContents = player.getInventory().getArmorContents().clone();
|
|
||||||
state.offHand = player.getInventory().getItemInOffHand().clone();
|
|
||||||
|
|
||||||
state.location = player.getLocation().clone();
|
|
||||||
|
|
||||||
state.health = player.getHealth();
|
|
||||||
state.foodLevel = player.getFoodLevel();
|
|
||||||
state.saturation = player.getSaturation();
|
|
||||||
state.exhaustion = player.getExhaustion();
|
|
||||||
|
|
||||||
state.exp = player.getExp();
|
|
||||||
state.level = player.getLevel();
|
|
||||||
state.totalExperience = player.getTotalExperience();
|
|
||||||
state.gameMode = player.getGameMode();
|
|
||||||
|
|
||||||
state.allowFlight = player.getAllowFlight();
|
|
||||||
state.flying = player.isFlying();
|
|
||||||
state.flySpeed = player.getFlySpeed();
|
|
||||||
state.walkSpeed = player.getWalkSpeed();
|
|
||||||
state.potionEffects = player.getActivePotionEffects();
|
|
||||||
state.fireTicks = player.getFireTicks();
|
|
||||||
state.profile = profile;
|
|
||||||
|
|
||||||
savedStates.put(player.getUniqueId(), state);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void clearPlayerState(Player player) {
|
|
||||||
player.getInventory().clear();
|
|
||||||
player.getInventory().setArmorContents(new ItemStack[4]);
|
|
||||||
player.getInventory().setItemInOffHand(new ItemStack(Material.AIR));
|
|
||||||
|
|
||||||
player.setHealth(20.0);
|
|
||||||
player.setFoodLevel(20);
|
|
||||||
player.setSaturation(5.0f);
|
|
||||||
player.setExhaustion(0.0f);
|
|
||||||
|
|
||||||
player.setExp(0);
|
|
||||||
player.setLevel(0);
|
|
||||||
player.setTotalExperience(0);
|
|
||||||
|
|
||||||
for (PotionEffect effect : player.getActivePotionEffects()) {
|
|
||||||
player.removePotionEffect(effect.getType());
|
|
||||||
}
|
|
||||||
|
|
||||||
player.setFireTicks(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void givePresetBlocks(Player player) {
|
|
||||||
if (!configManager.isGivePresetBlocks())
|
|
||||||
return;
|
|
||||||
|
|
||||||
List<String> presetBlocks = configManager.getPresetBlocks();
|
|
||||||
for (String blockStr : presetBlocks) {
|
|
||||||
try {
|
|
||||||
String[] parts = blockStr.split(":");
|
|
||||||
Material material = Material.valueOf(parts[0].toUpperCase());
|
|
||||||
int amount = parts.length > 1 ? Integer.parseInt(parts[1]) : 64;
|
|
||||||
|
|
||||||
ItemStack item = new ItemStack(material, amount);
|
|
||||||
player.getInventory().addItem(item);
|
|
||||||
} catch (Exception e) {
|
|
||||||
plugin.getLogger().warning("Неверный блок в preset_blocks: " + blockStr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setAdminGameMode(Player player) {
|
|
||||||
if (configManager.isForceSpectator()) {
|
|
||||||
player.setGameMode(GameMode.SPECTATOR);
|
|
||||||
} else {
|
|
||||||
// ВАЖНО: Не используем CREATIVE для модеров, только SURVIVAL!
|
|
||||||
player.setGameMode(GameMode.SURVIVAL);
|
|
||||||
}
|
|
||||||
// Всегда разрешаем полет в админ моде (даже в выживании)
|
|
||||||
player.setAllowFlight(true);
|
|
||||||
player.setFlying(true);
|
|
||||||
|
|
||||||
// Дополнительные возможности
|
|
||||||
if (configManager.isGodMode()) {
|
|
||||||
player.setInvulnerable(true);
|
|
||||||
}
|
|
||||||
if (configManager.getCustomFlySpeed() > 0) {
|
|
||||||
player.setFlySpeed(configManager.getCustomFlySpeed());
|
|
||||||
}
|
|
||||||
if (configManager.getCustomWalkSpeed() > 0) {
|
|
||||||
player.setWalkSpeed(configManager.getCustomWalkSpeed());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void savePlayerStateToFile(Player player) {
|
|
||||||
UUID playerId = player.getUniqueId();
|
|
||||||
PlayerState state = savedStates.get(playerId);
|
|
||||||
|
|
||||||
if (state == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
PlayerStateData data = new PlayerStateData();
|
|
||||||
data.inventory = state.inventory;
|
|
||||||
data.armorContents = state.armorContents;
|
|
||||||
data.offHand = state.offHand;
|
|
||||||
data.location = state.location;
|
|
||||||
data.health = state.health;
|
|
||||||
data.foodLevel = state.foodLevel;
|
|
||||||
data.saturation = state.saturation;
|
|
||||||
data.exhaustion = state.exhaustion;
|
|
||||||
data.exp = state.exp;
|
|
||||||
data.level = state.level;
|
|
||||||
data.totalExperience = state.totalExperience;
|
|
||||||
data.gameMode = state.gameMode;
|
|
||||||
data.allowFlight = state.allowFlight;
|
|
||||||
data.flying = state.flying;
|
|
||||||
data.flySpeed = state.flySpeed;
|
|
||||||
data.walkSpeed = state.walkSpeed;
|
|
||||||
data.potionEffects = state.potionEffects;
|
|
||||||
data.fireTicks = state.fireTicks;
|
|
||||||
data.profileKey = state.profile == null ? null : state.profile.getConfigKey();
|
|
||||||
|
|
||||||
dataManager.savePlayerState(playerId, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void loadAllStates() {
|
|
||||||
for (UUID playerId : dataManager.getAllSavedStates()) {
|
|
||||||
PlayerStateData data = dataManager.loadPlayerState(playerId);
|
|
||||||
|
|
||||||
if (data == null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
PlayerState state = new PlayerState();
|
|
||||||
state.inventory = data.inventory;
|
|
||||||
state.armorContents = data.armorContents;
|
|
||||||
state.offHand = data.offHand;
|
|
||||||
state.location = data.location;
|
|
||||||
state.health = data.health;
|
|
||||||
state.foodLevel = data.foodLevel;
|
|
||||||
state.saturation = data.saturation;
|
|
||||||
state.exhaustion = data.exhaustion;
|
|
||||||
state.exp = data.exp;
|
|
||||||
state.level = data.level;
|
|
||||||
state.totalExperience = data.totalExperience;
|
|
||||||
state.gameMode = data.gameMode;
|
|
||||||
state.allowFlight = data.allowFlight;
|
|
||||||
state.flying = data.flying;
|
|
||||||
state.flySpeed = data.flySpeed;
|
|
||||||
state.walkSpeed = data.walkSpeed;
|
|
||||||
state.potionEffects = data.potionEffects;
|
|
||||||
state.fireTicks = data.fireTicks;
|
|
||||||
state.profile = ModeratorProfile.fromConfigKey(data.profileKey).orElse(ModeratorProfile.SOFT_MODER);
|
|
||||||
|
|
||||||
savedStates.put(playerId, state);
|
|
||||||
activeProfiles.put(playerId, state.profile);
|
|
||||||
plugin.getLogger().info("Загружено состояние админ мода для: " + playerId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void restorePlayerState(Player player) {
|
|
||||||
UUID playerId = player.getUniqueId();
|
|
||||||
PlayerState state = savedStates.get(playerId);
|
|
||||||
|
|
||||||
if (state == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// КРИТИЧНО: Удаляем из savedStates ДО восстановления режима!
|
|
||||||
// Это предотвратит срабатывание GameModeChangeListener, который мог бы снова
|
|
||||||
// включить полет
|
|
||||||
savedStates.remove(playerId);
|
|
||||||
activeProfiles.remove(playerId);
|
|
||||||
|
|
||||||
// Восстанавливаем инвентарь
|
|
||||||
player.getInventory().setContents(state.inventory);
|
|
||||||
player.getInventory().setArmorContents(state.armorContents);
|
|
||||||
player.getInventory().setItemInOffHand(state.offHand);
|
|
||||||
|
|
||||||
if (state.location != null) {
|
|
||||||
player.teleport(state.location);
|
|
||||||
}
|
|
||||||
|
|
||||||
player.setHealth(state.health);
|
|
||||||
player.setFoodLevel(state.foodLevel);
|
|
||||||
player.setSaturation(state.saturation);
|
|
||||||
player.setExhaustion(state.exhaustion);
|
|
||||||
|
|
||||||
player.setExp(state.exp);
|
|
||||||
player.setLevel(state.level);
|
|
||||||
player.setTotalExperience(state.totalExperience);
|
|
||||||
|
|
||||||
// ВАЖНО: Сначала восстанавливаем gameMode
|
|
||||||
player.setGameMode(state.gameMode);
|
|
||||||
|
|
||||||
// КРИТИЧНО: ПОТОМ применяем железную очистку способностей!
|
|
||||||
// Это гарантирует, что даже в SPECTATOR режиме у игрока не будет полета
|
|
||||||
forceDisableAbilities(player);
|
|
||||||
|
|
||||||
for (PotionEffect effect : player.getActivePotionEffects()) {
|
|
||||||
player.removePotionEffect(effect.getType());
|
|
||||||
}
|
|
||||||
for (PotionEffect effect : state.potionEffects) {
|
|
||||||
player.addPotionEffect(effect);
|
|
||||||
}
|
|
||||||
|
|
||||||
player.setFireTicks(state.fireTicks);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Железное отключение всех админ способностей
|
|
||||||
* Используется при выходе из режима и в команде /admfix
|
|
||||||
*/
|
|
||||||
public void forceDisableAbilities(Player player) {
|
|
||||||
player.setInvulnerable(false); // Убираем бессмертие
|
|
||||||
player.setFlying(false); // Принудительно отключаем полет
|
|
||||||
player.setAllowFlight(false); // Запрещаем полет
|
|
||||||
player.setFlySpeed(0.1f); // Сброс скорости полета на дефолт
|
|
||||||
player.setWalkSpeed(0.2f); // Сброс скорости ходьбы на дефолт
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isInAdminMode(UUID playerId) {
|
|
||||||
return savedStates.containsKey(playerId);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean canUseHardActions(CommandSender sender) {
|
|
||||||
if (sender.hasPermission("adminmode.admin")) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(sender instanceof Player player)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return isInAdminMode(player.getUniqueId()) && getActiveProfile(player.getUniqueId()) == ModeratorProfile.HARD_MODER;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean validateHardActionPlayer(Player moderator) {
|
private boolean validateHardActionPlayer(Player moderator) {
|
||||||
if (!canUseHardActions(moderator)) {
|
if (!canUseHardActions(moderator)) {
|
||||||
moderator.sendMessage(ChatColor.RED + "Для этого действия нужен активный профиль Hard Moder.");
|
moderator.sendMessage(configManager.getPrefixedMessage("§cДля этого действия нужен активный профиль Hard Moder."));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Player validateActiveTarget(Player moderator, String targetName) {
|
||||||
|
if (!modeManager.hasSession(moderator.getUniqueId())) {
|
||||||
|
moderator.sendMessage(configManager.getPrefixedMessage("§cСначала войдите в режим модерации."));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return resolveOnlinePlayer(targetName, moderator);
|
||||||
|
}
|
||||||
|
|
||||||
private Player resolveOnlinePlayer(String targetName, CommandSender sender) {
|
private Player resolveOnlinePlayer(String targetName, CommandSender sender) {
|
||||||
if (targetName == null || targetName.isBlank()) {
|
if (targetName == null || targetName.isBlank()) {
|
||||||
sender.sendMessage(ChatColor.RED + "Укажите ник игрока.");
|
sender.sendMessage(configManager.getPrefixedMessage("§cУкажите ник игрока."));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -531,102 +286,10 @@ public class AdminModeCommand implements CommandExecutor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (target == null) {
|
if (target == null) {
|
||||||
sender.sendMessage(ChatColor.RED + "Игрок не найден!");
|
sender.sendMessage(configManager.getPrefixedMessage("§cИгрок не найден!"));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
private float clampSpeed(float value, float min) {
|
|
||||||
return Math.max(min, Math.min(1.0f, value));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void grantLuckPermsPermissions(Player player, ModeratorProfile profile) {
|
|
||||||
if (!configManager.isUseLuckPerms()) {
|
|
||||||
player.setOp(true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
LuckPerms luckPerms = LuckPermsProvider.get();
|
|
||||||
User user = luckPerms.getUserManager().getUser(player.getUniqueId());
|
|
||||||
|
|
||||||
if (user == null) {
|
|
||||||
player.sendMessage(ChatColor.RED + "⚠ Не удалось получить данные LuckPerms!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<String> groups = configManager.getLuckPermsGroups(profile);
|
|
||||||
|
|
||||||
for (String group : groups) {
|
|
||||||
Node groupNode = Node.builder("group." + group).build();
|
|
||||||
user.data().add(groupNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
luckPerms.getUserManager().saveUser(user);
|
|
||||||
|
|
||||||
player.sendMessage(ChatColor.GREEN + "✓ Права администратора выданы!");
|
|
||||||
} catch (IllegalStateException e) {
|
|
||||||
player.setOp(true);
|
|
||||||
player.sendMessage(ChatColor.YELLOW + "⚠ LuckPerms не найден, используется стандартный OP");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void removeLuckPermsPermissions(Player player, ModeratorProfile profile) {
|
|
||||||
if (!configManager.isUseLuckPerms()) {
|
|
||||||
player.setOp(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!configManager.isRemoveGroupsOnDisable()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
LuckPerms luckPerms = LuckPermsProvider.get();
|
|
||||||
User user = luckPerms.getUserManager().getUser(player.getUniqueId());
|
|
||||||
|
|
||||||
if (user == null) {
|
|
||||||
player.sendMessage(ChatColor.RED + "⚠ Не удалось получить данные LuckPerms!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<String> groups = configManager.getLuckPermsGroups(profile);
|
|
||||||
|
|
||||||
for (String group : groups) {
|
|
||||||
Node groupNode = Node.builder("group." + group).build();
|
|
||||||
user.data().remove(groupNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
luckPerms.getUserManager().saveUser(user);
|
|
||||||
|
|
||||||
player.sendMessage(ChatColor.GREEN + configManager.getMsgPermissionsRemoved());
|
|
||||||
} catch (IllegalStateException e) {
|
|
||||||
player.setOp(false);
|
|
||||||
player.sendMessage(ChatColor.YELLOW + "⚠ LuckPerms не найден, убран стандартный OP");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class PlayerState {
|
|
||||||
ItemStack[] inventory;
|
|
||||||
ItemStack[] armorContents;
|
|
||||||
ItemStack offHand;
|
|
||||||
Location location;
|
|
||||||
double health;
|
|
||||||
int foodLevel;
|
|
||||||
float saturation;
|
|
||||||
float exhaustion;
|
|
||||||
float exp;
|
|
||||||
int level;
|
|
||||||
int totalExperience;
|
|
||||||
GameMode gameMode;
|
|
||||||
boolean allowFlight;
|
|
||||||
boolean flying;
|
|
||||||
float flySpeed;
|
|
||||||
float walkSpeed;
|
|
||||||
Collection<PotionEffect> potionEffects;
|
|
||||||
int fireTicks;
|
|
||||||
ModeratorProfile profile;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.blz.adminmode.moderation.ModeratorProfile;
|
import org.blz.adminmode.moderation.ModeratorProfile;
|
||||||
|
import org.bukkit.Material;
|
||||||
import org.bukkit.configuration.file.FileConfiguration;
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.plugin.Plugin;
|
||||||
|
|
||||||
@@ -19,6 +20,17 @@ public class ConfigManager {
|
|||||||
private Map<ModeratorProfile, List<String>> luckPermsGroups;
|
private Map<ModeratorProfile, List<String>> luckPermsGroups;
|
||||||
private boolean removeGroupsOnDisable;
|
private boolean removeGroupsOnDisable;
|
||||||
private boolean dialogsEnabled;
|
private boolean dialogsEnabled;
|
||||||
|
private String baseGroup;
|
||||||
|
private String softGroup;
|
||||||
|
private String hardGroup;
|
||||||
|
private Material softPanelMaterial;
|
||||||
|
private Material hardPanelMaterial;
|
||||||
|
private Material cpInspectorMaterial;
|
||||||
|
private boolean coreProtectEnabled;
|
||||||
|
private int coreProtectDefaultRadius;
|
||||||
|
private String coreProtectDefaultTime;
|
||||||
|
private boolean sessionLoggingEnabled;
|
||||||
|
private String sessionLogFile;
|
||||||
|
|
||||||
private boolean preventItemDrop;
|
private boolean preventItemDrop;
|
||||||
private boolean preventItemPickup;
|
private boolean preventItemPickup;
|
||||||
@@ -50,6 +62,12 @@ public class ConfigManager {
|
|||||||
private String msgItemUseDenied;
|
private String msgItemUseDenied;
|
||||||
private String msgBlockPlaceDenied;
|
private String msgBlockPlaceDenied;
|
||||||
private String msgReloaded;
|
private String msgReloaded;
|
||||||
|
private String msgPrefix;
|
||||||
|
private String msgEnterSoft;
|
||||||
|
private String msgEnterHard;
|
||||||
|
private String msgExitMode;
|
||||||
|
private String msgCoreProtectUnavailable;
|
||||||
|
private String msgSessionRecovered;
|
||||||
|
|
||||||
public ConfigManager(Plugin plugin) {
|
public ConfigManager(Plugin plugin) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
@@ -66,14 +84,37 @@ public class ConfigManager {
|
|||||||
removeGroupsOnDisable = config.getBoolean("admin_mode.luckperms.remove_on_disable", true);
|
removeGroupsOnDisable = config.getBoolean("admin_mode.luckperms.remove_on_disable", true);
|
||||||
dialogsEnabled = config.getBoolean("admin_mode.dialogs.enabled", true);
|
dialogsEnabled = config.getBoolean("admin_mode.dialogs.enabled", true);
|
||||||
|
|
||||||
|
baseGroup = config.getString("groups.base", "moder");
|
||||||
|
softGroup = config.getString("groups.soft", "soft_moder_adm");
|
||||||
|
hardGroup = config.getString("groups.hard", "hard_moder_adm");
|
||||||
|
|
||||||
|
softPanelMaterial = readMaterial("items.soft_panel_material", Material.COMPASS);
|
||||||
|
hardPanelMaterial = readMaterial("items.hard_panel_material", Material.NETHER_STAR);
|
||||||
|
cpInspectorMaterial = readMaterial("items.cp_inspector_material", Material.STICK);
|
||||||
|
|
||||||
|
coreProtectEnabled = config.getBoolean("coreprotect.enabled", true);
|
||||||
|
coreProtectDefaultRadius = config.getInt("coreprotect.default_radius", 10);
|
||||||
|
coreProtectDefaultTime = config.getString("coreprotect.default_time", "24h");
|
||||||
|
|
||||||
|
sessionLoggingEnabled = config.getBoolean("logging.enabled", true);
|
||||||
|
sessionLogFile = config.getString("logging.log_file", "logs/sessions.log");
|
||||||
|
|
||||||
List<String> legacyGroups = config.getStringList("admin_mode.luckperms.groups");
|
List<String> legacyGroups = config.getStringList("admin_mode.luckperms.groups");
|
||||||
List<String> softGroups = config.getStringList("admin_mode.luckperms.profile_groups.soft_moder");
|
List<String> softGroups = config.getStringList("admin_mode.luckperms.profile_groups.soft_moder");
|
||||||
List<String> hardGroups = config.getStringList("admin_mode.luckperms.profile_groups.hard_moder");
|
List<String> hardGroups = config.getStringList("admin_mode.luckperms.profile_groups.hard_moder");
|
||||||
if (softGroups.isEmpty()) {
|
if (softGroups.isEmpty()) {
|
||||||
softGroups = new ArrayList<>(legacyGroups);
|
if (!legacyGroups.isEmpty()) {
|
||||||
|
softGroups = new ArrayList<>(legacyGroups);
|
||||||
|
} else {
|
||||||
|
softGroups = new ArrayList<>(List.of(softGroup));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (hardGroups.isEmpty()) {
|
if (hardGroups.isEmpty()) {
|
||||||
hardGroups = legacyGroups.isEmpty() ? new ArrayList<>(softGroups) : new ArrayList<>(legacyGroups);
|
if (!legacyGroups.isEmpty()) {
|
||||||
|
hardGroups = new ArrayList<>(legacyGroups);
|
||||||
|
} else {
|
||||||
|
hardGroups = new ArrayList<>(List.of(hardGroup));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
luckPermsGroups = new EnumMap<>(ModeratorProfile.class);
|
luckPermsGroups = new EnumMap<>(ModeratorProfile.class);
|
||||||
luckPermsGroups.put(ModeratorProfile.SOFT_MODER, new ArrayList<>(softGroups));
|
luckPermsGroups.put(ModeratorProfile.SOFT_MODER, new ArrayList<>(softGroups));
|
||||||
@@ -117,6 +158,15 @@ public class ConfigManager {
|
|||||||
msgBlockPlaceDenied = config.getString("admin_mode.messages.block_place_denied",
|
msgBlockPlaceDenied = config.getString("admin_mode.messages.block_place_denied",
|
||||||
"✖ Вы можете ставить только разрешенные блоки!");
|
"✖ Вы можете ставить только разрешенные блоки!");
|
||||||
msgReloaded = config.getString("admin_mode.messages.reloaded", "✓ Конфигурация AdminMode перезагружена!");
|
msgReloaded = config.getString("admin_mode.messages.reloaded", "✓ Конфигурация AdminMode перезагружена!");
|
||||||
|
|
||||||
|
msgPrefix = config.getString("messages.prefix", "§8[§bAdminMode§8] ");
|
||||||
|
msgEnterSoft = config.getString("messages.enter_soft", "§aВошёл в режим §bSOFT MODER");
|
||||||
|
msgEnterHard = config.getString("messages.enter_hard", "§aВошёл в режим §cHARD MODER");
|
||||||
|
msgExitMode = config.getString("messages.exit", "§7Режим деактивирован. Состояние восстановлено.");
|
||||||
|
msgCoreProtectUnavailable = config.getString("messages.cp_unavailable",
|
||||||
|
"§cCoreProtect не найден. Hard режим работает без CP.");
|
||||||
|
msgSessionRecovered = config.getString("messages.session_recovered",
|
||||||
|
"§eВаша активная сессия модерации была восстановлена и корректно завершена.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEnabled() {
|
public boolean isEnabled() {
|
||||||
@@ -143,6 +193,54 @@ public class ConfigManager {
|
|||||||
return dialogsEnabled;
|
return dialogsEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getBaseGroup() {
|
||||||
|
return baseGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSoftGroup() {
|
||||||
|
return softGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHardGroup() {
|
||||||
|
return hardGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getActiveGroup(ModeratorProfile profile) {
|
||||||
|
return profile != null && profile.isHardProfile() ? hardGroup : softGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Material getSoftPanelMaterial() {
|
||||||
|
return softPanelMaterial;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Material getHardPanelMaterial() {
|
||||||
|
return hardPanelMaterial;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Material getCpInspectorMaterial() {
|
||||||
|
return cpInspectorMaterial;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCoreProtectEnabled() {
|
||||||
|
return coreProtectEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCoreProtectDefaultRadius() {
|
||||||
|
return coreProtectDefaultRadius;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCoreProtectDefaultTime() {
|
||||||
|
return coreProtectDefaultTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSessionLoggingEnabled() {
|
||||||
|
return sessionLoggingEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSessionLogFile() {
|
||||||
|
return sessionLogFile;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isPreventItemDrop() {
|
public boolean isPreventItemDrop() {
|
||||||
return preventItemDrop;
|
return preventItemDrop;
|
||||||
}
|
}
|
||||||
@@ -254,4 +352,49 @@ public class ConfigManager {
|
|||||||
public String getMsgReloaded() {
|
public String getMsgReloaded() {
|
||||||
return msgReloaded;
|
return msgReloaded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getMsgPrefix() {
|
||||||
|
return msgPrefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMsgEnterSoft() {
|
||||||
|
return msgEnterSoft;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMsgEnterHard() {
|
||||||
|
return msgEnterHard;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMsgExitMode() {
|
||||||
|
return msgExitMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMsgCoreProtectUnavailable() {
|
||||||
|
return msgCoreProtectUnavailable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMsgSessionRecovered() {
|
||||||
|
return msgSessionRecovered;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPrefixedMessage(String message) {
|
||||||
|
if (message == null || message.isEmpty()) {
|
||||||
|
return msgPrefix;
|
||||||
|
}
|
||||||
|
return msgPrefix + message;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Material readMaterial(String path, Material fallback) {
|
||||||
|
String value = config.getString(path);
|
||||||
|
if (value == null || value.isBlank()) {
|
||||||
|
return fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return Material.valueOf(value.trim().toUpperCase());
|
||||||
|
} catch (IllegalArgumentException exception) {
|
||||||
|
plugin.getLogger().warning("Неизвестный material в конфиге " + path + ": " + value);
|
||||||
|
return fallback;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,9 @@ import net.kyori.adventure.text.event.ClickCallback;
|
|||||||
import org.blz.adminmode.commands.AdminModeCommand;
|
import org.blz.adminmode.commands.AdminModeCommand;
|
||||||
import org.blz.adminmode.config.ConfigManager;
|
import org.blz.adminmode.config.ConfigManager;
|
||||||
import org.blz.adminmode.moderation.ModeratorProfile;
|
import org.blz.adminmode.moderation.ModeratorProfile;
|
||||||
|
import org.blz.adminmode.moderation.PlayerListAction;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.plugin.Plugin;
|
||||||
|
|
||||||
@@ -21,6 +24,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@SuppressWarnings("UnstableApiUsage")
|
||||||
public class AdminDialogService {
|
public class AdminDialogService {
|
||||||
|
|
||||||
private static final ClickCallback.Options CALLBACK_OPTIONS = ClickCallback.Options.builder()
|
private static final ClickCallback.Options CALLBACK_OPTIONS = ClickCallback.Options.builder()
|
||||||
@@ -38,19 +42,19 @@ public class AdminDialogService {
|
|||||||
this.adminModeCommand = adminModeCommand;
|
this.adminModeCommand = adminModeCommand;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean openProfileSelectionDialog(Player player) {
|
public boolean openModeSelectDialog(Player player) {
|
||||||
if (!configManager.isDialogsEnabled()) {
|
if (!configManager.isDialogsEnabled()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<ModeratorProfile> profiles = adminModeCommand.getAvailableProfiles(player);
|
List<ModeratorProfile> profiles = adminModeCommand.getAvailableProfiles(player);
|
||||||
if (profiles.isEmpty()) {
|
if (profiles.isEmpty()) {
|
||||||
player.sendMessage(configManager.getMsgNoPermission());
|
player.sendMessage(configManager.getPrefixedMessage(configManager.getMsgNoPermission()));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (profiles.size() == 1) {
|
if (profiles.size() == 1) {
|
||||||
adminModeCommand.toggleAdminMode(player, profiles.get(0));
|
adminModeCommand.activateProfile(player, profiles.get(0));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,31 +62,37 @@ public class AdminDialogService {
|
|||||||
List<ActionButton> buttons = new ArrayList<>();
|
List<ActionButton> buttons = new ArrayList<>();
|
||||||
for (ModeratorProfile profile : profiles) {
|
for (ModeratorProfile profile : profiles) {
|
||||||
buttons.add(actionButton(
|
buttons.add(actionButton(
|
||||||
profile.getDisplayName(),
|
profile.isHardProfile() ? "🔨 Hard Moder" : "🔍 Soft Moder",
|
||||||
profile.isHardProfile()
|
profile.isHardProfile()
|
||||||
? "Полный режим модерации с сильными действиями"
|
? "Полный режим модерации, CoreProtect и сильные действия"
|
||||||
: "Базовый режим модерации для повседневной работы",
|
: "Наблюдение, spectate, invsee и безопасные действия",
|
||||||
(response, audience) -> withPlayer(audience, moderator -> {
|
(response, audience) -> withPlayer(audience, moderator -> {
|
||||||
adminModeCommand.toggleAdminMode(moderator, profile);
|
adminModeCommand.activateProfile(moderator, profile);
|
||||||
plugin.getServer().getScheduler().runTask(plugin, () -> {
|
plugin.getServer().getScheduler().runTask(plugin, () -> {
|
||||||
if (adminModeCommand.isInAdminMode(moderator.getUniqueId())) {
|
if (adminModeCommand.isInAdminMode(moderator.getUniqueId())) {
|
||||||
openModerationPanel(moderator);
|
openCurrentPanel(moderator);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
})));
|
})));
|
||||||
}
|
}
|
||||||
|
|
||||||
DialogBase base = DialogBase.builder(Component.text("Выбор профиля модерации"))
|
buttons.add(actionButton(
|
||||||
|
"Закрыть",
|
||||||
|
"Закрыть выбор режима",
|
||||||
|
(response, audience) -> {
|
||||||
|
}));
|
||||||
|
|
||||||
|
DialogBase base = DialogBase.builder(Component.text("⚙ Режим модерации"))
|
||||||
.canCloseWithEscape(true)
|
.canCloseWithEscape(true)
|
||||||
.pause(false)
|
.pause(false)
|
||||||
.afterAction(DialogBase.DialogAfterAction.CLOSE)
|
.afterAction(DialogBase.DialogAfterAction.CLOSE)
|
||||||
.body(List.of(DialogBody.plainMessage(Component.text(
|
.body(List.of(DialogBody.plainMessage(Component.text(
|
||||||
"Выберите профиль, с которым хотите войти в admin mode. Soft — для обычной модерации, Hard — для телепортов и сильных действий."),
|
"Выберите режим входа. Soft — наблюдение и безопасная модерация. Hard — полный контроль, телепорты и CoreProtect."),
|
||||||
360)))
|
360)))
|
||||||
.inputs(List.of())
|
.inputs(List.of())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
showDialog(player, base, DialogType.multiAction(buttons, closeButton(), 2));
|
showDialog(player, base, DialogType.multiAction(buttons, closeButton(), 1));
|
||||||
return true;
|
return true;
|
||||||
} catch (Exception exception) {
|
} catch (Exception exception) {
|
||||||
plugin.getLogger().warning("Не удалось открыть dialog выбора профиля: " + exception.getMessage());
|
plugin.getLogger().warning("Не удалось открыть dialog выбора профиля: " + exception.getMessage());
|
||||||
@@ -90,7 +100,21 @@ public class AdminDialogService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean openModerationPanel(Player player) {
|
public boolean openCurrentPanel(Player player) {
|
||||||
|
UUID playerId = player.getUniqueId();
|
||||||
|
ModeratorProfile profile = adminModeCommand.getActiveProfile(playerId);
|
||||||
|
if (profile == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (profile.isHardProfile()) {
|
||||||
|
return openHardPanel(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
return openSoftPanel(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean openSoftPanel(Player player) {
|
||||||
if (!configManager.isDialogsEnabled()) {
|
if (!configManager.isDialogsEnabled()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -100,70 +124,194 @@ public class AdminDialogService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
UUID playerId = player.getUniqueId();
|
|
||||||
ModeratorProfile profile = adminModeCommand.getActiveProfile(playerId);
|
|
||||||
boolean hardProfile = profile != null && profile.isHardProfile();
|
|
||||||
|
|
||||||
List<ActionButton> buttons = new ArrayList<>();
|
List<ActionButton> buttons = new ArrayList<>();
|
||||||
buttons.add(actionButton(
|
buttons.add(actionButton(
|
||||||
"Скорости и режим",
|
"👁 Spectate игрока",
|
||||||
"Открыть слайдеры скорости и переключатель бессмертия",
|
"Выбрать игрока для режима наблюдения",
|
||||||
|
(response, audience) -> withPlayer(audience, moderator -> schedule(
|
||||||
|
() -> openPlayerListDialog(moderator, PlayerListAction.SPECTATE)))));
|
||||||
|
buttons.add(actionButton(
|
||||||
|
"📍 TP к игроку",
|
||||||
|
"Выбрать игрока для телепортации",
|
||||||
|
(response, audience) -> withPlayer(audience, moderator -> schedule(
|
||||||
|
() -> openPlayerListDialog(moderator, PlayerListAction.TELEPORT)))));
|
||||||
|
buttons.add(actionButton(
|
||||||
|
"🎒 Invsee игрока",
|
||||||
|
"Открыть инвентарь игрока только для просмотра",
|
||||||
|
(response, audience) -> withPlayer(audience, moderator -> schedule(
|
||||||
|
() -> openPlayerListDialog(moderator, PlayerListAction.INVSEE)))));
|
||||||
|
buttons.add(actionButton(
|
||||||
|
"📋 Список онлайн",
|
||||||
|
"Показать онлайн-игроков и их координаты",
|
||||||
|
(response, audience) -> withPlayer(audience, moderator -> schedule(() -> openOnlineListDialog(moderator)))));
|
||||||
|
buttons.add(actionButton(
|
||||||
|
"🎛 Настройки режима",
|
||||||
|
"Скорость полёта, ходьбы и бессмертие",
|
||||||
(response, audience) -> withPlayer(audience, moderator -> schedule(() -> openSpeedPanel(moderator)))));
|
(response, audience) -> withPlayer(audience, moderator -> schedule(() -> openSpeedPanel(moderator)))));
|
||||||
buttons.add(actionButton(
|
buttons.add(actionButton(
|
||||||
"Выключить admin mode",
|
"🚪 Выйти из режима",
|
||||||
"Восстановить сохраненное состояние и снять временные права",
|
"Восстановить сохраненное состояние и снять временные права",
|
||||||
(response, audience) -> withPlayer(audience, adminModeCommand::toggleAdminMode)));
|
(response, audience) -> withPlayer(audience, moderator -> adminModeCommand.exitMode(moderator))));
|
||||||
|
|
||||||
if (hardProfile) {
|
|
||||||
buttons.add(actionButton(
|
|
||||||
"Телепорт к игроку",
|
|
||||||
"Телепортировать себя к цели из поля ниже",
|
|
||||||
(response, audience) -> withPlayer(audience, moderator -> {
|
|
||||||
String targetName = normalizeTarget(response.getText("target_player"));
|
|
||||||
adminModeCommand.teleportToPlayer(moderator, targetName);
|
|
||||||
})));
|
|
||||||
buttons.add(actionButton(
|
|
||||||
"Игрок ко мне",
|
|
||||||
"Телепортировать цель к себе",
|
|
||||||
(response, audience) -> withPlayer(audience, moderator -> {
|
|
||||||
String targetName = normalizeTarget(response.getText("target_player"));
|
|
||||||
adminModeCommand.teleportPlayerHere(moderator, targetName);
|
|
||||||
})));
|
|
||||||
buttons.add(actionButton(
|
|
||||||
"Сбросить способности",
|
|
||||||
"Отключить полет, бессмертие и скорости у цели",
|
|
||||||
(response, audience) -> withPlayer(audience, moderator -> {
|
|
||||||
String targetName = normalizeTarget(response.getText("target_player"));
|
|
||||||
adminModeCommand.forceDisableTarget(moderator, targetName);
|
|
||||||
})));
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Component> lines = new ArrayList<>();
|
List<Component> lines = new ArrayList<>();
|
||||||
lines.add(Component.text("Активный профиль: " + (profile == null ? "unknown" : profile.getDisplayName())));
|
lines.add(Component.text("Soft Moder предназначен для наблюдения, инвентарей и безопасной телепортации."));
|
||||||
lines.add(Component.text(hardProfile
|
lines.add(Component.text("Используйте компас в руке как panel item или /adminmode для повторного открытия."));
|
||||||
? "Hard профиль открывает телепорты и сильные действия."
|
|
||||||
: "Soft профиль оставляет только безопасные действия и настройку режима."));
|
|
||||||
lines.add(Component.text("Для действий по цели используйте поле с ником игрока."));
|
|
||||||
|
|
||||||
DialogBase base = DialogBase.builder(Component.text("Панель модератора"))
|
DialogBase base = DialogBase.builder(Component.text("🔍 Soft Moder"))
|
||||||
.canCloseWithEscape(true)
|
.canCloseWithEscape(true)
|
||||||
.pause(false)
|
.pause(false)
|
||||||
.afterAction(DialogBase.DialogAfterAction.CLOSE)
|
.afterAction(DialogBase.DialogAfterAction.CLOSE)
|
||||||
.body(List.of(DialogBody.plainMessage(joinLines(lines), 360)))
|
.body(List.of(DialogBody.plainMessage(joinLines(lines), 360)))
|
||||||
.inputs(List.of(DialogInput.text(
|
.inputs(List.of())
|
||||||
"target_player",
|
|
||||||
320,
|
|
||||||
Component.text("Ник цели"),
|
|
||||||
true,
|
|
||||||
"",
|
|
||||||
16,
|
|
||||||
null)))
|
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
showDialog(player, base, DialogType.multiAction(buttons, closeButton(), 2));
|
showDialog(player, base, DialogType.multiAction(buttons, closeButton(), 2));
|
||||||
return true;
|
return true;
|
||||||
} catch (Exception exception) {
|
} catch (Exception exception) {
|
||||||
plugin.getLogger().warning("Не удалось открыть moderation dialog: " + exception.getMessage());
|
plugin.getLogger().warning("Не удалось открыть soft panel dialog: " + exception.getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean openHardPanel(Player player) {
|
||||||
|
if (!configManager.isDialogsEnabled()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!adminModeCommand.isInAdminMode(player.getUniqueId())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
List<ActionButton> buttons = new ArrayList<>();
|
||||||
|
buttons.add(actionButton(
|
||||||
|
"👁 Spectate игрока",
|
||||||
|
"Выбрать игрока для режима наблюдения",
|
||||||
|
(response, audience) -> withPlayer(audience, moderator -> schedule(
|
||||||
|
() -> openPlayerListDialog(moderator, PlayerListAction.SPECTATE)))));
|
||||||
|
buttons.add(actionButton(
|
||||||
|
"📍 TP к игроку",
|
||||||
|
"Телепорт к выбранному игроку",
|
||||||
|
(response, audience) -> withPlayer(audience, moderator -> schedule(
|
||||||
|
() -> openPlayerListDialog(moderator, PlayerListAction.TELEPORT)))));
|
||||||
|
buttons.add(actionButton(
|
||||||
|
"🎒 Invsee игрока",
|
||||||
|
"Открыть инвентарь игрока только для просмотра",
|
||||||
|
(response, audience) -> withPlayer(audience, moderator -> schedule(
|
||||||
|
() -> openPlayerListDialog(moderator, PlayerListAction.INVSEE)))));
|
||||||
|
buttons.add(actionButton(
|
||||||
|
"📋 Список онлайн",
|
||||||
|
"Показать онлайн-игроков и координаты",
|
||||||
|
(response, audience) -> withPlayer(audience, moderator -> schedule(() -> openOnlineListDialog(moderator)))));
|
||||||
|
buttons.add(actionButton(
|
||||||
|
"🔍 Lookup логи CP",
|
||||||
|
"Открыть форму поиска по логам CoreProtect",
|
||||||
|
(response, audience) -> withPlayer(audience, moderator -> schedule(() -> openLookupDialog(moderator)))));
|
||||||
|
buttons.add(actionButton(
|
||||||
|
"↩ Откат области CP",
|
||||||
|
"Настроить rollback с подтверждением",
|
||||||
|
(response, audience) -> withPlayer(audience, moderator -> schedule(() -> openRollbackDialog(moderator)))));
|
||||||
|
buttons.add(actionButton(
|
||||||
|
"🎛 Настройки режима",
|
||||||
|
"Скорость полёта, ходьбы и бессмертие",
|
||||||
|
(response, audience) -> withPlayer(audience, moderator -> schedule(() -> openSpeedPanel(moderator)))));
|
||||||
|
buttons.add(actionButton(
|
||||||
|
"🚪 Выйти из режима",
|
||||||
|
"Восстановить сохраненное состояние и выйти из hard режима",
|
||||||
|
(response, audience) -> withPlayer(audience, moderator -> adminModeCommand.exitMode(moderator))));
|
||||||
|
|
||||||
|
List<Component> lines = new ArrayList<>();
|
||||||
|
lines.add(Component.text("Hard Moder включает полный доступ к сильным действиям и CoreProtect."));
|
||||||
|
lines.add(Component.text("Используйте Nether Star для панели и Stick для переключения co inspect."));
|
||||||
|
|
||||||
|
DialogBase base = DialogBase.builder(Component.text("🔨 Hard Moder"))
|
||||||
|
.canCloseWithEscape(true)
|
||||||
|
.pause(false)
|
||||||
|
.afterAction(DialogBase.DialogAfterAction.CLOSE)
|
||||||
|
.body(List.of(DialogBody.plainMessage(joinLines(lines), 360)))
|
||||||
|
.inputs(List.of())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
showDialog(player, base, DialogType.multiAction(buttons, closeButton(), 2));
|
||||||
|
return true;
|
||||||
|
} catch (Exception exception) {
|
||||||
|
plugin.getLogger().warning("Не удалось открыть hard panel dialog: " + exception.getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean openPlayerListDialog(Player player, PlayerListAction action) {
|
||||||
|
if (!adminModeCommand.isInAdminMode(player.getUniqueId())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
List<ActionButton> buttons = new ArrayList<>();
|
||||||
|
for (Player target : Bukkit.getOnlinePlayers()) {
|
||||||
|
if (target.getUniqueId().equals(player.getUniqueId())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
buttons.add(actionButton(
|
||||||
|
target.getName(),
|
||||||
|
target.getWorld().getName() + " | " + target.getLocation().getBlockX() + ", "
|
||||||
|
+ target.getLocation().getBlockY() + ", " + target.getLocation().getBlockZ(),
|
||||||
|
(response, audience) -> withPlayer(audience, moderator ->
|
||||||
|
adminModeCommand.performPlayerListAction(moderator, action, target.getName()))));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buttons.isEmpty()) {
|
||||||
|
buttons.add(actionButton(
|
||||||
|
"Нет целей",
|
||||||
|
"Кроме вас сейчас никого нет онлайн",
|
||||||
|
(response, audience) -> withPlayer(audience, moderator -> schedule(() -> openCurrentPanel(moderator)))));
|
||||||
|
}
|
||||||
|
|
||||||
|
ActionButton backButton = actionButton(
|
||||||
|
"Назад",
|
||||||
|
"Вернуться к основной панели",
|
||||||
|
(response, audience) -> withPlayer(audience, moderator -> schedule(() -> openCurrentPanel(moderator))));
|
||||||
|
|
||||||
|
DialogBase base = DialogBase.builder(Component.text(dialogTitleForAction(action)))
|
||||||
|
.canCloseWithEscape(true)
|
||||||
|
.pause(false)
|
||||||
|
.afterAction(DialogBase.DialogAfterAction.CLOSE)
|
||||||
|
.body(List.of(DialogBody.plainMessage(Component.text(dialogBodyForAction(action)), 360)))
|
||||||
|
.inputs(List.of())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
showDialog(player, base, DialogType.multiAction(buttons, backButton, 2));
|
||||||
|
return true;
|
||||||
|
} catch (Exception exception) {
|
||||||
|
plugin.getLogger().warning("Не удалось открыть список игроков: " + exception.getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean openOnlineListDialog(Player player) {
|
||||||
|
if (!adminModeCommand.isInAdminMode(player.getUniqueId())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
List<Component> lines = new ArrayList<>(adminModeCommand.getOnlineSummary(player));
|
||||||
|
ActionButton backButton = actionButton(
|
||||||
|
"Назад",
|
||||||
|
"Вернуться к панели режима",
|
||||||
|
(response, audience) -> withPlayer(audience, moderator -> schedule(() -> openCurrentPanel(moderator))));
|
||||||
|
|
||||||
|
DialogBase base = DialogBase.builder(Component.text("📋 Онлайн список"))
|
||||||
|
.canCloseWithEscape(true)
|
||||||
|
.pause(false)
|
||||||
|
.afterAction(DialogBase.DialogAfterAction.CLOSE)
|
||||||
|
.body(List.of(DialogBody.plainMessage(joinLines(lines), 360)))
|
||||||
|
.inputs(List.of())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
showDialog(player, base, DialogType.multiAction(List.of(), backButton, 1));
|
||||||
|
return true;
|
||||||
|
} catch (Exception exception) {
|
||||||
|
plugin.getLogger().warning("Не удалось открыть онлайн список: " + exception.getMessage());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -193,20 +341,20 @@ public class AdminDialogService {
|
|||||||
flySpeed == null ? currentFly : flySpeed,
|
flySpeed == null ? currentFly : flySpeed,
|
||||||
walkSpeed == null ? currentWalk : walkSpeed,
|
walkSpeed == null ? currentWalk : walkSpeed,
|
||||||
godMode != null && godMode);
|
godMode != null && godMode);
|
||||||
schedule(() -> openModerationPanel(moderator));
|
schedule(() -> openCurrentPanel(moderator));
|
||||||
}));
|
}));
|
||||||
|
|
||||||
ActionButton backButton = actionButton(
|
ActionButton backButton = actionButton(
|
||||||
"Назад",
|
"Назад",
|
||||||
"Вернуться в основную панель модератора",
|
"Вернуться в основную панель модератора",
|
||||||
(response, audience) -> withPlayer(audience, moderator -> schedule(() -> openModerationPanel(moderator))));
|
(response, audience) -> withPlayer(audience, moderator -> schedule(() -> openCurrentPanel(moderator))));
|
||||||
|
|
||||||
DialogBase base = DialogBase.builder(Component.text("Настройка admin mode"))
|
DialogBase base = DialogBase.builder(Component.text("🎛 Настройка режима"))
|
||||||
.canCloseWithEscape(true)
|
.canCloseWithEscape(true)
|
||||||
.pause(false)
|
.pause(false)
|
||||||
.afterAction(DialogBase.DialogAfterAction.CLOSE)
|
.afterAction(DialogBase.DialogAfterAction.CLOSE)
|
||||||
.body(List.of(DialogBody.plainMessage(Component.text(
|
.body(List.of(DialogBody.plainMessage(Component.text(
|
||||||
"Настройте полет, скорость передвижения и режим бессмертия через новые элементы dialog API."),
|
"Настройте скорость полёта, скорость ходьбы и бессмертие для текущей сессии модерации."),
|
||||||
360)))
|
360)))
|
||||||
.inputs(List.of(
|
.inputs(List.of(
|
||||||
DialogInput.numberRange(
|
DialogInput.numberRange(
|
||||||
@@ -243,7 +391,135 @@ public class AdminDialogService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean openLookupDialog(Player player) {
|
||||||
|
if (!adminModeCommand.isInAdminMode(player.getUniqueId())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
ActionButton lookupButton = actionButton(
|
||||||
|
"🔍 Найти",
|
||||||
|
"Выполнить co lookup с указанными параметрами",
|
||||||
|
(response, audience) -> withPlayer(audience, moderator -> {
|
||||||
|
String targetName = normalizeTarget(response.getText("cp_player"));
|
||||||
|
Integer radius = parseInteger(response.getText("cp_radius"), configManager.getCoreProtectDefaultRadius());
|
||||||
|
String time = normalizeTime(response.getText("cp_time"), configManager.getCoreProtectDefaultTime());
|
||||||
|
adminModeCommand.executeCPLookup(moderator, targetName, radius, time);
|
||||||
|
schedule(() -> openHardPanel(moderator));
|
||||||
|
}));
|
||||||
|
|
||||||
|
ActionButton backButton = actionButton(
|
||||||
|
"Назад",
|
||||||
|
"Вернуться в Hard Moder panel",
|
||||||
|
(response, audience) -> withPlayer(audience, moderator -> schedule(() -> openHardPanel(moderator))));
|
||||||
|
|
||||||
|
DialogBase base = DialogBase.builder(Component.text("🔍 Поиск в логах CP"))
|
||||||
|
.canCloseWithEscape(true)
|
||||||
|
.pause(false)
|
||||||
|
.afterAction(DialogBase.DialogAfterAction.CLOSE)
|
||||||
|
.body(List.of(DialogBody.plainMessage(Component.text(
|
||||||
|
"Фильтр по игроку опционален. Радиус и время можно оставить стандартными."), 360)))
|
||||||
|
.inputs(List.of(
|
||||||
|
DialogInput.text("cp_player", 300, Component.text("Игрок (пусто = все)"), false, "", 16, null),
|
||||||
|
DialogInput.text("cp_radius", 180, Component.text("Радиус"), true,
|
||||||
|
String.valueOf(configManager.getCoreProtectDefaultRadius()), 3, null),
|
||||||
|
DialogInput.text("cp_time", 180, Component.text("Время"), true,
|
||||||
|
configManager.getCoreProtectDefaultTime(), 4, null)))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
showDialog(player, base, DialogType.multiAction(List.of(lookupButton), backButton, 1));
|
||||||
|
return true;
|
||||||
|
} catch (Exception exception) {
|
||||||
|
plugin.getLogger().warning("Не удалось открыть lookup dialog: " + exception.getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean openRollbackDialog(Player player) {
|
||||||
|
if (!adminModeCommand.isInAdminMode(player.getUniqueId())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
ActionButton confirmButton = actionButton(
|
||||||
|
"✅ Далее к подтверждению",
|
||||||
|
"Открыть подтверждение rollback",
|
||||||
|
(response, audience) -> withPlayer(audience, moderator -> {
|
||||||
|
int radius = parseInteger(response.getText("rollback_radius"), configManager.getCoreProtectDefaultRadius());
|
||||||
|
String time = normalizeTime(response.getText("rollback_time"), configManager.getCoreProtectDefaultTime());
|
||||||
|
String targetPlayer = normalizeTarget(response.getText("rollback_player"));
|
||||||
|
schedule(() -> openRollbackConfirmDialog(moderator, radius, time, targetPlayer));
|
||||||
|
}));
|
||||||
|
|
||||||
|
ActionButton backButton = actionButton(
|
||||||
|
"Назад",
|
||||||
|
"Вернуться в Hard Moder panel",
|
||||||
|
(response, audience) -> withPlayer(audience, moderator -> schedule(() -> openHardPanel(moderator))));
|
||||||
|
|
||||||
|
DialogBase base = DialogBase.builder(Component.text("↩ Rollback CoreProtect"))
|
||||||
|
.canCloseWithEscape(true)
|
||||||
|
.pause(false)
|
||||||
|
.afterAction(DialogBase.DialogAfterAction.CLOSE)
|
||||||
|
.body(List.of(DialogBody.plainMessage(Component.text(
|
||||||
|
"Укажите радиус, временной диапазон и при необходимости игрока. Затем подтвердите откат."), 360)))
|
||||||
|
.inputs(List.of(
|
||||||
|
DialogInput.text("rollback_radius", 180, Component.text("Радиус"), true,
|
||||||
|
String.valueOf(configManager.getCoreProtectDefaultRadius()), 3, null),
|
||||||
|
DialogInput.text("rollback_time", 180, Component.text("Время"), true,
|
||||||
|
configManager.getCoreProtectDefaultTime(), 4, null),
|
||||||
|
DialogInput.text("rollback_player", 300, Component.text("Игрок (опционально)"), false,
|
||||||
|
"", 16, null)))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
showDialog(player, base, DialogType.multiAction(List.of(confirmButton), backButton, 1));
|
||||||
|
return true;
|
||||||
|
} catch (Exception exception) {
|
||||||
|
plugin.getLogger().warning("Не удалось открыть rollback dialog: " + exception.getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean openRollbackConfirmDialog(Player player, int radius, String time, String targetPlayer) {
|
||||||
|
if (!adminModeCommand.isInAdminMode(player.getUniqueId())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
List<Component> lines = new ArrayList<>();
|
||||||
|
lines.add(Component.text("Радиус: " + radius + " блоков"));
|
||||||
|
lines.add(Component.text("Время: " + time));
|
||||||
|
lines.add(Component.text(targetPlayer.isEmpty() ? "Игрок: все" : "Игрок: " + targetPlayer));
|
||||||
|
|
||||||
|
ActionButton confirmButton = actionButton(
|
||||||
|
"✅ Откатить",
|
||||||
|
"Подтвердить rollback по указанным параметрам",
|
||||||
|
(response, audience) -> withPlayer(audience, moderator -> {
|
||||||
|
adminModeCommand.executeCPRollback(moderator, radius, time, targetPlayer);
|
||||||
|
schedule(() -> openHardPanel(moderator));
|
||||||
|
}));
|
||||||
|
ActionButton cancelButton = actionButton(
|
||||||
|
"❌ Отмена",
|
||||||
|
"Отменить rollback и вернуться назад",
|
||||||
|
(response, audience) -> withPlayer(audience, moderator -> schedule(() -> openRollbackDialog(moderator))));
|
||||||
|
|
||||||
|
DialogBase base = DialogBase.builder(Component.text("⚠ Подтвердить откат?"))
|
||||||
|
.canCloseWithEscape(true)
|
||||||
|
.pause(false)
|
||||||
|
.afterAction(DialogBase.DialogAfterAction.CLOSE)
|
||||||
|
.body(List.of(DialogBody.plainMessage(joinLines(lines), 360)))
|
||||||
|
.inputs(List.of())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
showDialog(player, base, DialogType.multiAction(List.of(confirmButton, cancelButton), closeButton(), 1));
|
||||||
|
return true;
|
||||||
|
} catch (Exception exception) {
|
||||||
|
plugin.getLogger().warning("Не удалось открыть подтверждение rollback: " + exception.getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void showDialog(Player player, DialogBase base, io.papermc.paper.registry.data.dialog.type.DialogType type) {
|
private void showDialog(Player player, DialogBase base, io.papermc.paper.registry.data.dialog.type.DialogType type) {
|
||||||
|
player.closeInventory();
|
||||||
Dialog dialog = Dialog.create(factory -> {
|
Dialog dialog = Dialog.create(factory -> {
|
||||||
var builder = factory.empty();
|
var builder = factory.empty();
|
||||||
builder.base(base);
|
builder.base(base);
|
||||||
@@ -291,6 +567,46 @@ public class AdminDialogService {
|
|||||||
return targetName == null ? "" : targetName.trim();
|
return targetName == null ? "" : targetName.trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String normalizeTime(String input, String fallback) {
|
||||||
|
if (input == null || input.isBlank()) {
|
||||||
|
return fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
String normalized = input.trim().toLowerCase();
|
||||||
|
if (normalized.matches("\\d+[smhdw]")) {
|
||||||
|
return normalized;
|
||||||
|
}
|
||||||
|
return fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer parseInteger(String value, int fallback) {
|
||||||
|
if (value == null || value.isBlank()) {
|
||||||
|
return fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return Integer.parseInt(value.trim());
|
||||||
|
} catch (NumberFormatException exception) {
|
||||||
|
return fallback;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String dialogTitleForAction(PlayerListAction action) {
|
||||||
|
return switch (action) {
|
||||||
|
case SPECTATE -> "👁 Spectate игрока";
|
||||||
|
case TELEPORT -> "📍 TP к игроку";
|
||||||
|
case INVSEE -> "🎒 Invsee игрока";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private String dialogBodyForAction(PlayerListAction action) {
|
||||||
|
return switch (action) {
|
||||||
|
case SPECTATE -> "Выберите игрока, за которым хотите наблюдать.";
|
||||||
|
case TELEPORT -> "Выберите игрока, к которому хотите телепортироваться.";
|
||||||
|
case INVSEE -> "Выберите игрока, чей инвентарь хотите открыть.";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
private float clamp(float value, float min, float max) {
|
private float clamp(float value, float min, float max) {
|
||||||
return Math.max(min, Math.min(max, value));
|
return Math.max(min, Math.min(max, value));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,92 @@
|
|||||||
|
package org.blz.adminmode.integrations;
|
||||||
|
|
||||||
|
import org.blz.adminmode.config.ConfigManager;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
|
||||||
|
public class CoreProtectIntegration {
|
||||||
|
|
||||||
|
private final Plugin plugin;
|
||||||
|
private final ConfigManager configManager;
|
||||||
|
|
||||||
|
public CoreProtectIntegration(Plugin plugin, ConfigManager configManager) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.configManager = configManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAvailable() {
|
||||||
|
return configManager.isCoreProtectEnabled() && plugin.getServer().getPluginManager().getPlugin("CoreProtect") != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean toggleInspector(Player player) {
|
||||||
|
if (!isAvailable()) {
|
||||||
|
player.sendMessage(configManager.getPrefixedMessage(configManager.getMsgCoreProtectUnavailable()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Bukkit.dispatchCommand(player, "co inspect");
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean lookup(Player player, String targetPlayer, int radius, String time) {
|
||||||
|
if (!isAvailable()) {
|
||||||
|
player.sendMessage(configManager.getPrefixedMessage(configManager.getMsgCoreProtectUnavailable()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder command = new StringBuilder("co lookup");
|
||||||
|
appendPlayerFilter(command, targetPlayer);
|
||||||
|
command.append(" r:").append(normalizeRadius(radius));
|
||||||
|
command.append(" t:").append(normalizeTime(time));
|
||||||
|
return Bukkit.dispatchCommand(player, command.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean rollback(Player player, int radius, String time, String targetPlayer) {
|
||||||
|
if (!isAvailable()) {
|
||||||
|
player.sendMessage(configManager.getPrefixedMessage(configManager.getMsgCoreProtectUnavailable()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder command = new StringBuilder("co rollback");
|
||||||
|
appendPlayerFilter(command, targetPlayer);
|
||||||
|
command.append(" r:").append(normalizeRadius(radius));
|
||||||
|
command.append(" t:").append(normalizeTime(time));
|
||||||
|
return Bukkit.dispatchCommand(player, command.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void appendPlayerFilter(StringBuilder command, String targetPlayer) {
|
||||||
|
String sanitized = sanitizePlayerName(targetPlayer);
|
||||||
|
if (!sanitized.isEmpty()) {
|
||||||
|
command.append(" u:").append(sanitized);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int normalizeRadius(int radius) {
|
||||||
|
return Math.max(1, Math.min(100, radius));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String normalizeTime(String time) {
|
||||||
|
String fallback = configManager.getCoreProtectDefaultTime();
|
||||||
|
if (time == null || time.isBlank()) {
|
||||||
|
return fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
String normalized = time.trim().toLowerCase();
|
||||||
|
if (!normalized.matches("\\d+[smhdw]")) {
|
||||||
|
return fallback;
|
||||||
|
}
|
||||||
|
return normalized;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String sanitizePlayerName(String targetPlayer) {
|
||||||
|
if (targetPlayer == null || targetPlayer.isBlank()) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
String normalized = targetPlayer.trim();
|
||||||
|
if (normalized.matches("[A-Za-z0-9_]{1,16}")) {
|
||||||
|
return normalized;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
package org.blz.adminmode.integrations;
|
||||||
|
|
||||||
|
import net.luckperms.api.LuckPerms;
|
||||||
|
import net.luckperms.api.LuckPermsProvider;
|
||||||
|
import net.luckperms.api.model.user.User;
|
||||||
|
import net.luckperms.api.node.Node;
|
||||||
|
import org.blz.adminmode.config.ConfigManager;
|
||||||
|
import org.blz.adminmode.moderation.ModeSession;
|
||||||
|
import org.blz.adminmode.moderation.ModeratorProfile;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
|
||||||
|
public class LuckPermsIntegration {
|
||||||
|
|
||||||
|
private final Plugin plugin;
|
||||||
|
private final ConfigManager configManager;
|
||||||
|
|
||||||
|
public LuckPermsIntegration(Plugin plugin, ConfigManager configManager) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.configManager = configManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String resolveCurrentGroup(Player player) {
|
||||||
|
if (!configManager.isUseLuckPerms()) {
|
||||||
|
return configManager.getBaseGroup();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
User user = resolveUser(player);
|
||||||
|
if (user == null) {
|
||||||
|
return configManager.getBaseGroup();
|
||||||
|
}
|
||||||
|
return user.getPrimaryGroup();
|
||||||
|
} catch (IllegalStateException exception) {
|
||||||
|
return configManager.getBaseGroup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void enterMode(Player player, ModeratorProfile profile) {
|
||||||
|
if (!configManager.isUseLuckPerms()) {
|
||||||
|
player.setOp(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
User user = resolveUser(player);
|
||||||
|
if (user == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
removeKnownGroups(user);
|
||||||
|
user.data().add(groupNode(configManager.getActiveGroup(profile)));
|
||||||
|
saveUser(user);
|
||||||
|
} catch (IllegalStateException exception) {
|
||||||
|
player.setOp(true);
|
||||||
|
plugin.getLogger().warning("LuckPerms не найден, используется OP для " + player.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void exitMode(Player player, ModeSession session) {
|
||||||
|
if (!configManager.isUseLuckPerms()) {
|
||||||
|
player.setOp(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
User user = resolveUser(player);
|
||||||
|
if (user == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
removeKnownGroups(user);
|
||||||
|
String restoreGroup = session.getPreviousGroup();
|
||||||
|
if (restoreGroup == null || restoreGroup.isBlank() || "op".equalsIgnoreCase(restoreGroup)) {
|
||||||
|
restoreGroup = configManager.getBaseGroup();
|
||||||
|
}
|
||||||
|
user.data().add(groupNode(restoreGroup));
|
||||||
|
saveUser(user);
|
||||||
|
} catch (IllegalStateException exception) {
|
||||||
|
player.setOp(false);
|
||||||
|
plugin.getLogger().warning("LuckPerms не найден, снят OP у " + player.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private User resolveUser(Player player) {
|
||||||
|
LuckPerms luckPerms = LuckPermsProvider.get();
|
||||||
|
User user = luckPerms.getUserManager().getUser(player.getUniqueId());
|
||||||
|
if (user == null) {
|
||||||
|
user = luckPerms.getUserManager().loadUser(player.getUniqueId()).join();
|
||||||
|
}
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeKnownGroups(User user) {
|
||||||
|
user.data().remove(groupNode(configManager.getBaseGroup()));
|
||||||
|
user.data().remove(groupNode(configManager.getSoftGroup()));
|
||||||
|
user.data().remove(groupNode(configManager.getHardGroup()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Node groupNode(String group) {
|
||||||
|
return Node.builder("group." + group).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveUser(User user) {
|
||||||
|
LuckPermsProvider.get().getUserManager().saveUser(user);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,32 +1,39 @@
|
|||||||
package org.blz.adminmode.listeners;
|
package org.blz.adminmode.listeners;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.blz.adminmode.commands.AdminModeCommand;
|
import org.blz.adminmode.commands.AdminModeCommand;
|
||||||
import org.blz.adminmode.config.ConfigManager;
|
import org.blz.adminmode.config.ConfigManager;
|
||||||
import org.bukkit.ChatColor;
|
import org.blz.adminmode.dialog.AdminDialogService;
|
||||||
|
import org.blz.adminmode.moderation.ModeManager;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.EventPriority;
|
import org.bukkit.event.EventPriority;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.block.Action;
|
||||||
import org.bukkit.event.block.BlockPlaceEvent;
|
import org.bukkit.event.block.BlockPlaceEvent;
|
||||||
import org.bukkit.event.entity.EntityPickupItemEvent;
|
import org.bukkit.event.entity.EntityPickupItemEvent;
|
||||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||||
import org.bukkit.event.player.PlayerDropItemEvent;
|
import org.bukkit.event.player.PlayerDropItemEvent;
|
||||||
import org.bukkit.event.player.PlayerInteractEvent;
|
import org.bukkit.event.player.PlayerInteractEvent;
|
||||||
import org.bukkit.plugin.Plugin;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class AdminModeListener implements Listener {
|
public class AdminModeListener implements Listener {
|
||||||
|
|
||||||
private final Plugin plugin;
|
|
||||||
private final AdminModeCommand adminModeCommand;
|
private final AdminModeCommand adminModeCommand;
|
||||||
private final ConfigManager configManager;
|
private final ConfigManager configManager;
|
||||||
|
private final ModeManager modeManager;
|
||||||
|
private final AdminDialogService dialogService;
|
||||||
|
|
||||||
public AdminModeListener(Plugin plugin, AdminModeCommand adminModeCommand, ConfigManager configManager) {
|
public AdminModeListener(
|
||||||
this.plugin = plugin;
|
AdminModeCommand adminModeCommand,
|
||||||
|
ConfigManager configManager,
|
||||||
|
ModeManager modeManager,
|
||||||
|
AdminDialogService dialogService) {
|
||||||
this.adminModeCommand = adminModeCommand;
|
this.adminModeCommand = adminModeCommand;
|
||||||
this.configManager = configManager;
|
this.configManager = configManager;
|
||||||
|
this.modeManager = modeManager;
|
||||||
|
this.dialogService = dialogService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.HIGHEST)
|
@EventHandler(priority = EventPriority.HIGHEST)
|
||||||
@@ -37,7 +44,7 @@ public class AdminModeListener implements Listener {
|
|||||||
if (!configManager.isPreventItemDrop()) return;
|
if (!configManager.isPreventItemDrop()) return;
|
||||||
|
|
||||||
e.setCancelled(true);
|
e.setCancelled(true);
|
||||||
player.sendMessage(ChatColor.RED + configManager.getMsgItemDropDenied());
|
player.sendMessage(configManager.getPrefixedMessage(configManager.getMsgItemDropDenied()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.HIGHEST)
|
@EventHandler(priority = EventPriority.HIGHEST)
|
||||||
@@ -57,6 +64,11 @@ public class AdminModeListener implements Listener {
|
|||||||
if (!(e.getWhoClicked() instanceof Player)) return;
|
if (!(e.getWhoClicked() instanceof Player)) return;
|
||||||
|
|
||||||
Player player = (Player) e.getWhoClicked();
|
Player player = (Player) e.getWhoClicked();
|
||||||
|
|
||||||
|
if (modeManager.isReadOnlyViewedInventory(player, e.getView().getTopInventory())) {
|
||||||
|
e.setCancelled(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!adminModeCommand.isInAdminMode(player.getUniqueId())) return;
|
if (!adminModeCommand.isInAdminMode(player.getUniqueId())) return;
|
||||||
if (!configManager.isPreventContainerTransfer()) return;
|
if (!configManager.isPreventContainerTransfer()) return;
|
||||||
@@ -65,7 +77,7 @@ public class AdminModeListener implements Listener {
|
|||||||
if (e.getClickedInventory().getHolder() != null &&
|
if (e.getClickedInventory().getHolder() != null &&
|
||||||
!e.getClickedInventory().getHolder().equals(player)) {
|
!e.getClickedInventory().getHolder().equals(player)) {
|
||||||
e.setCancelled(true);
|
e.setCancelled(true);
|
||||||
player.sendMessage(ChatColor.RED + configManager.getMsgContainerTransferDenied());
|
player.sendMessage(configManager.getPrefixedMessage(configManager.getMsgContainerTransferDenied()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -74,7 +86,7 @@ public class AdminModeListener implements Listener {
|
|||||||
if (e.getView().getTopInventory().getHolder() != null &&
|
if (e.getView().getTopInventory().getHolder() != null &&
|
||||||
!e.getView().getTopInventory().getHolder().equals(player)) {
|
!e.getView().getTopInventory().getHolder().equals(player)) {
|
||||||
e.setCancelled(true);
|
e.setCancelled(true);
|
||||||
player.sendMessage(ChatColor.RED + configManager.getMsgContainerTransferDenied());
|
player.sendMessage(configManager.getPrefixedMessage(configManager.getMsgContainerTransferDenied()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -84,9 +96,25 @@ public class AdminModeListener implements Listener {
|
|||||||
Player player = e.getPlayer();
|
Player player = e.getPlayer();
|
||||||
|
|
||||||
if (!adminModeCommand.isInAdminMode(player.getUniqueId())) return;
|
if (!adminModeCommand.isInAdminMode(player.getUniqueId())) return;
|
||||||
|
|
||||||
|
if ((e.getAction() == Action.RIGHT_CLICK_AIR || e.getAction() == Action.RIGHT_CLICK_BLOCK)
|
||||||
|
&& e.getItem() != null
|
||||||
|
&& modeManager.isPanelItem(e.getItem())) {
|
||||||
|
e.setCancelled(true);
|
||||||
|
|
||||||
|
String panelType = modeManager.getPanelType(e.getItem());
|
||||||
|
if (ModeManager.PANEL_CP_INSPECTOR.equals(panelType)) {
|
||||||
|
adminModeCommand.toggleInspector(player);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dialogService.openCurrentPanel(player);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!configManager.isPreventItemUse()) return;
|
if (!configManager.isPreventItemUse()) return;
|
||||||
|
|
||||||
if (e.getAction() == org.bukkit.event.block.Action.RIGHT_CLICK_BLOCK) {
|
if (e.getAction() == Action.RIGHT_CLICK_BLOCK) {
|
||||||
if (e.getClickedBlock() != null) {
|
if (e.getClickedBlock() != null) {
|
||||||
Material blockType = e.getClickedBlock().getType();
|
Material blockType = e.getClickedBlock().getType();
|
||||||
|
|
||||||
@@ -102,7 +130,7 @@ public class AdminModeListener implements Listener {
|
|||||||
|
|
||||||
if (e.getItem() != null && e.getItem().getType() != Material.AIR) {
|
if (e.getItem() != null && e.getItem().getType() != Material.AIR) {
|
||||||
e.setCancelled(true);
|
e.setCancelled(true);
|
||||||
player.sendMessage(ChatColor.RED + configManager.getMsgItemUseDenied());
|
player.sendMessage(configManager.getPrefixedMessage(configManager.getMsgItemUseDenied()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,6 +152,6 @@ public class AdminModeListener implements Listener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
e.setCancelled(true);
|
e.setCancelled(true);
|
||||||
player.sendMessage(ChatColor.RED + configManager.getMsgBlockPlaceDenied());
|
player.sendMessage(configManager.getPrefixedMessage(configManager.getMsgBlockPlaceDenied()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
package org.blz.adminmode.listeners;
|
package org.blz.adminmode.listeners;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.blz.adminmode.commands.AdminModeCommand;
|
import org.blz.adminmode.commands.AdminModeCommand;
|
||||||
import org.blz.adminmode.config.ConfigManager;
|
import org.blz.adminmode.config.ConfigManager;
|
||||||
import org.bukkit.ChatColor;
|
import org.blz.adminmode.moderation.ModeratorProfile;
|
||||||
import org.bukkit.GameMode;
|
import org.bukkit.GameMode;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
@@ -11,8 +13,6 @@ import org.bukkit.event.Listener;
|
|||||||
import org.bukkit.event.player.PlayerGameModeChangeEvent;
|
import org.bukkit.event.player.PlayerGameModeChangeEvent;
|
||||||
import org.bukkit.event.player.PlayerToggleFlightEvent;
|
import org.bukkit.event.player.PlayerToggleFlightEvent;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class GameModeChangeListener implements Listener {
|
public class GameModeChangeListener implements Listener {
|
||||||
|
|
||||||
private final AdminModeCommand adminModeCommand;
|
private final AdminModeCommand adminModeCommand;
|
||||||
@@ -31,11 +31,16 @@ public class GameModeChangeListener implements Listener {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// КРИТИЧНО: Блокируем CREATIVE для всех в админ моде!
|
ModeratorProfile activeProfile = adminModeCommand.getActiveProfile(player.getUniqueId());
|
||||||
if (event.getNewGameMode() == GameMode.CREATIVE) {
|
boolean hardProfile = activeProfile != null && activeProfile.isHardProfile();
|
||||||
|
|
||||||
|
if (event.getNewGameMode() == GameMode.CREATIVE && !hardProfile) {
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
player.sendMessage(ChatColor.RED + "✖ В режиме модератора КРЕАТИВ запрещен!");
|
player.sendMessage(configManager.getPrefixedMessage("§c✖ В режиме Soft Moder креатив запрещен!"));
|
||||||
player.sendMessage(ChatColor.GRAY + "Доступные режимы: SURVIVAL, SPECTATOR");
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.getNewGameMode() == GameMode.CREATIVE && hardProfile) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,8 +51,8 @@ public class GameModeChangeListener implements Listener {
|
|||||||
|
|
||||||
if (!allowedModes.contains(newMode)) {
|
if (!allowedModes.contains(newMode)) {
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
player.sendMessage(ChatColor.RED + "✖ В админ моде можно переключаться только на разрешенные режимы!");
|
player.sendMessage(configManager.getPrefixedMessage("§c✖ В админ моде можно переключаться только на разрешенные режимы!"));
|
||||||
player.sendMessage(ChatColor.GRAY + "Разрешенные режимы: " + String.join(", ", allowedModes));
|
player.sendMessage(configManager.getPrefixedMessage("§7Разрешенные режимы: " + String.join(", ", allowedModes)));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package org.blz.adminmode.listeners;
|
||||||
|
|
||||||
|
import org.blz.adminmode.moderation.ModeManager;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.entity.PlayerDeathEvent;
|
||||||
|
|
||||||
|
public class PlayerDeathListener implements Listener {
|
||||||
|
|
||||||
|
private final ModeManager modeManager;
|
||||||
|
|
||||||
|
public PlayerDeathListener(ModeManager modeManager) {
|
||||||
|
this.modeManager = modeManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onPlayerDeath(PlayerDeathEvent event) {
|
||||||
|
modeManager.handleHardModeDeath(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package org.blz.adminmode.listeners;
|
||||||
|
|
||||||
|
import org.blz.adminmode.commands.AdminModeCommand;
|
||||||
|
import org.blz.adminmode.moderation.ModeManager;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.player.PlayerJoinEvent;
|
||||||
|
import org.bukkit.event.player.PlayerQuitEvent;
|
||||||
|
|
||||||
|
public class PlayerSessionListener implements Listener {
|
||||||
|
|
||||||
|
private final AdminModeCommand adminModeCommand;
|
||||||
|
private final ModeManager modeManager;
|
||||||
|
|
||||||
|
public PlayerSessionListener(AdminModeCommand adminModeCommand, ModeManager modeManager) {
|
||||||
|
this.adminModeCommand = adminModeCommand;
|
||||||
|
this.modeManager = modeManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onQuit(PlayerQuitEvent event) {
|
||||||
|
modeManager.markQuit(event.getPlayer());
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onJoin(PlayerJoinEvent event) {
|
||||||
|
Player player = event.getPlayer();
|
||||||
|
if (!modeManager.hasSession(player.getUniqueId())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
player.getServer().getScheduler().runTaskLater(
|
||||||
|
org.blz.adminmode.AdminMode.getInstance(),
|
||||||
|
() -> adminModeCommand.recoverSession(player),
|
||||||
|
1L);
|
||||||
|
}
|
||||||
|
}
|
||||||
410
src/main/java/org/blz/adminmode/moderation/ModeManager.java
Normal file
410
src/main/java/org/blz/adminmode/moderation/ModeManager.java
Normal file
@@ -0,0 +1,410 @@
|
|||||||
|
package org.blz.adminmode.moderation;
|
||||||
|
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
|
import org.blz.adminmode.config.ConfigManager;
|
||||||
|
import org.blz.adminmode.integrations.LuckPermsIntegration;
|
||||||
|
import org.blz.adminmode.session.SessionStorage;
|
||||||
|
import org.bukkit.GameMode;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.NamespacedKey;
|
||||||
|
import org.bukkit.attribute.Attribute;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.entity.PlayerDeathEvent;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.inventory.PlayerInventory;
|
||||||
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
|
import org.bukkit.persistence.PersistentDataContainer;
|
||||||
|
import org.bukkit.persistence.PersistentDataType;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
import org.bukkit.potion.PotionEffect;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class ModeManager {
|
||||||
|
|
||||||
|
public static final String PANEL_SOFT = "soft";
|
||||||
|
public static final String PANEL_HARD = "hard";
|
||||||
|
public static final String PANEL_CP_INSPECTOR = "cp_inspector";
|
||||||
|
|
||||||
|
private final Plugin plugin;
|
||||||
|
private final ConfigManager configManager;
|
||||||
|
private final LuckPermsIntegration luckPermsIntegration;
|
||||||
|
private final SessionStorage sessionStorage;
|
||||||
|
private final ModeSessionLogger sessionLogger;
|
||||||
|
private final NamespacedKey panelTypeKey;
|
||||||
|
private final Map<UUID, ModeSession> activeSessions = new HashMap<>();
|
||||||
|
|
||||||
|
public ModeManager(
|
||||||
|
Plugin plugin,
|
||||||
|
ConfigManager configManager,
|
||||||
|
LuckPermsIntegration luckPermsIntegration,
|
||||||
|
SessionStorage sessionStorage,
|
||||||
|
ModeSessionLogger sessionLogger) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.configManager = configManager;
|
||||||
|
this.luckPermsIntegration = luckPermsIntegration;
|
||||||
|
this.sessionStorage = sessionStorage;
|
||||||
|
this.sessionLogger = sessionLogger;
|
||||||
|
this.panelTypeKey = new NamespacedKey(plugin, "panel_type");
|
||||||
|
this.activeSessions.putAll(sessionStorage.loadSessions());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasSession(UUID playerId) {
|
||||||
|
return activeSessions.containsKey(playerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ModeSession getSession(UUID playerId) {
|
||||||
|
return activeSessions.get(playerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ModeSession getSession(Player player) {
|
||||||
|
return player == null ? null : getSession(player.getUniqueId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public ModeratorProfile getProfile(UUID playerId) {
|
||||||
|
ModeSession session = getSession(playerId);
|
||||||
|
return session == null ? null : session.getProfile();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ModeratorProfile> getAvailableProfiles(Player player) {
|
||||||
|
return ModeratorProfile.availableFor(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<ModeSession> getActiveSessions() {
|
||||||
|
return new ArrayList<>(activeSessions.values());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean enterMode(Player player, ModeratorProfile profile) {
|
||||||
|
if (player == null || profile == null || hasSession(player.getUniqueId())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
String previousGroup = luckPermsIntegration.resolveCurrentGroup(player);
|
||||||
|
String activeGroup = configManager.getActiveGroup(profile);
|
||||||
|
ModeSession session = ModeSession.capture(player, profile, previousGroup, activeGroup);
|
||||||
|
activeSessions.put(player.getUniqueId(), session);
|
||||||
|
persistSessions();
|
||||||
|
|
||||||
|
preparePlayerForModeration(player, profile);
|
||||||
|
luckPermsIntegration.enterMode(player, profile);
|
||||||
|
sessionLogger.logEnter(session);
|
||||||
|
|
||||||
|
String enterMessage = profile.isHardProfile() ? configManager.getMsgEnterHard() : configManager.getMsgEnterSoft();
|
||||||
|
player.sendMessage(configManager.getPrefixedMessage(enterMessage));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean exitMode(Player player) {
|
||||||
|
return finishSession(player, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean recoverSession(Player player) {
|
||||||
|
return finishSession(player, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void markQuit(Player player) {
|
||||||
|
if (player != null && hasSession(player.getUniqueId())) {
|
||||||
|
persistSessions();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean canUseHardActions(CommandSender sender) {
|
||||||
|
if (sender.hasPermission("adminmode.admin")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(sender instanceof Player player)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModeSession session = getSession(player);
|
||||||
|
return session != null && session.getProfile().isHardProfile();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean teleportToPlayer(Player moderator, Player target) {
|
||||||
|
if (moderator == null || target == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
moderator.teleport(target.getLocation());
|
||||||
|
moderator.sendMessage(configManager.getPrefixedMessage("§aТелепортация к §f" + target.getName() + "§a выполнена."));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean teleportPlayerHere(Player moderator, Player target) {
|
||||||
|
if (moderator == null || target == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
target.teleport(moderator.getLocation());
|
||||||
|
moderator.sendMessage(configManager.getPrefixedMessage("§aИгрок §f" + target.getName() + "§a телепортирован к вам."));
|
||||||
|
target.sendMessage(configManager.getPrefixedMessage("§eВас телепортировал модератор §f" + moderator.getName()));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean spectatePlayer(Player moderator, Player target) {
|
||||||
|
if (moderator == null || target == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (moderator.equals(target)) {
|
||||||
|
moderator.sendMessage(configManager.getPrefixedMessage("§cНельзя спектейтить самого себя."));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
moderator.setGameMode(GameMode.SPECTATOR);
|
||||||
|
moderator.setSpectatorTarget((Entity) target);
|
||||||
|
moderator.sendMessage(configManager.getPrefixedMessage("§bВы наблюдаете за §f" + target.getName()));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean openInvsee(Player moderator, Player target) {
|
||||||
|
if (moderator == null || target == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
moderator.openInventory(target.getInventory());
|
||||||
|
moderator.sendMessage(configManager.getPrefixedMessage("§7Открыт инвентарь игрока §f" + target.getName()));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void applyAdminSettings(Player player, float flySpeed, float walkSpeed, boolean invulnerable) {
|
||||||
|
if (!hasSession(player.getUniqueId())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
player.setAllowFlight(true);
|
||||||
|
player.setFlying(true);
|
||||||
|
player.setFlySpeed(clampSpeed(flySpeed, 0.1f));
|
||||||
|
player.setWalkSpeed(clampSpeed(walkSpeed, 0.1f));
|
||||||
|
player.setInvulnerable(invulnerable);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Player> listOtherOnlinePlayers(Player viewer) {
|
||||||
|
List<Player> players = new ArrayList<>(plugin.getServer().getOnlinePlayers());
|
||||||
|
players.removeIf(player -> viewer != null && player.getUniqueId().equals(viewer.getUniqueId()));
|
||||||
|
players.sort(Comparator.comparing(Player::getName, String.CASE_INSENSITIVE_ORDER));
|
||||||
|
return players;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Component> buildOnlineSummary(Player viewer) {
|
||||||
|
List<Component> lines = new ArrayList<>();
|
||||||
|
for (Player target : listOtherOnlinePlayers(viewer)) {
|
||||||
|
Location location = target.getLocation();
|
||||||
|
lines.add(Component.text(
|
||||||
|
target.getName() + " | " + target.getWorld().getName() + " | " +
|
||||||
|
location.getBlockX() + ", " + location.getBlockY() + ", " + location.getBlockZ(),
|
||||||
|
NamedTextColor.GRAY));
|
||||||
|
}
|
||||||
|
if (lines.isEmpty()) {
|
||||||
|
lines.add(Component.text("Нет других игроков онлайн.", NamedTextColor.DARK_GRAY));
|
||||||
|
}
|
||||||
|
return lines;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleHardModeDeath(PlayerDeathEvent event) {
|
||||||
|
Player player = event.getEntity();
|
||||||
|
ModeSession session = getSession(player);
|
||||||
|
if (session == null || !session.getProfile().isHardProfile()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
event.setKeepInventory(true);
|
||||||
|
event.setKeepLevel(true);
|
||||||
|
event.getDrops().clear();
|
||||||
|
Location restoreLocation = session.getLocation();
|
||||||
|
if (restoreLocation != null) {
|
||||||
|
plugin.getServer().getScheduler().runTask(plugin, () -> player.teleport(restoreLocation));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPanelItem(ItemStack itemStack) {
|
||||||
|
return getPanelType(itemStack) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPanelType(ItemStack itemStack) {
|
||||||
|
if (itemStack == null || itemStack.getType() == Material.AIR || !itemStack.hasItemMeta()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemMeta itemMeta = itemStack.getItemMeta();
|
||||||
|
PersistentDataContainer container = itemMeta.getPersistentDataContainer();
|
||||||
|
if (!container.has(panelTypeKey, PersistentDataType.STRING)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return container.get(panelTypeKey, PersistentDataType.STRING);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isReadOnlyViewedInventory(Player viewer, org.bukkit.inventory.Inventory inventory) {
|
||||||
|
if (viewer == null || inventory == null || inventory.getHolder() == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(inventory.getHolder() instanceof Player target)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hasSession(viewer.getUniqueId()) && !viewer.getUniqueId().equals(target.getUniqueId());
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean finishSession(Player player, boolean recovered) {
|
||||||
|
if (player == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModeSession session = activeSessions.remove(player.getUniqueId());
|
||||||
|
if (session == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
restorePlayerState(player, session);
|
||||||
|
luckPermsIntegration.exitMode(player, session);
|
||||||
|
persistSessions();
|
||||||
|
|
||||||
|
if (recovered) {
|
||||||
|
player.sendMessage(configManager.getPrefixedMessage(configManager.getMsgSessionRecovered()));
|
||||||
|
sessionLogger.logRecovered(session);
|
||||||
|
} else {
|
||||||
|
player.sendMessage(configManager.getPrefixedMessage(configManager.getMsgExitMode()));
|
||||||
|
sessionLogger.logExit(session);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void preparePlayerForModeration(Player player, ModeratorProfile profile) {
|
||||||
|
PlayerInventory inventory = player.getInventory();
|
||||||
|
inventory.clear();
|
||||||
|
inventory.setArmorContents(new ItemStack[4]);
|
||||||
|
inventory.setItemInOffHand(new ItemStack(Material.AIR));
|
||||||
|
|
||||||
|
player.closeInventory();
|
||||||
|
player.setSpectatorTarget(null);
|
||||||
|
for (PotionEffect effect : player.getActivePotionEffects()) {
|
||||||
|
player.removePotionEffect(effect.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
player.setFireTicks(0);
|
||||||
|
player.setHealth(resolveMaxHealth(player));
|
||||||
|
player.setFoodLevel(20);
|
||||||
|
player.setSaturation(20.0f);
|
||||||
|
player.setExhaustion(0.0f);
|
||||||
|
player.setExp(0.0f);
|
||||||
|
player.setLevel(0);
|
||||||
|
player.setTotalExperience(0);
|
||||||
|
player.setAllowFlight(true);
|
||||||
|
player.setFlying(true);
|
||||||
|
player.setFlySpeed(clampSpeed(configManager.getCustomFlySpeed(), 0.1f));
|
||||||
|
player.setWalkSpeed(clampSpeed(configManager.getCustomWalkSpeed(), 0.1f));
|
||||||
|
player.setInvulnerable(true);
|
||||||
|
player.setGameMode(profile.isHardProfile() ? GameMode.CREATIVE : GameMode.SPECTATOR);
|
||||||
|
|
||||||
|
inventory.setItem(0, createPanelItem(profile.isHardProfile() ? configManager.getHardPanelMaterial() : configManager.getSoftPanelMaterial(),
|
||||||
|
profile.isHardProfile() ? "Hard Panel" : "Soft Panel",
|
||||||
|
profile.isHardProfile() ? NamedTextColor.RED : NamedTextColor.AQUA,
|
||||||
|
profile.isHardProfile() ? PANEL_HARD : PANEL_SOFT));
|
||||||
|
|
||||||
|
if (profile.isHardProfile()) {
|
||||||
|
inventory.setItem(1, createPanelItem(
|
||||||
|
configManager.getCpInspectorMaterial(),
|
||||||
|
"CP Inspector",
|
||||||
|
NamedTextColor.YELLOW,
|
||||||
|
PANEL_CP_INSPECTOR));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (configManager.isGivePresetBlocks()) {
|
||||||
|
givePresetBlocks(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void restorePlayerState(Player player, ModeSession session) {
|
||||||
|
PlayerInventory inventory = player.getInventory();
|
||||||
|
inventory.clear();
|
||||||
|
inventory.setContents(session.getInventoryContents());
|
||||||
|
inventory.setArmorContents(session.getArmorContents());
|
||||||
|
inventory.setItemInOffHand(session.getOffHandItem());
|
||||||
|
|
||||||
|
player.setSpectatorTarget(null);
|
||||||
|
player.setInvulnerable(false);
|
||||||
|
player.setAllowFlight(false);
|
||||||
|
player.setFlying(false);
|
||||||
|
player.setFlySpeed(0.1f);
|
||||||
|
player.setWalkSpeed(0.2f);
|
||||||
|
|
||||||
|
if (player.getAttribute(Attribute.MAX_HEALTH) != null) {
|
||||||
|
player.getAttribute(Attribute.MAX_HEALTH).setBaseValue(session.getMaxHealth());
|
||||||
|
}
|
||||||
|
|
||||||
|
player.setGameMode(session.getGameMode());
|
||||||
|
if (session.getLocation() != null) {
|
||||||
|
player.teleport(session.getLocation());
|
||||||
|
}
|
||||||
|
|
||||||
|
player.setHealth(Math.min(resolveMaxHealth(player), session.getHealth()));
|
||||||
|
player.setFoodLevel(session.getFoodLevel());
|
||||||
|
player.setSaturation(session.getSaturation());
|
||||||
|
player.setExhaustion(session.getExhaustion());
|
||||||
|
player.setExp(session.getExp());
|
||||||
|
player.setLevel(session.getExpLevel());
|
||||||
|
player.setTotalExperience(session.getTotalExperience());
|
||||||
|
|
||||||
|
for (PotionEffect effect : player.getActivePotionEffects()) {
|
||||||
|
player.removePotionEffect(effect.getType());
|
||||||
|
}
|
||||||
|
for (PotionEffect effect : session.getPotionEffects()) {
|
||||||
|
player.addPotionEffect(effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
player.setFireTicks(session.getFireTicks());
|
||||||
|
player.setAllowFlight(session.isAllowFlight());
|
||||||
|
player.setFlying(session.isFlying());
|
||||||
|
player.setFlySpeed(clampSpeed(session.getFlySpeed(), 0.1f));
|
||||||
|
player.setWalkSpeed(clampSpeed(session.getWalkSpeed(), 0.1f));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void givePresetBlocks(Player player) {
|
||||||
|
for (String blockString : configManager.getPresetBlocks()) {
|
||||||
|
try {
|
||||||
|
String[] parts = blockString.split(":");
|
||||||
|
Material material = Material.valueOf(parts[0].trim().toUpperCase());
|
||||||
|
int amount = parts.length > 1 ? Integer.parseInt(parts[1].trim()) : 64;
|
||||||
|
player.getInventory().addItem(new ItemStack(material, Math.max(1, amount)));
|
||||||
|
} catch (Exception exception) {
|
||||||
|
plugin.getLogger().warning("Неверный блок в preset_blocks: " + blockString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ItemStack createPanelItem(Material material, String title, NamedTextColor color, String panelType) {
|
||||||
|
ItemStack itemStack = new ItemStack(material);
|
||||||
|
ItemMeta itemMeta = itemStack.getItemMeta();
|
||||||
|
itemMeta.displayName(Component.text("[" + title + "]", color));
|
||||||
|
itemMeta.getPersistentDataContainer().set(panelTypeKey, PersistentDataType.STRING, panelType);
|
||||||
|
itemStack.setItemMeta(itemMeta);
|
||||||
|
return itemStack;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void persistSessions() {
|
||||||
|
sessionStorage.saveSessions(activeSessions);
|
||||||
|
}
|
||||||
|
|
||||||
|
private double resolveMaxHealth(Player player) {
|
||||||
|
if (player.getAttribute(Attribute.MAX_HEALTH) != null) {
|
||||||
|
return player.getAttribute(Attribute.MAX_HEALTH).getValue();
|
||||||
|
}
|
||||||
|
return 20.0D;
|
||||||
|
}
|
||||||
|
|
||||||
|
private float clampSpeed(float value, float min) {
|
||||||
|
return Math.max(min, Math.min(1.0f, value));
|
||||||
|
}
|
||||||
|
}
|
||||||
253
src/main/java/org/blz/adminmode/moderation/ModeSession.java
Normal file
253
src/main/java/org/blz/adminmode/moderation/ModeSession.java
Normal file
@@ -0,0 +1,253 @@
|
|||||||
|
package org.blz.adminmode.moderation;
|
||||||
|
|
||||||
|
import org.bukkit.GameMode;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.attribute.Attribute;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.potion.PotionEffect;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public final class ModeSession {
|
||||||
|
|
||||||
|
private final UUID playerId;
|
||||||
|
private final String playerName;
|
||||||
|
private final ModeratorProfile profile;
|
||||||
|
private final long startTimestamp;
|
||||||
|
private final String previousGroup;
|
||||||
|
private final String activeGroup;
|
||||||
|
private final ItemStack[] inventoryContents;
|
||||||
|
private final ItemStack[] armorContents;
|
||||||
|
private final ItemStack offHandItem;
|
||||||
|
private final Location location;
|
||||||
|
private final GameMode gameMode;
|
||||||
|
private final double health;
|
||||||
|
private final double maxHealth;
|
||||||
|
private final int foodLevel;
|
||||||
|
private final float saturation;
|
||||||
|
private final float exhaustion;
|
||||||
|
private final int expLevel;
|
||||||
|
private final float exp;
|
||||||
|
private final int totalExperience;
|
||||||
|
private final Collection<PotionEffect> potionEffects;
|
||||||
|
private final boolean flying;
|
||||||
|
private final boolean allowFlight;
|
||||||
|
private final float flySpeed;
|
||||||
|
private final float walkSpeed;
|
||||||
|
private final int fireTicks;
|
||||||
|
|
||||||
|
public ModeSession(
|
||||||
|
UUID playerId,
|
||||||
|
String playerName,
|
||||||
|
ModeratorProfile profile,
|
||||||
|
long startTimestamp,
|
||||||
|
String previousGroup,
|
||||||
|
String activeGroup,
|
||||||
|
ItemStack[] inventoryContents,
|
||||||
|
ItemStack[] armorContents,
|
||||||
|
ItemStack offHandItem,
|
||||||
|
Location location,
|
||||||
|
GameMode gameMode,
|
||||||
|
double health,
|
||||||
|
double maxHealth,
|
||||||
|
int foodLevel,
|
||||||
|
float saturation,
|
||||||
|
float exhaustion,
|
||||||
|
int expLevel,
|
||||||
|
float exp,
|
||||||
|
int totalExperience,
|
||||||
|
Collection<PotionEffect> potionEffects,
|
||||||
|
boolean flying,
|
||||||
|
boolean allowFlight,
|
||||||
|
float flySpeed,
|
||||||
|
float walkSpeed,
|
||||||
|
int fireTicks) {
|
||||||
|
this.playerId = playerId;
|
||||||
|
this.playerName = playerName;
|
||||||
|
this.profile = profile;
|
||||||
|
this.startTimestamp = startTimestamp;
|
||||||
|
this.previousGroup = previousGroup;
|
||||||
|
this.activeGroup = activeGroup;
|
||||||
|
this.inventoryContents = cloneItems(inventoryContents);
|
||||||
|
this.armorContents = cloneItems(armorContents);
|
||||||
|
this.offHandItem = cloneItem(offHandItem);
|
||||||
|
this.location = location == null ? null : location.clone();
|
||||||
|
this.gameMode = gameMode;
|
||||||
|
this.health = health;
|
||||||
|
this.maxHealth = maxHealth;
|
||||||
|
this.foodLevel = foodLevel;
|
||||||
|
this.saturation = saturation;
|
||||||
|
this.exhaustion = exhaustion;
|
||||||
|
this.expLevel = expLevel;
|
||||||
|
this.exp = exp;
|
||||||
|
this.totalExperience = totalExperience;
|
||||||
|
this.potionEffects = potionEffects == null ? List.of() : new ArrayList<>(potionEffects);
|
||||||
|
this.flying = flying;
|
||||||
|
this.allowFlight = allowFlight;
|
||||||
|
this.flySpeed = flySpeed;
|
||||||
|
this.walkSpeed = walkSpeed;
|
||||||
|
this.fireTicks = fireTicks;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ModeSession capture(Player player, ModeratorProfile profile, String previousGroup, String activeGroup) {
|
||||||
|
double maxHealth = 20.0D;
|
||||||
|
if (player.getAttribute(Attribute.MAX_HEALTH) != null) {
|
||||||
|
maxHealth = player.getAttribute(Attribute.MAX_HEALTH).getBaseValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ModeSession(
|
||||||
|
player.getUniqueId(),
|
||||||
|
player.getName(),
|
||||||
|
profile,
|
||||||
|
System.currentTimeMillis(),
|
||||||
|
previousGroup,
|
||||||
|
activeGroup,
|
||||||
|
player.getInventory().getContents(),
|
||||||
|
player.getInventory().getArmorContents(),
|
||||||
|
player.getInventory().getItemInOffHand(),
|
||||||
|
player.getLocation(),
|
||||||
|
player.getGameMode(),
|
||||||
|
player.getHealth(),
|
||||||
|
maxHealth,
|
||||||
|
player.getFoodLevel(),
|
||||||
|
player.getSaturation(),
|
||||||
|
player.getExhaustion(),
|
||||||
|
player.getLevel(),
|
||||||
|
player.getExp(),
|
||||||
|
player.getTotalExperience(),
|
||||||
|
player.getActivePotionEffects(),
|
||||||
|
player.isFlying(),
|
||||||
|
player.getAllowFlight(),
|
||||||
|
player.getFlySpeed(),
|
||||||
|
player.getWalkSpeed(),
|
||||||
|
player.getFireTicks());
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUID getPlayerId() {
|
||||||
|
return playerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPlayerName() {
|
||||||
|
return playerName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ModeratorProfile getProfile() {
|
||||||
|
return profile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getStartTimestamp() {
|
||||||
|
return startTimestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPreviousGroup() {
|
||||||
|
return previousGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getActiveGroup() {
|
||||||
|
return activeGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemStack[] getInventoryContents() {
|
||||||
|
return cloneItems(inventoryContents);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemStack[] getArmorContents() {
|
||||||
|
return cloneItems(armorContents);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemStack getOffHandItem() {
|
||||||
|
return cloneItem(offHandItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Location getLocation() {
|
||||||
|
return location == null ? null : location.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
public GameMode getGameMode() {
|
||||||
|
return gameMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getHealth() {
|
||||||
|
return health;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getMaxHealth() {
|
||||||
|
return maxHealth;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFoodLevel() {
|
||||||
|
return foodLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getSaturation() {
|
||||||
|
return saturation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getExhaustion() {
|
||||||
|
return exhaustion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getExpLevel() {
|
||||||
|
return expLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getExp() {
|
||||||
|
return exp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTotalExperience() {
|
||||||
|
return totalExperience;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<PotionEffect> getPotionEffects() {
|
||||||
|
return new ArrayList<>(potionEffects);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isFlying() {
|
||||||
|
return flying;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAllowFlight() {
|
||||||
|
return allowFlight;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getFlySpeed() {
|
||||||
|
return flySpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getWalkSpeed() {
|
||||||
|
return walkSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFireTicks() {
|
||||||
|
return fireTicks;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getDurationMillis() {
|
||||||
|
return Math.max(0L, System.currentTimeMillis() - startTimestamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ItemStack[] cloneItems(ItemStack[] source) {
|
||||||
|
if (source == null) {
|
||||||
|
return new ItemStack[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemStack[] clone = new ItemStack[source.length];
|
||||||
|
for (int i = 0; i < source.length; i++) {
|
||||||
|
clone[i] = cloneItem(source[i]);
|
||||||
|
}
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ItemStack cloneItem(ItemStack item) {
|
||||||
|
if (item == null || item.getType() == Material.AIR) {
|
||||||
|
return new ItemStack(Material.AIR);
|
||||||
|
}
|
||||||
|
return item.clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
package org.blz.adminmode.moderation;
|
||||||
|
|
||||||
|
import org.blz.adminmode.config.ConfigManager;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileWriter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
|
||||||
|
public class ModeSessionLogger {
|
||||||
|
|
||||||
|
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||||
|
private final Plugin plugin;
|
||||||
|
private final ConfigManager configManager;
|
||||||
|
|
||||||
|
public ModeSessionLogger(Plugin plugin, ConfigManager configManager) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.configManager = configManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void logEnter(ModeSession session) {
|
||||||
|
writeLine("ENTER_" + modeSuffix(session), session, "-");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void logExit(ModeSession session) {
|
||||||
|
writeLine("EXIT_" + modeSuffix(session), session, formatDuration(session.getDurationMillis()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void logRecovered(ModeSession session) {
|
||||||
|
writeLine("RECOVER_" + modeSuffix(session), session, formatDuration(session.getDurationMillis()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeLine(String action, ModeSession session, String duration) {
|
||||||
|
if (!configManager.isSessionLoggingEnabled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
File logFile = new File(plugin.getDataFolder(), configManager.getSessionLogFile());
|
||||||
|
File parent = logFile.getParentFile();
|
||||||
|
if (parent != null && !parent.exists()) {
|
||||||
|
parent.mkdirs();
|
||||||
|
}
|
||||||
|
|
||||||
|
String line = String.format(
|
||||||
|
"[%s] %s | Player: %s | UUID: %s | Duration: %s%n",
|
||||||
|
LocalDateTime.now().format(DATE_TIME_FORMATTER),
|
||||||
|
action,
|
||||||
|
session.getPlayerName(),
|
||||||
|
session.getPlayerId(),
|
||||||
|
duration);
|
||||||
|
|
||||||
|
try (FileWriter writer = new FileWriter(logFile, true)) {
|
||||||
|
writer.write(line);
|
||||||
|
} catch (IOException exception) {
|
||||||
|
plugin.getLogger().warning("Не удалось записать сессионный лог: " + exception.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String modeSuffix(ModeSession session) {
|
||||||
|
return session.getProfile().isHardProfile() ? "HARD" : "SOFT";
|
||||||
|
}
|
||||||
|
|
||||||
|
private String formatDuration(long millis) {
|
||||||
|
Duration duration = Duration.ofMillis(Math.max(0L, millis));
|
||||||
|
long hours = duration.toHours();
|
||||||
|
long minutes = duration.toMinutesPart();
|
||||||
|
long seconds = duration.toSecondsPart();
|
||||||
|
|
||||||
|
if (hours > 0) {
|
||||||
|
return hours + "h " + minutes + "m " + seconds + "s";
|
||||||
|
}
|
||||||
|
if (minutes > 0) {
|
||||||
|
return minutes + "m " + seconds + "s";
|
||||||
|
}
|
||||||
|
return seconds + "s";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package org.blz.adminmode.moderation;
|
||||||
|
|
||||||
|
public enum PlayerListAction {
|
||||||
|
SPECTATE,
|
||||||
|
TELEPORT,
|
||||||
|
INVSEE
|
||||||
|
}
|
||||||
335
src/main/java/org/blz/adminmode/session/SessionStorage.java
Normal file
335
src/main/java/org/blz/adminmode/session/SessionStorage.java
Normal file
@@ -0,0 +1,335 @@
|
|||||||
|
package org.blz.adminmode.session;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
import com.google.gson.JsonArray;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonParser;
|
||||||
|
import org.blz.adminmode.moderation.ModeSession;
|
||||||
|
import org.blz.adminmode.moderation.ModeratorProfile;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.GameMode;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
import org.bukkit.potion.PotionEffect;
|
||||||
|
import org.bukkit.potion.PotionEffectType;
|
||||||
|
import org.bukkit.util.io.BukkitObjectInputStream;
|
||||||
|
import org.bukkit.util.io.BukkitObjectOutputStream;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.io.FileWriter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Base64;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class SessionStorage {
|
||||||
|
|
||||||
|
private final Plugin plugin;
|
||||||
|
private final File storageFile;
|
||||||
|
private final Gson gson;
|
||||||
|
|
||||||
|
public SessionStorage(Plugin plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.storageFile = new File(plugin.getDataFolder(), "sessions.json");
|
||||||
|
this.gson = new GsonBuilder().setPrettyPrinting().create();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<UUID, ModeSession> loadSessions() {
|
||||||
|
Map<UUID, ModeSession> sessions = new LinkedHashMap<>();
|
||||||
|
if (!storageFile.exists()) {
|
||||||
|
return sessions;
|
||||||
|
}
|
||||||
|
|
||||||
|
try (FileReader reader = new FileReader(storageFile)) {
|
||||||
|
JsonElement root = JsonParser.parseReader(reader);
|
||||||
|
if (!root.isJsonArray()) {
|
||||||
|
return sessions;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (JsonElement element : root.getAsJsonArray()) {
|
||||||
|
if (!element.isJsonObject()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModeSession session = deserializeSession(element.getAsJsonObject());
|
||||||
|
if (session != null) {
|
||||||
|
sessions.put(session.getPlayerId(), session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception exception) {
|
||||||
|
plugin.getLogger().warning("Не удалось загрузить sessions.json: " + exception.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return sessions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void saveSessions(Map<UUID, ModeSession> sessions) {
|
||||||
|
File parent = storageFile.getParentFile();
|
||||||
|
if (parent != null && !parent.exists()) {
|
||||||
|
parent.mkdirs();
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonArray array = new JsonArray();
|
||||||
|
for (ModeSession session : sessions.values()) {
|
||||||
|
array.add(serializeSession(session));
|
||||||
|
}
|
||||||
|
|
||||||
|
try (FileWriter writer = new FileWriter(storageFile)) {
|
||||||
|
writer.write(gson.toJson(array));
|
||||||
|
} catch (IOException exception) {
|
||||||
|
plugin.getLogger().warning("Не удалось сохранить sessions.json: " + exception.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private JsonObject serializeSession(ModeSession session) {
|
||||||
|
JsonObject json = new JsonObject();
|
||||||
|
json.addProperty("playerId", session.getPlayerId().toString());
|
||||||
|
json.addProperty("playerName", session.getPlayerName());
|
||||||
|
json.addProperty("profile", session.getProfile().getConfigKey());
|
||||||
|
json.addProperty("startTimestamp", session.getStartTimestamp());
|
||||||
|
json.addProperty("previousGroup", session.getPreviousGroup());
|
||||||
|
json.addProperty("activeGroup", session.getActiveGroup());
|
||||||
|
json.addProperty("inventory", serializeItemArray(session.getInventoryContents()));
|
||||||
|
json.addProperty("armorContents", serializeItemArray(session.getArmorContents()));
|
||||||
|
json.addProperty("offHand", serializeItem(session.getOffHandItem()));
|
||||||
|
json.add("location", serializeLocation(session.getLocation()));
|
||||||
|
json.addProperty("gameMode", session.getGameMode().name());
|
||||||
|
json.addProperty("health", session.getHealth());
|
||||||
|
json.addProperty("maxHealth", session.getMaxHealth());
|
||||||
|
json.addProperty("foodLevel", session.getFoodLevel());
|
||||||
|
json.addProperty("saturation", session.getSaturation());
|
||||||
|
json.addProperty("exhaustion", session.getExhaustion());
|
||||||
|
json.addProperty("expLevel", session.getExpLevel());
|
||||||
|
json.addProperty("exp", session.getExp());
|
||||||
|
json.addProperty("totalExperience", session.getTotalExperience());
|
||||||
|
json.addProperty("potionEffects", serializePotionEffects(session.getPotionEffects()));
|
||||||
|
json.addProperty("flying", session.isFlying());
|
||||||
|
json.addProperty("allowFlight", session.isAllowFlight());
|
||||||
|
json.addProperty("flySpeed", session.getFlySpeed());
|
||||||
|
json.addProperty("walkSpeed", session.getWalkSpeed());
|
||||||
|
json.addProperty("fireTicks", session.getFireTicks());
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ModeSession deserializeSession(JsonObject json) {
|
||||||
|
try {
|
||||||
|
UUID playerId = UUID.fromString(json.get("playerId").getAsString());
|
||||||
|
String playerName = json.get("playerName").getAsString();
|
||||||
|
ModeratorProfile profile = ModeratorProfile.fromConfigKey(json.get("profile").getAsString())
|
||||||
|
.orElse(ModeratorProfile.SOFT_MODER);
|
||||||
|
long startTimestamp = json.get("startTimestamp").getAsLong();
|
||||||
|
String previousGroup = getString(json, "previousGroup");
|
||||||
|
String activeGroup = getString(json, "activeGroup");
|
||||||
|
ItemStack[] inventory = deserializeItemArray(getString(json, "inventory"));
|
||||||
|
ItemStack[] armorContents = deserializeItemArray(getString(json, "armorContents"));
|
||||||
|
ItemStack offHand = deserializeItem(getString(json, "offHand"));
|
||||||
|
Location location = deserializeLocation(json.getAsJsonObject("location"));
|
||||||
|
GameMode gameMode = GameMode.valueOf(json.get("gameMode").getAsString());
|
||||||
|
double health = json.get("health").getAsDouble();
|
||||||
|
double maxHealth = json.get("maxHealth").getAsDouble();
|
||||||
|
int foodLevel = json.get("foodLevel").getAsInt();
|
||||||
|
float saturation = json.get("saturation").getAsFloat();
|
||||||
|
float exhaustion = json.get("exhaustion").getAsFloat();
|
||||||
|
int expLevel = json.get("expLevel").getAsInt();
|
||||||
|
float exp = json.get("exp").getAsFloat();
|
||||||
|
int totalExperience = json.get("totalExperience").getAsInt();
|
||||||
|
Collection<PotionEffect> potionEffects = deserializePotionEffects(getString(json, "potionEffects"));
|
||||||
|
boolean flying = json.get("flying").getAsBoolean();
|
||||||
|
boolean allowFlight = json.get("allowFlight").getAsBoolean();
|
||||||
|
float flySpeed = json.get("flySpeed").getAsFloat();
|
||||||
|
float walkSpeed = json.get("walkSpeed").getAsFloat();
|
||||||
|
int fireTicks = json.get("fireTicks").getAsInt();
|
||||||
|
|
||||||
|
return new ModeSession(
|
||||||
|
playerId,
|
||||||
|
playerName,
|
||||||
|
profile,
|
||||||
|
startTimestamp,
|
||||||
|
previousGroup,
|
||||||
|
activeGroup,
|
||||||
|
inventory,
|
||||||
|
armorContents,
|
||||||
|
offHand,
|
||||||
|
location,
|
||||||
|
gameMode,
|
||||||
|
health,
|
||||||
|
maxHealth,
|
||||||
|
foodLevel,
|
||||||
|
saturation,
|
||||||
|
exhaustion,
|
||||||
|
expLevel,
|
||||||
|
exp,
|
||||||
|
totalExperience,
|
||||||
|
potionEffects,
|
||||||
|
flying,
|
||||||
|
allowFlight,
|
||||||
|
flySpeed,
|
||||||
|
walkSpeed,
|
||||||
|
fireTicks);
|
||||||
|
} catch (Exception exception) {
|
||||||
|
plugin.getLogger().warning("Не удалось десериализовать session entry: " + exception.getMessage());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private JsonObject serializeLocation(Location location) {
|
||||||
|
JsonObject json = new JsonObject();
|
||||||
|
if (location == null || location.getWorld() == null) {
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
json.addProperty("world", location.getWorld().getName());
|
||||||
|
json.addProperty("x", location.getX());
|
||||||
|
json.addProperty("y", location.getY());
|
||||||
|
json.addProperty("z", location.getZ());
|
||||||
|
json.addProperty("yaw", location.getYaw());
|
||||||
|
json.addProperty("pitch", location.getPitch());
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Location deserializeLocation(JsonObject json) {
|
||||||
|
if (json == null || !json.has("world")) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
World world = Bukkit.getWorld(json.get("world").getAsString());
|
||||||
|
if (world == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Location(
|
||||||
|
world,
|
||||||
|
json.get("x").getAsDouble(),
|
||||||
|
json.get("y").getAsDouble(),
|
||||||
|
json.get("z").getAsDouble(),
|
||||||
|
json.get("yaw").getAsFloat(),
|
||||||
|
json.get("pitch").getAsFloat());
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getString(JsonObject json, String key) {
|
||||||
|
return json.has(key) && !json.get(key).isJsonNull() ? json.get(key).getAsString() : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
private String serializeItemArray(ItemStack[] items) {
|
||||||
|
try {
|
||||||
|
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||||
|
try (BukkitObjectOutputStream dataOutput = new BukkitObjectOutputStream(outputStream)) {
|
||||||
|
dataOutput.writeInt(items.length);
|
||||||
|
for (ItemStack item : items) {
|
||||||
|
dataOutput.writeObject(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Base64.getEncoder().encodeToString(outputStream.toByteArray());
|
||||||
|
} catch (Exception exception) {
|
||||||
|
plugin.getLogger().warning("Не удалось сериализовать item array: " + exception.getMessage());
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ItemStack[] deserializeItemArray(String data) {
|
||||||
|
if (data == null || data.isEmpty()) {
|
||||||
|
return new ItemStack[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
ByteArrayInputStream inputStream = new ByteArrayInputStream(Base64.getDecoder().decode(data));
|
||||||
|
try (BukkitObjectInputStream dataInput = new BukkitObjectInputStream(inputStream)) {
|
||||||
|
int length = dataInput.readInt();
|
||||||
|
ItemStack[] items = new ItemStack[length];
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
items[i] = (ItemStack) dataInput.readObject();
|
||||||
|
}
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
} catch (Exception exception) {
|
||||||
|
plugin.getLogger().warning("Не удалось десериализовать item array: " + exception.getMessage());
|
||||||
|
return new ItemStack[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String serializeItem(ItemStack item) {
|
||||||
|
try {
|
||||||
|
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||||
|
try (BukkitObjectOutputStream dataOutput = new BukkitObjectOutputStream(outputStream)) {
|
||||||
|
dataOutput.writeObject(item);
|
||||||
|
}
|
||||||
|
return Base64.getEncoder().encodeToString(outputStream.toByteArray());
|
||||||
|
} catch (Exception exception) {
|
||||||
|
plugin.getLogger().warning("Не удалось сериализовать item: " + exception.getMessage());
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ItemStack deserializeItem(String data) {
|
||||||
|
if (data == null || data.isEmpty()) {
|
||||||
|
return new ItemStack(Material.AIR);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
ByteArrayInputStream inputStream = new ByteArrayInputStream(Base64.getDecoder().decode(data));
|
||||||
|
try (BukkitObjectInputStream dataInput = new BukkitObjectInputStream(inputStream)) {
|
||||||
|
return (ItemStack) dataInput.readObject();
|
||||||
|
}
|
||||||
|
} catch (Exception exception) {
|
||||||
|
plugin.getLogger().warning("Не удалось десериализовать item: " + exception.getMessage());
|
||||||
|
return new ItemStack(Material.AIR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String serializePotionEffects(Collection<PotionEffect> effects) {
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
for (PotionEffect effect : effects) {
|
||||||
|
builder.append(effect.getType().getName()).append(':')
|
||||||
|
.append(effect.getDuration()).append(':')
|
||||||
|
.append(effect.getAmplifier()).append(':')
|
||||||
|
.append(effect.isAmbient()).append(':')
|
||||||
|
.append(effect.hasParticles()).append(':')
|
||||||
|
.append(effect.hasIcon()).append(';');
|
||||||
|
}
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Collection<PotionEffect> deserializePotionEffects(String data) {
|
||||||
|
List<PotionEffect> effects = new ArrayList<>();
|
||||||
|
if (data == null || data.isEmpty()) {
|
||||||
|
return effects;
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] effectStrings = data.split(";");
|
||||||
|
for (String effectString : effectStrings) {
|
||||||
|
if (effectString.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
String[] parts = effectString.split(":");
|
||||||
|
PotionEffectType type = PotionEffectType.getByName(parts[0]);
|
||||||
|
if (type == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
effects.add(new PotionEffect(
|
||||||
|
type,
|
||||||
|
Integer.parseInt(parts[1]),
|
||||||
|
Integer.parseInt(parts[2]),
|
||||||
|
Boolean.parseBoolean(parts[3]),
|
||||||
|
Boolean.parseBoolean(parts[4]),
|
||||||
|
Boolean.parseBoolean(parts[5])));
|
||||||
|
} catch (Exception exception) {
|
||||||
|
plugin.getLogger().warning("Не удалось десериализовать potion effect: " + effectString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return effects;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,12 +13,12 @@ admin_mode:
|
|||||||
# Группы которые выдаются при активации режима
|
# Группы которые выдаются при активации режима
|
||||||
# Можно указать несколько групп через запятую
|
# Можно указать несколько групп через запятую
|
||||||
groups:
|
groups:
|
||||||
- "soft_moder"
|
- "soft_moder_adm"
|
||||||
profile_groups:
|
profile_groups:
|
||||||
soft_moder:
|
soft_moder:
|
||||||
- "soft_moder"
|
- "soft_moder_adm"
|
||||||
hard_moder:
|
hard_moder:
|
||||||
- "hard_moder"
|
- "hard_moder_adm"
|
||||||
|
|
||||||
# Удалять ли группы при деактивации (если false - группы останутся)
|
# Удалять ли группы при деактивации (если false - группы останутся)
|
||||||
remove_on_disable: true
|
remove_on_disable: true
|
||||||
@@ -122,3 +122,30 @@ admin_mode:
|
|||||||
item_use_denied: "✖ В режиме администратора нельзя использовать предметы!"
|
item_use_denied: "✖ В режиме администратора нельзя использовать предметы!"
|
||||||
block_place_denied: "✖ Вы можете ставить только разрешенные блоки!"
|
block_place_denied: "✖ Вы можете ставить только разрешенные блоки!"
|
||||||
reloaded: "✓ Конфигурация AdminMode перезагружена!"
|
reloaded: "✓ Конфигурация AdminMode перезагружена!"
|
||||||
|
|
||||||
|
groups:
|
||||||
|
base: "moder"
|
||||||
|
soft: "soft_moder_adm"
|
||||||
|
hard: "hard_moder_adm"
|
||||||
|
|
||||||
|
items:
|
||||||
|
soft_panel_material: COMPASS
|
||||||
|
hard_panel_material: NETHER_STAR
|
||||||
|
cp_inspector_material: STICK
|
||||||
|
|
||||||
|
coreprotect:
|
||||||
|
enabled: true
|
||||||
|
default_radius: 10
|
||||||
|
default_time: "24h"
|
||||||
|
|
||||||
|
messages:
|
||||||
|
prefix: "§8[§bAdminMode§8] "
|
||||||
|
enter_soft: "§aВошёл в режим §bSOFT MODER"
|
||||||
|
enter_hard: "§aВошёл в режим §cHARD MODER"
|
||||||
|
exit: "§7Режим деактивирован. Состояние восстановлено."
|
||||||
|
cp_unavailable: "§cCoreProtect не найден. Hard режим работает без CP."
|
||||||
|
session_recovered: "§eВаша активная сессия модерации была восстановлена и корректно завершена."
|
||||||
|
|
||||||
|
logging:
|
||||||
|
enabled: true
|
||||||
|
log_file: "logs/sessions.log"
|
||||||
|
|||||||
@@ -4,7 +4,8 @@ main: org.blz.adminmode.AdminMode
|
|||||||
api-version: '1.21'
|
api-version: '1.21'
|
||||||
author: BelzeBool, Kilka_v_HJIebe
|
author: BelzeBool, Kilka_v_HJIebe
|
||||||
description: Плагин режима администратора с сохранением состояния игрока
|
description: Плагин режима администратора с сохранением состояния игрока
|
||||||
softdepend: [LuckPerms]
|
depend: [LuckPerms]
|
||||||
|
softdepend: [CoreProtect]
|
||||||
|
|
||||||
commands:
|
commands:
|
||||||
adminmode:
|
adminmode:
|
||||||
|
|||||||
Reference in New Issue
Block a user