Re-implement many converters using Piston utility converters

Dieser Commit ist enthalten in:
Kenzie Togami 2019-04-29 21:57:03 -07:00
Ursprung 3c04a83852
Commit d0f9a71d53
Es konnte kein GPG-Schlüssel zu dieser Signatur gefunden werden
GPG-Schlüssel-ID: 5D200B325E157A81
8 geänderte Dateien mit 91 neuen und 165 gelöschten Zeilen

Datei anzeigen

@ -19,49 +19,27 @@
package com.sk89q.worldedit.command.argument; package com.sk89q.worldedit.command.argument;
import com.google.common.collect.ImmutableSortedSet; import com.google.common.collect.ImmutableSetMultimap;
import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import org.enginehub.piston.CommandManager; import org.enginehub.piston.CommandManager;
import org.enginehub.piston.converter.ArgumentConverter; import org.enginehub.piston.converter.MultiKeyConverter;
import org.enginehub.piston.converter.ConversionResult;
import org.enginehub.piston.converter.FailedConversion;
import org.enginehub.piston.converter.SuccessfulConversion;
import org.enginehub.piston.inject.InjectedValueAccess;
import org.enginehub.piston.inject.Key; import org.enginehub.piston.inject.Key;
public class BooleanConverter implements ArgumentConverter<Boolean> { public class BooleanConverter {
public static void register(CommandManager commandManager) { public static void register(CommandManager commandManager) {
commandManager.registerConverter(Key.of(Boolean.class), new BooleanConverter()); commandManager.registerConverter(Key.of(Boolean.class),
MultiKeyConverter.builder(
ImmutableSetMultimap.<Boolean, String>builder()
.putAll(false, "off", "f", "false", "n", "no")
.putAll(true, "on", "t", "true", "y", "yes")
.build()
)
.errorMessage(arg -> "Not a boolean value" + arg)
.build()
);
} }
private static final ImmutableSortedSet<String> TRUE = ImmutableSortedSet
.orderedBy(String.CASE_INSENSITIVE_ORDER)
.add("on", "t", "true", "y", "yes")
.build();
private static final ImmutableSortedSet<String> FALSE = ImmutableSortedSet
.orderedBy(String.CASE_INSENSITIVE_ORDER)
.add("off", "f", "false", "n", "no")
.build();
private BooleanConverter() { private BooleanConverter() {
} }
@Override
public Component describeAcceptableArguments() {
return TextComponent.of("on|off|true|false");
}
@Override
public ConversionResult<Boolean> convert(String argument, InjectedValueAccess context) {
if (TRUE.contains(argument)) {
return SuccessfulConversion.fromSingle(true);
}
if (FALSE.contains(argument)) {
return SuccessfulConversion.fromSingle(false);
}
return FailedConversion.from(new IllegalArgumentException("Not a strictly boolean value: " + argument));
}
} }

Datei anzeigen

