Skip to content

Commit e174027

Browse files
committed
Added new npc features
1 parent 3e444bb commit e174027

18 files changed

Lines changed: 328 additions & 22 deletions

.github/workflows/build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,5 @@ jobs:
2222
uses: actions/upload-artifact@v7.0.0
2323
with:
2424
name: PexNPC
25-
path: build/libs/PexNPC-2.3.jar
25+
path: build/libs/PexNPC-2.4.jar
2626
archive: false

build.gradle.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ plugins {
44
}
55

66
group = "de.pascalpex"
7-
version = "2.3"
7+
version = "2.4"
88

99
repositories {
1010
mavenCentral()
@@ -19,7 +19,7 @@ dependencies {
1919
testImplementation(platform("org.junit:junit-bom:6.0.3"))
2020
testImplementation("org.junit.jupiter:junit-jupiter")
2121
compileOnly("me.clip:placeholderapi:2.12.2")
22-
paperweight.paperDevBundle("26.1.1.build.+")
22+
paperweight.paperDevBundle("26.1.2.build.+")
2323
}
2424

2525
java {

src/main/java/de/pascalpex/pexnpc/PexNPCBootstrap.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
package de.pascalpex.pexnpc;
22

3+
import com.mojang.brigadier.arguments.BoolArgumentType;
4+
import com.mojang.brigadier.arguments.DoubleArgumentType;
35
import com.mojang.brigadier.arguments.StringArgumentType;
46
import com.mojang.brigadier.tree.LiteralCommandNode;
57
import de.pascalpex.pexnpc.commands.IDArgument;
8+
import de.pascalpex.pexnpc.commands.NPCPoseArgument;
69
import de.pascalpex.pexnpc.commands.NPCSlotArgument;
710
import de.pascalpex.pexnpc.commands.subcommands.*;
811
import io.papermc.paper.command.brigadier.CommandSourceStack;
@@ -82,6 +85,22 @@ public void bootstrap(BootstrapContext context) {
8285
.executes(new ClearSubcommand())))
8386
.then(Commands.literal("inspect")
8487
.executes(new InspectSubcommand()))
88+
.then(Commands.literal("scale")
89+
.then(Commands.argument("npc", idArgument)
90+
.then(Commands.argument("scale", DoubleArgumentType.doubleArg())
91+
.executes(new ScaleSubcommand()))))
92+
.then(Commands.literal("burning")
93+
.then(Commands.argument("npc", idArgument)
94+
.then(Commands.argument("burning", BoolArgumentType.bool())
95+
.executes(new BurningSubcommand()))))
96+
.then(Commands.literal("glowing")
97+
.then(Commands.argument("npc", idArgument)
98+
.then(Commands.argument("glowing", BoolArgumentType.bool())
99+
.executes(new GlowingSubcommand()))))
100+
.then(Commands.literal("pose")
101+
.then(Commands.argument("npc", idArgument)
102+
.then(Commands.argument("pose", new NPCPoseArgument())
103+
.executes(new PoseSubcommand()))))
85104
.executes(helpSubcommand)
86105
.build();
87106

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package de.pascalpex.pexnpc.commands;
2+
3+
import com.mojang.brigadier.Message;
4+
import com.mojang.brigadier.arguments.ArgumentType;
5+
import com.mojang.brigadier.arguments.StringArgumentType;
6+
import com.mojang.brigadier.context.CommandContext;
7+
import com.mojang.brigadier.exceptions.CommandSyntaxException;
8+
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
9+
import com.mojang.brigadier.suggestion.Suggestions;
10+
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
11+
import de.pascalpex.pexnpc.npc.NPCPose;
12+
import de.pascalpex.pexnpc.util.MessageHandler;
13+
import io.papermc.paper.command.brigadier.MessageComponentSerializer;
14+
import io.papermc.paper.command.brigadier.argument.CustomArgumentType;
15+
import org.jetbrains.annotations.NotNull;
16+
17+
import java.util.concurrent.CompletableFuture;
18+
19+
public class NPCPoseArgument implements CustomArgumentType.Converted<NPCPose, String> {
20+
@Override
21+
public @NotNull NPCPose convert(@NotNull String nativeType) throws CommandSyntaxException {
22+
for (NPCPose pose : NPCPose.values()) {
23+
if (pose.name().equalsIgnoreCase(nativeType)) {
24+
return pose;
25+
}
26+
}
27+
final Message exceptionMessage = MessageComponentSerializer.message().serialize(MessageHandler.errorMessage("The NPC pose you entered is invalid. Valid options are STANDING, CROUCHING, SLEEPING and SWIMMING"));
28+
throw new CommandSyntaxException(new SimpleCommandExceptionType(exceptionMessage), exceptionMessage);
29+
}
30+
31+
@Override
32+
public @NotNull ArgumentType<String> getNativeType() {
33+
return StringArgumentType.word();
34+
}
35+
36+
@Override
37+
public <S> @NotNull CompletableFuture<Suggestions> listSuggestions(@NotNull CommandContext<S> context, @NotNull SuggestionsBuilder builder) {
38+
String currentInput = "";
39+
try {
40+
currentInput = context.getInput().split(" ")[3].toUpperCase();
41+
} catch (ArrayIndexOutOfBoundsException ignored) {
42+
} // Command does not contain the argument yet
43+
for (NPCPose pose : NPCPose.values()) {
44+
if (pose.name().startsWith(currentInput.toUpperCase())) {
45+
builder.suggest(pose.name());
46+
}
47+
}
48+
return builder.buildFuture();
49+
}
50+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package de.pascalpex.pexnpc.commands.subcommands;
2+
3+
import com.mojang.brigadier.Command;
4+
import com.mojang.brigadier.arguments.BoolArgumentType;
5+
import com.mojang.brigadier.context.CommandContext;
6+
import de.pascalpex.pexnpc.PexNPC;
7+
import de.pascalpex.pexnpc.files.NPCData;
8+
import de.pascalpex.pexnpc.npc.NPCSender;
9+
import de.pascalpex.pexnpc.npc.PlaceableNPC;
10+
import de.pascalpex.pexnpc.util.MessageHandler;
11+
import io.papermc.paper.command.brigadier.CommandSourceStack;
12+
import org.bukkit.command.CommandSender;
13+
14+
public class BurningSubcommand implements Command<CommandSourceStack> {
15+
@Override
16+
public int run(CommandContext<CommandSourceStack> context) {
17+
CommandSender sender = context.getSource().getSender();
18+
PlaceableNPC placeableNPC = context.getArgument("npc", PlaceableNPC.class);
19+
boolean burning = BoolArgumentType.getBool(context, "burning");
20+
21+
PexNPC.getPlacedNpcs().remove(placeableNPC);
22+
NPCSender.removeNPC(placeableNPC);
23+
24+
placeableNPC.getNpc().setBurning(burning);
25+
PlaceableNPC newPlaceableNPC = new PlaceableNPC(placeableNPC.getNpc());
26+
PexNPC.getPlacedNpcs().add(newPlaceableNPC);
27+
NPCSender.sendNpcToPlayers(newPlaceableNPC);
28+
NPCData.saveNpc(newPlaceableNPC.getNpc());
29+
30+
sender.sendMessage(MessageHandler.prefixedMini("The NPC with the ID <gold>" + placeableNPC.getNpc().getId() + " <aqua>is " + (burning ? "now" : "no longer") + " burning"));
31+
32+
return SINGLE_SUCCESS;
33+
}
34+
}

src/main/java/de/pascalpex/pexnpc/commands/subcommands/CreateSubcommand.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public int run(CommandContext<CommandSourceStack> context) {
2727
}
2828

2929
String name = StringArgumentType.getString(context, "name").replace("&", "§");
30-
if (Util.isNameInvalid(name)) {
30+
if (Util.isNameInvalid(name, -1)) {
3131
sender.sendMessage(MessageHandler.errorMessage("The first 16 characters of this name are already in use"));
3232
return SINGLE_SUCCESS;
3333
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package de.pascalpex.pexnpc.commands.subcommands;
2+
3+
import com.mojang.brigadier.Command;
4+
import com.mojang.brigadier.arguments.BoolArgumentType;
5+
import com.mojang.brigadier.context.CommandContext;
6+
import de.pascalpex.pexnpc.PexNPC;
7+
import de.pascalpex.pexnpc.files.NPCData;
8+
import de.pascalpex.pexnpc.npc.NPCSender;
9+
import de.pascalpex.pexnpc.npc.PlaceableNPC;
10+
import de.pascalpex.pexnpc.util.MessageHandler;
11+
import io.papermc.paper.command.brigadier.CommandSourceStack;
12+
import org.bukkit.command.CommandSender;
13+
14+
public class GlowingSubcommand implements Command<CommandSourceStack> {
15+
@Override
16+
public int run(CommandContext<CommandSourceStack> context) {
17+
CommandSender sender = context.getSource().getSender();
18+
PlaceableNPC placeableNPC = context.getArgument("npc", PlaceableNPC.class);
19+
boolean glowing = BoolArgumentType.getBool(context, "glowing");
20+
21+
PexNPC.getPlacedNpcs().remove(placeableNPC);
22+
NPCSender.removeNPC(placeableNPC);
23+
24+
placeableNPC.getNpc().setGlowing(glowing);
25+
PlaceableNPC newPlaceableNPC = new PlaceableNPC(placeableNPC.getNpc());
26+
PexNPC.getPlacedNpcs().add(newPlaceableNPC);
27+
NPCSender.sendNpcToPlayers(newPlaceableNPC);
28+
NPCData.saveNpc(newPlaceableNPC.getNpc());
29+
30+
sender.sendMessage(MessageHandler.prefixedMini("The NPC with the ID <gold>" + placeableNPC.getNpc().getId() + " <aqua>is " + (glowing ? "now" : "no longer") + " glowing"));
31+
32+
return SINGLE_SUCCESS;
33+
}
34+
}

src/main/java/de/pascalpex/pexnpc/commands/subcommands/HelpSubcommand.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ public int run(CommandContext<CommandSourceStack> context) {
3232
sender.sendMessage(MessageHandler.prefixedMini("/pexnpc clear [ID] <dark_gray>| <gold>Clears the command, message and items of a NPC").hoverEvent(hoverEvent).clickEvent(ClickEvent.suggestCommand("/pexnpc clear")));
3333
sender.sendMessage(MessageHandler.prefixedMini("/pexnpc tp [ID] <dark_gray>| <gold>Teleports to a NPC").hoverEvent(hoverEvent).clickEvent(ClickEvent.suggestCommand("/pexnpc tp")));
3434
sender.sendMessage(MessageHandler.prefixedMini("/pexnpc inspect <dark_gray>| <gold>Toggles the inspection mode").hoverEvent(hoverEvent).clickEvent(ClickEvent.suggestCommand("/pexnpc inspect")));
35+
sender.sendMessage(MessageHandler.prefixedMini("/pexnpc scale [ID] [SCALE] <dark_gray>| <gold>Sets the scale").hoverEvent(hoverEvent).clickEvent(ClickEvent.suggestCommand("/pexnpc scale")));
36+
sender.sendMessage(MessageHandler.prefixedMini("/pexnpc burning [ID] [BURNING] <dark_gray>| <gold>Turns burning on or off").hoverEvent(hoverEvent).clickEvent(ClickEvent.suggestCommand("/pexnpc burning")));
37+
sender.sendMessage(MessageHandler.prefixedMini("/pexnpc glowing [ID] [GLOWING] <dark_gray>| <gold>Turns glowing on or off").hoverEvent(hoverEvent).clickEvent(ClickEvent.suggestCommand("/pexnpc glowing")));
38+
sender.sendMessage(MessageHandler.prefixedMini("/pexnpc pose [ID] [POSE] <dark_gray>| <gold>Changes the pose").hoverEvent(hoverEvent).clickEvent(ClickEvent.suggestCommand("/pexnpc pose")));
39+
3540
return SINGLE_SUCCESS;
3641
}
3742
}

src/main/java/de/pascalpex/pexnpc/commands/subcommands/NameSubcommand.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public int run(CommandContext<CommandSourceStack> context) {
1919
PlaceableNPC placeableNPC = context.getArgument("npc", PlaceableNPC.class);
2020
String name = StringArgumentType.getString(context, "name").replace("&", "§");
2121

22-
if (Util.isNameInvalid(name)) {
22+
if (Util.isNameInvalid(name, placeableNPC.getNpc().getId())) {
2323
sender.sendMessage(MessageHandler.errorMessage("The first 16 characters of this name are already in use"));
2424
return SINGLE_SUCCESS;
2525
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package de.pascalpex.pexnpc.commands.subcommands;
2+
3+
import com.mojang.brigadier.Command;
4+
import com.mojang.brigadier.context.CommandContext;
5+
import de.pascalpex.pexnpc.PexNPC;
6+
import de.pascalpex.pexnpc.files.NPCData;
7+
import de.pascalpex.pexnpc.npc.NPCPose;
8+
import de.pascalpex.pexnpc.npc.NPCSender;
9+
import de.pascalpex.pexnpc.npc.PlaceableNPC;
10+
import de.pascalpex.pexnpc.util.MessageHandler;
11+
import io.papermc.paper.command.brigadier.CommandSourceStack;
12+
import org.bukkit.command.CommandSender;
13+
14+
public class PoseSubcommand implements Command<CommandSourceStack> {
15+
@Override
16+
public int run(CommandContext<CommandSourceStack> context) {
17+
CommandSender sender = context.getSource().getSender();
18+
PlaceableNPC placeableNPC = context.getArgument("npc", PlaceableNPC.class);
19+
NPCPose pose = context.getArgument("pose", NPCPose.class);
20+
21+
PexNPC.getPlacedNpcs().remove(placeableNPC);
22+
NPCSender.removeNPC(placeableNPC);
23+
24+
placeableNPC.getNpc().setPose(pose);
25+
PlaceableNPC newPlaceableNPC = new PlaceableNPC(placeableNPC.getNpc());
26+
PexNPC.getPlacedNpcs().add(newPlaceableNPC);
27+
NPCSender.sendNpcToPlayers(newPlaceableNPC);
28+
NPCData.saveNpc(newPlaceableNPC.getNpc());
29+
30+
sender.sendMessage(MessageHandler.prefixedMini("The NPC with the ID <gold>" + placeableNPC.getNpc().getId() + " <aqua>now has the pose <gold>" + pose.getName()));
31+
32+
return SINGLE_SUCCESS;
33+
}
34+
}

0 commit comments

Comments
 (0)