Backup before major refactor of AdminMode based on user feedback

This commit is contained in:
2026-03-26 22:38:29 +07:00
parent b439a42134
commit ef128cc08d
25 changed files with 2130 additions and 582 deletions

View File

@@ -1,47 +1,36 @@
package org.blz.adminmode.commands;
import net.luckperms.api.LuckPerms;
import net.luckperms.api.LuckPermsProvider;
import net.luckperms.api.model.user.User;
import net.luckperms.api.node.Node;
import java.util.List;
import java.util.UUID;
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.ChatColor;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
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 java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import net.kyori.adventure.text.Component;
public class AdminModeCommand implements CommandExecutor {
private final Plugin plugin;
private final ConfigManager configManager;
private final Map<UUID, PlayerState> savedStates = new HashMap<>();
private final Map<UUID, ModeratorProfile> activeProfiles = new HashMap<>();
private final AdminModeDataManager dataManager;
private final ModeManager modeManager;
private final CoreProtectIntegration coreProtectIntegration;
private AdminDialogService dialogService;
public AdminModeCommand(Plugin plugin, ConfigManager configManager) {
this.plugin = plugin;
public AdminModeCommand(
ConfigManager configManager,
ModeManager modeManager,
CoreProtectIntegration coreProtectIntegration) {
this.configManager = configManager;
this.dataManager = new AdminModeDataManager(plugin);
loadAllStates();
this.modeManager = modeManager;
this.coreProtectIntegration = coreProtectIntegration;
}
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) {
if (args.length > 0 && args[0].equalsIgnoreCase("reload")) {
if (!sender.hasPermission("adminmode.reload")) {
sender.sendMessage(ChatColor.RED + configManager.getMsgNoPermission());
sender.sendMessage(configManager.getPrefixedMessage(configManager.getMsgNoPermission()));
return true;
}
configManager.loadConfig();
sender.sendMessage(ChatColor.GREEN + configManager.getMsgReloaded());
sender.sendMessage(configManager.getPrefixedMessage(configManager.getMsgReloaded()));
return true;
}
// Команда disable <игрок> - принудительно отключить способности
if (args.length > 0 && args[0].equalsIgnoreCase("disable")) {
if (!canUseHardActions(sender)) {
sender.sendMessage(ChatColor.RED + configManager.getMsgNoPermission());
sender.sendMessage(configManager.getPrefixedMessage(configManager.getMsgNoPermission()));
return true;
}
if (args.length < 2) {
sender.sendMessage(ChatColor.RED + "Использование: /adminmode disable <игрок>");
sender.sendMessage(configManager.getPrefixedMessage("§cИспользование: /adminmode disable <игрок>"));
return true;
}
@@ -76,132 +64,121 @@ public class AdminModeCommand implements CommandExecutor {
return true;
}
if (!(sender instanceof Player)) {
sender.sendMessage(ChatColor.RED + "Эта команда доступна только игрокам!");
if (!(sender instanceof Player player)) {
sender.sendMessage("Эта команда доступна только игрокам!");
return true;
}
Player player = (Player) sender;
if (!configManager.isEnabled()) {
player.sendMessage(ChatColor.RED + "Режим администратора отключен!");
player.sendMessage(configManager.getPrefixedMessage("§cРежим администратора отключен!"));
return true;
}
if (args.length > 0 && args[0].equalsIgnoreCase("dialog")) {
if (!openRelevantDialog(player)) {
player.sendMessage(ChatColor.YELLOW + "Dialog-панель недоступна. Используйте /adminmode enable <soft|hard>.");
player.sendMessage(configManager.getPrefixedMessage("§eDialog-панель сейчас недоступна."));
}
return true;
}
if (args.length > 0 && (args[0].equalsIgnoreCase("enable") || args[0].equalsIgnoreCase("profile"))) {
if (args.length < 2) {
if (!openRelevantDialog(player)) {
player.sendMessage(ChatColor.YELLOW + "Использование: /adminmode enable <soft|hard>");
}
openRelevantDialog(player);
return true;
}
ModeratorProfile profile = ModeratorProfile.fromInput(args[1]).orElse(null);
if (profile == null) {
player.sendMessage(ChatColor.RED + "Неизвестный профиль. Доступно: soft, hard.");
player.sendMessage(configManager.getPrefixedMessage("§cНеизвестный профиль. Доступно: soft, hard."));
return true;
}
toggleAdminMode(player, profile);
activateProfile(player, profile);
return true;
}
if (!isInAdminMode(player.getUniqueId()) && getAvailableProfiles(player).isEmpty()) {
player.sendMessage(ChatColor.RED + configManager.getMsgNoPermission());
player.sendMessage(configManager.getPrefixedMessage(configManager.getMsgNoPermission()));
return true;
}
toggleAdminMode(player);
openRelevantDialog(player);
return true;
}
public void toggleAdminMode(Player player) {
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) {
public boolean activateProfile(Player player, ModeratorProfile profile) {
if (profile == null) {
toggleAdminMode(player);
return;
}
if (isInAdminMode(player.getUniqueId())) {
ModeratorProfile activeProfile = getActiveProfile(player.getUniqueId());
if (activeProfile == profile) {
disableAdminMode(player);
} else {
player.sendMessage(ChatColor.YELLOW + "Сначала выключите текущий режим модерации, затем включите новый профиль.");
}
return;
return openRelevantDialog(player);
}
if (!profile.isAvailableFor(player)) {
player.sendMessage(ChatColor.RED + 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)) {
player.sendMessage(configManager.getPrefixedMessage(configManager.getMsgNoPermission()));
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) {
return false;
}
moderator.teleport(target.getLocation());
moderator.sendMessage(ChatColor.GREEN + "✓ Вы телепортированы к игроку " + target.getName());
return true;
return switch (action) {
case SPECTATE -> modeManager.spectatePlayer(moderator, target);
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) {
@@ -210,19 +187,12 @@ public class AdminModeCommand implements CommandExecutor {
}
Player target = resolveOnlinePlayer(targetName, moderator);
if (target == null) {
return false;
}
target.teleport(moderator.getLocation());
moderator.sendMessage(ChatColor.GREEN + "✓ Игрок " + target.getName() + " телепортирован к вам.");
target.sendMessage(ChatColor.YELLOW + "Вас телепортировал модератор " + moderator.getName());
return true;
return target != null && modeManager.teleportPlayerHere(moderator, target);
}
public boolean forceDisableTarget(CommandSender sender, String targetName) {
if (!canUseHardActions(sender)) {
sender.sendMessage(ChatColor.RED + configManager.getMsgNoPermission());
sender.sendMessage(configManager.getPrefixedMessage(configManager.getMsgNoPermission()));
return false;
}
@@ -232,296 +202,81 @@ public class AdminModeCommand implements CommandExecutor {
}
forceDisableAbilities(target);
sender.sendMessage(ChatColor.GREEN + "Все способности отключены для игрока " + target.getName());
target.sendMessage(ChatColor.YELLOW + "Ваши способности были сброшены модератором");
sender.sendMessage(configManager.getPrefixedMessage("§aРежим и способности игрока §f" + target.getName() + "§a сброшены."));
target.sendMessage(configManager.getPrefixedMessage("§eВаш режим модерации был принудительно отключен."));
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) {
if (dialogService == null || !configManager.isDialogsEnabled()) {
return false;
}
if (isInAdminMode(player.getUniqueId())) {
return dialogService.openModerationPanel(player);
if (modeManager.hasSession(player.getUniqueId())) {
return dialogService.openCurrentPanel(player);
}
return dialogService.openProfileSelectionDialog(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;
return dialogService.openModeSelectDialog(player);
}
private boolean validateHardActionPlayer(Player moderator) {
if (!canUseHardActions(moderator)) {
moderator.sendMessage(ChatColor.RED + "Для этого действия нужен активный профиль Hard Moder.");
moderator.sendMessage(configManager.getPrefixedMessage("§cДля этого действия нужен активный профиль Hard Moder."));
return false;
}
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) {
if (targetName == null || targetName.isBlank()) {
sender.sendMessage(ChatColor.RED + "Укажите ник игрока.");
sender.sendMessage(configManager.getPrefixedMessage("§cУкажите ник игрока."));
return null;
}
@@ -531,102 +286,10 @@ public class AdminModeCommand implements CommandExecutor {
}
if (target == null) {
sender.sendMessage(ChatColor.RED + "Игрок не найден!");
sender.sendMessage(configManager.getPrefixedMessage("§cИгрок не найден!"));
return null;
}
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;
}
}