diff options
Diffstat (limited to 'src/main/java/de/hysky/skyblocker/utils')
8 files changed, 463 insertions, 0 deletions
diff --git a/src/main/java/de/hysky/skyblocker/utils/command/argumenttypes/EggTypeArgumentType.java b/src/main/java/de/hysky/skyblocker/utils/command/argumenttypes/EggTypeArgumentType.java new file mode 100644 index 00000000..a6532ff8 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/utils/command/argumenttypes/EggTypeArgumentType.java @@ -0,0 +1,40 @@ +package de.hysky.skyblocker.utils.command.argumenttypes; + +import com.mojang.brigadier.StringReader; +import com.mojang.brigadier.arguments.ArgumentType; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.suggestion.Suggestions; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; +import de.hysky.skyblocker.skyblock.chocolatefactory.EggFinder; +import net.minecraft.command.CommandSource; + +import java.util.Collection; +import java.util.concurrent.CompletableFuture; + +public final class EggTypeArgumentType implements ArgumentType<EggFinder.EggType> { + @Override + public EggFinder.EggType parse(StringReader reader) throws CommandSyntaxException { + String name = reader.readUnquotedString(); + for (EggFinder.EggType type : EggFinder.EggType.entries) { + if (type.name().equalsIgnoreCase(name)) return type; + } + throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument().create(); + } + + @Override + public <S> CompletableFuture<Suggestions> listSuggestions(CommandContext<S> context, SuggestionsBuilder builder) { + return context.getSource() instanceof CommandSource + ? CommandSource.suggestMatching(EggFinder.EggType.entries.stream().map(EggFinder.EggType::name).map(String::toLowerCase), builder) + : Suggestions.empty(); + } + + @Override + public Collection<String> getExamples() { + return EggFinder.EggType.entries.stream().map(EggFinder.EggType::name).map(String::toLowerCase).toList(); + } + + public static EggTypeArgumentType eggType() { + return new EggTypeArgumentType(); + } +} diff --git a/src/main/java/de/hysky/skyblocker/utils/command/argumenttypes/blockpos/ClientBlockPosArgumentType.java b/src/main/java/de/hysky/skyblocker/utils/command/argumenttypes/blockpos/ClientBlockPosArgumentType.java new file mode 100644 index 00000000..3a226414 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/utils/command/argumenttypes/blockpos/ClientBlockPosArgumentType.java @@ -0,0 +1,72 @@ +package de.hysky.skyblocker.utils.command.argumenttypes.blockpos; + +import com.mojang.brigadier.StringReader; +import com.mojang.brigadier.arguments.ArgumentType; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.suggestion.Suggestions; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; +import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.command.CommandSource; +import net.minecraft.command.argument.BlockPosArgumentType; +import net.minecraft.server.command.CommandManager; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +import java.util.Collection; +import java.util.Collections; +import java.util.concurrent.CompletableFuture; + +import static net.minecraft.command.argument.BlockPosArgumentType.*; + +// Uses the static fields of BlockPosArgumentType to not create the same field twice +public class ClientBlockPosArgumentType implements ArgumentType<ClientPosArgument> { + public static ClientBlockPosArgumentType blockPos() { + return new ClientBlockPosArgumentType(); + } + + public static BlockPos getLoadedBlockPos(CommandContext<FabricClientCommandSource> context, String name) throws CommandSyntaxException { + return getLoadedBlockPos(context, context.getSource().getWorld(), name); + } + + public static BlockPos getLoadedBlockPos(CommandContext<FabricClientCommandSource> context, ClientWorld world, String name) throws CommandSyntaxException { + BlockPos blockPos = getBlockPos(context, name); + if (!world.isChunkLoaded(blockPos)) throw UNLOADED_EXCEPTION.create(); + if (!world.isInBuildLimit(blockPos)) throw OUT_OF_WORLD_EXCEPTION.create(); + + return blockPos; + } + + public static BlockPos getBlockPos(CommandContext<FabricClientCommandSource> context, String name) { + return context.getArgument(name, ClientPosArgument.class).toAbsoluteBlockPos(context.getSource()); + } + + public static BlockPos getValidBlockPos(CommandContext<FabricClientCommandSource> context, String name) throws CommandSyntaxException { + BlockPos blockPos = getBlockPos(context, name); + if (!World.isValid(blockPos)) { + throw OUT_OF_BOUNDS_EXCEPTION.create(); + } else { + return blockPos; + } + } + + public ClientPosArgument parse(StringReader stringReader) throws CommandSyntaxException { + return stringReader.canRead() && stringReader.peek() == '^' ? LookingClientPosArgument.parse(stringReader) : DefaultClientPosArgument.parse(stringReader); + } + + @Override + public <S> CompletableFuture<Suggestions> listSuggestions(CommandContext<S> context, SuggestionsBuilder builder) { + if (!(context.getSource() instanceof CommandSource commandSource)) return Suggestions.empty(); + + String string = builder.getRemaining(); + Collection<CommandSource.RelativePosition> collection = !string.isEmpty() && string.charAt(0) == '^' ? Collections.singleton(CommandSource.RelativePosition.ZERO_LOCAL) : commandSource.getBlockPositionSuggestions(); + + return CommandSource.suggestPositions(string, collection, builder, CommandManager.getCommandValidator(this::parse)); + } + + @Override + public Collection<String> getExamples() { + return BlockPosArgumentType.EXAMPLES; + } +} diff --git a/src/main/java/de/hysky/skyblocker/utils/command/argumenttypes/blockpos/ClientPosArgument.java b/src/main/java/de/hysky/skyblocker/utils/command/argumenttypes/blockpos/ClientPosArgument.java new file mode 100644 index 00000000..3dff86ab --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/utils/command/argumenttypes/blockpos/ClientPosArgument.java @@ -0,0 +1,27 @@ +package de.hysky.skyblocker.utils.command.argumenttypes.blockpos; + +import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec2f; +import net.minecraft.util.math.Vec3d; + +/** + * This interface, its 2 implementations and ClientBlockPosArgumentType are all copied from minecraft + * and converted to use FabricClientCommandSource instead of ServerCommandSource. + * This removes the need for hacky workarounds such as creating new ServerCommandSources with null or 0 on every argument. + */ +public interface ClientPosArgument { + Vec3d toAbsolutePos(FabricClientCommandSource source); + + Vec2f toAbsoluteRotation(FabricClientCommandSource source); + + default BlockPos toAbsoluteBlockPos(FabricClientCommandSource source) { + return BlockPos.ofFloored(this.toAbsolutePos(source)); + } + + boolean isXRelative(); + + boolean isYRelative(); + + boolean isZRelative(); +} diff --git a/src/main/java/de/hysky/skyblocker/utils/command/argumenttypes/blockpos/DefaultClientPosArgument.java b/src/main/java/de/hysky/skyblocker/utils/command/argumenttypes/blockpos/DefaultClientPosArgument.java new file mode 100644 index 00000000..47258b9f --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/utils/command/argumenttypes/blockpos/DefaultClientPosArgument.java @@ -0,0 +1,113 @@ +package de.hysky.skyblocker.utils.command.argumenttypes.blockpos; + +import com.mojang.brigadier.StringReader; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; +import net.minecraft.command.argument.CoordinateArgument; +import net.minecraft.command.argument.Vec3ArgumentType; +import net.minecraft.util.math.Vec2f; +import net.minecraft.util.math.Vec3d; + +public class DefaultClientPosArgument implements ClientPosArgument { + private final CoordinateArgument x; + private final CoordinateArgument y; + private final CoordinateArgument z; + + public DefaultClientPosArgument(CoordinateArgument x, CoordinateArgument y, CoordinateArgument z) { + this.x = x; + this.y = y; + this.z = z; + } + + @Override + public Vec3d toAbsolutePos(FabricClientCommandSource source) { + Vec3d vec3d = source.getPosition(); + return new Vec3d(this.x.toAbsoluteCoordinate(vec3d.x), this.y.toAbsoluteCoordinate(vec3d.y), this.z.toAbsoluteCoordinate(vec3d.z)); + } + + @Override + public Vec2f toAbsoluteRotation(FabricClientCommandSource source) { + Vec2f vec2f = source.getRotation(); + return new Vec2f((float)this.x.toAbsoluteCoordinate(vec2f.x), (float)this.y.toAbsoluteCoordinate(vec2f.y)); + } + + @Override + public boolean isXRelative() { + return this.x.isRelative(); + } + + @Override + public boolean isYRelative() { + return this.y.isRelative(); + } + + @Override + public boolean isZRelative() { + return this.z.isRelative(); + } + + public boolean equals(Object o) { + if (this == o) return true; + + return o instanceof DefaultClientPosArgument defaultPosArgument && + this.x.equals(defaultPosArgument.x) && this.y.equals(defaultPosArgument.y) && this.z.equals(defaultPosArgument.z); + } + + public static DefaultClientPosArgument parse(StringReader reader) throws CommandSyntaxException { + int i = reader.getCursor(); + CoordinateArgument coordinateArgument = CoordinateArgument.parse(reader); + if (reader.canRead() && reader.peek() == ' ') { + reader.skip(); + CoordinateArgument coordinateArgument2 = CoordinateArgument.parse(reader); + if (reader.canRead() && reader.peek() == ' ') { + reader.skip(); + CoordinateArgument coordinateArgument3 = CoordinateArgument.parse(reader); + return new DefaultClientPosArgument(coordinateArgument, coordinateArgument2, coordinateArgument3); + } else { + reader.setCursor(i); + throw Vec3ArgumentType.INCOMPLETE_EXCEPTION.createWithContext(reader); + } + } else { + reader.setCursor(i); + throw Vec3ArgumentType.INCOMPLETE_EXCEPTION.createWithContext(reader); + } + } + + public static DefaultClientPosArgument parse(StringReader reader, boolean centerIntegers) throws CommandSyntaxException { + int i = reader.getCursor(); + CoordinateArgument coordinateArgument = CoordinateArgument.parse(reader, centerIntegers); + if (reader.canRead() && reader.peek() == ' ') { + reader.skip(); + CoordinateArgument coordinateArgument2 = CoordinateArgument.parse(reader, false); + if (reader.canRead() && reader.peek() == ' ') { + reader.skip(); + CoordinateArgument coordinateArgument3 = CoordinateArgument.parse(reader, centerIntegers); + return new DefaultClientPosArgument(coordinateArgument, coordinateArgument2, coordinateArgument3); + } else { + reader.setCursor(i); + throw Vec3ArgumentType.INCOMPLETE_EXCEPTION.createWithContext(reader); + } + } else { + reader.setCursor(i); + throw Vec3ArgumentType.INCOMPLETE_EXCEPTION.createWithContext(reader); + } + } + + public static DefaultClientPosArgument absolute(double x, double y, double z) { + return new DefaultClientPosArgument(new CoordinateArgument(false, x), new CoordinateArgument(false, y), new CoordinateArgument(false, z)); + } + + public static DefaultClientPosArgument absolute(Vec2f vec) { + return new DefaultClientPosArgument(new CoordinateArgument(false, vec.x), new CoordinateArgument(false, vec.y), new CoordinateArgument(true, 0.0)); + } + + public static DefaultClientPosArgument zero() { + return new DefaultClientPosArgument(new CoordinateArgument(true, 0.0), new CoordinateArgument(true, 0.0), new CoordinateArgument(true, 0.0)); + } + + public int hashCode() { + int i = this.x.hashCode(); + i = 31 * i + this.y.hashCode(); + return 31 * i + this.z.hashCode(); + } +} diff --git a/src/main/java/de/hysky/skyblocker/utils/command/argumenttypes/blockpos/LookingClientPosArgument.java b/src/main/java/de/hysky/skyblocker/utils/command/argumenttypes/blockpos/LookingClientPosArgument.java new file mode 100644 index 00000000..3f89f9c7 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/utils/command/argumenttypes/blockpos/LookingClientPosArgument.java @@ -0,0 +1,106 @@ +package de.hysky.skyblocker.utils.command.argumenttypes.blockpos; + +import com.mojang.brigadier.StringReader; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; +import net.minecraft.command.argument.CoordinateArgument; +import net.minecraft.command.argument.Vec3ArgumentType; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec2f; +import net.minecraft.util.math.Vec3d; + +import java.util.Objects; + +public class LookingClientPosArgument implements ClientPosArgument { + private final double x; + private final double y; + private final double z; + + public LookingClientPosArgument(double x, double y, double z) { + this.x = x; + this.y = y; + this.z = z; + } + + @Override + public Vec3d toAbsolutePos(FabricClientCommandSource source) { + Vec2f vec2f = source.getRotation(); + Vec3d vec3d = source.getPlayer().getPos(); + float f = MathHelper.cos((vec2f.y + 90.0F) * (float) (Math.PI / 180.0)); + float g = MathHelper.sin((vec2f.y + 90.0F) * (float) (Math.PI / 180.0)); + float h = MathHelper.cos(-vec2f.x * (float) (Math.PI / 180.0)); + float i = MathHelper.sin(-vec2f.x * (float) (Math.PI / 180.0)); + float j = MathHelper.cos((-vec2f.x + 90.0F) * (float) (Math.PI / 180.0)); + float k = MathHelper.sin((-vec2f.x + 90.0F) * (float) (Math.PI / 180.0)); + Vec3d vec3d2 = new Vec3d(f * h, i, g * h); + Vec3d vec3d3 = new Vec3d(f * j, k, g * j); + Vec3d vec3d4 = vec3d2.crossProduct(vec3d3).multiply(-1.0); + double d = vec3d2.x * this.z + vec3d3.x * this.y + vec3d4.x * this.x; + double e = vec3d2.y * this.z + vec3d3.y * this.y + vec3d4.y * this.x; + double l = vec3d2.z * this.z + vec3d3.z * this.y + vec3d4.z * this.x; + return new Vec3d(vec3d.x + d, vec3d.y + e, vec3d.z + l); + } + + @Override + public Vec2f toAbsoluteRotation(FabricClientCommandSource source) { + return Vec2f.ZERO; + } + + @Override + public boolean isXRelative() { + return true; + } + + @Override + public boolean isYRelative() { + return true; + } + + @Override + public boolean isZRelative() { + return true; + } + + public static LookingClientPosArgument parse(StringReader reader) throws CommandSyntaxException { + int i = reader.getCursor(); + double d = readCoordinate(reader, i); + if (reader.canRead() && reader.peek() == ' ') { + reader.skip(); + double e = readCoordinate(reader, i); + if (reader.canRead() && reader.peek() == ' ') { + reader.skip(); + double f = readCoordinate(reader, i); + return new LookingClientPosArgument(d, e, f); + } else { + reader.setCursor(i); + throw Vec3ArgumentType.INCOMPLETE_EXCEPTION.createWithContext(reader); + } + } else { + reader.setCursor(i); + throw Vec3ArgumentType.INCOMPLETE_EXCEPTION.createWithContext(reader); + } + } + + private static double readCoordinate(StringReader reader, int startingCursorPos) throws CommandSyntaxException { + if (!reader.canRead()) { + throw CoordinateArgument.MISSING_COORDINATE.createWithContext(reader); + } else if (reader.peek() != '^') { + reader.setCursor(startingCursorPos); + throw Vec3ArgumentType.MIXED_COORDINATE_EXCEPTION.createWithContext(reader); + } else { + reader.skip(); + return reader.canRead() && reader.peek() != ' ' ? reader.readDouble() : 0.0; + } + } + + public boolean equals(Object o) { + if (this == o) return true; + + return o instanceof LookingClientPosArgument lookingPosArgument + && this.x == lookingPosArgument.x && this.y == lookingPosArgument.y && this.z == lookingPosArgument.z; + } + + public int hashCode() { + return Objects.hash(x, y, z); + } +} diff --git a/src/main/java/de/hysky/skyblocker/utils/command/argumenttypes/color/ColorArgumentType.java b/src/main/java/de/hysky/skyblocker/utils/command/argumenttypes/color/ColorArgumentType.java new file mode 100644 index 00000000..a6dc8510 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/utils/command/argumenttypes/color/ColorArgumentType.java @@ -0,0 +1,28 @@ +package de.hysky.skyblocker.utils.command.argumenttypes.color; + +import com.mojang.brigadier.context.CommandContext; +import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; + +/** + * Utility class that provides static methods for abstracting away the actual argument type classes. + */ +public final class ColorArgumentType { + private ColorArgumentType() {} // Prevent instantiation + + public static RgbColorArgumentType rgb() { + return new RgbColorArgumentType(); + } + + public static HexColorArgumentType hex() { + return new HexColorArgumentType(); + } + + public static int getIntFromHex(CommandContext<FabricClientCommandSource> context, String name) { + return HexColorArgumentType.getInt(context, name); + } + + public static int getIntFromRgb(CommandContext<FabricClientCommandSource> context, String name) { + return RgbColorArgumentType.getInt(context, name); + } +} + diff --git a/src/main/java/de/hysky/skyblocker/utils/command/argumenttypes/color/HexColorArgumentType.java b/src/main/java/de/hysky/skyblocker/utils/command/argumenttypes/color/HexColorArgumentType.java new file mode 100644 index 00000000..516eb7b9 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/utils/command/argumenttypes/color/HexColorArgumentType.java @@ -0,0 +1,38 @@ +package de.hysky.skyblocker.utils.command.argumenttypes.color; + +import com.mojang.brigadier.StringReader; +import com.mojang.brigadier.arguments.ArgumentType; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.exceptions.DynamicCommandExceptionType; +import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; +import net.minecraft.text.Text; +import org.apache.commons.lang3.StringUtils; + +@SuppressWarnings("RedundantCast") +public final class HexColorArgumentType implements ArgumentType<Integer> { + public static final DynamicCommandExceptionType WRONG_INPUT_WIDTH = new DynamicCommandExceptionType(found -> Text.translatable("argument.color.hex.invalidString", ((String) found).length())); + public static final DynamicCommandExceptionType INVALID_CHARACTER = new DynamicCommandExceptionType(character -> Text.translatable("argument.color.hex.invalidChar", (String) character)); + + @Override + public Integer parse(StringReader reader) throws CommandSyntaxException { + String input = reader.readString(); + if (StringUtils.startsWithIgnoreCase(input, "0x")) input = input.substring(2); +// else if (input.startsWith("#")) input = input.substring(1); // This doesn't work because minecraft has the # prefix reserved for tags, so inputs with that prefix never reach this reader + + if (input.length() != 6) throw WRONG_INPUT_WIDTH.create(input); + + for (int i = 0; i < input.length(); i++) { + char character = input.charAt(i); + if ((character < '0' || character > '9') && (character < 'a' || character > 'f') && (character < 'A' || character > 'F')) { + throw INVALID_CHARACTER.create(String.valueOf(character)); //Have to wrap character in a string, because mcdev doesn't appreciate chars and I cba to suppress the warnings + } + } + + return Integer.decode("#" + input); + } + + public static int getInt(CommandContext<FabricClientCommandSource> context, String name) { + return context.getArgument(name, Integer.class); + } +} diff --git a/src/main/java/de/hysky/skyblocker/utils/command/argumenttypes/color/RgbColorArgumentType.java b/src/main/java/de/hysky/skyblocker/utils/command/argumenttypes/color/RgbColorArgumentType.java new file mode 100644 index 00000000..d9a99fae --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/utils/command/argumenttypes/color/RgbColorArgumentType.java @@ -0,0 +1,39 @@ +package de.hysky.skyblocker.utils.command.argumenttypes.color; + +import com.mojang.brigadier.StringReader; +import com.mojang.brigadier.arguments.ArgumentType; +import com.mojang.brigadier.arguments.IntegerArgumentType; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; +import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; +import net.minecraft.text.Text; + +public final class RgbColorArgumentType implements ArgumentType<Integer> { + public static final SimpleCommandExceptionType INCOMPLETE_EXCEPTION = new SimpleCommandExceptionType(Text.translatable("argument.color.rgb.incomplete")); + + @Override + public Integer parse(StringReader reader) throws CommandSyntaxException { + int i = reader.getCursor(); + int redArgument = IntegerArgumentType.integer(0x00, 0xFF).parse(reader); + if (reader.canRead() && reader.peek() == ' ') { + reader.skip(); + int greenArgument = IntegerArgumentType.integer(0x00, 0xFF).parse(reader); + if (reader.canRead() && reader.peek() == ' ') { + reader.skip(); + int blueArgument = IntegerArgumentType.integer(0x00, 0xFF).parse(reader); + return redArgument << 16 | greenArgument << 8 | blueArgument; + } else { + reader.setCursor(i); + throw INCOMPLETE_EXCEPTION.createWithContext(reader); + } + } else { + reader.setCursor(i); + throw INCOMPLETE_EXCEPTION.createWithContext(reader); + } + } + + public static int getInt(CommandContext<FabricClientCommandSource> context, String name) { + return context.getArgument(name, Integer.class); + } +} |