Better Effect List, Give and Remove Commands with Tab Completion

This commit is contained in:
Kam committed 2025-03-05 23:13:39 -05:00
1 parent 7a16cdf520
commit f334980f22
2 files changed
+166 -84

No files matched your search

@@ -15,6 +15,8 @@ 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<String, CommandKamkeelBase> map = new HashMap<String, CommandKamkeelBase>();
@@ -123,6 +125,9 @@ public class CommandKamkeel extends CommandBase{
} else if (usage.equals("<requirement>")) {
List<String> keys = new ArrayList<>(RequirementCheckerRegistry.getAllKeys());
return CommandBase.getListOfStringsMatchingLastWord(args, keys.toArray(new String[keys.size()]));
} else if(usage.equals("<effectName>")){
List<String> keys = getSortedEffectNames();
return CommandBase.getListOfStringsMatchingLastWord(args, keys.toArray(new String[keys.size()]));
}
}
}
@@ -163,5 +168,6 @@ public class CommandKamkeel extends CommandBase{
return false;
}
}
@@ -8,10 +8,7 @@ import noppes.npcs.controllers.data.CustomEffect;
import noppes.npcs.controllers.data.PlayerData;
import noppes.npcs.scripted.event.PlayerEvent.EffectEvent.ExpirationType;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.*;
import static kamkeel.npcs.util.ColorUtil.sendError;
import static kamkeel.npcs.util.ColorUtil.sendResult;
@@ -28,7 +25,8 @@ public class EffectCommand extends CommandKamkeelBase {
return "effect";
}
@SubCommand(desc = "Lists all Effects")
// 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()) {
@@ -36,36 +34,59 @@ public class EffectCommand extends CommandKamkeelBase {
return;
}
sendResult(sender, "--------------------");
// Get all indices, sort them in ascending order.
List<Integer> indices = new ArrayList<>(controller.indexMapper.keySet());
Collections.sort(indices);
for (Integer idx : indices) {
Map<Integer, CustomEffect> effects = controller.indexMapper.get(idx);
// Flatten effects into a list
List<EffectEntry> effectsList = new ArrayList<>();
for (Map.Entry<Integer, HashMap<Integer, CustomEffect>> entry : controller.indexMapper.entrySet()) {
int idx = entry.getKey();
Map<Integer, CustomEffect> effects = entry.getValue();
if (effects == null || effects.isEmpty())
continue;
// Sort the effect IDs in ascending order.
List<Integer> effectIds = new ArrayList<>(effects.keySet());
Collections.sort(effectIds);
for (Integer id : effectIds) {
CustomEffect effect = effects.get(id);
sendResult(sender, String.format("\u00a7b%s \u00a77(ID: %d, INDEX: %d)",
effect.getName(),
id,
idx));
for (Map.Entry<Integer, CustomEffect> 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: <player> <time> <effectName> [index]
@SubCommand(desc = "Gives an effect to a player", usage = "<player> <time> <effectName> [index]")
// Usage: <player> <time> <effectName>
@SubCommand(desc = "Gives an effect to a player", usage = "<player> <time> <effectName>")
public void give(ICommandSender sender, String[] args) throws CommandException {
if (args.length < 3) {
sendError(sender, "Usage: <player> <time> <effectName> [index]");
sendError(sender, "Usage: <player> <time> <effectName>");
return;
}
@@ -78,28 +99,31 @@ public class EffectCommand extends CommandKamkeelBase {
return;
}
int index = 0;
String effectName;
if (args.length > 3) {
// Try to parse the last argument as the index.
try {
index = Integer.parseInt(args[args.length - 1]);
StringBuilder sb = new StringBuilder();
for (int i = 2; i < args.length - 1; i++) {
sb.append(args[i]).append(i < args.length - 2 ? " " : "");
}
effectName = sb.toString();
} catch (NumberFormatException e) {
// If parsing fails, assume the entire remainder is the effect name.
StringBuilder sb = new StringBuilder();
for (int i = 2; i < args.length; i++) {
sb.append(args[i]).append(i < args.length - 1 ? " " : "");
}
effectName = sb.toString();
}
} else {
effectName = args[2];
// Join all remaining arguments as the effect name.
StringBuilder sb = new StringBuilder();
for (int i = 2; i < args.length; i++) {
sb.append(args[i]).append(i < args.length - 1 ? " " : "");
}
String effectName = sb.toString();
List<EffectEntry> matches = findEffectsByName(effectName);
if (matches.isEmpty()) {
sendError(sender, "Unknown effect: " + effectName);
return;
}
if (matches.size() > 1) {
StringBuilder ambig = new StringBuilder();
ambig.append("Ambiguous effect name '").append(effectName).append("'. Multiple matches: ");
for (EffectEntry match : matches) {
ambig.append(match.effect.getName())
.append(" (ID: ").append(match.id)
.append(", INDEX: ").append(match.index)
.append("), ");
}
sendError(sender, ambig.substring(0, ambig.length() - 2));
return;
}
EffectEntry match = matches.get(0);
List<PlayerData> players = PlayerDataController.Instance.getPlayersData(sender, playername);
if (players.isEmpty()) {
@@ -107,51 +131,50 @@ public class EffectCommand extends CommandKamkeelBase {
return;
}
CustomEffect effect = CustomEffectController.getInstance().get(effectName, index);
if (effect == null) {
sendError(sender, "Unknown effect: " + effectName + " with index " + index);
return;
}
for (PlayerData pdata : players) {
CustomEffectController.getInstance().applyEffect(pdata.player, effect.getID(), time, (byte) 1, index);
sendResult(sender, String.format("%s §agiven to §7'§b%s§7'", effect.getName(), pdata.playername));
CustomEffectController.getInstance().applyEffect(pdata.player, match.id, time, (byte) 1, match.index);
sendResult(sender, String.format("%s §agiven to §7'§b%s§7'", match.effect.getName(), pdata.playername));
if (sender != pdata.player) {
sendResult(pdata.player, String.format("Effect §7%s §aadded.", effect.getName()));
sendResult(pdata.player, String.format("Effect §7%s §aadded.", match.effect.getName()));
}
}
}
// Remove effect by name.
// Usage: <player> <effectName> [index]
@SubCommand(desc = "Removes an effect from a player", usage = "<player> <effectName> [index]")
// Usage: <player> <effectName>
@SubCommand(desc = "Removes an effect from a player", usage = "<player> <effectName>")
public void remove(ICommandSender sender, String[] args) throws CommandException {
if (args.length < 2) {
sendError(sender, "Usage: <player> <effectName> [index]");
sendError(sender, "Usage: <player> <effectName>");
return;
}
String playername = args[0];
int index = 0;
String effectName;
if (args.length > 2) {
try {
index = Integer.parseInt(args[args.length - 1]);
StringBuilder sb = new StringBuilder();
for (int i = 1; i < args.length - 1; i++) {
sb.append(args[i]).append(i < args.length - 2 ? " " : "");
}
effectName = sb.toString();
} catch (NumberFormatException e) {
StringBuilder sb = new StringBuilder();
for (int i = 1; i < args.length; i++) {
sb.append(args[i]).append(i < args.length - 1 ? " " : "");
}
effectName = sb.toString();
}
} else {
effectName = args[1];
// Join all remaining arguments as the effect name.
StringBuilder sb = new StringBuilder();
for (int i = 1; i < args.length; i++) {
sb.append(args[i]).append(i < args.length - 1 ? " " : "");
}
String effectName = sb.toString();
List<EffectEntry> matches = findEffectsByName(effectName);
if (matches.isEmpty()) {
sendError(sender, "Unknown effect: " + effectName);
return;
}
if (matches.size() > 1) {
StringBuilder ambig = new StringBuilder();
ambig.append("Ambiguous effect name '").append(effectName).append("'. Multiple matches: ");
for (EffectEntry match : matches) {
ambig.append(match.effect.getName())
.append(" (ID: ").append(match.id)
.append(", INDEX: ").append(match.index)
.append("), ");
}
sendError(sender, ambig.substring(0, ambig.length() - 2));
return;
}
EffectEntry match = matches.get(0);
List<PlayerData> players = PlayerDataController.Instance.getPlayersData(sender, playername);
if (players.isEmpty()) {
@@ -159,15 +182,9 @@ public class EffectCommand extends CommandKamkeelBase {
return;
}
CustomEffect effect = CustomEffectController.getInstance().get(effectName, index);
if (effect == null) {
sendError(sender, "Unknown effect: " + effectName + " with index " + index);
return;
}
for (PlayerData pdata : players) {
CustomEffectController.getInstance().removeEffect(pdata.player, effect.getID(), index, ExpirationType.REMOVED);
sendResult(sender, String.format("Effect %s removed from %s", effect.getName(), pdata.playername));
CustomEffectController.getInstance().removeEffect(pdata.player, match.id, match.index, ExpirationType.REMOVED);
sendResult(sender, String.format("Effect %s removed from %s", match.effect.getName(), pdata.playername));
}
}
@@ -266,4 +283,63 @@ public class EffectCommand extends CommandKamkeelBase {
sendResult(sender, String.format("Effect %d removed from %s", effectId, pdata.playername));
}
}
private static class EffectEntry {
int index;
int id;
CustomEffect effect;
public EffectEntry(int index, int id, CustomEffect effect) {
this.index = index;
this.id = id;
this.effect = effect;
}
}
// Helper method to find effects by name.
private List<EffectEntry> findEffectsByName(String name) {
List<EffectEntry> matches = new ArrayList<>();
CustomEffectController controller = CustomEffectController.getInstance();
for (Map.Entry<Integer, HashMap<Integer, CustomEffect>> entry : controller.indexMapper.entrySet()) {
int idx = entry.getKey();
Map<Integer, CustomEffect> effects = entry.getValue();
if (effects == null) continue;
for (Map.Entry<Integer, CustomEffect> effectEntry : effects.entrySet()) {
int id = effectEntry.getKey();
CustomEffect effect = effectEntry.getValue();
if (effect.getName().equalsIgnoreCase(name)) {
List<EffectEntry> exact = new ArrayList<>();
exact.add(new EffectEntry(idx, id, effect));
return exact;
} else if (effect.getName().toLowerCase().contains(name.toLowerCase())) {
matches.add(new EffectEntry(idx, id, effect));
}
}
}
return matches;
}
public static List<String> getSortedEffectNames() {
List<EffectEntry> entries = new ArrayList<>();
CustomEffectController controller = CustomEffectController.getInstance();
for (Map.Entry<Integer, HashMap<Integer, CustomEffect>> indexEntry : controller.indexMapper.entrySet()) {
int index = indexEntry.getKey();
Map<Integer, CustomEffect> effects = indexEntry.getValue();
if (effects != null) {
for (Map.Entry<Integer, CustomEffect> effectEntry : effects.entrySet()) {
int id = effectEntry.getKey();
CustomEffect effect = effectEntry.getValue();
entries.add(new EffectEntry(index, id, effect));
}
}
}
// Sort entries by index then by effect ID.
entries.sort(Comparator.comparingInt((EffectEntry e) -> e.index)
.thenComparingInt(e -> e.id));
List<String> effectNames = new ArrayList<>();
for (EffectEntry entry : entries) {
effectNames.add(entry.effect.getName());
}
return effectNames;
}
}