diff --git a/build.gradle b/build.gradle index e1c581324..3eade4447 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ plugins { id 'idea' } -version = "1.9.4-beta1" +version = "1.10-beta5" group= "kamkeel.customnpc-plus" archivesBaseName = "CustomNPC-Plus" @@ -37,4 +37,4 @@ sourceSets { } // Modify the existing 'build' task to depend on 'updateAPI' -tasks.apiClasses.dependsOn 'updateAPI' +//tasks.apiClasses.dependsOn 'updateAPI' diff --git a/gradle.properties b/gradle.properties index fb3e039b4..83a8d5e6c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -199,4 +199,4 @@ disableCheckstyle = true # ideaCheckSpotlessOnBuild = true # Non-GTNH properties -modVersion = 1.9.3 +modVersion = 1.10 diff --git a/src/api b/src/api index 17d165e62..a876b4d19 160000 --- a/src/api +++ b/src/api @@ -1 +1 @@ -Subproject commit 17d165e62846b73b13f82af0e93b84704db4e11a +Subproject commit a876b4d191412dcd0738778ec38b8c6721c24aea diff --git a/src/main/java/foxz/command/CmdClone.java b/src/main/java/foxz/command/CmdClone.java index 75627a9f1..9a6cd1923 100644 --- a/src/main/java/foxz/command/CmdClone.java +++ b/src/main/java/foxz/command/CmdClone.java @@ -172,7 +172,7 @@ public class CmdClone extends ChMcLogger { entity.setPosition(posX + 0.5, posY + 1, posZ + 0.5); if(entity instanceof EntityNPCInterface){ EntityNPCInterface npc = (EntityNPCInterface) entity; - npc.ai.startPos = new int[]{MathHelper.floor_double(posX), MathHelper.floor_double(posY), MathHelper.floor_double(posZ)}; + npc.ais.startPos = new int[]{MathHelper.floor_double(posX), MathHelper.floor_double(posY), MathHelper.floor_double(posZ)}; if(newname != null && !newname.isEmpty()) npc.display.name = newname.replaceAll("%", " "); // like name, newname must use % in place of space to keep a logical way } @@ -274,7 +274,7 @@ public class CmdClone extends ChMcLogger { entity.setPosition(posX + 0.5 + x, yy + 1, posZ + 0.5 + z); if(entity instanceof EntityNPCInterface){ EntityNPCInterface npc = (EntityNPCInterface) entity; - npc.ai.startPos = new int[]{xx, yy, zz}; + npc.ais.startPos = new int[]{xx, yy, zz}; if(newname != null && !newname.isEmpty()) npc.display.name = newname.replaceAll("%", " "); // like name, newname must use % in place of space to keep a logical way } diff --git a/src/main/java/foxz/command/CmdConfig.java b/src/main/java/foxz/command/CmdConfig.java index d947513b0..597db83a1 100644 --- a/src/main/java/foxz/command/CmdConfig.java +++ b/src/main/java/foxz/command/CmdConfig.java @@ -5,15 +5,16 @@ import foxz.commandhelper.annotations.Command; import foxz.commandhelper.annotations.SubCommand; import foxz.commandhelper.permissions.OpOnly; import foxz.commandhelper.permissions.PlayerOnly; +import kamkeel.npcs.network.PacketHandler; +import kamkeel.npcs.network.enums.EnumConfigOperation; +import kamkeel.npcs.network.packets.data.ConfigCommandPacket; import net.minecraft.block.Block; import net.minecraft.block.BlockIce; import net.minecraft.block.BlockLeavesBase; import net.minecraft.block.BlockVine; import net.minecraft.entity.player.EntityPlayerMP; import noppes.npcs.CustomNpcs; -import noppes.npcs.Server; import noppes.npcs.config.ConfigMain; -import noppes.npcs.constants.EnumPacketClient; import noppes.npcs.controllers.ChunkController; import java.util.Arrays; @@ -207,6 +208,6 @@ public class CmdConfig extends ChMcLogger { for(int i = 0; i < args.length; i++){ font += " " + args[i]; } - Server.sendData((EntityPlayerMP)this.pcParam, EnumPacketClient.CONFIG, 0, font.trim(), size); + PacketHandler.Instance.sendToPlayer(new ConfigCommandPacket(EnumConfigOperation.FONT, font.trim(), size), (EntityPlayerMP)this.pcParam); } } diff --git a/src/main/java/foxz/command/CmdDialog.java b/src/main/java/foxz/command/CmdDialog.java index 250717dd4..3b6a3e857 100644 --- a/src/main/java/foxz/command/CmdDialog.java +++ b/src/main/java/foxz/command/CmdDialog.java @@ -5,12 +5,12 @@ import foxz.commandhelper.annotations.Command; import foxz.commandhelper.annotations.SubCommand; import foxz.commandhelper.permissions.OpOnly; import foxz.commandhelper.permissions.ParamCheck; +import kamkeel.npcs.controllers.SyncController; import net.minecraft.command.CommandBase; import net.minecraft.entity.player.EntityPlayer; import noppes.npcs.NoppesUtilServer; import noppes.npcs.client.EntityUtil; import noppes.npcs.controllers.DialogController; -import noppes.npcs.controllers.SyncController; import noppes.npcs.controllers.data.Dialog; import noppes.npcs.controllers.data.DialogOption; import noppes.npcs.controllers.data.PlayerData; diff --git a/src/main/java/foxz/command/CmdNpc.java b/src/main/java/foxz/command/CmdNpc.java index a4cffbc4e..aaec029a4 100644 --- a/src/main/java/foxz/command/CmdNpc.java +++ b/src/main/java/foxz/command/CmdNpc.java @@ -50,7 +50,7 @@ public class CmdNpc extends ChMcLogger { posZ = CommandBase.func_110666_a(pcParam, selectedNpc.posZ, args[2]); } - selectedNpc.ai.startPos = new int[]{MathHelper.floor_double(posX), MathHelper.floor_double(posY), MathHelper.floor_double(posZ)}; + selectedNpc.ais.startPos = new int[]{MathHelper.floor_double(posX), MathHelper.floor_double(posY), MathHelper.floor_double(posZ)}; } @SubCommand( @@ -144,7 +144,7 @@ public class CmdNpc extends ChMcLogger { if(args.length > 0) npc.display.name = args[0]; npc.setPositionAndRotation(player.posX, player.posY, player.posZ, player.cameraYaw, player.cameraPitch); - npc.ai.startPos = new int[]{MathHelper.floor_double(player.posX),MathHelper.floor_double(player.posY),MathHelper.floor_double(player.posZ)}; + npc.ais.startPos = new int[]{MathHelper.floor_double(player.posX),MathHelper.floor_double(player.posY),MathHelper.floor_double(player.posZ)}; pw.spawnEntityInWorld(npc); npc.setHealth(npc.getMaxHealth()); NoppesUtilServer.sendOpenGui(player, EnumGuiType.MainMenuDisplay, npc); diff --git a/src/main/java/foxz/command/CmdQuest.java b/src/main/java/foxz/command/CmdQuest.java index e0500f3e1..78cce2830 100644 --- a/src/main/java/foxz/command/CmdQuest.java +++ b/src/main/java/foxz/command/CmdQuest.java @@ -5,11 +5,11 @@ import foxz.commandhelper.annotations.Command; import foxz.commandhelper.annotations.SubCommand; import foxz.commandhelper.permissions.OpOnly; import foxz.commandhelper.permissions.ParamCheck; +import kamkeel.npcs.controllers.SyncController; +import kamkeel.npcs.network.packets.data.AchievementPacket; +import kamkeel.npcs.network.packets.data.ChatAlertPacket; import net.minecraft.entity.player.EntityPlayerMP; -import noppes.npcs.Server; -import noppes.npcs.constants.EnumPacketClient; import noppes.npcs.controllers.QuestController; -import noppes.npcs.controllers.SyncController; import noppes.npcs.controllers.data.PlayerData; import noppes.npcs.controllers.data.Quest; import noppes.npcs.controllers.data.QuestData; @@ -58,8 +58,8 @@ public class CmdQuest extends ChMcLogger{ playerdata.questData.activeQuests.put(questid, questdata); playerdata.save(); if(playerdata.player != null){ - Server.sendData((EntityPlayerMP)playerdata.player, EnumPacketClient.MESSAGE, "quest.newquest", quest.title); - Server.sendData((EntityPlayerMP)playerdata.player, EnumPacketClient.CHAT, "quest.newquest", ": ", quest.title); + AchievementPacket.sendAchievement((EntityPlayerMP) playerdata.player, false, "quest.newquest", quest.title); + ChatAlertPacket.sendChatAlert((EntityPlayerMP) playerdata.player, "quest.newquest", ": ", quest.title); } playerdata.updateClient = true; } diff --git a/src/main/java/kamkeel/command/CommandKamkeel.java b/src/main/java/kamkeel/command/CommandKamkeel.java deleted file mode 100644 index 86c192847..000000000 --- a/src/main/java/kamkeel/command/CommandKamkeel.java +++ /dev/null @@ -1,153 +0,0 @@ -package kamkeel.command; - -import net.minecraft.command.CommandBase; -import net.minecraft.command.CommandException; -import net.minecraft.command.ICommandSender; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.server.MinecraftServer; -import noppes.npcs.CustomNpcsPermissions; -import noppes.npcs.scripted.CustomNPCsException; - -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class CommandKamkeel extends CommandBase{ - - public Map map = new HashMap(); - public HelpCommand help = new HelpCommand(this); - public String[] alias = {"kam"}; - - public CommandKamkeel(){ - registerCommand(help); - registerCommand(new ScriptCommand()); - registerCommand(new SlayCommand()); - registerCommand(new QuestCommand()); - registerCommand(new QuestCategoryCommand()); - registerCommand(new DialogCommand()); - registerCommand(new DialogCategoryCommand()); - registerCommand(new FactionCommand()); - registerCommand(new NpcCommand()); - registerCommand(new CloneCommand()); - registerCommand(new ConfigCommand()); - registerCommand(new AnimationCommand()); - registerCommand(new OverlayCommand()); - registerCommand(new CommandCommand()); - } - - public void registerCommand(CommandKamkeelBase command){ - String name = command.getCommandName().toLowerCase(); - if(map.containsKey(name)) - throw new CustomNPCsException("Already a subcommand with the name: " + name); - map.put(name, command); - } - - @Override - public String getCommandName() { - return "kamkeel"; - } - - @Override - public List getCommandAliases() - { - return Arrays.asList(alias); - } - - @Override - public String getCommandUsage(ICommandSender sender) { - return "Use as /kamkeel subcommand"; - } - - @Override - public void processCommand(ICommandSender sender, String[] args) throws CommandException { - if(args.length == 0){ - help.processCommand(sender, args); - return; - } - - CommandKamkeelBase command = getCommand(args); - if(command == null) - throw new CommandException("Unknown command " + args[0]); - - args = Arrays.copyOfRange(args, 1, args.length); - if(command.subcommands.isEmpty() || !command.runSubCommands()){ - if(!canSendCommand(sender, command)) - throw new CommandException("You are not allowed to use this command: " + command); - command.canRun(sender, command.getUsage(), args); - command.processCommand(sender, args); - return; - } - - if(args.length == 0){ - help.processCommand(sender, new String[]{command.getCommandName()}); - return; - } - - command.processSubCommand(sender, args[0], Arrays.copyOfRange(args, 1, args.length)); - } - - @Override - public List addTabCompletionOptions(ICommandSender sender, String[] args){ - if(args.length == 1) - return CommandBase.getListOfStringsMatchingLastWord(args, map.keySet().toArray(new String[map.size()])); - CommandKamkeelBase command = getCommand(args); - if(command == null) - return null; - if(args.length == 2 && command.runSubCommands()) - return CommandBase.getListOfStringsMatchingLastWord(args, command.subcommands.keySet().toArray(new String[command.subcommands.keySet().size()])); - String[] useArgs = command.getUsage().split(" "); - if(command.runSubCommands()) { - Method m = command.subcommands.get(args[1].toLowerCase()); - if(m != null) { - useArgs = m.getAnnotation(CommandKamkeelBase.SubCommand.class).usage().split(" "); - } - } - if(args.length <= useArgs.length + 2) { - if(args.length - 3 >= 0){ - String usage = useArgs[args.length - 3]; - if(usage.equals("") || usage.equals("[player]")) { - return CommandBase.getListOfStringsMatchingLastWord(args, MinecraftServer.getServer().getAllUsernames()); - } - } - } - return command.addTabCompletionOptions(sender, Arrays.copyOfRange(args, 1, args.length)); - } - - public CommandKamkeelBase getCommand(String[] args){ - if(args.length == 0) - return null; - return map.get(args[0].toLowerCase()); - } - - @Override - public int getRequiredPermissionLevel(){ - return 2; - } - - public static String getCommandPermission(String command){ - return "cnpc.kamkeel." + command.toLowerCase(); - } - - public static String getUniversalPermission(){ - return "cnpc.kamkeel.*"; - } - - public static boolean canSendCommand(ICommandSender sender, CommandKamkeelBase command){ - if(sender.canCommandSenderUseCommand(command.getRequiredPermissionLevel(), getUniversalPermission())){ - return true; - } - - if(sender.canCommandSenderUseCommand(command.getRequiredPermissionLevel(), getCommandPermission(command.getCommandName()))){ - return true; - } - - if(sender instanceof EntityPlayer){ - return CustomNpcsPermissions.hasCustomPermission((EntityPlayer) sender, getCommandPermission(command.getCommandName())); - } - - return false; - } -} - diff --git a/src/main/java/kamkeel/command/profile/CommandHelpProfile.java b/src/main/java/kamkeel/command/profile/CommandHelpProfile.java deleted file mode 100644 index fe228dfa1..000000000 --- a/src/main/java/kamkeel/command/profile/CommandHelpProfile.java +++ /dev/null @@ -1,70 +0,0 @@ -package kamkeel.command.profile; - -import net.minecraft.command.CommandException; -import net.minecraft.command.ICommandSender; -import net.minecraft.util.ChatComponentTranslation; - -import java.lang.reflect.Method; -import java.util.Map.Entry; - -public class CommandHelpProfile extends CommandProfileBase { - private CommandProfile parent; - - public CommandHelpProfile(CommandProfile parent){ - this.parent = parent; - } - - @Override - public String getCommandName() { - return "help"; - } - - @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; - } - - CommandProfileBase command = parent.getCommand(args); - if(command == null){ - sendError(sender, "Unknown command " + args[0]); - 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]))); - } - } -} diff --git a/src/main/java/kamkeel/command/profile/CommandProfileChange.java b/src/main/java/kamkeel/command/profile/CommandProfileChange.java deleted file mode 100644 index 8cda00afc..000000000 --- a/src/main/java/kamkeel/command/profile/CommandProfileChange.java +++ /dev/null @@ -1,61 +0,0 @@ -package kamkeel.command.profile; - -import kamkeel.controllers.ProfileController; -import kamkeel.controllers.data.Profile; -import net.minecraft.command.CommandException; -import net.minecraft.command.ICommandSender; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.entity.player.EntityPlayerMP; - -public class CommandProfileChange extends CommandProfileBase { - - - @Override - public String getCommandName() { - return "change"; - } - - @Override - public String getDescription() { - return "change profiles"; - } - - @Override - public String getUsage() { - return ""; - } - - @Override - public boolean runSubCommands(){ - return false; - } - - @Override - public void processCommand(ICommandSender sender, String[] args) throws CommandException { - if(!(sender instanceof EntityPlayer)){ - sendError(sender, "This command can only be sent by a player"); - return; - } - - int slotID; - try { - slotID = Integer.parseInt(args[0]); - } catch (NumberFormatException ex) { - sendError(sender, "Slot ID must be a number: " + args[1]); - return; - } - - // TODO: Check if the player has permission to switch to this slot - EntityPlayerMP player = (EntityPlayerMP) sender; - - Profile profile = ProfileController.activeProfiles.get(player.getUniqueID()); - if(profile == null){ - sendError(sender, "Could not find a valid profile file"); - return; - } - - ProfileController.changePlayerSlot(player, slotID); - // TODO: Add Cooldown to successful operation - sendResult(sender, String.format("Switched to Slot \u00A7b%d\u00A77", slotID)); - } -} diff --git a/src/main/java/kamkeel/controllers/ProfileController.java b/src/main/java/kamkeel/controllers/ProfileController.java deleted file mode 100644 index a5f9a86da..000000000 --- a/src/main/java/kamkeel/controllers/ProfileController.java +++ /dev/null @@ -1,176 +0,0 @@ -package kamkeel.controllers; - -import kamkeel.controllers.data.IProfileData; -import kamkeel.controllers.data.Profile; -import kamkeel.controllers.data.Slot; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.nbt.CompressedStreamTools; -import net.minecraft.nbt.NBTTagCompound; -import noppes.npcs.CustomNpcs; -import noppes.npcs.LogWriter; -import noppes.npcs.util.CustomNPCsThreader; -import noppes.npcs.util.NBTJsonUtil; - -import java.io.File; -import java.io.FileOutputStream; -import java.util.HashMap; -import java.util.UUID; - -public class ProfileController { - - public static HashMap profileTypes; - public static HashMap activeProfiles; - - public static String profile_directory = "profiles"; - - public ProfileController(){ - profileTypes = new HashMap<>(); - activeProfiles = new HashMap<>(); - } - - /** - * Register during ServerStartEvent() - * - * @param type - IProfile Type to always Save/Load - * @return true/false if profile was successfully added - */ - public static boolean registerProfileType(IProfileData type){ - if(profileTypes.containsKey(type.getTagName())) - return false; - - profileTypes.put(type.getTagName(), type); - return true; - } - - public static File getProfileDir(){ - try{ - File file = new File(CustomNpcs.getWorldSaveDirectory(), profile_directory); - if(!file.exists()) - file.mkdir(); - return file; - } - catch (Exception e) { - e.printStackTrace(); - return null; - } - } - - public static synchronized void login(EntityPlayer player){ - if(player == null) - return; - - Profile profile; - if(activeProfiles.containsKey(player.getUniqueID())){ - profile = activeProfiles.get(player.getUniqueID()); - profile.player = player; - } else { - NBTTagCompound profileCompound = load(player); - profile = new Profile(player, profileCompound); - activeProfiles.put(player.getUniqueID(), profile); - } - } - - public static synchronized NBTTagCompound load(EntityPlayer player) { - File saveDir = getProfileDir(); - String filename = player.getUniqueID().toString(); - filename += ".dat"; - try { - File file = new File(saveDir, filename); - if(file.exists()){ - return NBTJsonUtil.loadNBTData(file); - } - } catch (Exception e) { - LogWriter.error("Error loading profile file: " + filename, e); - } - return new NBTTagCompound(); - } - - public static synchronized void save(EntityPlayer player, Profile profile) { - CustomNPCsThreader.customNPCThread.execute(() -> { - final NBTTagCompound compound = profile.writeToNBT(); - final String filename = player.getUniqueID() + ".dat"; - try { - File saveDir = getProfileDir(); - File file = new File(saveDir, filename + "_new"); - File file1 = new File(saveDir, filename); - CompressedStreamTools.writeCompressed(compound, new FileOutputStream(file)); - if(file1.exists()){ - file1.delete(); - } - file.renameTo(file1); - } catch (Exception e) { - LogWriter.except(e); - } - }); - } - - public static void changeSlot(EntityPlayer player, int slotNumber){ - if(!activeProfiles.containsKey(player.getUniqueID())) - return; - - Profile profile = activeProfiles.get(player.getUniqueID()); - if(profile.currentID == slotNumber) - return; - - // Saves Current Slot Data - saveSlotData(player); - - // Sets Player to New Slot - changePlayerSlot(player, slotNumber); - - // Save Slot File - save(player, profile); - } - - public static void saveSlotData(EntityPlayer player){ - if(!activeProfiles.containsKey(player.getUniqueID())) - return; - - NBTTagCompound dataCompound; - Slot slot; - - Profile profile = activeProfiles.get(player.getUniqueID()); - if(!profile.slots.isEmpty() && profile.slots.containsKey(profile.currentID)){ - slot = profile.slots.get(profile.currentID); - dataCompound = (NBTTagCompound) slot.getCompound().copy(); - } else { - slot = new Slot(profile.currentID, "Slot " + profile.currentID); - dataCompound = new NBTTagCompound(); - slot.setCompound(dataCompound); - } - - for(IProfileData profileData : profileTypes.values()){ - NBTTagCompound cloned = (NBTTagCompound) profileData.getCurrentNBT(player).copy(); - dataCompound.setTag(profileData.getTagName(), cloned); - } - - slot.setCompound(dataCompound); - } - - public static void changePlayerSlot(EntityPlayer player, int id){ - if(!activeProfiles.containsKey(player.getUniqueID())) - return; - - NBTTagCompound slotCompound; - Slot slot; - Profile profile = activeProfiles.get(player.getUniqueID()); - if(!profile.slots.isEmpty() && profile.slots.containsKey(id)){ - slot = profile.slots.get(id); - slotCompound = (NBTTagCompound) slot.getCompound().copy(); - } else { - slot = new Slot(id, "Slot " + id); - slotCompound = new NBTTagCompound(); - slot.setCompound(slotCompound); - } - - slot.setLastLoaded(System.currentTimeMillis()); - profile.slots.put(id, slot); - - for(IProfileData profileData : profileTypes.values()){ - profileData.setNBT(player, slotCompound.getCompoundTag(profileData.getTagName())); - profileData.save(player); - } - - profile.currentID = id; - } -} diff --git a/src/main/java/kamkeel/controllers/data/CNPCData.java b/src/main/java/kamkeel/controllers/data/CNPCData.java deleted file mode 100644 index fc1ae9d72..000000000 --- a/src/main/java/kamkeel/controllers/data/CNPCData.java +++ /dev/null @@ -1,39 +0,0 @@ -package kamkeel.controllers.data; - -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.nbt.NBTTagCompound; -import noppes.npcs.controllers.data.PlayerData; - -public class CNPCData implements IProfileData { - - @Override - public String getTagName() { - return "CustomNPC+"; - } - - @Override - public NBTTagCompound getCurrentNBT(EntityPlayer player) { - PlayerData customNPCData = PlayerData.get(player); - return customNPCData.getNBT(); - } - - @Override - public void save(EntityPlayer player) { - PlayerData customNPCData = PlayerData.get(player); - customNPCData.save(); - } - - @Override - public void setNBT(EntityPlayer player, NBTTagCompound replace) { - PlayerData customNPCData = PlayerData.get(player); - if(replace.hasNoTags()){ - PlayerData newData = new PlayerData(); - newData.player = player; - customNPCData.setNBT((NBTTagCompound) newData.getNBT().copy()); - } - else { - customNPCData.setNBT(replace); - } - customNPCData.updateClient = true; - } -} diff --git a/src/main/java/kamkeel/controllers/data/IProfileData.java b/src/main/java/kamkeel/controllers/data/IProfileData.java deleted file mode 100644 index 52653dc53..000000000 --- a/src/main/java/kamkeel/controllers/data/IProfileData.java +++ /dev/null @@ -1,29 +0,0 @@ -package kamkeel.controllers.data; - -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.nbt.NBTTagCompound; - -public interface IProfileData { - - /** - * Do not use the tag: - Name, lastLoaded, ID - * - * @return The Save Tag utilized in the Profile - */ - public String getTagName(); - - /** - * @return NBTTagCompound of their Current Data for a given Entity Player - */ - public NBTTagCompound getCurrentNBT(EntityPlayer player); - - /** - * Called immediately after setNBT() Replaces existing NBT - */ - public void save(EntityPlayer player); - - /** - * Replaces their Current Data operation when changing Profiles - */ - public void setNBT(EntityPlayer player, NBTTagCompound replace); -} diff --git a/src/main/java/kamkeel/controllers/data/Profile.java b/src/main/java/kamkeel/controllers/data/Profile.java deleted file mode 100644 index 94726b5b9..000000000 --- a/src/main/java/kamkeel/controllers/data/Profile.java +++ /dev/null @@ -1,57 +0,0 @@ -package kamkeel.controllers.data; - -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.nbt.NBTTagCompound; - -import java.util.HashMap; -import java.util.Set; - -public class Profile { - - public EntityPlayer player; - public int currentID; - public HashMap slots = new HashMap<>(); - - public Profile(EntityPlayer player, NBTTagCompound compound){ - this.player = player; - if(compound.hasKey("CurrentID")){ - this.currentID = compound.getInteger("CurrentID"); - } else { - this.currentID = 1; - } - - if (compound.hasKey("Slots")) { - // Load Slots - NBTTagCompound slotsCompound = compound.getCompoundTag("Slots"); - for (String key : (Set) slotsCompound.func_150296_c()) { - int slotID = Integer.parseInt(key); - NBTTagCompound slotNBT = slotsCompound.getCompoundTag(key); - Slot slot = Slot.fromNBT(slotID, slotNBT); - slots.put(slotID, slot); - } - } - } - - public NBTTagCompound writeToNBT() { - NBTTagCompound fullCompound = new NBTTagCompound(); - - if(this.player != null) - fullCompound.setString("Name", player.getCommandSenderName()); - fullCompound.setInteger("CurrentID", currentID); - - if(!slots.isEmpty()){ - NBTTagCompound slotsCompound = new NBTTagCompound(); - for (HashMap.Entry entry : slots.entrySet()) { - int id = entry.getKey(); - Slot slot = entry.getValue(); - slot.setId(id); - - NBTTagCompound slotTag = slot.toNBT(); - slotsCompound.setTag(String.valueOf(id), slotTag); - } - - fullCompound.setTag("Slots", slotsCompound); - } - return fullCompound; - } -} diff --git a/src/main/java/kamkeel/controllers/data/Slot.java b/src/main/java/kamkeel/controllers/data/Slot.java deleted file mode 100644 index 592497f54..000000000 --- a/src/main/java/kamkeel/controllers/data/Slot.java +++ /dev/null @@ -1,72 +0,0 @@ -package kamkeel.controllers.data; - -import kamkeel.controllers.ProfileController; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.nbt.NBTTagCompound; - -public class Slot { - - private int id; - private String name; - private long lastLoaded; - private NBTTagCompound compound; - - public Slot(int id, String name) { - this.id = id; - this.name = name; - } - - public Slot(int id, String name, NBTTagCompound compound, long last) { - this.id = id; - this.name = name; - this.compound = compound; - this.lastLoaded = last; - } - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public long getLastLoaded() { - return lastLoaded; - } - - public void setLastLoaded(long lastLoaded) { - this.lastLoaded = lastLoaded; - } - - public NBTTagCompound getCompound() { - return compound; - } - - public void setCompound(NBTTagCompound compound) { - this.compound = compound; - } - - public NBTTagCompound toNBT() { - NBTTagCompound slotNBT = new NBTTagCompound(); - slotNBT.setString("Name", name); - slotNBT.setLong("LastLoaded", lastLoaded); - slotNBT.setTag("Data", compound); - return slotNBT; - } - - public static Slot fromNBT(int id, NBTTagCompound slotNBT) { - String name = slotNBT.getString("Name"); - long lastLoaded = slotNBT.getLong("LastLoaded"); - NBTTagCompound compound = slotNBT.getCompoundTag("Data"); - return new Slot(id, name, compound, lastLoaded); - } -} diff --git a/src/main/java/kamkeel/network/PacketChannel.java b/src/main/java/kamkeel/network/PacketChannel.java deleted file mode 100644 index 19f677c72..000000000 --- a/src/main/java/kamkeel/network/PacketChannel.java +++ /dev/null @@ -1,39 +0,0 @@ -package kamkeel.network; - -import kamkeel.network.enums.EnumPacketType; - -import java.util.Hashtable; -import java.util.Map; - -public class PacketChannel { - - private String channelName; - private EnumPacketType channelType; - - public Map packets = new Hashtable<>(); - - public PacketChannel(String channelName, EnumPacketType channelType) { - this.channelName = channelName; - this.channelType = channelType; - } - - public String getChannelName() { - return channelName; - } - - public void setChannelName(String channelName) { - this.channelName = channelName; - } - - public EnumPacketType getChannelType() { - return channelType; - } - - public void setChannelType(EnumPacketType channelType) { - this.channelType = channelType; - } - - public void registerPacket(Enum ord, AbstractPacket packet) { - this.packets.put(ord.ordinal(), packet); - } -} diff --git a/src/main/java/kamkeel/network/PacketHandler.java b/src/main/java/kamkeel/network/PacketHandler.java deleted file mode 100644 index 8e15f8761..000000000 --- a/src/main/java/kamkeel/network/PacketHandler.java +++ /dev/null @@ -1,76 +0,0 @@ -package kamkeel.network; - -import cpw.mods.fml.common.eventhandler.SubscribeEvent; -import cpw.mods.fml.common.network.FMLEventChannel; -import cpw.mods.fml.common.network.FMLNetworkEvent; -import cpw.mods.fml.common.network.NetworkRegistry; -import cpw.mods.fml.common.network.internal.FMLProxyPacket; -import cpw.mods.fml.relauncher.Side; -import io.netty.buffer.ByteBuf; -import kamkeel.network.enums.EnumPacketType; -import kamkeel.util.ByteBufUtils; -import net.minecraft.entity.Entity; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraft.network.NetHandlerPlayServer; -import noppes.npcs.CustomNpcs; - -import java.util.*; - -public final class PacketHandler { - public static PacketHandler Instance; - - public Map channels = new Hashtable<>(); - - public final static PacketChannel INFO_PACKET = new PacketChannel("CNPC+|Info", EnumPacketType.INFO); - public final static PacketChannel DATA_PACKET = new PacketChannel("CNPC+|Data", EnumPacketType.DATA); - public final static PacketChannel CLIENT_PACKET = new PacketChannel("CNPC+|Client", EnumPacketType.CLIENT); - public final static PacketChannel LARGE_PACKET = new PacketChannel("CNPC+|Large", EnumPacketType.LARGE); - - public final static List packetChannels = new ArrayList<>(); - - public PacketHandler() { - // Register Channels - packetChannels.add(INFO_PACKET); - packetChannels.add(DATA_PACKET); - packetChannels.add(CLIENT_PACKET); - this.registerChannels(); - - // Register Info Packets - - // Register Data Packets - - // Register Client Packets - - // Register Packets - // map.put(PingPacket.packetName, new PingPacket()); - } - - public void registerChannels() { - FMLEventChannel eventChannel; - for (PacketChannel channel : packetChannels) { - eventChannel = NetworkRegistry.INSTANCE.newEventDrivenChannel(channel.getChannelName()); - eventChannel.register(this); - channels.put(channel.getChannelType(), eventChannel); - } - } - - public PacketChannel getPacketChannel(EnumPacketType type){ - PacketChannel packetChannel; - switch (type){ - case DATA: - packetChannel = DATA_PACKET; - break; - case INFO: - packetChannel = INFO_PACKET; - break; - case LARGE: - packetChannel = LARGE_PACKET; - break; - default: - packetChannel = CLIENT_PACKET; - break; - } - return packetChannel; - } -} diff --git a/src/main/java/kamkeel/network/enums/EnumClientPacket.java b/src/main/java/kamkeel/network/enums/EnumClientPacket.java deleted file mode 100644 index 24f677c84..000000000 --- a/src/main/java/kamkeel/network/enums/EnumClientPacket.java +++ /dev/null @@ -1,4 +0,0 @@ -package kamkeel.network.enums; - -public enum EnumClientPacket { -} diff --git a/src/main/java/kamkeel/network/enums/EnumDataPacket.java b/src/main/java/kamkeel/network/enums/EnumDataPacket.java deleted file mode 100644 index 2481eb446..000000000 --- a/src/main/java/kamkeel/network/enums/EnumDataPacket.java +++ /dev/null @@ -1,4 +0,0 @@ -package kamkeel.network.enums; - -public enum EnumDataPacket { -} diff --git a/src/main/java/kamkeel/network/enums/EnumInfoPacket.java b/src/main/java/kamkeel/network/enums/EnumInfoPacket.java deleted file mode 100644 index 06586758d..000000000 --- a/src/main/java/kamkeel/network/enums/EnumInfoPacket.java +++ /dev/null @@ -1,5 +0,0 @@ -package kamkeel.network.enums; - -public enum EnumInfoPacket { - LOGIN, -} diff --git a/src/main/java/kamkeel/network/enums/EnumPacketType.java b/src/main/java/kamkeel/network/enums/EnumPacketType.java deleted file mode 100644 index e38ad0ac4..000000000 --- a/src/main/java/kamkeel/network/enums/EnumPacketType.java +++ /dev/null @@ -1,5 +0,0 @@ -package kamkeel.network.enums; - -public enum EnumPacketType { - INFO, DATA, CLIENT, LARGE -} diff --git a/src/main/java/kamkeel/network/packets/LoginPacket.java b/src/main/java/kamkeel/network/packets/LoginPacket.java deleted file mode 100644 index 82d5899d4..000000000 --- a/src/main/java/kamkeel/network/packets/LoginPacket.java +++ /dev/null @@ -1,40 +0,0 @@ -package kamkeel.network.packets; - -import io.netty.buffer.ByteBuf; -import kamkeel.network.AbstractPacket; -import kamkeel.network.PacketChannel; -import kamkeel.network.PacketHandler; -import kamkeel.network.enums.EnumInfoPacket; -import kamkeel.util.ByteBufUtils; -import net.minecraft.entity.player.EntityPlayer; - -import java.io.IOException; - -public final class LoginPacket extends AbstractPacket { - public static final String packetName = "CNPC+|LoginPacket"; - - public LoginPacket() {} - - - @Override - public Enum getType() { - return EnumInfoPacket.LOGIN; - } - - @Override - public PacketChannel getChannel() { - return PacketHandler.INFO_PACKET; - } - - @Override - public void sendData(ByteBuf out) throws IOException { -// ByteBufUtils.writeUTF8String(out, this.data.player.getCommandSenderName()); -// ByteBufUtils.writeNBT(out,this.data.saveFromNBT(new NBTTagCompound())); - } - - @Override - public void receiveData(ByteBuf in, EntityPlayer player) throws IOException { - String playerName = ByteBufUtils.readUTF8String(in); - - } -} diff --git a/src/main/java/kamkeel/npcs/CustomAttributes.java b/src/main/java/kamkeel/npcs/CustomAttributes.java new file mode 100644 index 000000000..58aa51cac --- /dev/null +++ b/src/main/java/kamkeel/npcs/CustomAttributes.java @@ -0,0 +1,72 @@ +package kamkeel.npcs; + +import kamkeel.npcs.controllers.AttributeController; +import kamkeel.npcs.controllers.data.attribute.AttributeDefinition; +import kamkeel.npcs.controllers.data.attribute.AttributeValueType; +import kamkeel.npcs.controllers.data.attribute.requirement.types.QuestActiveRequirement; +import kamkeel.npcs.controllers.data.attribute.requirement.types.QuestCompletedRequirement; +import kamkeel.npcs.controllers.data.attribute.requirement.RequirementCheckerRegistry; + +/** + * ModAttributes registers the core attributes (both non–magic and magic–based). + */ +public class CustomAttributes { + public static final String HEALTH_KEY = "health"; + public static final String MAIN_ATTACK_KEY = "main_attack"; + public static final String MAIN_ATTACK_BOOST_KEY = "main_attack_boost"; + public static final String NEUTRAL_KEY = "neutral"; + public static final String NEUTRAL_BOOST_KEY = "neutral_boost"; + public static final String CRITICAL_DAMAGE_KEY = "critical_damage"; + public static final String CRITICAL_CHANCE_KEY = "critical_chance"; + public static final String MAGIC_DAMAGE_KEY = "magic_damage"; + public static final String MAGIC_BOOST_KEY = "magic_boost"; + public static final String MAGIC_DEFENSE_KEY = "magic_defense"; + public static final String MAGIC_RESISTANCE_KEY = "magic_resistance"; + + + public static AttributeDefinition MAIN_ATTACK; + public static AttributeDefinition MAIN_BOOST; + public static AttributeDefinition NEUTRAL_ATTACK; + public static AttributeDefinition NEUTRAL_BOOST; + + public static AttributeDefinition HEALTH; + public static AttributeDefinition CRITICAL_CHANCE; + public static AttributeDefinition CRITICAL_DAMAGE; + + public static AttributeDefinition MAGIC_DAMAGE; + public static AttributeDefinition MAGIC_BOOST; + public static AttributeDefinition MAGIC_DEFENSE; + public static AttributeDefinition MAGIC_RESISTANCE; + + public CustomAttributes(){ + HEALTH = AttributeController.registerAttribute(HEALTH_KEY, "Health", 'c', AttributeValueType.FLAT, AttributeDefinition.AttributeSection.BASE); + + MAIN_ATTACK = AttributeController.registerAttribute(MAIN_ATTACK_KEY, "Main Attack Damage", '4', AttributeValueType.FLAT, AttributeDefinition.AttributeSection.BASE); + MAIN_BOOST = AttributeController.registerAttribute(MAIN_ATTACK_BOOST_KEY, "Main Attack Damage", '4', AttributeValueType.PERCENT, AttributeDefinition.AttributeSection.MODIFIER); + + NEUTRAL_ATTACK = AttributeController.registerAttribute(NEUTRAL_KEY, "Neutral Damage", '6', AttributeValueType.FLAT, AttributeDefinition.AttributeSection.BASE); + NEUTRAL_BOOST = AttributeController.registerAttribute(NEUTRAL_BOOST_KEY, "Neutral Damage", '6', AttributeValueType.PERCENT, AttributeDefinition.AttributeSection.MODIFIER); + + CRITICAL_CHANCE = AttributeController.registerAttribute(CRITICAL_CHANCE_KEY, "Critical Chance", '6', AttributeValueType.PERCENT, AttributeDefinition.AttributeSection.INFO); + CRITICAL_DAMAGE = AttributeController.registerAttribute(CRITICAL_DAMAGE_KEY, "Critical Damage", '6', AttributeValueType.FLAT, AttributeDefinition.AttributeSection.INFO); + + MAGIC_DAMAGE = AttributeController.registerAttribute(MAGIC_DAMAGE_KEY, "Magic Damage", '3', AttributeValueType.MAGIC, AttributeDefinition.AttributeSection.BASE); + MAGIC_BOOST = AttributeController.registerAttribute(MAGIC_BOOST_KEY, "Magic Damage", '3', AttributeValueType.MAGIC, AttributeDefinition.AttributeSection.MODIFIER); + + MAGIC_DEFENSE = AttributeController.registerAttribute(MAGIC_DEFENSE_KEY, "Magic Defense", 'b', AttributeValueType.MAGIC, AttributeDefinition.AttributeSection.BASE); + MAGIC_RESISTANCE = AttributeController.registerAttribute(MAGIC_RESISTANCE_KEY, "Magic Resistance", 'b', AttributeValueType.MAGIC, AttributeDefinition.AttributeSection.MODIFIER); + + + // TODO: Attributes + // Durability Attribute + // Unique Name Attribute + + // Requirement + RequirementCheckerRegistry.registerChecker(new QuestCompletedRequirement()); + RequirementCheckerRegistry.registerChecker(new QuestActiveRequirement()); + + // TODO: Requirements + // Player Requirement : Soulbound UUID + // Profile Requirement : Slot Number + } +} diff --git a/src/main/java/kamkeel/addon/AddonManager.java b/src/main/java/kamkeel/npcs/addon/AddonManager.java similarity index 78% rename from src/main/java/kamkeel/addon/AddonManager.java rename to src/main/java/kamkeel/npcs/addon/AddonManager.java index 52aabb0f6..24b58dc3e 100644 --- a/src/main/java/kamkeel/addon/AddonManager.java +++ b/src/main/java/kamkeel/npcs/addon/AddonManager.java @@ -1,7 +1,7 @@ -package kamkeel.addon; +package kamkeel.npcs.addon; -import kamkeel.addon.client.DBCClient; -import kamkeel.addon.client.GeckoAddonClient; +import kamkeel.npcs.addon.client.DBCClient; +import kamkeel.npcs.addon.client.GeckoAddonClient; public class AddonManager { public static AddonManager Instance; diff --git a/src/main/java/kamkeel/addon/DBCAddon.java b/src/main/java/kamkeel/npcs/addon/DBCAddon.java similarity index 89% rename from src/main/java/kamkeel/addon/DBCAddon.java rename to src/main/java/kamkeel/npcs/addon/DBCAddon.java index e8f446143..4e4ff5371 100644 --- a/src/main/java/kamkeel/addon/DBCAddon.java +++ b/src/main/java/kamkeel/npcs/addon/DBCAddon.java @@ -1,6 +1,6 @@ -package kamkeel.addon; +package kamkeel.npcs.addon; -import io.netty.buffer.ByteBuf; +import cpw.mods.fml.common.Loader; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; @@ -22,6 +22,10 @@ public class DBCAddon { instance = this; } + public static boolean IsAvailable() { + return Loader.isModLoaded("npcdbc"); + } + public void dbcCopyData(EntityLivingBase copied, EntityLivingBase entity){} // AI / STATS diff --git a/src/main/java/kamkeel/addon/GeckoAddon.java b/src/main/java/kamkeel/npcs/addon/GeckoAddon.java similarity index 94% rename from src/main/java/kamkeel/addon/GeckoAddon.java rename to src/main/java/kamkeel/npcs/addon/GeckoAddon.java index 97c7a50c2..ee0f72141 100644 --- a/src/main/java/kamkeel/addon/GeckoAddon.java +++ b/src/main/java/kamkeel/npcs/addon/GeckoAddon.java @@ -1,4 +1,4 @@ -package kamkeel.addon; +package kamkeel.npcs.addon; import net.minecraft.entity.EntityLivingBase; @@ -17,4 +17,4 @@ public class GeckoAddon { public void geckoCopyData(EntityLivingBase copied, EntityLivingBase entity){} -} \ No newline at end of file +} diff --git a/src/main/java/kamkeel/addon/client/DBCClient.java b/src/main/java/kamkeel/npcs/addon/client/DBCClient.java similarity index 75% rename from src/main/java/kamkeel/addon/client/DBCClient.java rename to src/main/java/kamkeel/npcs/addon/client/DBCClient.java index f148439d6..9f839936b 100644 --- a/src/main/java/kamkeel/addon/client/DBCClient.java +++ b/src/main/java/kamkeel/npcs/addon/client/DBCClient.java @@ -1,15 +1,9 @@ -package kamkeel.addon.client; +package kamkeel.npcs.addon.client; -import io.netty.buffer.ByteBuf; -import net.minecraft.client.model.ModelBase; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; import noppes.npcs.client.gui.mainmenu.GuiNpcStats; -import noppes.npcs.client.gui.model.GuiCreationScreen; -import noppes.npcs.client.gui.player.inventory.GuiCNPCInventory; import noppes.npcs.client.gui.util.GuiNPCInterface2; import noppes.npcs.client.gui.util.GuiNpcButton; -import noppes.npcs.client.model.ModelMPM; import noppes.npcs.entity.EntityNPCInterface; public class DBCClient { @@ -39,7 +33,4 @@ public class DBCClient { public GuiNPCInterface2 manageCustomForms(EntityNPCInterface npcInterface){ return null; } // Manage Custom Forms public GuiNPCInterface2 manageCustomAuras(EntityNPCInterface npcInterface){ return null; } - - // Inventory GUI - public GuiCNPCInventory inventoryGUI(){ return null; } } diff --git a/src/main/java/kamkeel/addon/client/GeckoAddonClient.java b/src/main/java/kamkeel/npcs/addon/client/GeckoAddonClient.java similarity index 97% rename from src/main/java/kamkeel/addon/client/GeckoAddonClient.java rename to src/main/java/kamkeel/npcs/addon/client/GeckoAddonClient.java index 088488314..f014b07ad 100644 --- a/src/main/java/kamkeel/addon/client/GeckoAddonClient.java +++ b/src/main/java/kamkeel/npcs/addon/client/GeckoAddonClient.java @@ -1,4 +1,4 @@ -package kamkeel.addon.client; +package kamkeel.npcs.addon.client; import net.minecraft.client.model.ModelBase; import net.minecraft.entity.EntityLivingBase; diff --git a/src/main/java/kamkeel/command/AnimationCommand.java b/src/main/java/kamkeel/npcs/command/AnimationCommand.java similarity index 97% rename from src/main/java/kamkeel/command/AnimationCommand.java rename to src/main/java/kamkeel/npcs/command/AnimationCommand.java index 8a6beec18..e8388e802 100644 --- a/src/main/java/kamkeel/command/AnimationCommand.java +++ b/src/main/java/kamkeel/npcs/command/AnimationCommand.java @@ -1,4 +1,4 @@ -package kamkeel.command; +package kamkeel.npcs.command; import net.minecraft.command.CommandException; import net.minecraft.command.ICommandSender; @@ -9,6 +9,9 @@ import noppes.npcs.controllers.data.PlayerData; import java.util.List; +import static kamkeel.npcs.util.ColorUtil.sendError; +import static kamkeel.npcs.util.ColorUtil.sendResult; + public class AnimationCommand extends CommandKamkeelBase { @Override diff --git a/src/main/java/kamkeel/npcs/command/AttributeCommand.java b/src/main/java/kamkeel/npcs/command/AttributeCommand.java new file mode 100644 index 000000000..5a964db85 --- /dev/null +++ b/src/main/java/kamkeel/npcs/command/AttributeCommand.java @@ -0,0 +1,245 @@ +package kamkeel.npcs.command; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; +import net.minecraft.item.ItemStack; +import net.minecraft.entity.player.EntityPlayer; +import kamkeel.npcs.controllers.AttributeController; +import kamkeel.npcs.controllers.data.attribute.AttributeDefinition; +import kamkeel.npcs.controllers.data.attribute.AttributeValueType; +import kamkeel.npcs.util.AttributeItemUtil; +import noppes.npcs.controllers.MagicController; + +import static kamkeel.npcs.util.ColorUtil.sendError; +import static kamkeel.npcs.util.ColorUtil.sendResult; + +public class AttributeCommand extends CommandKamkeelBase { + + @Override + public String getCommandName() { + return "attribute"; + } + + @Override + public String getDescription() { + return "Manage attributes on your held item"; + } + + @SubCommand( + name = "list", + usage = "[page]", + desc = "Lists all available attributes" + ) + public void list(ICommandSender sender, String[] args) throws CommandException { + // Get all registered attributes. + List defs = new ArrayList(AttributeController.getAllAttributes()); + if(defs.isEmpty()){ + sendError(sender, "No attributes found."); + return; + } + // Sort attributes by display name. + Collections.sort(defs, new Comparator() { + @Override + public int compare(AttributeDefinition a, AttributeDefinition b) { + return a.getKey().compareToIgnoreCase(b.getKey()); + } + }); + + // Determine which page to show. + int page = 1; + if(args.length > 0) { + try { + page = Integer.parseInt(args[0]); + } catch(NumberFormatException e) { + // If parsing fails, default to page 1. + } + } + int perPage = 10; + int total = defs.size(); + int totalPages = (int)Math.ceil(total / (double) perPage); + if(page < 1) page = 1; + if(page > totalPages) page = totalPages; + int startIndex = (page - 1) * perPage; + int endIndex = Math.min(startIndex + perPage, total); + + sendResult(sender, "--------------------"); + sendResult(sender, "Attributes (Page " + page + "/" + totalPages + "):"); + for (int i = startIndex; i < endIndex; i++) { + AttributeDefinition def = defs.get(i); + // First line: numbered display name. + sendResult(sender, (i + 1) + ". " + def.getDisplayName()); + // Second line: key and value type. + sendResult(sender, " - " + def.getKey() + ", " + def.getValueType()); + } + sendResult(sender, "--------------------"); + } + + @SubCommand( + name = "apply", + usage = " [magicID]", + desc = "Applies an attribute to your held item. For magic attributes, provide a magicID." + ) + public void apply(ICommandSender sender, String[] args) throws CommandException { + if(!(sender instanceof EntityPlayer)){ + sendError(sender, "Only players can use this command."); + return; + } + + EntityPlayer player = (EntityPlayer)sender; + ItemStack held = player.getHeldItem(); + if(held == null){ + sendError(sender, "You are not holding an item."); + return; + } + + String attrKey = args[0]; + AttributeDefinition def = AttributeController.getAttribute(attrKey); + if(def == null){ + sendError(sender, "Unknown attribute: " + attrKey); + return; + } + + // Check if this is a magic attribute. + if(def.getValueType() == AttributeValueType.MAGIC) { + if(args.length < 3){ + sendError(sender, "Usage for magic attribute: apply "); + return; + } + int magicId; + float value; + try { + value = Float.parseFloat(args[1]); + magicId = Integer.parseInt(args[2]); + } catch(NumberFormatException e) { + sendError(sender, "Invalid number format for magicID or value."); + return; + } + + if(MagicController.getInstance().getMagic(magicId) == null){ + sendError(sender, "No Magic Found for Magic ID %d", magicId); + return; + } + + AttributeItemUtil.writeMagicAttribute(held, attrKey, magicId, value); + sendResult(sender, "Applied magic attribute " + attrKey + " with magicID " + magicId + " and value " + value + " to held item."); + } else { + if(args.length < 2){ + sendError(sender, "Usage: "); + return; + } + float value; + try { + value = Float.parseFloat(args[1]); + } catch(NumberFormatException e) { + sendError(sender, "Invalid number format for value."); + return; + } + AttributeItemUtil.applyAttribute(held, attrKey, value); + sendResult(sender, "Applied attribute " + attrKey + " with value " + value + " to held item."); + } + } + + @SubCommand( + name = "remove", + usage = " [magicID)", + desc = "Removes an attribute from your held item. For magic attributes, provide a magicID." + ) + public void remove(ICommandSender sender, String[] args) throws CommandException { + if(!(sender instanceof EntityPlayer)){ + sendError(sender, "Only players can use this command."); + return; + } + EntityPlayer player = (EntityPlayer)sender; + ItemStack held = player.getHeldItem(); + if(held == null){ + sendError(sender, "You are not holding an item."); + return; + } + + String attrKey = args[0]; + AttributeDefinition def = AttributeController.getAttribute(attrKey); + if(def == null){ + sendError(sender, "Unknown attribute: " + attrKey); + return; + } + + if(def.getValueType() == AttributeValueType.MAGIC) { + if(args.length < 2){ + sendError(sender, "Usage for magic attribute: remove "); + return; + } + int magicId; + try { + magicId = Integer.parseInt(args[1]); + } catch(NumberFormatException e) { + sendError(sender, "Invalid magicID format."); + return; + } + + if(MagicController.getInstance().getMagic(magicId) == null){ + sendError(sender, "No Magic Found for Magic ID %d", magicId); + return; + } + + AttributeItemUtil.removeMagicAttribute(held, attrKey, magicId); + sendResult(sender, "Removed magic attribute " + attrKey + " (magicID " + magicId + ") from held item."); + } else { + AttributeItemUtil.removeAttribute(held, attrKey); + sendResult(sender, "Removed attribute " + attrKey + " from held item."); + } + } + + @SubCommand( + name = "requirement", + usage = " [value]", + desc = "Apply or remove a requirement from your held item." + ) + public void requirement(ICommandSender sender, String[] args) throws CommandException { + if (!(sender instanceof EntityPlayer)) { + sendError(sender, "Only players can use this command."); + return; + } + EntityPlayer player = (EntityPlayer) sender; + ItemStack held = player.getHeldItem(); + if (held == null) { + sendError(sender, "You are not holding an item."); + return; + } + if (args.length < 2) { + sendError(sender, "Usage: requirement [value]"); + return; + } + String action = args[0]; + String reqKey = args[1]; + if (action.equalsIgnoreCase("apply")) { + if (args.length < 3) { + sendError(sender, "Usage: requirement apply "); + return; + } + String valueStr = args[2]; + Object value; + try { + value = Integer.parseInt(valueStr); + } catch (NumberFormatException e1) { + try { + value = Float.parseFloat(valueStr); + } catch (NumberFormatException e2) { + value = valueStr; + } + } + + AttributeItemUtil.applyRequirement(held, reqKey, value); + sendResult(sender, "Applied requirement " + reqKey + " with value " + value + " to held item."); + } else if (action.equalsIgnoreCase("remove")) { + AttributeItemUtil.removeRequirement(held, reqKey); + sendResult(sender, "Removed requirement " + reqKey + " from held item."); + } else { + sendError(sender, "Invalid action. Use apply or remove."); + } + } +} diff --git a/src/main/java/kamkeel/command/CloneCommand.java b/src/main/java/kamkeel/npcs/command/CloneCommand.java similarity index 94% rename from src/main/java/kamkeel/command/CloneCommand.java rename to src/main/java/kamkeel/npcs/command/CloneCommand.java index 174d1039a..3ce2f02b8 100644 --- a/src/main/java/kamkeel/command/CloneCommand.java +++ b/src/main/java/kamkeel/npcs/command/CloneCommand.java @@ -1,8 +1,7 @@ -package kamkeel.command; +package kamkeel.npcs.command; import foxz.utils.Utils; import net.minecraft.block.Block; -import net.minecraft.command.CommandBase; import net.minecraft.command.CommandException; import net.minecraft.command.ICommandSender; import net.minecraft.entity.Entity; @@ -18,6 +17,8 @@ import noppes.npcs.entity.EntityNPCInterface; import java.util.List; +import static kamkeel.npcs.util.ColorUtil.*; + public class CloneCommand extends CommandKamkeelBase { @Override @@ -180,9 +181,9 @@ public class CloneCommand extends CommandKamkeelBase { return; } try{ - posX = CommandBase.func_110666_a(sender, posX, par[0]); - posY = CommandBase.func_110665_a(sender, posY, par[1].trim(), 0, 0); - posZ = CommandBase.func_110666_a(sender, posZ, par[2]); + posX = func_110666_a(sender, posX, par[0]); + posY = func_110665_a(sender, posY, par[1].trim(), 0, 0); + posZ = func_110666_a(sender, posZ, par[2]); } catch(NumberFormatException ex){ sendError(sender, "Location should be in numbers"); return; @@ -204,7 +205,7 @@ public class CloneCommand extends CommandKamkeelBase { entity.setPosition(posX + 0.5, posY + 1, posZ + 0.5); if(entity instanceof EntityNPCInterface){ EntityNPCInterface npc = (EntityNPCInterface) entity; - npc.ai.startPos = new int[]{MathHelper.floor_double(posX), MathHelper.floor_double(posY), MathHelper.floor_double(posZ)}; + npc.ais.startPos = new int[]{MathHelper.floor_double(posX), MathHelper.floor_double(posY), MathHelper.floor_double(posZ)}; if(newname != null && !newname.isEmpty()) npc.display.name = newname.replaceAll("%", " "); // like name, newname must use % in place of space to keep a logical way } @@ -272,9 +273,9 @@ public class CloneCommand extends CommandKamkeelBase { return; } try{ - posX = CommandBase.func_110666_a(sender, posX, par[0]); - posY = CommandBase.func_110665_a(sender, posY, par[1].trim(), 0, 0); - posZ = CommandBase.func_110666_a(sender, posZ, par[2]); + posX = func_110666_a(sender, posX, par[0]); + posY = func_110665_a(sender, posY, par[1].trim(), 0, 0); + posZ = func_110666_a(sender, posZ, par[2]); } catch(NumberFormatException ex){ sendError(sender, "Location should be in numbers"); return; @@ -310,7 +311,7 @@ public class CloneCommand extends CommandKamkeelBase { entity.setPosition(posX + 0.5 + x, yy + 1, posZ + 0.5 + z); if(entity instanceof EntityNPCInterface){ EntityNPCInterface npc = (EntityNPCInterface) entity; - npc.ai.startPos = new int[]{xx, yy, zz}; + npc.ais.startPos = new int[]{xx, yy, zz}; if(newname != null && !newname.isEmpty()) npc.display.name = newname.replaceAll("%", " "); // like name, newname must use % in place of space to keep a logical way } diff --git a/src/main/java/kamkeel/command/CommandCommand.java b/src/main/java/kamkeel/npcs/command/CommandCommand.java similarity index 92% rename from src/main/java/kamkeel/command/CommandCommand.java rename to src/main/java/kamkeel/npcs/command/CommandCommand.java index 80a41ec28..edc20b84d 100644 --- a/src/main/java/kamkeel/command/CommandCommand.java +++ b/src/main/java/kamkeel/npcs/command/CommandCommand.java @@ -1,4 +1,4 @@ -package kamkeel.command; +package kamkeel.npcs.command; import net.minecraft.command.CommandException; import net.minecraft.command.ICommandSender; @@ -10,6 +10,9 @@ import noppes.npcs.api.IWorld; import noppes.npcs.scripted.NpcAPI; import noppes.npcs.scripted.event.CustomNPCsEvent; +import static kamkeel.npcs.util.ColorUtil.sendError; +import static kamkeel.npcs.util.ColorUtil.sendMessage; + public class CommandCommand extends CommandKamkeelBase { @Override diff --git a/src/main/java/kamkeel/npcs/command/CommandKamkeel.java b/src/main/java/kamkeel/npcs/command/CommandKamkeel.java new file mode 100644 index 000000000..4e0b26afd --- /dev/null +++ b/src/main/java/kamkeel/npcs/command/CommandKamkeel.java @@ -0,0 +1,173 @@ +package kamkeel.npcs.command; + +import kamkeel.npcs.controllers.data.attribute.requirement.RequirementCheckerRegistry; +import net.minecraft.command.CommandBase; +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.server.MinecraftServer; +import noppes.npcs.CustomNpcsPermissions; +import kamkeel.npcs.controllers.AttributeController; +import kamkeel.npcs.controllers.data.attribute.AttributeDefinition; +import noppes.npcs.config.ConfigMain; +import noppes.npcs.scripted.CustomNPCsException; + +import java.lang.reflect.Method; +import java.util.*; + +import static kamkeel.npcs.command.EffectCommand.getSortedEffectNames; + +public class CommandKamkeel extends CommandBase{ + + public Map map = new HashMap(); + public HelpCommand help = new HelpCommand(this); + public String[] alias = {"kam"}; + + public CommandKamkeel(){ + registerCommand(help); + registerCommand(new ScriptCommand()); + registerCommand(new SlayCommand()); + registerCommand(new QuestCommand()); + registerCommand(new QuestCategoryCommand()); + registerCommand(new DialogCommand()); + registerCommand(new DialogCategoryCommand()); + registerCommand(new FactionCommand()); + registerCommand(new NpcCommand()); + registerCommand(new CloneCommand()); + registerCommand(new ConfigCommand()); + registerCommand(new AnimationCommand()); + registerCommand(new OverlayCommand()); + registerCommand(new CommandCommand()); + registerCommand(new EffectCommand()); + if(ConfigMain.AttributesEnabled) + registerCommand(new AttributeCommand()); + } + + public void registerCommand(CommandKamkeelBase command){ + String name = command.getCommandName().toLowerCase(); + if(map.containsKey(name)) + throw new CustomNPCsException("Already a subcommand with the name: " + name); + map.put(name, command); + } + + @Override + public String getCommandName() { + return "kamkeel"; + } + + @Override + public List getCommandAliases() + { + return Arrays.asList(alias); + } + + @Override + public String getCommandUsage(ICommandSender sender) { + return "Use as /kamkeel subcommand"; + } + + @Override + public void processCommand(ICommandSender sender, String[] args) throws CommandException { + if(args.length == 0){ + help.processCommand(sender, args); + return; + } + + CommandKamkeelBase command = getCommand(args); + if(command == null) + throw new CommandException("Unknown command " + args[0]); + + args = Arrays.copyOfRange(args, 1, args.length); + if(command.subcommands.isEmpty() || !command.runSubCommands()){ + if(!canSendCommand(sender, command)) + throw new CommandException("You are not allowed to use this command: " + command); + command.canRun(sender, command.getUsage(), args); + command.processCommand(sender, args); + return; + } + + if(args.length == 0){ + help.processCommand(sender, new String[]{command.getCommandName()}); + return; + } + + command.processSubCommand(sender, args[0], Arrays.copyOfRange(args, 1, args.length)); + } + + @Override + public List addTabCompletionOptions(ICommandSender sender, String[] args){ + if(args.length == 1) + return CommandBase.getListOfStringsMatchingLastWord(args, map.keySet().toArray(new String[map.size()])); + CommandKamkeelBase command = getCommand(args); + if(command == null) + return null; + if(args.length == 2 && command.runSubCommands()) + return CommandBase.getListOfStringsMatchingLastWord(args, command.subcommands.keySet().toArray(new String[command.subcommands.keySet().size()])); + String[] useArgs = command.getUsage().split(" "); + if(command.runSubCommands()) { + Method m = command.subcommands.get(args[1].toLowerCase()); + if(m != null) { + useArgs = m.getAnnotation(CommandKamkeelBase.SubCommand.class).usage().split(" "); + } + } + if(args.length <= useArgs.length + 2) { + if(args.length - 3 >= 0){ + String usage = useArgs[args.length - 3]; + if(usage.equals("") || usage.equals("[player]")) { + return CommandBase.getListOfStringsMatchingLastWord(args, MinecraftServer.getServer().getAllUsernames()); + } + else if(usage.equals("")) { + List keys = new ArrayList<>(); + for (AttributeDefinition def : AttributeController.getAllAttributes()) { + keys.add(def.getKey()); + } + return CommandBase.getListOfStringsMatchingLastWord(args, keys.toArray(new String[keys.size()])); + } else if (usage.equals("")) { + List keys = new ArrayList<>(RequirementCheckerRegistry.getAllKeys()); + return CommandBase.getListOfStringsMatchingLastWord(args, keys.toArray(new String[keys.size()])); + } else if(usage.equals("")){ + List keys = getSortedEffectNames(); + return CommandBase.getListOfStringsMatchingLastWord(args, keys.toArray(new String[keys.size()])); + } + } + } + return command.addTabCompletionOptions(sender, Arrays.copyOfRange(args, 1, args.length)); + } + + public CommandKamkeelBase getCommand(String[] args){ + if(args.length == 0) + return null; + return map.get(args[0].toLowerCase()); + } + + @Override + public int getRequiredPermissionLevel(){ + return 2; + } + + public static String getCommandPermission(String command){ + return "cnpc.kamkeel." + command.toLowerCase(); + } + + public static String getUniversalPermission(){ + return "cnpc.kamkeel.*"; + } + + public static boolean canSendCommand(ICommandSender sender, CommandKamkeelBase command){ + if(sender.canCommandSenderUseCommand(command.getRequiredPermissionLevel(), getUniversalPermission())){ + return true; + } + + if(sender.canCommandSenderUseCommand(command.getRequiredPermissionLevel(), getCommandPermission(command.getCommandName()))){ + return true; + } + + if(sender instanceof EntityPlayer){ + return CustomNpcsPermissions.hasCustomPermission((EntityPlayer) sender, getCommandPermission(command.getCommandName())); + } + + return false; + } + +} + diff --git a/src/main/java/kamkeel/command/CommandKamkeelBase.java b/src/main/java/kamkeel/npcs/command/CommandKamkeelBase.java similarity index 85% rename from src/main/java/kamkeel/command/CommandKamkeelBase.java rename to src/main/java/kamkeel/npcs/command/CommandKamkeelBase.java index 9c380f7c2..cc874f392 100644 --- a/src/main/java/kamkeel/command/CommandKamkeelBase.java +++ b/src/main/java/kamkeel/npcs/command/CommandKamkeelBase.java @@ -1,10 +1,9 @@ -package kamkeel.command; +package kamkeel.npcs.command; import net.minecraft.command.CommandBase; import net.minecraft.command.CommandException; import net.minecraft.command.ICommandSender; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.util.ChatComponentTranslation; import noppes.npcs.CustomNpcsPermissions; import java.lang.annotation.ElementType; @@ -55,18 +54,6 @@ public abstract class CommandKamkeelBase extends CommandBase{ return !subcommands.isEmpty(); } - protected static void sendMessage(ICommandSender sender, String message, Object... obs) { - sender.addChatMessage(new ChatComponentTranslation(message, obs)); - } - - protected static void sendResult(ICommandSender sender, String message, Object... obs) { - sender.addChatMessage(new ChatComponentTranslation("\u00A76[\u00A7eCNPC+\u00A76]\u00A77 " + message, obs)); - } - - protected static void sendError(ICommandSender sender, String message, Object... obs) { - sender.addChatMessage(new ChatComponentTranslation("\u00A76[\u00A7eCNPC+\u00A76]\u00A74 Error:\u00A7c " + message, obs)); - } - @Retention(value = RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface SubCommand { diff --git a/src/main/java/kamkeel/command/ConfigCommand.java b/src/main/java/kamkeel/npcs/command/ConfigCommand.java similarity index 95% rename from src/main/java/kamkeel/command/ConfigCommand.java rename to src/main/java/kamkeel/npcs/command/ConfigCommand.java index 4be014417..b432df26e 100644 --- a/src/main/java/kamkeel/command/ConfigCommand.java +++ b/src/main/java/kamkeel/npcs/command/ConfigCommand.java @@ -1,6 +1,9 @@ -package kamkeel.command; +package kamkeel.npcs.command; import foxz.utils.Market; +import kamkeel.npcs.network.PacketHandler; +import kamkeel.npcs.network.enums.EnumConfigOperation; +import kamkeel.npcs.network.packets.data.ConfigCommandPacket; import net.minecraft.block.Block; import net.minecraft.block.BlockIce; import net.minecraft.block.BlockLeavesBase; @@ -10,15 +13,16 @@ import net.minecraft.command.ICommandSender; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.util.ResourceLocation; import noppes.npcs.CustomNpcs; -import noppes.npcs.Server; import noppes.npcs.config.ConfigMain; -import noppes.npcs.constants.EnumPacketClient; import noppes.npcs.controllers.ChunkController; import noppes.npcs.controllers.PlayerDataController; import java.util.Arrays; import java.util.Set; +import static kamkeel.npcs.util.ColorUtil.sendError; +import static kamkeel.npcs.util.ColorUtil.sendResult; + public class ConfigCommand extends CommandKamkeelBase { @@ -291,8 +295,7 @@ public class ConfigCommand extends CommandKamkeelBase { for(int i = 0; i < args.length; i++){ font += " " + args[i]; } - Server.sendData((EntityPlayerMP)sender, EnumPacketClient.CONFIG, 0, font.trim(), size); + PacketHandler.Instance.sendToPlayer(new ConfigCommandPacket(EnumConfigOperation.FONT, font.trim(), size), (EntityPlayerMP)sender); } - } diff --git a/src/main/java/kamkeel/command/DialogCategoryCommand.java b/src/main/java/kamkeel/npcs/command/DialogCategoryCommand.java similarity index 97% rename from src/main/java/kamkeel/command/DialogCategoryCommand.java rename to src/main/java/kamkeel/npcs/command/DialogCategoryCommand.java index 648920e06..cf1424386 100644 --- a/src/main/java/kamkeel/command/DialogCategoryCommand.java +++ b/src/main/java/kamkeel/npcs/command/DialogCategoryCommand.java @@ -1,4 +1,4 @@ -package kamkeel.command; +package kamkeel.npcs.command; import net.minecraft.command.CommandException; import net.minecraft.command.ICommandSender; @@ -11,6 +11,9 @@ import noppes.npcs.controllers.data.PlayerData; import java.util.Collection; import java.util.List; +import static kamkeel.npcs.util.ColorUtil.sendError; +import static kamkeel.npcs.util.ColorUtil.sendResult; + public class DialogCategoryCommand extends CommandKamkeelBase { @Override diff --git a/src/main/java/kamkeel/command/DialogCommand.java b/src/main/java/kamkeel/npcs/command/DialogCommand.java similarity index 98% rename from src/main/java/kamkeel/command/DialogCommand.java rename to src/main/java/kamkeel/npcs/command/DialogCommand.java index ac9ecd543..d3953bad3 100644 --- a/src/main/java/kamkeel/command/DialogCommand.java +++ b/src/main/java/kamkeel/npcs/command/DialogCommand.java @@ -1,5 +1,6 @@ -package kamkeel.command; +package kamkeel.npcs.command; +import kamkeel.npcs.controllers.SyncController; import net.minecraft.command.CommandBase; import net.minecraft.command.CommandException; import net.minecraft.command.ICommandSender; @@ -10,7 +11,6 @@ import noppes.npcs.constants.EnumAvailabilityDialog; import noppes.npcs.constants.EnumAvailabilityQuest; import noppes.npcs.controllers.DialogController; import noppes.npcs.controllers.PlayerDataController; -import noppes.npcs.controllers.SyncController; import noppes.npcs.controllers.data.Availability; import noppes.npcs.controllers.data.Dialog; import noppes.npcs.controllers.data.DialogOption; @@ -20,6 +20,9 @@ import noppes.npcs.entity.EntityDialogNpc; import java.util.Collection; import java.util.List; +import static kamkeel.npcs.util.ColorUtil.sendError; +import static kamkeel.npcs.util.ColorUtil.sendResult; + public class DialogCommand extends CommandKamkeelBase { @Override diff --git a/src/main/java/kamkeel/npcs/command/EffectCommand.java b/src/main/java/kamkeel/npcs/command/EffectCommand.java new file mode 100644 index 000000000..85c9da734 --- /dev/null +++ b/src/main/java/kamkeel/npcs/command/EffectCommand.java @@ -0,0 +1,345 @@ +package kamkeel.npcs.command; + +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; +import noppes.npcs.controllers.CustomEffectController; +import noppes.npcs.controllers.PlayerDataController; +import noppes.npcs.controllers.data.CustomEffect; +import noppes.npcs.controllers.data.PlayerData; +import noppes.npcs.scripted.event.PlayerEvent.EffectEvent.ExpirationType; + +import java.util.*; + +import static kamkeel.npcs.util.ColorUtil.sendError; +import static kamkeel.npcs.util.ColorUtil.sendResult; + +public class EffectCommand extends CommandKamkeelBase { + + @Override + public String getDescription() { + return "Custom Effect operations"; + } + + @Override + public String getCommandName() { + return "effect"; + } + + // List command with pagination + @SubCommand(desc = "Lists all Effects", usage = "[page]") + public void list(ICommandSender sender, String[] args) throws CommandException { + CustomEffectController controller = CustomEffectController.getInstance(); + if (controller.indexMapper.isEmpty()) { + sendError(sender, "No effects found."); + return; + } + + // Flatten effects into a list + List effectsList = new ArrayList<>(); + for (Map.Entry> entry : controller.indexMapper.entrySet()) { + int idx = entry.getKey(); + Map effects = entry.getValue(); + if (effects == null || effects.isEmpty()) + continue; + for (Map.Entry effectEntry : effects.entrySet()) { + int id = effectEntry.getKey(); + CustomEffect effect = effectEntry.getValue(); + effectsList.add(new EffectEntry(idx, id, effect)); + } + } + // Sort by index then by effect ID + Collections.sort(effectsList, Comparator.comparingInt((EffectEntry e) -> e.index) + .thenComparingInt(e -> e.id)); + + // Determine page number + int page = 1; + if (args.length > 0) { + try { + page = Integer.parseInt(args[0]); + } catch (NumberFormatException e) { + // default to page 1 + } + } + int perPage = 10; + int total = effectsList.size(); + int totalPages = (int) Math.ceil(total / (double) perPage); + if (page < 1) page = 1; + if (page > totalPages) page = totalPages; + int startIndex = (page - 1) * perPage; + int endIndex = Math.min(startIndex + perPage, total); + + sendResult(sender, "--------------------"); + sendResult(sender, "Effects (Page " + page + "/" + totalPages + "):"); + for (int i = startIndex; i < endIndex; i++) { + EffectEntry entry = effectsList.get(i); + sendResult(sender, String.format("\u00a7b%s \u00a77(ID: %d, INDEX: %d)", + entry.effect.getName(), + entry.id, + entry.index)); + } + sendResult(sender, "--------------------"); + } + + + // Give effect by name. + // Usage: