From cf6e6dd65545008c8444c204b2355b2bed12add6 Mon Sep 17 00:00:00 2001 From: Kam Date: Wed, 19 Feb 2025 18:15:05 -0500 Subject: [PATCH] Implement Profile Regions --- .../command/profile/CommandHelpProfile.java | 124 ++++++----- .../npcs/command/profile/CommandProfile.java | 1 + .../command/profile/CommandProfileAdmin.java | 108 ++++----- .../command/profile/CommandProfileChange.java | 30 +-- .../command/profile/CommandProfileCreate.java | 33 +-- .../command/profile/CommandProfileRegion.java | 160 ++++++++++++++ .../command/profile/CommandProfileRemove.java | 24 +- .../npcs/controllers/ProfileController.java | 207 ++++++++++-------- .../npcs/controllers/data/CNPCData.java | 9 +- .../data/EnumProfileOperation.java | 7 + .../npcs/controllers/data/IProfileData.java | 2 +- .../controllers/data/ProfileOperation.java | 38 +++- .../noppes/npcs/CustomNpcsPermissions.java | 1 + .../java/noppes/npcs/config/ConfigMain.java | 25 +++ 14 files changed, 486 insertions(+), 283 deletions(-) create mode 100644 src/main/java/kamkeel/npcs/command/profile/CommandProfileRegion.java create mode 100644 src/main/java/kamkeel/npcs/controllers/data/EnumProfileOperation.java diff --git a/src/main/java/kamkeel/npcs/command/profile/CommandHelpProfile.java b/src/main/java/kamkeel/npcs/command/profile/CommandHelpProfile.java index effecd494..987f4a1b2 100644 --- a/src/main/java/kamkeel/npcs/command/profile/CommandHelpProfile.java +++ b/src/main/java/kamkeel/npcs/command/profile/CommandHelpProfile.java @@ -2,72 +2,90 @@ package kamkeel.npcs.command.profile; import net.minecraft.command.CommandException; import net.minecraft.command.ICommandSender; +import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.ChatComponentTranslation; - import java.lang.reflect.Method; import java.util.Map.Entry; - import static kamkeel.npcs.util.ColorUtil.sendError; import static kamkeel.npcs.util.ColorUtil.sendMessage; +import noppes.npcs.CustomNpcsPermissions; public class CommandHelpProfile extends CommandProfileBase { - private CommandProfile parent; + private CommandProfile parent; - public CommandHelpProfile(CommandProfile parent){ - this.parent = parent; - } + public CommandHelpProfile(CommandProfile parent){ + this.parent = parent; + } - @Override - public String getCommandName() { - return "help"; - } + @Override + public String getCommandName() { + return "help"; + } - @Override - public String getDescription() { - return "help [command]"; - } + @Override + public String getDescription() { + return "help [command]"; + } - - @Override - public void processCommand(ICommandSender sender, String[] args) throws CommandException { - if(args.length == 0){ - sendMessage(sender, "\u00A78------ \u00A7aProfile Commands \u00A78------"); - for(Entry entry : parent.map.entrySet()){ - sendMessage(sender, "\u00A77> " + "\u00A7e" + entry.getKey() + "\u00A78: \u00A77" + entry.getValue().getCommandUsage(sender)); - } - return; - } + @Override + public void processCommand(ICommandSender sender, String[] args) throws CommandException { + if(args.length == 0){ + sendMessage(sender, "\u00A78------ \u00A7aProfile Commands \u00A78------"); + for(Entry entry : parent.map.entrySet()){ + sendMessage(sender, "\u00A77> " + "\u00A7e" + entry.getKey() + "\u00A78: \u00A77" + + entry.getValue().getCommandUsage(sender)); + } + return; + } CommandProfileBase command = parent.getCommand(args); - if(command == null){ - sendError(sender, "Unknown command " + args[0]); - return; - } + if(command == null){ + sendError(sender, "Unknown command " + args[0]); + return; + } - if(command.subcommands.isEmpty()){ - sender.addChatMessage(new ChatComponentTranslation(command.getCommandUsage(sender))); - return; - } + if(command.subcommands.isEmpty()){ + sender.addChatMessage(new ChatComponentTranslation(command.getCommandUsage(sender))); + return; + } - Method m = null; - if(args.length > 1){ - m = command.subcommands.get(args[1].toLowerCase()); - } - if(m == null){ - sendMessage(sender, "\u00A78------ \u00A7a" + command.getCommandName().toUpperCase() + " SubCommands \u00A78------"); - sendMessage(sender, "\u00A77Usage: \u00A76" + command.getUsage()); - for(Entry entry : command.subcommands.entrySet()){ - sender.addChatMessage(new ChatComponentTranslation("\u00A77> " + "\u00A7e" + entry.getKey() + "\u00A78: \u00A77" + entry.getValue().getAnnotation(SubCommand.class).desc())); - } - sender.addChatMessage(new ChatComponentTranslation("\u00A78Permission:\u00A77 " + CommandProfile.getCommandPermission(command.getCommandName()))); - } - else{ - sendMessage(sender, "\u00A78------ \u00A7b" + command.getCommandName().toUpperCase() + "." + args[1].toUpperCase() + " Command \u00A78------"); - SubCommand sc = m.getAnnotation(SubCommand.class); - sender.addChatMessage(new ChatComponentTranslation("\u00A77" + sc.desc())); - if(!sc.usage().isEmpty()) - sender.addChatMessage(new ChatComponentTranslation("\u00A77Usage: \u00A76" + sc.usage())); - sender.addChatMessage(new ChatComponentTranslation("\u00A78Permission:\u00A77 " + getSubCommandPermission(args[1]))); - } - } + Method m = null; + if(args.length > 1){ + m = command.subcommands.get(args[1].toLowerCase()); + } + if(m == null){ + sendMessage(sender, "\u00A78------ \u00A7a" + command.getCommandName().toUpperCase() + + " SubCommands \u00A78------"); + sendMessage(sender, "\u00A77Usage: \u00A76" + command.getUsage()); + for(Entry entry : command.subcommands.entrySet()){ + SubCommand sc = entry.getValue().getAnnotation(SubCommand.class); + // For players, only list subcommands if they have permission; for console, show all. + if(!(sender instanceof EntityPlayer) || command.canSendCommand(sender, sc, entry.getKey())){ + sender.addChatMessage(new ChatComponentTranslation("\u00A77> " + + "\u00A7e" + entry.getKey() + + "\u00A78: \u00A77" + sc.desc())); + } + } + // Show permission node only if sender is console or has permission. + if(!(sender instanceof EntityPlayer) || + CustomNpcsPermissions.hasPermission((EntityPlayer)sender, CustomNpcsPermissions.PROFILE_ADMIN)){ + sender.addChatMessage(new ChatComponentTranslation("\u00A78Permission:\u00A77 " + + CommandProfile.getCommandPermission(command.getCommandName()))); + } + } + else{ + sendMessage(sender, "\u00A78------ \u00A7b" + command.getCommandName().toUpperCase() + + "." + args[1].toUpperCase() + " Command \u00A78------"); + SubCommand sc = m.getAnnotation(SubCommand.class); + sender.addChatMessage(new ChatComponentTranslation("\u00A77" + sc.desc())); + if(!sc.usage().isEmpty()){ + sender.addChatMessage(new ChatComponentTranslation("\u00A77Usage: \u00A76" + sc.usage())); + } + if(!(sender instanceof EntityPlayer) || + CustomNpcsPermissions.hasPermission((EntityPlayer)sender, CustomNpcsPermissions.PROFILE_ADMIN)){ + sender.addChatMessage(new ChatComponentTranslation("\u00A78Permission:\u00A77 " + + getSubCommandPermission(args[1]))); + } + } + } } diff --git a/src/main/java/kamkeel/npcs/command/profile/CommandProfile.java b/src/main/java/kamkeel/npcs/command/profile/CommandProfile.java index ed3133eaf..4987f1bbf 100644 --- a/src/main/java/kamkeel/npcs/command/profile/CommandProfile.java +++ b/src/main/java/kamkeel/npcs/command/profile/CommandProfile.java @@ -26,6 +26,7 @@ public class CommandProfile extends CommandBase { registerCommand(new CommandProfileCreate()); registerCommand(new CommandProfileRemove()); registerCommand(new CommandProfileAdmin()); + registerCommand(new CommandProfileRegion()); registerCommand(new CommandProfileList()); registerCommand(new CommandProfileRename()); } diff --git a/src/main/java/kamkeel/npcs/command/profile/CommandProfileAdmin.java b/src/main/java/kamkeel/npcs/command/profile/CommandProfileAdmin.java index c2c710a08..44acdcfbd 100644 --- a/src/main/java/kamkeel/npcs/command/profile/CommandProfileAdmin.java +++ b/src/main/java/kamkeel/npcs/command/profile/CommandProfileAdmin.java @@ -3,11 +3,11 @@ package kamkeel.npcs.command.profile; import kamkeel.npcs.controllers.ProfileController; import kamkeel.npcs.controllers.data.Profile; import kamkeel.npcs.controllers.data.ProfileOperation; +import kamkeel.npcs.controllers.data.EnumProfileOperation; import kamkeel.npcs.controllers.data.Slot; import noppes.npcs.LogWriter; import net.minecraft.command.CommandException; import net.minecraft.command.ICommandSender; - import java.io.File; import java.util.Map; import java.util.UUID; @@ -51,26 +51,15 @@ public class CommandProfileAdmin extends CommandProfileBase { } boolean temporary = (args.length >= 5 && args[4].equalsIgnoreCase("temp")); ProfileOperation result = ProfileController.cloneSlot(sourcePlayer, sourceSlot, destinationSlot, temporary); - switch(result) { - case SUCCESS: - sendResult(sender, "Successfully cloned slot %d from %s to slot %d for %s.", sourceSlot, sourcePlayer, destinationSlot, destinationPlayer); - break; - case NEW_SLOT_CREATED: - sendResult(sender, "Successfully cloned slot %d from %s to NEW slot %d for %s.", sourceSlot, sourcePlayer, destinationSlot, destinationPlayer); - break; - case LOCKED: - sendError(sender, "Profile is locked. Please try again later."); - break; - case VERIFICATION_FAILED: - sendError(sender, "Profile verification failed. Change not permitted."); - break; - case PLAYER_NOT_FOUND: - sendError(sender, "Player profile not found."); - break; - case ERROR: - default: - sendError(sender, "Error cloning slot."); - break; + if(result.getResult() == EnumProfileOperation.SUCCESS) { + sendResult(sender, "Successfully cloned slot %d from %s to slot %d for %s.", sourceSlot, sourcePlayer, destinationSlot, destinationPlayer); + } else if(result.getResult() == EnumProfileOperation.LOCKED) { + // Detail message for admins – note: using result.getMessage() for further details. + sendError(sender, "Clone failed for %s: Profile is locked. Details: %s", sourcePlayer, result.getMessage()); + } else if(result.getResult() == EnumProfileOperation.ERROR) { + sendError(sender, "Error cloning slot for %s: %s", sourcePlayer, result.getMessage()); + } else { + sendError(sender, "Unexpected error cloning slot: %s", result.getMessage()); } } @@ -92,20 +81,17 @@ public class CommandProfileAdmin extends CommandProfileBase { return; } ProfileOperation result = ProfileController.removeSlot(targetPlayer, slotId); - switch(result) { - case SUCCESS: - sendResult(sender, "Successfully removed slot %d from %s.", slotId, targetPlayer); - break; - case LOCKED: - sendError(sender, "Profile for %s is locked. Please try again later.", targetPlayer); - break; - default: - sendError(sender, "Error removing slot %d from %s.", slotId, targetPlayer); - break; + if(result.getResult() == EnumProfileOperation.SUCCESS) { + sendResult(sender, "Successfully removed slot %d from %s.", slotId, targetPlayer); + } else if(result.getResult() == EnumProfileOperation.LOCKED) { + sendError(sender, "Remove failed for %s: Profile is locked. Details: %s", targetPlayer, result.getMessage()); + } else if(result.getResult() == EnumProfileOperation.ERROR) { + sendError(sender, "Error removing slot %d from %s: %s", slotId, targetPlayer, result.getMessage()); + } else { + sendError(sender, "Unexpected error during removal: %s", result.getMessage()); } } - // Existing change subcommand update: @SubCommand( desc = "Change a specified player's active slot.", usage = " " @@ -124,28 +110,17 @@ public class CommandProfileAdmin extends CommandProfileBase { return; } ProfileOperation result = ProfileController.changeSlot(targetPlayer, newSlotId); - switch(result) { - case SUCCESS: - sendResult(sender, "Successfully changed %s's active slot to %d.", targetPlayer, newSlotId); - break; - case NEW_SLOT_CREATED: - sendResult(sender, "Switched %s to NEW slot %d (new profile created).", targetPlayer, newSlotId); - break; - case ALREADY_ACTIVE: - sendError(sender, "Slot %d is already active for %s.", newSlotId, targetPlayer); - break; - case LOCKED: - sendError(sender, "Profile for %s is locked. Please try again later.", targetPlayer); - break; - case VERIFICATION_FAILED: - sendError(sender, "Profile verification failed for %s.", targetPlayer); - break; - default: - sendError(sender, "Error changing active slot for %s.", targetPlayer); + if(result.getResult() == EnumProfileOperation.SUCCESS) { + sendResult(sender, "Successfully changed %s's active slot to %d.", targetPlayer, newSlotId); + } else if(result.getResult() == EnumProfileOperation.LOCKED) { + sendError(sender, "Change failed for %s: Profile is locked. Details: %s", targetPlayer, result.getMessage()); + } else if(result.getResult() == EnumProfileOperation.ERROR) { + sendError(sender, "Error changing active slot for %s: %s", targetPlayer, result.getMessage()); + } else { + sendError(sender, "Unexpected error during change: %s", result.getMessage()); } } - // New admin create subcommand: @SubCommand( desc = "Create a new slot for a specified player's profile.", usage = "" @@ -158,25 +133,18 @@ public class CommandProfileAdmin extends CommandProfileBase { String targetPlayer = args[0]; Profile profile = ProfileController.getProfile(targetPlayer); if(profile == null) { - sendError(sender, "Profile not found for player: " + targetPlayer); + sendError(sender, "Profile not found for player: %s", targetPlayer); return; } ProfileOperation result = ProfileController.createSlotInternal(profile); - switch(result) { - case NEW_SLOT_CREATED: - sendResult(sender, "New slot created successfully for %s.", targetPlayer); - break; - case MAX_SLOTS: - sendError(sender, "Player %s has reached maximum allowed slots.", targetPlayer); - break; - case LOCKED: - sendError(sender, "Profile for %s is locked. Please try again later.", targetPlayer); - break; - case VERIFICATION_FAILED: - sendError(sender, "Profile verification failed for %s.", targetPlayer); - break; - default: - sendError(sender, "Error creating new slot for %s.", targetPlayer); + if(result.getResult() == EnumProfileOperation.SUCCESS) { + sendResult(sender, "New slot created successfully for %s.", targetPlayer); + } else if(result.getResult() == EnumProfileOperation.LOCKED) { + sendError(sender, "Create failed for %s: Profile is locked. Details: %s", targetPlayer, result.getMessage()); + } else if(result.getResult() == EnumProfileOperation.ERROR) { + sendError(sender, "Error creating new slot for %s: %s", targetPlayer, result.getMessage()); + } else { + sendError(sender, "Unexpected error during slot creation: %s", result.getMessage()); } } @@ -192,7 +160,7 @@ public class CommandProfileAdmin extends CommandProfileBase { String targetPlayer = args[0]; Profile profile = ProfileController.getProfile(targetPlayer); if(profile == null) { - sendError(sender, "Profile not found for player: " + targetPlayer); + sendError(sender, "Profile not found for player: %s", targetPlayer); return; } sendMessage(sender, "Profile Slots for %s:", targetPlayer); @@ -236,7 +204,7 @@ public class CommandProfileAdmin extends CommandProfileBase { } Profile profile = ProfileController.getProfile(targetPlayer); if(profile == null) { - sendError(sender, "Profile not found for player: " + targetPlayer); + sendError(sender, "Profile not found for player: %s", targetPlayer); return; } if(profile.locked) { @@ -268,7 +236,7 @@ public class CommandProfileAdmin extends CommandProfileBase { return; } String targetPlayer = args[0]; - String backupFileName = args[1] += ".dat"; + String backupFileName = args[1] + ".dat"; File backupDir = new File(ProfileController.getBackupDir(), ProfileController.getProfile(targetPlayer).player.getUniqueID().toString()); File backupFile = new File(backupDir, backupFileName); if(!backupFile.exists()){ diff --git a/src/main/java/kamkeel/npcs/command/profile/CommandProfileChange.java b/src/main/java/kamkeel/npcs/command/profile/CommandProfileChange.java index 8f8c46fbc..c0a0c9706 100644 --- a/src/main/java/kamkeel/npcs/command/profile/CommandProfileChange.java +++ b/src/main/java/kamkeel/npcs/command/profile/CommandProfileChange.java @@ -2,11 +2,11 @@ package kamkeel.npcs.command.profile; import kamkeel.npcs.controllers.ProfileController; import kamkeel.npcs.controllers.data.ProfileOperation; +import kamkeel.npcs.controllers.data.EnumProfileOperation; import net.minecraft.command.CommandException; import net.minecraft.command.ICommandSender; import net.minecraft.entity.player.EntityPlayer; -import static kamkeel.npcs.util.ColorUtil.sendError; -import static kamkeel.npcs.util.ColorUtil.sendResult; +import static kamkeel.npcs.util.ColorUtil.*; public class CommandProfileChange extends CommandProfileBase { @@ -49,24 +49,14 @@ public class CommandProfileChange extends CommandProfileBase { } EntityPlayer player = (EntityPlayer)sender; ProfileOperation result = ProfileController.changeSlot(player, slotId); - switch(result) { - case SUCCESS: - sendResult(sender, "Successfully changed profile slot to %d.", slotId); - break; - case NEW_SLOT_CREATED: - sendResult(sender, "Switched to new slot %d (new profile created).", slotId); - break; - case ALREADY_ACTIVE: - sendError(sender, "Slot %d is already active.", slotId); - break; - case LOCKED: - sendError(sender, "Profile is locked. Please try again later."); - break; - case VERIFICATION_FAILED: - sendError(sender, "Profile verification failed. Change not permitted."); - break; - default: - sendError(sender, "Error occurred while changing your profile slot."); + if(result.getResult() == EnumProfileOperation.SUCCESS) { + sendResult(sender, "Successfully changed profile slot to %d.", slotId); + } else if(result.getResult() == EnumProfileOperation.LOCKED) { + sendError(sender, "Profile is locked. Details: %s", result.getMessage()); + } else if(result.getResult() == EnumProfileOperation.ERROR) { + sendError(sender, "Error changing your profile slot: %s", result.getMessage()); + } else { + sendError(sender, "Unexpected error: %s", result.getMessage()); } } } diff --git a/src/main/java/kamkeel/npcs/command/profile/CommandProfileCreate.java b/src/main/java/kamkeel/npcs/command/profile/CommandProfileCreate.java index b8610f33c..1ca777382 100644 --- a/src/main/java/kamkeel/npcs/command/profile/CommandProfileCreate.java +++ b/src/main/java/kamkeel/npcs/command/profile/CommandProfileCreate.java @@ -1,13 +1,12 @@ package kamkeel.npcs.command.profile; import kamkeel.npcs.controllers.ProfileController; -import kamkeel.npcs.controllers.data.Profile; import kamkeel.npcs.controllers.data.ProfileOperation; +import kamkeel.npcs.controllers.data.EnumProfileOperation; import net.minecraft.command.CommandException; import net.minecraft.command.ICommandSender; import net.minecraft.entity.player.EntityPlayer; -import static kamkeel.npcs.util.ColorUtil.sendError; -import static kamkeel.npcs.util.ColorUtil.sendResult; +import static kamkeel.npcs.util.ColorUtil.*; public class CommandProfileCreate extends CommandProfileBase { @@ -38,27 +37,19 @@ public class CommandProfileCreate extends CommandProfileBase { return; } EntityPlayer player = (EntityPlayer)sender; - Profile profile = ProfileController.getProfile(player); - if(profile == null) { + if(ProfileController.getProfile(player) == null) { sendError(sender, "Profile not found."); return; } - ProfileOperation result = ProfileController.createSlotInternal(profile); - switch(result) { - case NEW_SLOT_CREATED: - sendResult(sender, "New profile slot created successfully."); - break; - case MAX_SLOTS: - sendError(sender, "You have reached the maximum allowed slots."); - break; - case LOCKED: - sendError(sender, "Profile is locked. Please try again later."); - break; - case VERIFICATION_FAILED: - sendError(sender, "Profile verification failed. Creation not permitted."); - break; - default: - sendError(sender, "Error occurred while creating a new profile slot."); + ProfileOperation result = ProfileController.createSlotInternal(ProfileController.getProfile(player)); + if(result.getResult() == EnumProfileOperation.SUCCESS) { + sendResult(sender, "New profile slot created successfully."); + } else if(result.getResult() == EnumProfileOperation.LOCKED) { + sendError(sender, "Profile is locked. Details: %s", result.getMessage()); + } else if(result.getResult() == EnumProfileOperation.ERROR) { + sendError(sender, "Error creating new profile slot: %s", result.getMessage()); + } else { + sendError(sender, "Unexpected error: %s", result.getMessage()); } } } diff --git a/src/main/java/kamkeel/npcs/command/profile/CommandProfileRegion.java b/src/main/java/kamkeel/npcs/command/profile/CommandProfileRegion.java new file mode 100644 index 000000000..91071f132 --- /dev/null +++ b/src/main/java/kamkeel/npcs/command/profile/CommandProfileRegion.java @@ -0,0 +1,160 @@ +package kamkeel.npcs.command.profile; + +import noppes.npcs.config.ConfigMain; +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; +import java.util.ArrayList; +import java.util.List; + +import static kamkeel.npcs.util.ColorUtil.sendError; +import static kamkeel.npcs.util.ColorUtil.sendMessage; +import static kamkeel.npcs.util.ColorUtil.sendResult; + +public class CommandProfileRegion extends CommandProfileBase { + + @Override + public String getCommandName() { + return "region"; + } + + @Override + public String getDescription() { + return "Manage profile region switching and restricted regions"; + } + + @Override + public String getUsage() { + return ""; + } + + @SubCommand( + desc = "Enable region-based profile switching", + usage = "" + ) + public void enable(ICommandSender sender, String[] args) throws CommandException { + ConfigMain.RegionProfileSwitching = true; + ConfigMain.RegionProfileSwitchingProperty.set(true); + if(ConfigMain.config.hasChanged()){ + ConfigMain.config.save(); + } + sendResult(sender, "Profile region switching enabled."); + } + + @SubCommand( + desc = "Disable region-based profile switching", + usage = "" + ) + public void disable(ICommandSender sender, String[] args) throws CommandException { + ConfigMain.RegionProfileSwitching = false; + ConfigMain.RegionProfileSwitchingProperty.set(false); + if(ConfigMain.config.hasChanged()){ + ConfigMain.config.save(); + } + sendResult(sender, "Profile region switching disabled."); + } + + @SubCommand( + desc = "Add a new region. Format: DIM, X1, Y1, Z1, X2, Y2, Z2", + usage = " " + ) + public void add(ICommandSender sender, String[] args) throws CommandException { + if(args.length < 1){ + sendError(sender, "Usage: /profile region add "); + return; + } + // Combine args in case the region data was split by spaces + String regionStr = String.join(" ", args).trim(); + String[] parts = regionStr.split(","); + if(parts.length != 7){ + sendError(sender, "Invalid region format. Must contain 7 integers separated by commas."); + return; + } + List regionList = new ArrayList<>(); + try { + for(String part : parts){ + regionList.add(Integer.parseInt(part.trim())); + } + } catch(NumberFormatException e){ + sendError(sender, "Invalid number format in region data."); + return; + } + ConfigMain.RestrictedProfileRegions.add(regionList); + // Update config property value + List regionStrings = new ArrayList<>(); + for(List region : ConfigMain.RestrictedProfileRegions) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < region.size(); i++) { + if(i > 0) sb.append(", "); + sb.append(region.get(i)); + } + regionStrings.add(sb.toString()); + } + ConfigMain.RestrictedProfileRegionsProperty.set(regionStrings.toArray(new String[0])); + if(ConfigMain.config.hasChanged()){ + ConfigMain.config.save(); + } + sendResult(sender, "Region added successfully."); + } + + @SubCommand( + desc = "Remove a region by its index (1-based).", + usage = "" + ) + public void remove(ICommandSender sender, String[] args) throws CommandException { + if(args.length < 1){ + sendError(sender, "Usage: /profile region remove "); + return; + } + int index; + try { + index = Integer.parseInt(args[0]); + } catch(NumberFormatException e){ + sendError(sender, "Index must be a number."); + return; + } + index = index - 1; // Convert to 0-based index + if(index < 0 || index >= ConfigMain.RestrictedProfileRegions.size()){ + sendError(sender, "Invalid index. Must be between 1 and " + ConfigMain.RestrictedProfileRegions.size()); + return; + } + ConfigMain.RestrictedProfileRegions.remove(index); + // Update config property value + List regionStrings = new ArrayList<>(); + for(List region : ConfigMain.RestrictedProfileRegions) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < region.size(); i++) { + if(i > 0) sb.append(", "); + sb.append(region.get(i)); + } + regionStrings.add(sb.toString()); + } + ConfigMain.RestrictedProfileRegionsProperty.set(regionStrings.toArray(new String[0])); + if(ConfigMain.config.hasChanged()){ + ConfigMain.config.save(); + } + sendResult(sender, "Region removed successfully."); + } + + @SubCommand( + desc = "List all restricted profile regions.", + usage = "" + ) + public void list(ICommandSender sender, String[] args) throws CommandException { + if(ConfigMain.RestrictedProfileRegions.isEmpty()){ + sendMessage(sender, "No restricted profile regions configured."); + return; + } + sendMessage(sender, "Restricted Profile Regions:"); + int i = 1; + for(List region : ConfigMain.RestrictedProfileRegions) { + StringBuilder sb = new StringBuilder(); + sb.append(i).append(": "); + for (int j = 0; j < region.size(); j++) { + if(j > 0) sb.append(", "); + sb.append(region.get(j)); + } + sendMessage(sender, sb.toString()); + i++; + } + } +} diff --git a/src/main/java/kamkeel/npcs/command/profile/CommandProfileRemove.java b/src/main/java/kamkeel/npcs/command/profile/CommandProfileRemove.java index 81d7e6a4b..b5cc04556 100644 --- a/src/main/java/kamkeel/npcs/command/profile/CommandProfileRemove.java +++ b/src/main/java/kamkeel/npcs/command/profile/CommandProfileRemove.java @@ -2,11 +2,11 @@ package kamkeel.npcs.command.profile; import kamkeel.npcs.controllers.ProfileController; import kamkeel.npcs.controllers.data.ProfileOperation; +import kamkeel.npcs.controllers.data.EnumProfileOperation; import net.minecraft.command.CommandException; import net.minecraft.command.ICommandSender; import net.minecraft.entity.player.EntityPlayer; -import static kamkeel.npcs.util.ColorUtil.sendError; -import static kamkeel.npcs.util.ColorUtil.sendResult; +import static kamkeel.npcs.util.ColorUtil.*; public class CommandProfileRemove extends CommandProfileBase { @@ -49,18 +49,14 @@ public class CommandProfileRemove extends CommandProfileBase { } EntityPlayer player = (EntityPlayer)sender; ProfileOperation result = ProfileController.removeSlot(player, slotId); - switch(result) { - case SUCCESS: - sendResult(sender, "Successfully removed slot %d from your profile.", slotId); - break; - case LOCKED: - sendError(sender, "Profile is locked. Please try again later."); - break; - case ERROR: - sendError(sender, "Error removing slot. Ensure the slot exists and is not your active slot."); - break; - default: - sendError(sender, "Operation could not be completed."); + if(result.getResult() == EnumProfileOperation.SUCCESS) { + sendResult(sender, "Successfully removed slot %d from your profile.", slotId); + } else if(result.getResult() == EnumProfileOperation.LOCKED) { + sendError(sender, "Profile is locked. Details: %s", result.getMessage()); + } else if(result.getResult() == EnumProfileOperation.ERROR) { + sendError(sender, "Error removing slot: %s", result.getMessage()); + } else { + sendError(sender, "Unexpected error: %s", result.getMessage()); } } } diff --git a/src/main/java/kamkeel/npcs/controllers/ProfileController.java b/src/main/java/kamkeel/npcs/controllers/ProfileController.java index be8ce4912..769cdb237 100644 --- a/src/main/java/kamkeel/npcs/controllers/ProfileController.java +++ b/src/main/java/kamkeel/npcs/controllers/ProfileController.java @@ -21,8 +21,41 @@ import java.net.URL; import java.text.SimpleDateFormat; import java.util.*; +import static noppes.npcs.CustomNpcsPermissions.PROFILE_REGION_BYPASS; +import static noppes.npcs.CustomNpcsPermissions.hasPermission; + public class ProfileController { + // ------------------- Message Constants ------------------- + // General messages + private static final String MSG_PLAYER_NOT_FOUND = "Player not found."; + + // Clone Slot messages + private static final String MSG_PROFILE_LOCKED_CLONE = "Profile is locked; cannot clone slot."; + private static final String MSG_SOURCE_SLOT_NOT_EXIST = "Source slot does not exist."; + private static final String MSG_CANNOT_CLONE_CURRENT = "Cannot clone to the current active slot."; + private static final String MSG_INVALID_DEST_SLOT = "Invalid destination slot id."; + private static final String MSG_CLONE_SUCCESS = "Slot cloned successfully."; + + // Remove Slot messages + private static final String MSG_PROFILE_LOCKED_REMOVE = "Profile is locked; cannot remove slot."; + private static final String MSG_CANNOT_REMOVE_ACTIVE = "Cannot remove the currently active slot."; + private static final String MSG_SLOT_NOT_EXIST = "Slot does not exist."; + private static final String MSG_REMOVE_SUCCESS = "Slot removed successfully."; + + // Create Slot messages + private static final String MSG_PROFILE_LOCKED_CREATE = "Profile is locked; cannot create slot."; + private static final String MSG_MAX_SLOTS_REACHED = "Maximum allowed slots reached."; + private static final String MSG_NEW_SLOT_CREATED = "New slot created successfully."; + + // Change Slot messages + private static final String MSG_PROFILE_LOCKED_CHANGE = "Profile is locked; cannot change slot."; + private static final String MSG_SLOT_ALREADY_ACTIVE = "Slot is already active."; + private static final String MSG_REGION_NOT_ALLOWED = "Profile switching not allowed from your current location."; + private static final String MSG_CHANGE_SUCCESS = "Slot changed successfully."; + + // ------------------- End Constants ------------------- + public static HashMap profileTypes; public static HashMap activeProfiles; public static String profile_directory = "profiles"; @@ -175,7 +208,6 @@ public class ProfileController { // Now enforce backup amount limit. File[] backups = backupDir.listFiles((dir, name) -> name.endsWith(".dat")); if(backups != null && backups.length > ConfigMain.ProfileBackupAmount) { - // Sort backups by last modified ascending (oldest first) Arrays.sort(backups, Comparator.comparingLong(File::lastModified)); for(int i = 0; i < backups.length - ConfigMain.ProfileBackupAmount; i++){ backups[i].delete(); @@ -291,7 +323,6 @@ public class ProfileController { } // ---------- Internal Slot Operation Helpers ---------- - // Returns the next available temporary (negative) slot id (starting at -1) private static int getNextAvailableTempSlot(Profile profile) { int id = -1; while(profile.slots.containsKey(id)) { @@ -301,120 +332,127 @@ public class ProfileController { } // Clone a slot within a Profile. - // If temporary==true, destinationSlotId is computed automatically. private static ProfileOperation cloneSlotInternal(Profile profile, int sourceSlotId, int destinationSlotId, boolean temporary) { if(profile.locked) { - LogWriter.error("Profile is locked; cannot clone slot."); - return ProfileOperation.LOCKED; + return ProfileOperation.locked(MSG_PROFILE_LOCKED_CLONE); } - // Run verification checks on all IProfileData in priority order. if(profile.player != null) { List dataList = new ArrayList<>(profileTypes.values()); dataList.sort(Comparator.comparingInt(IProfileData::getSwitchPriority)); for(IProfileData pd : dataList) { - if(!pd.verifySwitch(profile.player)) { - LogWriter.error("Verification check failed for profile type: " + pd.getTagName()); - return ProfileOperation.VERIFICATION_FAILED; + if (pd.verifySwitch(profile.player).getResult() != EnumProfileOperation.SUCCESS) { + return pd.verifySwitch(profile.player); } } } if(!profile.slots.containsKey(sourceSlotId)) { - LogWriter.error("Source slot " + sourceSlotId + " does not exist."); - return ProfileOperation.ERROR; + return ProfileOperation.error(MSG_SOURCE_SLOT_NOT_EXIST); } if(destinationSlotId == profile.currentID) { - LogWriter.error("Cannot clone to the current active slot (" + profile.currentID + ")."); - return ProfileOperation.ERROR; + return ProfileOperation.error(MSG_CANNOT_CLONE_CURRENT); } if(temporary) { destinationSlotId = getNextAvailableTempSlot(profile); } else { if(destinationSlotId <= 0) { - LogWriter.error("Invalid destination slot id for a non-temporary clone."); - return ProfileOperation.ERROR; + return ProfileOperation.error(MSG_INVALID_DEST_SLOT); } } Slot sourceSlot = profile.slots.get(sourceSlotId); NBTTagCompound clonedData = (NBTTagCompound) sourceSlot.getCompound().copy(); Slot clonedSlot = new Slot(destinationSlotId, "Cloned Slot " + destinationSlotId, clonedData, System.currentTimeMillis(), temporary); profile.slots.put(destinationSlotId, clonedSlot); - return ProfileOperation.SUCCESS; + return ProfileOperation.success(MSG_CLONE_SUCCESS); } // Remove a slot from a Profile. private static ProfileOperation removeSlotInternal(Profile profile, int slotId) { if(profile.locked) { - LogWriter.error("Profile is locked; cannot remove slot."); - return ProfileOperation.LOCKED; + return ProfileOperation.locked(MSG_PROFILE_LOCKED_REMOVE); } if(slotId == profile.currentID) { - LogWriter.error("Cannot remove the currently active slot (" + profile.currentID + ")."); - return ProfileOperation.ERROR; + return ProfileOperation.error(MSG_CANNOT_REMOVE_ACTIVE); } if(!profile.slots.containsKey(slotId)) { - LogWriter.error("Slot " + slotId + " does not exist."); - return ProfileOperation.ERROR; + return ProfileOperation.error(MSG_SLOT_NOT_EXIST); } profile.slots.remove(slotId); - return ProfileOperation.SUCCESS; + return ProfileOperation.success(MSG_REMOVE_SUCCESS); } public static ProfileOperation createSlotInternal(Profile profile) { if (profile.locked) { - LogWriter.error("Profile is locked; cannot create slot."); - return ProfileOperation.LOCKED; + return ProfileOperation.locked(MSG_PROFILE_LOCKED_CREATE); } int newSlotId = 0; while (profile.slots.containsKey(newSlotId)) { newSlotId++; } - - // Check if the player is allowed to create a new slot. if (!allowSlotPermission(profile.player)) { - LogWriter.error("Player has reached maximum allowed slots."); - return ProfileOperation.MAX_SLOTS; + return ProfileOperation.error(MSG_MAX_SLOTS_REACHED); } - // Run verification checks from all IProfileData in order of priority. if (profile.player != null) { List dataList = new ArrayList<>(profileTypes.values()); dataList.sort(Comparator.comparingInt(IProfileData::getSwitchPriority)); for (IProfileData pd : dataList) { - if (!pd.verifySwitch(profile.player)) { - LogWriter.error("Verification check failed for profile type: " + pd.getTagName()); - return ProfileOperation.VERIFICATION_FAILED; + if (pd.verifySwitch(profile.player).getResult() != EnumProfileOperation.SUCCESS) { + return pd.verifySwitch(profile.player); } } } - // Create and add the new slot. Slot newSlot = new Slot(newSlotId, "Slot " + newSlotId); newSlot.setCompound(new NBTTagCompound()); profile.slots.put(newSlotId, newSlot); - return ProfileOperation.NEW_SLOT_CREATED; + return ProfileOperation.success(MSG_NEW_SLOT_CREATED); } - // Change the active slot in a profile without automatically creating a new one. - // If the target slot does not exist, the operation fails. private static ProfileOperation changeSlotInternal(Profile profile, int newSlotId) { if (profile.locked) { - LogWriter.error("Profile is locked; cannot change slot."); - return ProfileOperation.LOCKED; + return ProfileOperation.locked(MSG_PROFILE_LOCKED_CHANGE); } if (profile.currentID == newSlotId) { - LogWriter.error("Slot " + newSlotId + " is already active."); - return ProfileOperation.ALREADY_ACTIVE; + return ProfileOperation.error(MSG_SLOT_ALREADY_ACTIVE); } if (!profile.slots.containsKey(newSlotId)) { - LogWriter.error("Slot " + newSlotId + " does not exist."); - return ProfileOperation.ERROR; + return ProfileOperation.error(MSG_SLOT_NOT_EXIST); + } + // Region-based check: if enabled, ensure the player is within an allowed region. + if (ConfigMain.RegionProfileSwitching && profile.player != null) { + boolean allowed = hasPermission(profile.player, PROFILE_REGION_BYPASS); + if(!allowed){ + int playerDim = profile.player.dimension; + int playerX = (int) profile.player.posX; + int playerY = (int) profile.player.posY; + int playerZ = (int) profile.player.posZ; + for (List region : ConfigMain.RestrictedProfileRegions) { + if(region.size() == 7) { + int dim = region.get(0); + int x1 = Math.min(region.get(1), region.get(4)); + int y1 = Math.min(region.get(2), region.get(5)); + int z1 = Math.min(region.get(3), region.get(6)); + int x2 = Math.max(region.get(1), region.get(4)); + int y2 = Math.max(region.get(2), region.get(5)); + int z2 = Math.max(region.get(3), region.get(6)); + if(playerDim == dim && + playerX >= x1 && playerX <= x2 && + playerY >= y1 && playerY <= y2 && + playerZ >= z1 && playerZ <= z2) { + allowed = true; + break; + } + } + } + } + if (!allowed) { + return ProfileOperation.error(MSG_REGION_NOT_ALLOWED); + } } - // Run verification checks on all IProfileData in priority order. if (profile.player != null) { List dataList = new ArrayList<>(profileTypes.values()); dataList.sort(Comparator.comparingInt(IProfileData::getSwitchPriority)); for (IProfileData pd : dataList) { - if (!pd.verifySwitch(profile.player)) { - LogWriter.error("Verification check failed for profile type: " + pd.getTagName()); - return ProfileOperation.VERIFICATION_FAILED; + if (pd.verifySwitch(profile.player).getResult() != EnumProfileOperation.SUCCESS) { + return pd.verifySwitch(profile.player); } } } @@ -424,31 +462,32 @@ public class ProfileController { profile.currentID = newSlotId; if (profile.player != null) { loadSlotData(profile.player); - } - if (profile.player != null) { PlayerData pdata = PlayerData.get(profile.player); pdata.profileSlot = newSlotId; pdata.save(); } - return ProfileOperation.SUCCESS; + return ProfileOperation.success(MSG_CHANGE_SUCCESS); } // ---------- Public Operations (Overloaded for EntityPlayer, UUID, or username) ---------- // ----- Clone Slot ----- public static ProfileOperation cloneSlot(EntityPlayer player, int sourceSlotId, int destinationSlotId, boolean temporary) { Profile profile = getProfile(player); - if(profile == null) return ProfileOperation.PLAYER_NOT_FOUND; + if(profile == null) + return ProfileOperation.error(MSG_PLAYER_NOT_FOUND); ProfileOperation result = cloneSlotInternal(profile, sourceSlotId, destinationSlotId, temporary); - if(result == ProfileOperation.SUCCESS && player != null) + if(result.getResult() == EnumProfileOperation.SUCCESS && player != null) { save(player, profile); + } return result; } public static ProfileOperation cloneSlot(UUID uuid, int sourceSlotId, int destinationSlotId, boolean temporary) { Profile profile = getProfile(uuid); - if(profile == null) return ProfileOperation.PLAYER_NOT_FOUND; + if(profile == null) + return ProfileOperation.error(MSG_PLAYER_NOT_FOUND); ProfileOperation result = cloneSlotInternal(profile, sourceSlotId, destinationSlotId, temporary); - if(result == ProfileOperation.SUCCESS) { + if(result.getResult() == EnumProfileOperation.SUCCESS) { if(profile.player != null) save(profile.player, profile); else @@ -459,9 +498,10 @@ public class ProfileController { public static ProfileOperation cloneSlot(String username, int sourceSlotId, int destinationSlotId, boolean temporary) { Profile profile = getProfile(username); - if(profile == null) return ProfileOperation.PLAYER_NOT_FOUND; + if(profile == null) + return ProfileOperation.error(MSG_PLAYER_NOT_FOUND); ProfileOperation result = cloneSlotInternal(profile, sourceSlotId, destinationSlotId, temporary); - if(result == ProfileOperation.SUCCESS) { + if(result.getResult() == EnumProfileOperation.SUCCESS) { if(profile.player != null) save(profile.player, profile); else { @@ -476,18 +516,21 @@ public class ProfileController { // ----- Remove Slot ----- public static ProfileOperation removeSlot(EntityPlayer player, int slotId) { Profile profile = getProfile(player); - if(profile == null) return ProfileOperation.PLAYER_NOT_FOUND; + if(profile == null) + return ProfileOperation.error(MSG_PLAYER_NOT_FOUND); ProfileOperation result = removeSlotInternal(profile, slotId); - if(result == ProfileOperation.SUCCESS && player != null) + if(result.getResult() == EnumProfileOperation.SUCCESS && player != null) { save(player, profile); + } return result; } public static ProfileOperation removeSlot(UUID uuid, int slotId) { Profile profile = getProfile(uuid); - if(profile == null) return ProfileOperation.PLAYER_NOT_FOUND; + if(profile == null) + return ProfileOperation.error(MSG_PLAYER_NOT_FOUND); ProfileOperation result = removeSlotInternal(profile, slotId); - if(result == ProfileOperation.SUCCESS) { + if(result.getResult() == EnumProfileOperation.SUCCESS) { if(profile.player != null) save(profile.player, profile); else @@ -498,9 +541,10 @@ public class ProfileController { public static ProfileOperation removeSlot(String username, int slotId) { Profile profile = getProfile(username); - if(profile == null) return ProfileOperation.PLAYER_NOT_FOUND; + if(profile == null) + return ProfileOperation.error(MSG_PLAYER_NOT_FOUND); ProfileOperation result = removeSlotInternal(profile, slotId); - if(result == ProfileOperation.SUCCESS) { + if(result.getResult() == EnumProfileOperation.SUCCESS) { if(profile.player != null) save(profile.player, profile); else { @@ -515,18 +559,20 @@ public class ProfileController { // ----- Change Slot ----- public static ProfileOperation changeSlot(EntityPlayer player, int newSlotId) { Profile profile = getProfile(player); - if(profile == null) return ProfileOperation.PLAYER_NOT_FOUND; + if(profile == null) + return ProfileOperation.error(MSG_PLAYER_NOT_FOUND); ProfileOperation result = changeSlotInternal(profile, newSlotId); - if((result == ProfileOperation.SUCCESS || result == ProfileOperation.NEW_SLOT_CREATED) && player != null) + if(result.getResult() == EnumProfileOperation.SUCCESS && player != null) save(player, profile); return result; } public static ProfileOperation changeSlot(UUID uuid, int newSlotId) { Profile profile = getProfile(uuid); - if(profile == null) return ProfileOperation.PLAYER_NOT_FOUND; + if(profile == null) + return ProfileOperation.error(MSG_PLAYER_NOT_FOUND); ProfileOperation result = changeSlotInternal(profile, newSlotId); - if(result == ProfileOperation.SUCCESS || result == ProfileOperation.NEW_SLOT_CREATED) { + if(result.getResult() == EnumProfileOperation.SUCCESS) { if(profile.player != null) save(profile.player, profile); else @@ -537,9 +583,10 @@ public class ProfileController { public static ProfileOperation changeSlot(String username, int newSlotId) { Profile profile = getProfile(username); - if(profile == null) return ProfileOperation.PLAYER_NOT_FOUND; + if(profile == null) + return ProfileOperation.error(MSG_PLAYER_NOT_FOUND); ProfileOperation result = changeSlotInternal(profile, newSlotId); - if(result == ProfileOperation.SUCCESS || result == ProfileOperation.NEW_SLOT_CREATED) { + if(result.getResult() == EnumProfileOperation.SUCCESS) { if(profile.player != null) save(profile.player, profile); else { @@ -557,7 +604,6 @@ public class ProfileController { return; Profile profile = activeProfiles.get(player.getUniqueID()); if(profile.locked) { - LogWriter.error("Profile is locked; cannot save slot data."); return; } NBTTagCompound dataCompound; @@ -634,7 +680,6 @@ public class ProfileController { return infoList; } - public static boolean allowSlotPermission(EntityPlayer player) { Profile profile = ProfileController.getProfile(player); int currentSlots = profile.slots.size(); @@ -659,28 +704,6 @@ public class ProfileController { return currentSlots < highestAllowed; } - public void sendChatAlert(ProfileOperation operation, EntityPlayerMP player){ - switch (operation){ - case SUCCESS: - ChatAlertPacket.sendChatAlert(player, "quest.newquest", ": ", ""); - break; - case ERROR: - break; - case LOCKED: - break; - case PLAYER_NOT_FOUND: - break; - case NEW_SLOT_CREATED: - break; - case ALREADY_ACTIVE: - break; - case VERIFICATION_FAILED: - break; - case MAX_SLOTS: - break; - } - } - public static EntityPlayerMP getPlayer(String username){ return MinecraftServer.getServer().getConfigurationManager().func_152612_a(username); } diff --git a/src/main/java/kamkeel/npcs/controllers/data/CNPCData.java b/src/main/java/kamkeel/npcs/controllers/data/CNPCData.java index 6a60ade72..c40c43ca4 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/CNPCData.java +++ b/src/main/java/kamkeel/npcs/controllers/data/CNPCData.java @@ -4,6 +4,7 @@ import kamkeel.npcs.controllers.SyncController; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.nbt.NBTTagCompound; +import noppes.npcs.controllers.PartyController; import noppes.npcs.controllers.data.PlayerData; import java.util.ArrayList; import java.util.List; @@ -48,8 +49,12 @@ public class CNPCData implements IProfileData { } @Override - public boolean verifySwitch(EntityPlayer player) { - return true; + public ProfileOperation verifySwitch(EntityPlayer player) { + PlayerData playerData = PlayerData.get(player); + if(playerData.partyUUID != null) + return ProfileOperation.error("Cannot switch while in Party"); + + return ProfileOperation.success(""); } @Override diff --git a/src/main/java/kamkeel/npcs/controllers/data/EnumProfileOperation.java b/src/main/java/kamkeel/npcs/controllers/data/EnumProfileOperation.java new file mode 100644 index 000000000..b4c10d3ec --- /dev/null +++ b/src/main/java/kamkeel/npcs/controllers/data/EnumProfileOperation.java @@ -0,0 +1,7 @@ +package kamkeel.npcs.controllers.data; + +public enum EnumProfileOperation { + SUCCESS, + ERROR, + LOCKED +} diff --git a/src/main/java/kamkeel/npcs/controllers/data/IProfileData.java b/src/main/java/kamkeel/npcs/controllers/data/IProfileData.java index 2b5e308b5..846d93acc 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/IProfileData.java +++ b/src/main/java/kamkeel/npcs/controllers/data/IProfileData.java @@ -38,7 +38,7 @@ public interface IProfileData { * @param player The player switching profiles. * @return true if allowed, false if not. */ - public boolean verifySwitch(EntityPlayer player); + public ProfileOperation verifySwitch(EntityPlayer player); /** * NEW: Builds and returns a list of informational strings about this profile data, diff --git a/src/main/java/kamkeel/npcs/controllers/data/ProfileOperation.java b/src/main/java/kamkeel/npcs/controllers/data/ProfileOperation.java index 59dc7e2ef..7c3844794 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/ProfileOperation.java +++ b/src/main/java/kamkeel/npcs/controllers/data/ProfileOperation.java @@ -1,13 +1,31 @@ package kamkeel.npcs.controllers.data; -public enum ProfileOperation { - SUCCESS, - ERROR, - LOCKED, - PLAYER_NOT_FOUND, - NEW_SLOT_CREATED, - ALREADY_ACTIVE, - VERIFICATION_FAILED, - MAX_SLOTS -} +public class ProfileOperation { + private final EnumProfileOperation result; + private final String message; + public ProfileOperation(EnumProfileOperation result, String message) { + this.result = result; + this.message = message; + } + + public EnumProfileOperation getResult() { + return result; + } + + public String getMessage() { + return message; + } + + public static ProfileOperation success(String message) { + return new ProfileOperation(EnumProfileOperation.SUCCESS, message); + } + + public static ProfileOperation error(String message) { + return new ProfileOperation(EnumProfileOperation.ERROR, message); + } + + public static ProfileOperation locked(String message) { + return new ProfileOperation(EnumProfileOperation.LOCKED, message); + } +} diff --git a/src/main/java/noppes/npcs/CustomNpcsPermissions.java b/src/main/java/noppes/npcs/CustomNpcsPermissions.java index 35aa84c0e..71419fada 100644 --- a/src/main/java/noppes/npcs/CustomNpcsPermissions.java +++ b/src/main/java/noppes/npcs/CustomNpcsPermissions.java @@ -94,6 +94,7 @@ public class CustomNpcsPermissions{ public static final Permission PROFILE_DELETE = new Permission("customnpcs.profile.delete"); public static final Permission PROFILE_RENAME = new Permission("customnpcs.profile.rename"); public static final Permission PROFILE_CHANGE = new Permission("customnpcs.profile.change"); + public static final Permission PROFILE_REGION_BYPASS = new Permission("customnpcs.profile.region-bypass"); public static final Permission PROFILE_MAX = new Permission("customnpcs.profile.max.*"); public static CustomNpcsPermissions Instance; diff --git a/src/main/java/noppes/npcs/config/ConfigMain.java b/src/main/java/noppes/npcs/config/ConfigMain.java index 8f0846b60..7732dd7c5 100644 --- a/src/main/java/noppes/npcs/config/ConfigMain.java +++ b/src/main/java/noppes/npcs/config/ConfigMain.java @@ -8,6 +8,8 @@ import noppes.npcs.config.legacy.LegacyConfig; import org.apache.logging.log4j.Level; import java.io.File; +import java.util.ArrayList; +import java.util.List; public class ConfigMain { @@ -87,6 +89,11 @@ public class ConfigMain public static boolean AllowProfileBackups = true; public static int ProfileBackupAmount = 5; + public static Property RegionProfileSwitchingProperty; + public static boolean RegionProfileSwitching = false; + + public static Property RestrictedProfileRegionsProperty; + public static List> RestrictedProfileRegions = new ArrayList<>(); /** * General NPC Properties @@ -230,6 +237,24 @@ public class ConfigMain AllowProfileBackups = config.get(PROFILES, "Enable Profile Backups", true, "Will create backups of profile changes").getBoolean(true); ProfileBackupAmount = config.get(PROFILES, "Number of Backups", 5, "How many backups per player to save").getInt(5); + RegionProfileSwitchingProperty = config.get(PROFILES, "Region Profile Switching", false, "If true, only allows profile switching in certain regions."); + RegionProfileSwitching = RegionProfileSwitchingProperty.getBoolean(false); + + RestrictedProfileRegionsProperty = config.get(PROFILES, "Restricted Profile Regions", new String[]{ + "0, 100, 64, 100, 200, 80, 200", + "1, 50, 60, 50, 150, 75, 150" + }, "List of restricted regions where profile switching is enabled. Format: DIM, X1, Y1, Z1, X2, Y2, Z2"); + + RestrictedProfileRegions.clear(); + for (String region : RestrictedProfileRegionsProperty.getStringList()) { + String[] parts = region.split(", "); + List regionList = new ArrayList<>(); + for (String part : parts) { + regionList.add(Integer.parseInt(part)); + } + RestrictedProfileRegions.add(regionList); + } + // Convert to Legacy if(CustomNpcs.legacyExist){ EnableUpdateChecker = LegacyConfig.EnableUpdateChecker;