Skip to content
This repository was archived by the owner on Aug 12, 2025. It is now read-only.

Commit ee62d50

Browse files
committed
Refactor NPC action handling to use a map for actions and improve command structure
1 parent 8e23838 commit ee62d50

1 file changed

Lines changed: 153 additions & 46 deletions

File tree

src/main/java/gg/nextforge/command/builtin/NPCCommand.java

Lines changed: 153 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,7 @@
1515
import org.bukkit.inventory.EntityEquipment;
1616
import org.bukkit.inventory.ItemStack;
1717

18-
import java.util.Arrays;
19-
import java.util.Comparator;
20-
import java.util.List;
21-
import java.util.Map;
18+
import java.util.*;
2219
import java.util.stream.Collectors;
2320

2421
public class NPCCommand {
@@ -133,7 +130,7 @@ private void handleCreate(CommandContext ctx) {
133130
.turnToPlayer(false)
134131
.turnToPlayerDistance(3.0)
135132
.attributes(new java.util.HashMap<>())
136-
.actions(new java.util.ArrayList<>())
133+
.actions(new java.util.HashMap<>())
137134
.location(loc)
138135
.build();
139136
npcManager.register(npc);
@@ -170,7 +167,7 @@ private void handleCopy(CommandContext ctx) {
170167
.turnToPlayer(orig.isTurnToPlayer())
171168
.turnToPlayerDistance(orig.getTurnToPlayerDistance())
172169
.attributes(new java.util.HashMap<>(orig.getAttributes()))
173-
.actions(new java.util.ArrayList<>(orig.getActions()))
170+
.actions(new java.util.HashMap<>(orig.getActions()))
174171
.location(orig.getLocation())
175172
.build();
176173
npcManager.register(copy);
@@ -263,10 +260,12 @@ private void handleInfo(CommandContext ctx) {
263260
if (npc.getActions().isEmpty()) {
264261
textManager.send(ctx.sender(), plugin.getMessagesFile().getString("commands.npc.info.actions.empty", "<gold>│</gold> <gray>No actions defined.</gray>"));
265262
} else {
266-
for (String action : npc.getActions()) {
267-
textManager.send(ctx.sender(), plugin.getMessagesFile().getString("commands.npc.info.actions.line", "<gold>│</gold> <gray>%action% (%trigger%)</gray>").replace("%action%", action)
268-
.replace("%trigger%", action.split(" ")[0]) // Assuming the trigger is the first word in the action string
269-
);
263+
for (NPC.ClickType action : npc.getActions().keySet()) {
264+
textManager.send(ctx.sender(), plugin.getMessagesFile().getString("commands.npc.info.actions.line", "<gold>│</gold> <gray>%action% (%trigger%)</gray>").replace("%action%", npc.getActions().get(action).stream()
265+
// Aus jedem CommandAction nur den eigentlichen Befehl ziehen
266+
.map(NPC.CommandAction::getCommand)
267+
.collect(Collectors.joining(", "))
268+
.replace("%trigger%", action.name())));
270269
}
271270
}
272271
textManager.send(ctx.sender(), plugin.getMessagesFile().getString("commands.npc.info.attributes.header", "<gold>│</gold> <gray>Attributes:</gray>"));
@@ -843,55 +842,163 @@ private void handleTeleport(CommandContext ctx) {
843842
}
844843

845844
private void handleAction(CommandContext ctx) {
846-
if (ctx.args().length < 3) {
847-
textManager.send(ctx.sender(), plugin.getMessagesFile().getString("commands.npc.action.usage", "%prefix% <red>Usage: /npc action (npc) add|remove|clear|list [params]</red>"));
845+
String[] args = ctx.args();
846+
// /npc action <npcId> add|remove|clear|list [...]
847+
if (args.length < 2) {
848+
textManager.send(ctx.sender(),
849+
plugin.getMessagesFile()
850+
.getString("commands.npc.action.usage",
851+
"%prefix% <red>Usage: /npc action <npc> add|remove|clear|list [params]</red>"));
848852
return;
849853
}
850-
String id = ctx.args()[0];
851-
String sub = ctx.args()[1];
852-
NPC npc = npcManager.getNpcs().get(id);
853-
if (npc == null) { textManager.send(ctx.sender(), plugin.getMessagesFile().getString("commands.npc.action.not-found", "%prefix% <red>NPC '%name%' not found.</red>")); return; }
854-
switch (sub.toLowerCase()) {
855-
case "list":
854+
855+
String id = args[0];
856+
String sub = args[1].toLowerCase();
857+
NPC npc = npcManager.getNpcs().get(id);
858+
859+
if (npc == null) {
860+
textManager.send(ctx.sender(),
861+
plugin.getMessagesFile()
862+
.getString("commands.npc.action.not-found",
863+
"%prefix% <red>NPC '%name%' not found.</red>")
864+
.replace("%name%", id));
865+
return;
866+
}
867+
868+
switch (sub) {
869+
case "list" -> {
856870
if (npc.getActions().isEmpty()) {
857-
textManager.send(ctx.sender(), plugin.getMessagesFile().getString("commands.npc.action.list.empty", "%prefix% <yellow>NPC '%name%' has no actions.</yellow>").replace("%name%", id));
871+
textManager.send(ctx.sender(),
872+
plugin.getMessagesFile()
873+
.getString("commands.npc.action.list.empty",
874+
"%prefix% <yellow>NPC '%name%' has no actions.</yellow>")
875+
.replace("%name%", id));
858876
} else {
859-
for (String header : plugin.getMessagesFile().getStringList("commands.npc.action.list.header")) {
860-
header = header.replace("%name%", id);
861-
textManager.send(ctx.sender(), header);
877+
// Header
878+
for (String line : plugin.getMessagesFile().getStringList("commands.npc.action.list.header")) {
879+
textManager.send(ctx.sender(), line.replace("%name%", id));
862880
}
863-
for (String action : npc.getActions()) {
864-
textManager.send(ctx.sender(), plugin.getMessagesFile().getString("commands.npc.action.list.line", "<gold>│</gold> <gray>%action%</gray>").replace("%action%", action));
881+
// Jede Click-Type einzeln listen
882+
for (NPC.ClickType click : npc.getActions().keySet()) {
883+
String joined = npc.getActions()
884+
.get(click)
885+
.stream()
886+
.map(ca -> ca.getActionType().name() + ":" + ca.getCommand())
887+
.collect(Collectors.joining(", "));
888+
String template = plugin.getMessagesFile()
889+
.getString("commands.npc.action.list.line",
890+
"<gold>│</gold> <gray>%trigger% – %action%</gray>");
891+
String filled = template
892+
.replace("%trigger%", click.name())
893+
.replace("%action%", joined);
894+
textManager.send(ctx.sender(), filled);
865895
}
866-
for (String footer : plugin.getMessagesFile().getStringList("commands.npc.action.list.footer")) {
867-
footer = footer.replace("%name%", id);
868-
textManager.send(ctx.sender(), footer);
896+
// Footer
897+
for (String line : plugin.getMessagesFile().getStringList("commands.npc.action.list.footer")) {
898+
textManager.send(ctx.sender(), line.replace("%name%", id));
869899
}
870900
}
871-
break;
872-
case "clear":
873-
npcManager.modify(id, n -> { n.getActions().clear(); return n; });
874-
npcManager.save();
875-
textManager.send(ctx.sender(), plugin.getMessagesFile().getString("commands.npc.action.clear.success", "%prefix% <green>All actions cleared for NPC '%name%'.</green>").replace("%name%", id));
876-
break;
877-
case "add":
878-
String action = ctx.args()[2];
879-
npcManager.modify(id, n -> { n.getActions().add(action); return n; });
901+
}
902+
903+
case "clear" -> {
904+
// Optional: /npc action <npc> clear [ClickType]
905+
if (args.length == 3) {
906+
try {
907+
NPC.ClickType click = NPC.ClickType.valueOf(args[2].toUpperCase());
908+
npcManager.modify(id, n -> { n.getActions().remove(click); return n; });
909+
} catch (IllegalArgumentException ex) {
910+
textManager.send(ctx.sender(),
911+
"<red>Unknown click type: " + args[2] + "</red>");
912+
return;
913+
}
914+
} else {
915+
// Ohne ClickType → alle löschen
916+
npcManager.modify(id, n -> { n.getActions().clear(); return n; });
917+
}
880918
npcManager.save();
881-
textManager.send(ctx.sender(), plugin.getMessagesFile().getString("commands.npc.action.add.success", "%prefix% <green>Action '%action%' added to NPC '%name%'.</green>").replace("%action%", action).replace("%name%", id));
882-
break;
883-
case "remove":
884-
String rem = ctx.args()[2];
885-
npcManager.modify(id, n -> { n.getActions().remove(rem); return n; });
919+
textManager.send(ctx.sender(),
920+
plugin.getMessagesFile()
921+
.getString("commands.npc.action.clear.success",
922+
"%prefix% <green>Actions cleared for NPC '%name%'.</green>")
923+
.replace("%name%", id));
924+
}
925+
926+
case "add" -> {
927+
// /npc action <npc> add <ClickType> <ActionType> <command...>
928+
if (args.length < 5) {
929+
textManager.send(ctx.sender(),
930+
"<red>Usage: /npc action " + id + " add <any_click|left_click|right_click> <player_command|console_command> <command...></red>");
931+
return;
932+
}
933+
NPC.ClickType click;
934+
NPC.ActionType type;
935+
try {
936+
click = NPC.ClickType.valueOf(args[2].toUpperCase());
937+
type = NPC.ActionType.valueOf(args[3].toUpperCase());
938+
} catch (IllegalArgumentException ex) {
939+
textManager.send(ctx.sender(),
940+
"<red>Invalid click- or action-type!</red>");
941+
return;
942+
}
943+
String command = String.join(" ", Arrays.copyOfRange(args, 4, args.length));
944+
npcManager.modify(id, n -> {
945+
n.getActions()
946+
.computeIfAbsent(click, k -> new ArrayList<>())
947+
.add(new NPC.CommandAction(type, command));
948+
return n;
949+
});
886950
npcManager.save();
887-
textManager.send(ctx.sender(), plugin.getMessagesFile().getString("commands.npc.action.remove.success", "%prefix% <green>Action '%action%' removed from NPC '%name%'.</green>").replace("%action%", rem).replace("%name%", id));
888-
break;
889-
default:
890-
textManager.send(ctx.sender(), plugin.getMessagesFile().getString("commands.npc.action.usage", "%prefix% <red>Usage: /npc action (npc) add|remove|clear|list [params]</red>"));
891-
break;
951+
textManager.send(ctx.sender(),
952+
plugin.getMessagesFile()
953+
.getString("commands.npc.action.add.success",
954+
"%prefix% <green>Action '%action%' added to NPC '%name%'.</green>")
955+
.replace("%action%", type.name() + ":" + command)
956+
.replace("%name%", id));
957+
}
958+
959+
case "remove" -> {
960+
// /npc action <npc> remove <ClickType> <index>
961+
if (args.length != 4) {
962+
textManager.send(ctx.sender(),
963+
"<red>Usage: /npc action " + id + " remove <any_click|left_click|right_click> <index></red>");
964+
return;
965+
}
966+
NPC.ClickType click;
967+
int index;
968+
try {
969+
click = NPC.ClickType.valueOf(args[2].toUpperCase());
970+
index = Integer.parseInt(args[3]);
971+
} catch (IllegalArgumentException ex) {
972+
textManager.send(ctx.sender(),
973+
"<red>Invalid click-type or index!</red>");
974+
return;
975+
}
976+
final boolean removed = npcManager.getNpcs()
977+
.get(id)
978+
.removeAction(click, index);
979+
if (removed) {
980+
npcManager.save();
981+
textManager.send(ctx.sender(),
982+
plugin.getMessagesFile()
983+
.getString("commands.npc.action.remove.success",
984+
"%prefix% <green>Action removed from NPC '%name%'.</green>")
985+
.replace("%name%", id));
986+
} else {
987+
textManager.send(ctx.sender(),
988+
"<red>No action at index " + index + " for " + click.name() + "!</red>");
989+
}
990+
}
991+
992+
default -> {
993+
textManager.send(ctx.sender(),
994+
plugin.getMessagesFile()
995+
.getString("commands.npc.action.usage",
996+
"%prefix% <red>Usage: /npc action <npc> add|remove|clear|list [params]</red>"));
997+
}
892998
}
893999
}
8941000

1001+
8951002
private void handleInteractionCooldown(CommandContext ctx) {
8961003
if (ctx.args().length < 2) {
8971004
textManager.send(ctx.sender(), plugin.getMessagesFile().getString("commands.npc.interaction_cooldown.usage", "%prefix% <red>Usage: /npc interaction_cooldown (npc) [disabled | ticks]</red>"));

0 commit comments

Comments
 (0)