@ -71,7 +71,7 @@ public class CommaSeparatedValuesConverter<T> implements ArgumentConverter<T> {
@Override @Override
public List<String> getSuggestions(String input) { public List<String> getSuggestions(String input) {
String lastInput = Iterables.getLast(COMMA.split(input)); String lastInput = Iterables.getLast(COMMA.split(input), "");
return delegate.getSuggestions(lastInput); return delegate.getSuggestions(lastInput);
} }

Datei anzeigen

@ -41,6 +41,7 @@ import org.enginehub.piston.inject.Key;
import java.util.List; import java.util.List;
import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toList;
import static org.enginehub.piston.converter.SuggestionHelper.limitByPrefix;
public class DirectionConverter implements ArgumentConverter<BlockVector3> { public class DirectionConverter implements ArgumentConverter<BlockVector3> {
@ -113,8 +114,6 @@ public class DirectionConverter implements ArgumentConverter<BlockVector3> {
@Override @Override
public List<String> getSuggestions(String input) { public List<String> getSuggestions(String input) {
return suggestions.stream() return limitByPrefix(suggestions.stream(), input);
.filter(s -> s.startsWith(input))
.collect(toList());
} }
} }

Datei anzeigen

@ -19,31 +19,20 @@
package com.sk89q.worldedit.command.argument; package com.sk89q.worldedit.command.argument;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedMap;
import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.util.TreeGenerator; import com.sk89q.worldedit.util.TreeGenerator;
import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import org.enginehub.piston.CommandManager; import org.enginehub.piston.CommandManager;
import org.enginehub.piston.converter.ArgumentConverter; import org.enginehub.piston.converter.ArgumentConverter;
import org.enginehub.piston.converter.ConversionResult; import org.enginehub.piston.converter.MultiKeyConverter;
import org.enginehub.piston.converter.FailedConversion;
import org.enginehub.piston.converter.SuccessfulConversion;
import org.enginehub.piston.inject.InjectedValueAccess;
import org.enginehub.piston.inject.Key; import org.enginehub.piston.inject.Key;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.Set; import java.util.Set;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Stream;
import static com.google.common.base.Preconditions.checkState; public class EnumConverter {
import static java.util.stream.Collectors.joining;
public class EnumConverter<E extends Enum<E>> implements ArgumentConverter<E> {
public static void register(CommandManager commandManager) { public static void register(CommandManager commandManager) {
commandManager.registerConverter(Key.of(SelectorChoice.class), commandManager.registerConverter(Key.of(SelectorChoice.class),
@ -58,59 +47,25 @@ public class EnumConverter<E extends Enum<E>> implements ArgumentConverter<E> {
null)); null));
} }
private static <E extends Enum<E>> EnumConverter<E> basic(Class<E> enumClass) { private static <E extends Enum<E>> ArgumentConverter<E> basic(Class<E> enumClass) {
return full(enumClass, e -> ImmutableSet.of(e.name()), null); return full(enumClass, e -> ImmutableSet.of(e.name()), null);
} }
private static <E extends Enum<E>> EnumConverter<E> basic(Class<E> enumClass, E unknownValue) { private static <E extends Enum<E>> ArgumentConverter<E> basic(Class<E> enumClass, E unknownValue) {
return full(enumClass, e -> ImmutableSet.of(e.name()), unknownValue); return full(enumClass, e -> ImmutableSet.of(e.name()), unknownValue);
} }
private static <E extends Enum<E>> EnumConverter<E> full(Class<E> enumClass, private static <E extends Enum<E>> ArgumentConverter<E> full(Class<E> enumClass,
Function<E, Set<String>> lookupKeys, Function<E, Set<String>> lookupKeys,
@Nullable E unknownValue) { @Nullable E unknownValue) {
return new EnumConverter<>(enumClass, lookupKeys, unknownValue); return MultiKeyConverter.from(
EnumSet.allOf(enumClass),
lookupKeys,
unknownValue
);
} }
private final Component choices; private EnumConverter() {
private final ImmutableMap<String, E> map;
@Nullable
private final E unknownValue;
private EnumConverter(Class<E> enumClass,
Function<E, Set<String>> lookupKeys,
@Nullable E unknownValue) {
ImmutableSortedMap.Builder<String, E> map = ImmutableSortedMap.orderedBy(String.CASE_INSENSITIVE_ORDER);
Stream.Builder<Set<String>> choices = Stream.builder();
EnumSet<E> validValues = EnumSet.allOf(enumClass);
if (unknownValue != null) {
validValues.remove(unknownValue);
}
for (E e : validValues) {
Set<String> keys = lookupKeys.apply(e);
checkState(keys.size() > 0, "No lookup keys for enum value %s", e);
choices.add(keys);
for (String key : keys) {
map.put(key, e);
}
}
this.choices = TextComponent.of(choices.build()
.map(choice -> choice.stream().collect(joining("|", "[", "]")))
.collect(joining("|")));
this.map = map.build();
this.unknownValue = unknownValue;
} }
@Override
public Component describeAcceptableArguments() {
return choices;
}
@Override
public ConversionResult<E> convert(String argument, InjectedValueAccess context) {
E result = map.getOrDefault(argument, unknownValue);
return result == null
? FailedConversion.from(new IllegalArgumentException("Not a valid choice: " + argument))
: SuccessfulConversion.fromSingle(result);
}
} }

Datei anzeigen

@ -31,9 +31,10 @@ import org.enginehub.piston.inject.InjectedValueAccess;
import org.enginehub.piston.inject.Key; import org.enginehub.piston.inject.Key;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
import static org.enginehub.piston.converter.SuggestionHelper.limitByPrefix;
public class ExpandAmountConverter implements ArgumentConverter<ExpandAmount> { public class ExpandAmountConverter implements ArgumentConverter<ExpandAmount> {
public static void register(CommandManager commandManager) { public static void register(CommandManager commandManager) {
@ -53,9 +54,9 @@ public class ExpandAmountConverter implements ArgumentConverter<ExpandAmount> {
@Override @Override
public List<String> getSuggestions(String input) { public List<String> getSuggestions(String input) {
return Stream.concat(Stream.of("vert"), integerConverter.getSuggestions(input).stream()) return limitByPrefix(Stream.concat(
.filter(x -> x.startsWith(input)) Stream.of("vert"), integerConverter.getSuggestions(input).stream()
.collect(Collectors.toList()); ), input);
} }
@Override @Override

Datei anzeigen

@ -19,54 +19,31 @@
package com.sk89q.worldedit.command.argument; package com.sk89q.worldedit.command.argument;
import com.google.common.collect.ImmutableSetMultimap;
import com.sk89q.worldedit.regions.factory.CuboidRegionFactory; import com.sk89q.worldedit.regions.factory.CuboidRegionFactory;
import com.sk89q.worldedit.regions.factory.CylinderRegionFactory; import com.sk89q.worldedit.regions.factory.CylinderRegionFactory;
import com.sk89q.worldedit.regions.factory.RegionFactory; import com.sk89q.worldedit.regions.factory.RegionFactory;
import com.sk89q.worldedit.regions.factory.SphereRegionFactory; import com.sk89q.worldedit.regions.factory.SphereRegionFactory;
import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import org.enginehub.piston.CommandManager; import org.enginehub.piston.CommandManager;
import org.enginehub.piston.converter.ArgumentConverter; import org.enginehub.piston.converter.MultiKeyConverter;
import org.enginehub.piston.converter.ConversionResult;
import org.enginehub.piston.converter.FailedConversion;
import org.enginehub.piston.converter.SuccessfulConversion;
import org.enginehub.piston.inject.InjectedValueAccess;
import org.enginehub.piston.inject.Key; import org.enginehub.piston.inject.Key;
public class RegionFactoryConverter implements ArgumentConverter<RegionFactory> { public class RegionFactoryConverter {
public static void register(CommandManager commandManager) { public static void register(CommandManager commandManager) {
commandManager.registerConverter(Key.of(RegionFactory.class), new RegionFactoryConverter()); commandManager.registerConverter(Key.of(RegionFactory.class),
MultiKeyConverter.builder(
ImmutableSetMultimap.<RegionFactory, String>builder()
.put(new CuboidRegionFactory(), "cuboid")
.put(new SphereRegionFactory(), "sphere")
.putAll(new CylinderRegionFactory(1), "cyl", "cylinder")
.build()
)
.errorMessage(arg -> "Not a known region type: " + arg)
.build()
);
} }
private RegionFactoryConverter() { private RegionFactoryConverter() {
} }
@Override
public Component describeAcceptableArguments() {
return TextComponent.of("cuboid|sphere|cyl");
}
@Override
public ConversionResult<RegionFactory> convert(String argument, InjectedValueAccess context) {
try {
return SuccessfulConversion.fromSingle(parse(argument));
} catch (Exception e) {
return FailedConversion.from(e);
}
}
private RegionFactory parse(String argument) {
switch (argument) {
case "cuboid":
return new CuboidRegionFactory();
case "sphere":
return new SphereRegionFactory();
case "cyl":
case "cylinder":
return new CylinderRegionFactory(1); // TODO: Adjustable height
default:
throw new IllegalArgumentException("Not a known region type: " + argument);
}
}
} }

Datei anzeigen

@ -19,6 +19,7 @@
package com.sk89q.worldedit.command.argument; package com.sk89q.worldedit.command.argument;
import com.google.common.collect.ImmutableList;
import com.sk89q.worldedit.registry.Registry; import com.sk89q.worldedit.registry.Registry;
import com.sk89q.worldedit.util.formatting.text.Component; import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.util.formatting.text.TextComponent; import com.sk89q.worldedit.util.formatting.text.TextComponent;
@ -40,40 +41,52 @@ import org.enginehub.piston.converter.SuccessfulConversion;
import org.enginehub.piston.inject.InjectedValueAccess; import org.enginehub.piston.inject.InjectedValueAccess;
import org.enginehub.piston.inject.Key; import org.enginehub.piston.inject.Key;
import java.lang.reflect.Field;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
import static org.enginehub.piston.converter.SuggestionHelper.limitByPrefix;
public class RegistryConverter<V> implements ArgumentConverter<V> { public class RegistryConverter<V> implements ArgumentConverter<V> {
@SuppressWarnings("unchecked")
public static void register(CommandManager commandManager) { public static void register(CommandManager commandManager) {
commandManager.registerConverter(Key.of(BlockType.class), ImmutableList.of(
new RegistryConverter<>(BlockType.class, BlockType.REGISTRY)); BlockType.class,
commandManager.registerConverter(Key.of(BlockCategory.class), BlockCategory.class,
new RegistryConverter<>(BlockCategory.class, BlockCategory.REGISTRY)); ItemType.class,
commandManager.registerConverter(Key.of(ItemType.class), ItemCategory.class,
new RegistryConverter<>(ItemType.class, ItemType.REGISTRY)); BiomeType.class,
commandManager.registerConverter(Key.of(ItemCategory.class), EntityType.class,
new RegistryConverter<>(ItemCategory.class, ItemCategory.REGISTRY)); FluidType.class,
commandManager.registerConverter(Key.of(BiomeType.class), FluidCategory.class,
new RegistryConverter<>(BiomeType.class, BiomeType.REGISTRY)); GameMode.class,
commandManager.registerConverter(Key.of(EntityType.class), WeatherType.class
new RegistryConverter<>(EntityType.class, EntityType.REGISTRY)); ).stream()
commandManager.registerConverter(Key.of(FluidType.class), .map(c -> (Class<Object>) c)
new RegistryConverter<>(FluidType.class, FluidType.REGISTRY)); .forEach(registryType ->
commandManager.registerConverter(Key.of(FluidCategory.class), commandManager.registerConverter(Key.of(registryType), from(registryType))
new RegistryConverter<>(FluidCategory.class, FluidCategory.REGISTRY)); );
commandManager.registerConverter(Key.of(GameMode.class), }
new RegistryConverter<>(GameMode.class, GameMode.REGISTRY));
commandManager.registerConverter(Key.of(WeatherType.class), @SuppressWarnings("unchecked")
new RegistryConverter<>(WeatherType.class, WeatherType.REGISTRY)); private static <V> RegistryConverter<V> from(Class<V> registryType) {
try {
Field registryField = registryType.getDeclaredField("REGISTRY");
Registry<V> registry = (Registry<V>) registryField.get(null);
return new RegistryConverter<>(registryType, registry);
} catch (NoSuchFieldException e) {
throw new IllegalArgumentException("Not a registry-backed type: " + registryType.getName());
} catch (IllegalAccessException e) {
throw new IllegalStateException("Registry field inaccessible on " + registryType.getName());
}
} }
private final Registry<V> registry; private final Registry<V> registry;
private final TextComponent choices; private final TextComponent choices;
public RegistryConverter(Class<V> clazz, Registry<V> registry) { private RegistryConverter(Class<V> clazz, Registry<V> registry) {
this.registry = registry; this.registry = registry;
this.choices = TextComponent.of("any " + clazz.getSimpleName()); this.choices = TextComponent.of("any " + registry.getName());
} }
@Override @Override
@ -85,14 +98,13 @@ public class RegistryConverter<V> implements ArgumentConverter<V> {
public ConversionResult<V> convert(String argument, InjectedValueAccess injectedValueAccess) { public ConversionResult<V> convert(String argument, InjectedValueAccess injectedValueAccess) {
V result = registry.get(argument); V result = registry.get(argument);
return result == null return result == null
? FailedConversion.from(new IllegalArgumentException("Not a valid choice: " + argument)) ? FailedConversion.from(new IllegalArgumentException(
"Not a valid " + registry.getName() + ": " + argument))
: SuccessfulConversion.fromSingle(result); : SuccessfulConversion.fromSingle(result);
} }
@Override @Override
public List<String> getSuggestions(String input) { public List<String> getSuggestions(String input) {
return registry.keySet().stream() return limitByPrefix(registry.keySet().stream(), input);
.filter(string -> string.startsWith(input))
.collect(Collectors.toList());
} }
} }

Datei anzeigen

@ -39,6 +39,10 @@ public class Registry<V> implements Iterable<V> {
this.name = name; this.name = name;
} }
public String getName() {
return name;
}
public @Nullable V get(final String key) { public @Nullable V get(final String key) {
checkState(key.equals(key.toLowerCase()), "key must be lowercase"); checkState(key.equals(key.toLowerCase()), "key must be lowercase");
return this.map.get(key); return this.map.get(key);