Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 14 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,20 @@ As of right now there's only two built-in parsers that I bothered to add.

## Included parsers

| Parser | Type | Description |
|-----------------------|-----------------|-----------------------------------------------------------------------------------------------------|
| `PlayerParser` | `Player` | Resolves an online player by username |
| `EntityTypeParser` | `EntityType` | Resolves an entity type by namespaced key |
| `InstanceParser` | `Instance` | Resolves a loaded instance by UUID |
| `GameModeParser` | `GameMode` | Resolves a game mode by name |
| `DimensionTypeParser` | `DimensionType` | Resolves a dimension type by namespaced key |
| `VecParser` | `Vec` | Resolves a `Vec` from `x y z` (supports relative coordinates (`~ ~ ~`) |
| `PosParser` | `Pos` | Resolves a `Pos` from `x y z`, (+ optional pitch/yaw - also supports relative coords (`~ ~ ~ ~ ~`)) |
You'll see a decent amount of random parsers that I've added after needing them lol

| Parser | Type | Description |
|----------------------------|----------------------------|-----------------------------------------------------------------------------------------------------|
| `PlayerParser` | `Player` | Resolves an online player by username |
| `EntityTypeParser` | `EntityType` | Resolves an entity type by namespaced key |
| `InstanceParser` | `Instance` | Resolves a loaded instance by UUID |
| `DimensionTypeParser` | `DimensionType` | Resolves a dimension type by namespaced key |
| `VecParser` | `Vec` | Resolves a `Vec` from `x y z` (supports relative coordinates (`~ ~ ~`) |
| `PosParser` | `Pos` | Resolves a `Pos` from `x y z`, (+ optional pitch/yaw - also supports relative coords (`~ ~ ~ ~ ~`)) |
| `ItemStackParser` | `ItemStack` | Resolves an `ItemStack` from `id:meta:count` |
| `EnchantmentParser` | `RegistryKey<Enchantment>` | Resolves an enchantment registry key by namespaced key |
| `SoundEventParser` | `SoundEvent` | Resolves a builtin sound event by namespaced key |
| `AttributeParser` | `Attribute` | Resolves an entity attribute by namespaced key |

## links

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,13 @@
import org.incendo.cloud.execution.ExecutionCoordinator;
import org.incendo.cloud.minestom.caption.MinestomDefaultCaptionsProvider;
import org.incendo.cloud.minestom.parser.DimensionTypeParser;
import org.incendo.cloud.minestom.parser.EnchantmentParser;
import org.incendo.cloud.minestom.parser.EntityTypeParser;
import org.incendo.cloud.minestom.parser.GameModeParser;
import org.incendo.cloud.minestom.parser.InstanceParser;
import org.incendo.cloud.minestom.parser.ItemStackParser;
import org.incendo.cloud.minestom.parser.PlayerParser;
import org.incendo.cloud.minestom.parser.SoundEventParser;
import org.incendo.cloud.minestom.parser.attribute.AttributeParser;
import org.incendo.cloud.minestom.parser.location.PosParser;
import org.incendo.cloud.minestom.parser.location.VecParser;

Expand Down Expand Up @@ -80,11 +82,13 @@ public MinestomCommandManager(
.registerParser(PlayerParser.playerParser())
.registerParser(EntityTypeParser.entityTypeParser())
.registerParser(InstanceParser.instanceParser())
.registerParser(GameModeParser.gameModeParser())
.registerParser(DimensionTypeParser.dimensionTypeParser())
.registerParser(PosParser.posParser())
.registerParser(VecParser.vecParser())
.registerParser(ItemStackParser.itemStackParser());
.registerParser(ItemStackParser.itemStackParser())
.registerParser(EnchantmentParser.enchantmentParser())
.registerParser(SoundEventParser.soundEventParser())
.registerParser(AttributeParser.attributeParser());

this.captionRegistry().registerProvider(new MinestomDefaultCaptionsProvider<>());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,6 @@ public final class MinestomCaptionKeys {
*/
public static final Caption ARGUMENT_PARSE_FAILURE_INSTANCE = of("argument.parse.failure.instance");

/**
* Variables: {@code <input>}
*/
public static final Caption ARGUMENT_PARSE_FAILURE_GAME_MODE = of("argument.parse.failure.game_mode");

/**
* Variables: {@code <input>}
*/
Expand All @@ -77,6 +72,21 @@ public final class MinestomCaptionKeys {
*/
public static final Caption ARGUMENT_PARSE_FAILURE_ITEM_STACK = of("argument.parse.failure.item_stack");

/**
* Variables: {@code <input>}
*/
public static final Caption ARGUMENT_PARSE_FAILURE_ENCHANTMENT = of("argument.parse.failure.enchantment");

/**
* Variables: {@code <input>}
*/
public static final Caption ARGUMENT_PARSE_FAILURE_SOUND_EVENT = of("argument.parse.failure.sound_event");

/**
* Variables: {@code <input>}
*/
public static final Caption ARGUMENT_PARSE_FAILURE_ATTRIBUTE = of("argument.parse.failure.attribute");

private MinestomCaptionKeys() {
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,6 @@ public final class MinestomDefaultCaptionsProvider<C> extends DelegatingCaptionP
*/
public static final String ARGUMENT_PARSE_FAILURE_INSTANCE = "No instance found for input '<input>'";

/**
* Default caption for {@link MinestomCaptionKeys#ARGUMENT_PARSE_FAILURE_GAME_MODE}
*/
public static final String ARGUMENT_PARSE_FAILURE_GAME_MODE = "'<input>' is not a valid game mode";

/**
* Default caption for {@link MinestomCaptionKeys#ARGUMENT_PARSE_FAILURE_DIMENSION_TYPE}
*/
Expand All @@ -74,15 +69,32 @@ public final class MinestomDefaultCaptionsProvider<C> extends DelegatingCaptionP
*/
public static final String ARGUMENT_PARSE_FAILURE_ITEM_STACK = "'<input>' is not a valid item";

/**
* Default caption for {@link MinestomCaptionKeys#ARGUMENT_PARSE_FAILURE_ENCHANTMENT}
*/
public static final String ARGUMENT_PARSE_FAILURE_ENCHANTMENT = "'<input>' is not a valid enchantment";

/**
* Default caption for {@link MinestomCaptionKeys#ARGUMENT_PARSE_FAILURE_SOUND_EVENT}
*/
public static final String ARGUMENT_PARSE_FAILURE_SOUND_EVENT = "'<input>' is not a valid sound event";

/**
* Default caption for {@link MinestomCaptionKeys#ARGUMENT_PARSE_FAILURE_ATTRIBUTE}
*/
public static final String ARGUMENT_PARSE_FAILURE_ATTRIBUTE = "'<input>' is not a valid attribute";

private static final CaptionProvider<?> PROVIDER = CaptionProvider.constantProvider()
.putCaption(MinestomCaptionKeys.ARGUMENT_PARSE_FAILURE_PLAYER, ARGUMENT_PARSE_FAILURE_PLAYER)
.putCaption(MinestomCaptionKeys.ARGUMENT_PARSE_FAILURE_ENTITY_TYPE, ARGUMENT_PARSE_FAILURE_ENTITY_TYPE)
.putCaption(MinestomCaptionKeys.ARGUMENT_PARSE_FAILURE_INSTANCE, ARGUMENT_PARSE_FAILURE_INSTANCE)
.putCaption(MinestomCaptionKeys.ARGUMENT_PARSE_FAILURE_GAME_MODE, ARGUMENT_PARSE_FAILURE_GAME_MODE)
.putCaption(MinestomCaptionKeys.ARGUMENT_PARSE_FAILURE_DIMENSION_TYPE, ARGUMENT_PARSE_FAILURE_DIMENSION_TYPE)
.putCaption(MinestomCaptionKeys.ARGUMENT_PARSE_FAILURE_VEC, ARGUMENT_PARSE_FAILURE_VEC)
.putCaption(MinestomCaptionKeys.ARGUMENT_PARSE_FAILURE_POS, ARGUMENT_PARSE_FAILURE_POS)
.putCaption(MinestomCaptionKeys.ARGUMENT_PARSE_FAILURE_ITEM_STACK, ARGUMENT_PARSE_FAILURE_ITEM_STACK)
.putCaption(MinestomCaptionKeys.ARGUMENT_PARSE_FAILURE_ENCHANTMENT, ARGUMENT_PARSE_FAILURE_ENCHANTMENT)
.putCaption(MinestomCaptionKeys.ARGUMENT_PARSE_FAILURE_SOUND_EVENT, ARGUMENT_PARSE_FAILURE_SOUND_EVENT)
.putCaption(MinestomCaptionKeys.ARGUMENT_PARSE_FAILURE_ATTRIBUTE, ARGUMENT_PARSE_FAILURE_ATTRIBUTE)
.build();

@SuppressWarnings("unchecked")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,16 +47,6 @@ public ProtoItemStack(final @NonNull Material material) {
this.material = material;
}

/**
* Get the {@link Material} of this {@link ProtoItemStack}.
*
* @return the {@link Material}
* @since 1.5.0
*/
public @NonNull Material material() {
return this.material;
}

/**
* Creates an {@link ItemStack} from this proto item stack with the given amount.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
//
// MIT License
//
// Copyright (c) 2024 Incendo
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
package org.incendo.cloud.minestom.parser;

import java.util.stream.Collectors;
import net.kyori.adventure.key.Key;
import net.minestom.server.MinecraftServer;
import net.minestom.server.item.enchant.Enchantment;
import net.minestom.server.registry.RegistryKey;
import org.apiguardian.api.API;
import org.incendo.cloud.caption.CaptionVariable;
import org.incendo.cloud.component.CommandComponent;
import org.incendo.cloud.context.CommandContext;
import org.incendo.cloud.context.CommandInput;
import org.incendo.cloud.exception.parsing.ParserException;
import org.incendo.cloud.minestom.caption.MinestomCaptionKeys;
import org.incendo.cloud.parser.ArgumentParseResult;
import org.incendo.cloud.parser.ArgumentParser;
import org.incendo.cloud.parser.ParserDescriptor;
import org.incendo.cloud.suggestion.BlockingSuggestionProvider;
import org.jspecify.annotations.NonNull;

/**
* Parser for {@link RegistryKey} referencing an {@link Enchantment}, resolved by namespaced key.
*
* @param <C> command sender type
*/
public final class EnchantmentParser<C> implements ArgumentParser<C, RegistryKey<Enchantment>>, BlockingSuggestionProvider.Strings<C> {

/**
* Creates a new enchantment parser.
*
* @param <C> command sender type
* @return the created parser
* @since 2.0.0
*/
@API(status = API.Status.STABLE, since = "2.0.0")
@SuppressWarnings("unchecked")
public static <C> @NonNull ParserDescriptor<C, RegistryKey<Enchantment>> enchantmentParser() {
return ParserDescriptor.of(new EnchantmentParser<>(), (Class<RegistryKey<Enchantment>>) (Class<?>) RegistryKey.class);
}

/**
* Returns a {@link CommandComponent.Builder} using {@link #enchantmentParser()} as the parser.
*
* @param <C> the command sender type
* @return the component builder
* @since 2.0.0
*/
@API(status = API.Status.STABLE, since = "2.0.0")
@SuppressWarnings("unchecked")
public static <C> CommandComponent.@NonNull Builder<C, RegistryKey<Enchantment>> enchantmentComponent() {
return CommandComponent.<C, RegistryKey<Enchantment>>builder().parser(enchantmentParser());
}

@Override
public @NonNull ArgumentParseResult<@NonNull RegistryKey<Enchantment>> parse(
final @NonNull CommandContext<@NonNull C> commandContext,
final @NonNull CommandInput commandInput
) {
final String input = commandInput.readString();
final Key key = input.contains(":") ? Key.key(input) : Key.key("minecraft", input);
final RegistryKey<Enchantment> registryKey = MinecraftServer.getEnchantmentRegistry().getKey(key);
if (registryKey == null) {
return ArgumentParseResult.failure(
new EnchantmentParseException(input, commandContext)
);
}
return ArgumentParseResult.success(registryKey);
}

@Override
public @NonNull Iterable<@NonNull String> stringSuggestions(
final @NonNull CommandContext<C> commandContext,
final @NonNull CommandInput input
) {
return MinecraftServer.getEnchantmentRegistry().keys().stream()
.map(k -> k.key().value())
.collect(Collectors.toList());
}

/**
* Exception thrown when an enchantment cannot be found for the input provided.
*/
public static final class EnchantmentParseException extends ParserException {

private final String input;

/**
* Create a new enchantment parse exception.
*
* @param input string input
* @param context command context
*/
public EnchantmentParseException(
final @NonNull String input,
final @NonNull CommandContext<?> context
) {
super(
EnchantmentParser.class,
context,
MinestomCaptionKeys.ARGUMENT_PARSE_FAILURE_ENCHANTMENT,
CaptionVariable.of("input", input)
);
this.input = input;
}

/**
* Returns the supplied input.
*
* @return input value
*/
public @NonNull String input() {
return this.input;
}
}
}
Loading