Skip to content

Commit

Permalink
Enable pose validation based on entity type.
Browse files Browse the repository at this point in the history
Introduced a filtering mechanism to validate if specific poses are applicable to an entity type. Updated commands and pose setting logic to incorporate this validation. This ensures pose compatibility and prevents invalid pose assignments.
  • Loading branch information
NonSwag committed Jan 20, 2025
1 parent 8a64bf4 commit 15bc2d7
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ public boolean setPersistent(boolean persistent) {

@Override
public boolean setPose(Pose pose) {
if (pose == this.pose) return false;
if (pose == this.pose || !canHavePose(type, pose)) return false;
getEntity().ifPresent(entity -> entity.setPose(pose, true));
this.pose = pose;
return true;
Expand Down Expand Up @@ -477,6 +477,25 @@ public void remove() {
despawn();
}

public static boolean canHavePose(EntityType type, Pose pose) {
return switch (pose) {
case EMERGING, ROARING, DIGGING, SNIFFING -> type == EntityType.WARDEN;
case FALL_FLYING, SPIN_ATTACK, SWIMMING -> type == EntityType.PLAYER;
case INHALING, SHOOTING, SLIDING -> type == EntityType.BREEZE;
case LONG_JUMPING -> switch (type) {
case GOAT, FROG, BREEZE -> true;
default -> false;
};
case SITTING -> type == EntityType.CAMEL;
case SNEAKING -> switch (type) {
case CAT, OCELOT, PLAYER -> true;
default -> false;
};
case USING_TONGUE, CROAKING -> type == EntityType.FROG;
default -> true;
};
}

protected void preSpawn(T entity) {
if (entity instanceof Attributable attributable) {
var scale = attributable.getAttribute(Attribute.SCALE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
import net.thenextlvl.character.Character;
import net.thenextlvl.character.plugin.CharacterPlugin;
import net.thenextlvl.character.plugin.character.PaperCharacter;
import net.thenextlvl.character.plugin.command.argument.EnumArgument;
import org.bukkit.entity.Pose;
import org.jspecify.annotations.NullMarked;
Expand All @@ -24,7 +25,10 @@ static LiteralArgumentBuilder<CommandSourceStack> create(CharacterPlugin plugin)
}

private static ArgumentBuilder<CommandSourceStack, ?> poseArgument(CharacterPlugin plugin) {
return Commands.argument("pose", new EnumArgument<>(Pose.class));
return Commands.argument("pose", new EnumArgument<>(Pose.class, (context, pose) -> {
var character = context.getLastChild().getArgument("character", Character.class);
return PaperCharacter.canHavePose(character.getType(), pose);
}));
}

private static ArgumentBuilder<CommandSourceStack, ?> reset(CharacterPlugin plugin) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
package net.thenextlvl.character.plugin.command.argument;

import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.context.CommandContext;
import core.paper.command.WrappedArgumentType;

import java.util.Arrays;
import java.util.function.BiPredicate;

public class EnumArgument<T extends Enum<T>> extends WrappedArgumentType<String, T> {
public EnumArgument(Class<T> enumClass) {
this(enumClass, (c, e) -> true);
}

public EnumArgument(Class<T> enumClass, BiPredicate<CommandContext<?>, T> filter) {
super(StringArgumentType.word(),
(reader, type) -> Enum.valueOf(enumClass, type.toUpperCase()),
(context, builder) -> {
Arrays.stream(enumClass.getEnumConstants())
.filter(e -> filter.test(context, e))
.map(Enum::name)
.map(String::toLowerCase)
.filter(name -> name.contains(builder.getRemaining()))
Expand Down

0 comments on commit 15bc2d7

Please sign in to comment.