Skip to content

Commit

Permalink
Merge branch 'Revxrsal:v4' into v4
Browse files Browse the repository at this point in the history
  • Loading branch information
CamperSamu authored Dec 27, 2024
2 parents 2319b8c + 8b0ec72 commit 36b4fc2
Show file tree
Hide file tree
Showing 32 changed files with 1,072 additions and 328 deletions.
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ plugins {
}

group = "io.github.revxrsal"
version = "4.0.0-beta.19"
version = "4.0.0-beta.25"

java {
toolchain {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
package revxrsal.commands.bukkit;

import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.OfflinePlayer;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
Expand Down Expand Up @@ -135,6 +136,7 @@ public final class BukkitVisitors {
.addParameterTypeLast(Player.class, new PlayerParameterType(brigadierEnabled))
.addParameterTypeLast(OfflinePlayer.class, new OfflinePlayerParameterType(brigadierEnabled))
.addParameterTypeLast(World.class, new WorldParameterType())
.addParameterTypeLast(Location.class, new LocationParameterType())
.addParameterTypeFactoryLast(new EntitySelectorParameterTypeFactory());
if (BukkitVersion.isBrigadierSupported())
builder.parameterTypes()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
package revxrsal.commands.bukkit.brigadier;

import com.mojang.brigadier.arguments.ArgumentType;
import org.bukkit.Location;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
Expand Down Expand Up @@ -63,6 +64,7 @@ public final class BukkitArgumentTypes {
.addTypeLast(OfflinePlayer.class, SINGLE_PLAYER)
.addTypeLast(Player.class, SINGLE_PLAYER)
.addTypeLast(Entity.class, SINGLE_ENTITY)
.addTypeLast(Location.class, MinecraftArgumentType.BLOCK_POS.get())
.addTypeFactoryLast((parameter) -> {
if (parameter.type() != EntitySelector.class)
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

import java.lang.reflect.Constructor;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

Expand All @@ -49,95 +50,95 @@ public enum MinecraftArgumentType {
* - boolean single
* - boolean playerOnly
*/
ENTITY("ArgumentEntity", boolean.class, boolean.class),
ENTITY(new String[]{"ArgumentEntity", "EntityArgument"}, boolean.class, boolean.class),

/**
* A player, online or not. Can also use a selector, which may match one or more
* players (but not entities).
*/
GAME_PROFILE("ArgumentProfile"),
GAME_PROFILE("ArgumentProfile", "GameProfileArgument"),

/**
* A chat color. One of the names from <a href="https://wiki.vg/Chat#Colors">colors</a>, or {@code reset}.
* Case-insensitive.
*/
COLOR("ArgumentChatFormat"),
COLOR("ArgumentChatFormat", "ColorArgument"),

/**
* A JSON Chat component.
*/
COMPONENT("ArgumentChatComponent"),
COMPONENT("ArgumentChatComponent", "ComponentArgument"),

/**
* A regular message, potentially including selectors.
*/
MESSAGE("ArgumentChat"),
MESSAGE("ArgumentChat", "MessageArgument"),

/**
* An NBT value, parsed using JSON-NBT rules. This represents a full NBT tag.
*/
NBT("ArgumentNBTTag"),
NBT("ArgumentNBTTag", "CompoundTagArgument"),

/**
* Represents a partial NBT tag, usable in data modify command.
*/
NBT_TAG("ArgumentNBTBase"),
NBT_TAG("ArgumentNBTBase", "NbtTagArgument"),

/**
* A path within an NBT value, allowing for array and member accesses.
*/
NBT_PATH("ArgumentNBTKey"),
NBT_PATH("ArgumentNBTKey", "NbtPathArgument"),

/**
* A scoreboard objective.
*/
SCOREBOARD_OBJECTIVE("ArgumentScoreboardObjective"),
SCOREBOARD_OBJECTIVE("ArgumentScoreboardObjective", "ObjectiveArgument"),

/**
* A single score criterion.
*/
OBJECTIVE_CRITERIA("ArgumentScoreboardCriteria"),
OBJECTIVE_CRITERIA("ArgumentScoreboardCriteria", "ObjectiveCriteriaArgument"),

/**
* A scoreboard operator.
*/
SCOREBOARD_SLOT("ArgumentScoreboardSlot"),
SCOREBOARD_SLOT("ArgumentScoreboardSlot", "SlotArgument"),

/**
* Something that can join a team. Allows selectors and *.
*/
SCORE_HOLDER("ArgumentScoreholder"),
SCORE_HOLDER("ArgumentScoreholder", "ScoreHolderArgument"),

/**
* The name of a team. Parsed as an unquoted string.
*/
TEAM("ArgumentScoreboardTeam"),
TEAM("ArgumentScoreboardTeam", "TeamArgument"),

/**
* A scoreboard operator.
*/
OPERATION("ArgumentMathOperation"),
OPERATION("ArgumentMathOperation", "OperationArgument"),

/**
* A particle effect (an identifier with extra information following it for
* specific particles, mirroring the Particle packet)
*/
PARTICLE("ArgumentParticle"),
PARTICLE("ArgumentParticle", "ParticleArgument"),

/**
* Represents an angle.
*/
ANGLE("ArgumentAngle"),
ANGLE("ArgumentAngle", "AngleArgument"),

/**
* A name for an inventory slot.
*/
ITEM_SLOT("ArgumentInventorySlot"),
ITEM_SLOT("ArgumentInventorySlot", "SlotArgument"),

/**
* An Identifier.
*/
RESOURCE_LOCATION("ArgumentMinecraftKeyRegistered"),
RESOURCE_LOCATION("ArgumentMinecraftKeyRegistered", "ResourceLocationArgument"),

/**
* A potion effect.
Expand All @@ -157,95 +158,95 @@ public enum MinecraftArgumentType {
/**
* Represents a dimension.
*/
DIMENSION("ArgumentDimension"),
DIMENSION("ArgumentDimension", "DimensionArgument"),

/**
* Represents a time duration.
*/
TIME("ArgumentTime"),
TIME("ArgumentTime", "TimeArgument"),

/**
* Represents a UUID value.
*
* @since Minecraft 1.16
*/
UUID("ArgumentUUID"),
UUID("ArgumentUUID", "UuidArgument"),

/**
* A location, represented as 3 numbers (which must be integers). May use relative locations
* with ~
*/
BLOCK_POS("coordinates.ArgumentPosition"),
BLOCK_POS("coordinates.ArgumentPosition", "coordinates.BlockPosArgument"),

/**
* A column location, represented as 3 numbers (which must be integers). May use relative locations
* A column location, represented as 2 numbers (which must be integers). May use relative locations
* with ~.
*/
COLUMN_POS("coordinates.ArgumentVec2I"),
COLUMN_POS("coordinates.ArgumentVec2I", "coordinates.ColumnPosArgument"),

/**
* A location, represented as 3 numbers (which may have a decimal point, but will be moved to the
* center of a block if none is specified). May use relative locations with ~.
*/
VECTOR_3("coordinates.ArgumentVec3"),
VECTOR_3("coordinates.ArgumentVec3", "coordinates.Vec3Argument"),

/**
* A location, represented as 2 numbers (which may have a decimal point, but will be moved to the center
* of a block if none is specified). May use relative locations with ~.
*/
VECTOR_2("coordinates.ArgumentVec2"),
VECTOR_2("coordinates.ArgumentVec2", "coordinates.Vec2Argument"),

/**
* An angle, represented as 2 numbers (which may have a decimal point, but will be moved to the
* center of a block if none is specified). May use relative locations with ~.
*/
ROTATION("coordinates.ArgumentRotation"),
ROTATION("coordinates.ArgumentRotation", "coordinates.RotationArgument"),

/**
* A collection of up to 3 axes.
*/
SWIZZLE("coordinates.ArgumentRotationAxis"),
SWIZZLE("coordinates.ArgumentRotationAxis", "coordinates.SwizzleArgument"),

/**
* A block state, optionally including NBT and state information.
*/
BLOCK_STATE("blocks.ArgumentTile"),
BLOCK_STATE("blocks.ArgumentTile", "blocks.BlockStateArgument"),

/**
* A block, or a block tag.
*/
BLOCK_PREDICATE("blocks.ArgumentBlockPredicate"),
BLOCK_PREDICATE("blocks.ArgumentBlockPredicate", "blocks.BlockPredicateArgument"),

/**
* An item, optionally including NBT.
*/
ITEM_STACK("item.ArgumentItemStack"),
ITEM_STACK("item.ArgumentItemStack", "item.ItemArgument"),

/**
* An item, or an item tag.
*/
ITEM_PREDICATE("item.ArgumentItemPredicate"),
ITEM_PREDICATE("item.ArgumentItemPredicate", "item.ItemPredicateArgument"),

/**
* A function.
*/
FUNCTION("item.ArgumentTag"),
FUNCTION("item.ArgumentTag", "item.FunctionArgument"),

/**
* The entity anchor related to the facing argument in the teleport command,
* is feet or eyes.
*/
ENTITY_ANCHOR("ArgumentAnchor"),
ENTITY_ANCHOR("ArgumentAnchor", "EntityAnchorArgument"),

/**
* An integer range of values with a min and a max.
*/
INT_RANGE("ArgumentCriterionValue$b"),
INT_RANGE("ArgumentCriterionValue$b", "RangeArgument$Ints"),

/**
* A floating-point range of values with a min and a max.
*/
FLOAT_RANGE("ArgumentCriterionValue$a"),
FLOAT_RANGE("ArgumentCriterionValue$a", "RangeArgument$Floats"),

/**
* Template mirror
Expand All @@ -265,8 +266,17 @@ public enum MinecraftArgumentType {
private @Nullable ArgumentType<?> argumentType;
private @Nullable Constructor<? extends ArgumentType> argumentConstructor;

MinecraftArgumentType(String name, Class<?>... parameters) {
Class<?> argumentClass = resolveArgumentClass(name);
MinecraftArgumentType(String... names) {
this(names, new Class[0]);
}

MinecraftArgumentType(String[] names, Class<?>... parameters) {
Class<?> argumentClass = null;
for (String name : names) {
argumentClass = resolveArgumentClass(name);
if (argumentClass != null)
break;
}
this.parameters = parameters;
if (argumentClass == null) {
argumentType = null;
Expand All @@ -288,25 +298,32 @@ public enum MinecraftArgumentType {
}
}

static class Data {
private static final List<String> POSSIBLE_CLASS_NAMES = Arrays.asList(
"net.minecraft.server.{name}",
"net.minecraft.server.{version}.{name}",
"net.minecraft.commands.arguments.{name}",
"net.minecraft.server.{version}.{stripped_name}"
);
}

private static @Nullable Class<?> resolveArgumentClass(String name) {
try {
if (BukkitVersion.supports(1, 16)) {
try {
return BukkitVersion.findNmsClass("commands.arguments." + name);
} catch (Throwable ignored) {
return Class.forName("net.minecraft.commands.arguments." + name);
}
} else {
String stripped;
if (name.lastIndexOf('.') != -1)
stripped = name.substring(name.lastIndexOf('.') + 1);
else
stripped = name;
return BukkitVersion.findNmsClass(stripped);
String strippedName;
if (name.lastIndexOf('.') != -1)
strippedName = name.substring(name.lastIndexOf('.') + 1);
else
strippedName = name;
for (String s : Data.POSSIBLE_CLASS_NAMES) {
String className = s
.replace("{version}", BukkitVersion.version())
.replace("{name}", name)
.replace("{stripped_name}", strippedName);
try {
return Class.forName(className);
} catch (ClassNotFoundException ignored) {
}
} catch (Throwable t) {
return null;
}
return null;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ public void onInvalidWorld(InvalidWorldException e, BukkitCommandActor actor) {
actor.error(legacyColorize("&cInvalid world: &e" + e.input() + "&c."));
}

@HandleException
public void onInvalidWorld(MissingLocationParameterException e, BukkitCommandActor actor) {
actor.error(legacyColorize("&cExpected &e" + e.axis().name().toLowerCase() + "&c."));
}

@HandleException
public void onSenderNotConsole(SenderNotConsoleException e, BukkitCommandActor actor) {
actor.error(legacyColorize("&cYou must be the console to execute this command!"));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package revxrsal.commands.bukkit.exception;

import org.jetbrains.annotations.NotNull;
import revxrsal.commands.exception.InvalidValueException;

/**
* Thrown when a parameter of {@link org.bukkit.Location} is not specified, such
* as {@code x} or {@code y} or {@code z}.
*/
public class MissingLocationParameterException extends InvalidValueException {

public enum MissingAxis {
X, Y, Z
}

private final @NotNull MissingAxis missingAxis;

public MissingLocationParameterException(@NotNull String input, @NotNull MissingAxis missingAxis) {
super(input);
this.missingAxis = missingAxis;
}

public @NotNull MissingAxis axis() {
return missingAxis;
}
}
Loading

0 comments on commit 36b4fc2

Please sign in to comment.