Skip to content

Commit

Permalink
Support minecraft 1.21.3 old enums
Browse files Browse the repository at this point in the history
  • Loading branch information
Rollczi committed Jan 6, 2025
1 parent d9c899e commit 86f559e
Show file tree
Hide file tree
Showing 13 changed files with 186 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ repositories {

maven("https://maven.fabricmc.net/") // fabric
maven("https://repo.dmulloy2.net/repository/public/") // protocol lib
maven("https://papermc.io/repo/repository/maven-public/") // paper, adventure, velocity
maven("https://repo.papermc.io/repository/maven-public/") // paper, adventure, velocity
maven("https://repo.opencollab.dev/maven-snapshots") // nukkit
maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/") // spigot
maven("https://jitpack.io/") // minestom
Expand Down
4 changes: 2 additions & 2 deletions examples/bukkit/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ tasks.shadowJar {

tasks.withType<JavaCompile> {
options.compilerArgs.add("-parameters")
options.release = 17
options.release = 21
}

sourceSets.test {
Expand All @@ -54,6 +54,6 @@ sourceSets.test {
}

tasks.runServer {
minecraftVersion("1.21")
minecraftVersion("1.21.4")
allJvmArgs = listOf("-DPaper.IgnoreJavaVersion=true")
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package dev.rollczi.example.bukkit;

import dev.rollczi.example.bukkit.argument.GameModeArgument;
import dev.rollczi.example.bukkit.command.CatCommand;
import dev.rollczi.example.bukkit.command.ConvertCommand;
import dev.rollczi.example.bukkit.command.FlyCommand;
import dev.rollczi.example.bukkit.command.GameModeCommand;
Expand Down Expand Up @@ -67,6 +68,7 @@ public void onEnable() {
new NumberCommand(),
new CurrencyCommand(currencyService),
new CurrencyBalanceCommand(currencyService),
new CatCommand(),
new UserCommand()
)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package dev.rollczi.example.bukkit.command;

import dev.rollczi.litecommands.annotations.argument.Arg;
import dev.rollczi.litecommands.annotations.command.Command;
import dev.rollczi.litecommands.annotations.context.Context;
import dev.rollczi.litecommands.annotations.execute.Execute;
import org.bukkit.Location;
import org.bukkit.entity.Cat;
import org.bukkit.entity.EntityType;

@Command(name = "cat")
public class CatCommand {

@Execute
void executeCat(@Context Location currentLocation, @Arg Cat.Type type) {
Cat cat = (Cat) currentLocation.getWorld().spawnEntity(currentLocation, EntityType.CAT);
cat.setCatType(type);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public void execute(
@Arg("item") Material item,
@OptionalArg("amount") Integer amount
) {
if (amount != null) {
if (amount == null) {
amount = 1;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@
import dev.rollczi.litecommands.LiteCommandsFactory;
import dev.rollczi.litecommands.bukkit.argument.LocationArgument;
import dev.rollczi.litecommands.bukkit.argument.OfflinePlayerArgument;
import dev.rollczi.litecommands.bukkit.argument.OldEnumAccessor;
import dev.rollczi.litecommands.bukkit.argument.OldEnumArgument;
import dev.rollczi.litecommands.bukkit.argument.PlayerArgument;
import dev.rollczi.litecommands.bukkit.argument.WorldArgument;
import dev.rollczi.litecommands.bukkit.context.LocationContext;
import dev.rollczi.litecommands.bukkit.context.PlayerOnlyContextProvider;
import dev.rollczi.litecommands.bukkit.context.WorldContext;
import dev.rollczi.litecommands.bukkit.util.BukkitFallbackPrefixUtil;
import dev.rollczi.litecommands.message.MessageRegistry;
import dev.rollczi.litecommands.reflect.type.TypeRange;
import org.bukkit.Location;
import org.bukkit.OfflinePlayer;
import org.bukkit.Server;
Expand Down Expand Up @@ -75,6 +78,11 @@ public static <B extends LiteCommandsBuilder<CommandSender, LiteBukkitSettings,
.context(Location.class, new LocationContext(messageRegistry))

.result(String.class, new StringHandler());

if (OldEnumAccessor.isAvailable()) {
TypeRange<Object> upwards = (TypeRange<Object>) TypeRange.upwards(OldEnumAccessor.getTypeOrThrow());
builder.advanced().argument(upwards, new OldEnumArgument());
}
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@ public class LiteBukkitSettings implements PlatformSettings {
private BukkitCommandsRegistry commandsRegistry;
private TabComplete tabCompleter;

public LiteBukkitSettings() {
public LiteBukkitSettings(BukkitCommandsRegistry commandsRegistry) {
this.commandsRegistry = commandsRegistry;
}

LiteBukkitSettings(Server server) {
public LiteBukkitSettings(Server server) {
this.commandsRegistry = BukkitCommandsRegistryImpl.create(server);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package dev.rollczi.litecommands.bukkit.argument;

import dev.rollczi.litecommands.reflect.LiteCommandsReflectException;
import dev.rollczi.litecommands.reflect.ReflectUtil;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import org.jetbrains.annotations.NotNull;

public class OldEnumAccessor {

private static final Map<Class<?>, Method> VALUE_OF_METHODS = new HashMap<>();
private static final Map<Class<?>, Method> NAME_METHODS = new HashMap<>();
private static final Map<Class<?>, Method> VALUES_METHODS = new HashMap<>();

public static boolean isAvailable() {
return getType().isPresent();
}

public static Class<?> getTypeOrThrow() {
return getType().orElseThrow(() -> new IllegalStateException("OldEnum is not available"));
}

public static Optional<Class<?>> getType() {
try {
return Optional.of(Class.forName("org.bukkit.util.OldEnum"));
} catch (ClassNotFoundException classNotFoundException) {
return Optional.empty();
}
}

public static Object invokeValueOf(Class<?> type, String source) {
if (!isInstanceOfOldEnum(type)) {
throw new IllegalArgumentException("Type is not an instance of OldEnum");
}

Method valueOfMethod = VALUE_OF_METHODS.computeIfAbsent(type, key -> ReflectUtil.getMethod(type, "valueOf", String.class));
try {
return ReflectUtil.invokeStaticMethod(valueOfMethod, source);
} catch (LiteCommandsReflectException exception) {
throw exception.toRuntimeException();
}
}

public static String invokeName(Object source) {
Class<?> type = source.getClass();
if (!isInstanceOfOldEnum(type)) {
throw new IllegalArgumentException("Type is not an instance of OldEnum");
}

Method nameMethod = NAME_METHODS.computeIfAbsent(type, key -> ReflectUtil.getMethod(type, "name"));
try {
return ReflectUtil.invokeMethod(nameMethod, source);
} catch (LiteCommandsReflectException exception) {
throw exception.toRuntimeException();
}
}

public static Object[] invokeValues(Class<?> type) {
if (!isInstanceOfOldEnum(type)) {
throw new IllegalArgumentException("Type is not an instance of OldEnum");
}

Method valuesMethod = VALUES_METHODS.computeIfAbsent(type, key -> ReflectUtil.getMethod(type, "values"));
try {
return ReflectUtil.invokeStaticMethod(valuesMethod);
} catch (LiteCommandsReflectException exception) {
throw exception.toRuntimeException();
}
}

private static @NotNull Boolean isInstanceOfOldEnum(Class<?> type) {
return getType()
.map(oldEnum -> oldEnum.isAssignableFrom(type))
.orElse(false);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package dev.rollczi.litecommands.bukkit.argument;

import dev.rollczi.litecommands.argument.Argument;
import dev.rollczi.litecommands.argument.parser.ParseResult;
import dev.rollczi.litecommands.argument.resolver.ArgumentResolver;
import dev.rollczi.litecommands.invalidusage.InvalidUsage;
import dev.rollczi.litecommands.invocation.Invocation;
import dev.rollczi.litecommands.suggestion.SuggestionContext;
import dev.rollczi.litecommands.suggestion.SuggestionResult;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import org.bukkit.command.CommandSender;

public class OldEnumArgument extends ArgumentResolver<CommandSender, Object> {

private final Map<Class<?>, SuggestionResult> cachedOldEnumSuggestions = new HashMap<>();

@Override
public boolean canParse(Argument<Object> argument) {
return OldEnumAccessor.getType().map(type -> type.isAssignableFrom(argument.getType().getRawType()))
.orElseThrow(() -> new IllegalStateException("OldEnumArgument can't be used without on old bukkit version"));
}

@Override
protected ParseResult<Object> parse(Invocation<CommandSender> invocation, Argument<Object> context, String argument) {
try {
return ParseResult.success(OldEnumAccessor.invokeValueOf(context.getType().getRawType(), argument));
} catch (IllegalArgumentException ignored) {
return ParseResult.failure(InvalidUsage.Cause.INVALID_ARGUMENT);
}
}

@Override
public SuggestionResult suggest(Invocation<CommandSender> invocation, Argument<Object> argument, SuggestionContext context) {
Class<?> oldEnumClass = argument.getType().getRawType();

return cachedOldEnumSuggestions.computeIfAbsent(oldEnumClass, key -> {
Object[] oldEnums = OldEnumAccessor.invokeValues(oldEnumClass);
if (oldEnums.length == 0) {
return SuggestionResult.empty();
}

return Arrays.stream(oldEnums)
.map(oldEnum -> OldEnumAccessor.invokeName(oldEnum))
.collect(SuggestionResult.collector());
});
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,11 @@ public LiteCommandsException(String message, List<? extends Throwable> exception
exceptions.forEach(exception -> addSuppressed(exception));
}

public RuntimeException toRuntimeException() {
if (getCause() instanceof Exception) {
return (RuntimeException) getCause();
}
return this;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import java.util.function.Function;
import java.util.function.Supplier;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.UnknownNullability;

public interface ParseResult<EXCEPTED> extends RequirementFutureResult<EXCEPTED> {

Expand Down Expand Up @@ -71,7 +72,7 @@ static <EXPECTED> ParseAsyncResult<EXPECTED> completableFuture(CompletableFuture
}

@ApiStatus.Experimental
static <T, EXPECTED> ParseAsyncResult<EXPECTED> completableFuture(CompletableFuture<T> future, Function<T, ? extends ParseResult<EXPECTED>> mapper) {
static <T, EXPECTED> ParseAsyncResult<EXPECTED> completableFuture(CompletableFuture<T> future, Function<@UnknownNullability T, ? extends ParseResult<EXPECTED>> mapper) {
return new ParseAsyncResult<>(future.thenApply(mapper));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,14 @@ public Iterator<Class<?>> iterator() {
private class TypeIterator implements Iterator<Class<?>> {

private Class<?> next;
private Class<?> lastSuperclass;
private final Queue<Class<?>> interfaces = new LinkedList<>();
private final Set<Class<?>> visitedInterfaces = new HashSet<>();

private TypeIterator() {
this.next = baseType;
this.lastSuperclass = baseType;
this.interfaces.addAll(ReflectIndex.getInterfaces(baseType));
}

@Override
Expand Down Expand Up @@ -60,10 +63,11 @@ public Class<?> next() {
return nextToReturn;
}

Class<?> superclass = nextToReturn.getSuperclass();
Class<?> superclass = this.lastSuperclass.getSuperclass();

if (superclass != null) {
this.next = superclass;
this.lastSuperclass = superclass;
interfaces.addAll(ReflectIndex.getInterfaces(superclass));
return nextToReturn;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
Expand Down Expand Up @@ -147,8 +148,11 @@ public static <T> T invokeMethod(Method method, Object instance, Object... param
try {
return (T) method.invoke(instance, params);
}
catch (Exception exception) {
throw new LiteCommandsReflectException("Unable to invoke method " + method.getName() + " in " + instance.getClass(), exception);
catch (InvocationTargetException invocationTargetException) {
throw new LiteCommandsReflectException("Unable to invoke method " + method.getName() + " in " + instance.getClass(), invocationTargetException.getCause());
}
catch (IllegalAccessException exception) {
throw new LiteCommandsReflectException("Cannot access method " + method.getName() + " in " + instance.getClass(), exception);
}
}

Expand Down

0 comments on commit 86f559e

Please sign in to comment.