Skip to content

Commit 1219502

Browse files
committed
Enhance HighlightWaypointUtil
- Use BlockPosArgument instead multi IntegerArgumentType - Advanced position pattern logic - Fix wrong position used by click event Signed-off-by: Hendrix-Shen <[email protected]>
1 parent 3712d5c commit 1219502

File tree

7 files changed

+620
-190
lines changed

7 files changed

+620
-190
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
package com.plusls.ommc.api.command;
2+
3+
import com.mojang.brigadier.StringReader;
4+
import com.mojang.brigadier.arguments.ArgumentType;
5+
import com.mojang.brigadier.context.CommandContext;
6+
import com.mojang.brigadier.exceptions.CommandSyntaxException;
7+
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
8+
import com.mojang.brigadier.suggestion.Suggestions;
9+
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
10+
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
11+
import net.minecraft.client.multiplayer.ClientLevel;
12+
import net.minecraft.commands.Commands;
13+
import net.minecraft.commands.SharedSuggestionProvider;
14+
import net.minecraft.core.BlockPos;
15+
import net.minecraft.world.level.Level;
16+
import org.jetbrains.annotations.Contract;
17+
import org.jetbrains.annotations.NotNull;
18+
import top.hendrixshen.magiclib.compat.minecraft.api.network.chat.ComponentCompatApi;
19+
20+
import java.util.Arrays;
21+
import java.util.Collection;
22+
import java.util.Collections;
23+
import java.util.concurrent.CompletableFuture;
24+
25+
// Modified from brigadier
26+
public class ClientBlockPosArgument implements ArgumentType<ClientCoordinates> {
27+
private static final Collection<String> EXAMPLES = Arrays.asList("0 0 0", "~ ~ ~", "^ ^ ^", "^1 ^ ^-5", "~0.5 ~1 ~-5");
28+
public static final SimpleCommandExceptionType ERROR_NOT_LOADED = new SimpleCommandExceptionType(ComponentCompatApi.translatable("argument.pos.unloaded"));
29+
public static final SimpleCommandExceptionType ERROR_OUT_OF_WORLD = new SimpleCommandExceptionType(ComponentCompatApi.translatable("argument.pos.outofworld"));
30+
public static final SimpleCommandExceptionType ERROR_OUT_OF_BOUNDS = new SimpleCommandExceptionType(ComponentCompatApi.translatable("argument.pos.outofbounds"));
31+
32+
@Contract(value = " -> new", pure = true)
33+
public static @NotNull ClientBlockPosArgument blockPos() {
34+
return new ClientBlockPosArgument();
35+
}
36+
37+
public static BlockPos getLoadedBlockPos(@NotNull CommandContext<FabricClientCommandSource> context, String name) throws CommandSyntaxException {
38+
ClientLevel clientLevel = context.getSource().getWorld();
39+
return getLoadedBlockPos(context, clientLevel, name);
40+
}
41+
42+
public static BlockPos getLoadedBlockPos(CommandContext<FabricClientCommandSource> context, @NotNull ClientLevel clientLevel, String name) throws CommandSyntaxException {
43+
BlockPos blockPos = getBlockPos(context, name);
44+
45+
if (!clientLevel.isLoaded(blockPos)) {
46+
throw ERROR_NOT_LOADED.create();
47+
} else if (!clientLevel.isInWorldBounds(blockPos)) {
48+
throw ERROR_OUT_OF_WORLD.create();
49+
} else {
50+
return blockPos;
51+
}
52+
}
53+
54+
public static BlockPos getBlockPos(@NotNull CommandContext<FabricClientCommandSource> commandContext, String string) {
55+
return commandContext.getArgument(string, ClientCoordinates.class).getBlockPos(commandContext.getSource());
56+
}
57+
58+
//#if MC > 11502
59+
public static BlockPos getSpawnablePos(CommandContext<FabricClientCommandSource> commandContext, String string) throws CommandSyntaxException {
60+
BlockPos blockPos = getBlockPos(commandContext, string);
61+
if (!Level.isInSpawnableBounds(blockPos)) {
62+
throw ERROR_OUT_OF_BOUNDS.create();
63+
} else {
64+
return blockPos;
65+
}
66+
}
67+
//#endif
68+
69+
public ClientCoordinates parse(@NotNull StringReader stringReader) throws CommandSyntaxException {
70+
return stringReader.canRead() && stringReader.peek() == '^' ? ClientLocalCoordinates.parse(stringReader) : ClientWorldCoordinates.parseInt(stringReader);
71+
}
72+
73+
@Override
74+
public <S> CompletableFuture<Suggestions> listSuggestions(@NotNull CommandContext<S> commandContext, SuggestionsBuilder suggestionsBuilder) {
75+
if (!(commandContext.getSource() instanceof SharedSuggestionProvider)) {
76+
return Suggestions.empty();
77+
} else {
78+
String string = suggestionsBuilder.getRemaining();
79+
Collection<SharedSuggestionProvider.TextCoordinates> collection;
80+
if (!string.isEmpty() && string.charAt(0) == '^') {
81+
collection = Collections.singleton(SharedSuggestionProvider.TextCoordinates.DEFAULT_LOCAL);
82+
} else {
83+
collection = ((SharedSuggestionProvider)commandContext.getSource()).getRelevantCoordinates();
84+
}
85+
86+
return SharedSuggestionProvider.suggestCoordinates(string, collection, suggestionsBuilder, Commands.createValidator(this::parse));
87+
}
88+
}
89+
90+
@Override
91+
public Collection<String> getExamples() {
92+
return EXAMPLES;
93+
}
94+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.plusls.ommc.api.command;
2+
3+
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
4+
import net.minecraft.core.BlockPos;
5+
import net.minecraft.world.phys.Vec2;
6+
import net.minecraft.world.phys.Vec3;
7+
8+
// Modified from brigadier
9+
public interface ClientCoordinates {
10+
Vec3 getPosition(FabricClientCommandSource commandSourceStack);
11+
12+
Vec2 getRotation(FabricClientCommandSource commandSourceStack);
13+
14+
default BlockPos getBlockPos(FabricClientCommandSource commandSourceStack) {
15+
//#if MC > 11903
16+
return BlockPos.containing(this.getPosition(commandSourceStack));
17+
//#else
18+
//$$ return new BlockPos(this.getPosition(commandSourceStack));
19+
//#endif
20+
}
21+
22+
boolean isXRelative();
23+
24+
boolean isYRelative();
25+
26+
boolean isZRelative();
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
package com.plusls.ommc.api.command;
2+
3+
import com.google.common.collect.Maps;
4+
import com.mojang.brigadier.StringReader;
5+
import com.mojang.brigadier.arguments.ArgumentType;
6+
import com.mojang.brigadier.context.CommandContext;
7+
import com.mojang.brigadier.exceptions.CommandSyntaxException;
8+
import com.mojang.brigadier.exceptions.DynamicCommandExceptionType;
9+
import com.mojang.brigadier.suggestion.Suggestions;
10+
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
11+
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
12+
import net.minecraft.Util;
13+
import net.minecraft.commands.SharedSuggestionProvider;
14+
import net.minecraft.world.entity.Entity;
15+
import net.minecraft.world.phys.Vec3;
16+
import org.jetbrains.annotations.NotNull;
17+
import org.jetbrains.annotations.Nullable;
18+
import top.hendrixshen.magiclib.compat.minecraft.api.network.chat.ComponentCompatApi;
19+
20+
import java.util.Arrays;
21+
import java.util.Collection;
22+
import java.util.Map;
23+
import java.util.concurrent.CompletableFuture;
24+
import java.util.function.BiFunction;
25+
26+
// Modified from brigadier
27+
public class ClientEntityAnchorArgument implements ArgumentType<ClientEntityAnchorArgument.Anchor> {
28+
private static final Collection<String> EXAMPLES = Arrays.asList("eyes", "feet");
29+
private static final DynamicCommandExceptionType ERROR_INVALID = new DynamicCommandExceptionType(
30+
object -> ComponentCompatApi.translatable("argument.anchor.invalid", object)
31+
);
32+
33+
public static ClientEntityAnchorArgument.Anchor getAnchor(@NotNull CommandContext<FabricClientCommandSource> commandContext, String string) {
34+
return commandContext.getArgument(string, ClientEntityAnchorArgument.Anchor.class);
35+
}
36+
37+
public static ClientEntityAnchorArgument anchor() {
38+
return new ClientEntityAnchorArgument();
39+
}
40+
41+
@Override
42+
public ClientEntityAnchorArgument.Anchor parse(StringReader stringReader) throws CommandSyntaxException {
43+
int i = stringReader.getCursor();
44+
String string = stringReader.readUnquotedString();
45+
ClientEntityAnchorArgument.Anchor anchor = ClientEntityAnchorArgument.Anchor.getByName(string);
46+
if (anchor == null) {
47+
stringReader.setCursor(i);
48+
throw ERROR_INVALID.createWithContext(stringReader, string);
49+
} else {
50+
return anchor;
51+
}
52+
}
53+
54+
@Override
55+
public <S> CompletableFuture<Suggestions> listSuggestions(CommandContext<S> commandContext, SuggestionsBuilder suggestionsBuilder) {
56+
return SharedSuggestionProvider.suggest(ClientEntityAnchorArgument.Anchor.BY_NAME.keySet(), suggestionsBuilder);
57+
}
58+
59+
@Override
60+
public Collection<String> getExamples() {
61+
return EXAMPLES;
62+
}
63+
64+
public static enum Anchor {
65+
FEET("feet", (vec3, entity) -> vec3),
66+
EYES("eyes", (vec3, entity) -> new Vec3(vec3.x, vec3.y + (double)entity.getEyeHeight(), vec3.z));
67+
68+
static final Map<String, ClientEntityAnchorArgument.Anchor> BY_NAME = Util.make(Maps.newHashMap(), hashMap -> {
69+
for(ClientEntityAnchorArgument.Anchor anchor : values()) {
70+
hashMap.put(anchor.name, anchor);
71+
}
72+
});
73+
74+
private final String name;
75+
private final BiFunction<Vec3, Entity, Vec3> transform;
76+
77+
Anchor(String string2, BiFunction<Vec3, Entity, Vec3> biFunction) {
78+
this.name = string2;
79+
this.transform = biFunction;
80+
}
81+
82+
@Nullable
83+
public static ClientEntityAnchorArgument.Anchor getByName(String string) {
84+
return BY_NAME.get(string);
85+
}
86+
87+
public Vec3 apply(Entity entity) {
88+
return this.transform.apply(entity.position(), entity);
89+
}
90+
91+
public Vec3 apply(@NotNull FabricClientCommandSource commandSourceStack) {
92+
Entity entity = commandSourceStack.getEntity();
93+
return entity == null ? commandSourceStack.getPosition() : this.transform.apply(commandSourceStack.getPosition(), entity);
94+
}
95+
}
96+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
package com.plusls.ommc.api.command;
2+
3+
import com.mojang.brigadier.StringReader;
4+
import com.mojang.brigadier.exceptions.CommandSyntaxException;
5+
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
6+
import net.minecraft.commands.arguments.coordinates.Vec3Argument;
7+
import net.minecraft.commands.arguments.coordinates.WorldCoordinate;
8+
import net.minecraft.util.Mth;
9+
import net.minecraft.world.phys.Vec2;
10+
import net.minecraft.world.phys.Vec3;
11+
import org.jetbrains.annotations.Contract;
12+
import org.jetbrains.annotations.NotNull;
13+
14+
import java.util.Objects;
15+
16+
// Modified from brigadier
17+
public class ClientLocalCoordinates implements ClientCoordinates {
18+
private final double left;
19+
private final double up;
20+
private final double forwards;
21+
22+
public ClientLocalCoordinates(double left, double up, double forwards) {
23+
this.left = left;
24+
this.up = up;
25+
this.forwards = forwards;
26+
}
27+
28+
@Override
29+
public Vec3 getPosition(@NotNull FabricClientCommandSource commandSourceStack) {
30+
Vec2 rotation = commandSourceStack.getRotation();
31+
Vec3 pos = ClientEntityAnchorArgument.Anchor.FEET.apply(commandSourceStack);
32+
float f = Mth.cos((rotation.y + 90.0F) * (float) (Math.PI / 180.0));
33+
float g = Mth.sin((rotation.y + 90.0F) * (float) (Math.PI / 180.0));
34+
float h = Mth.cos(-rotation.x * (float) (Math.PI / 180.0));
35+
float i = Mth.sin(-rotation.x * (float) (Math.PI / 180.0));
36+
float j = Mth.cos((-rotation.x + 90.0F) * (float) (Math.PI / 180.0));
37+
float k = Mth.sin((-rotation.x + 90.0F) * (float) (Math.PI / 180.0));
38+
Vec3 vec32 = new Vec3(f * h, i, g * h);
39+
Vec3 vec33 = new Vec3(f * j, k, g * j);
40+
Vec3 vec34 = vec32.cross(vec33).scale(-1.0);
41+
double d = vec32.x * this.forwards + vec33.x * this.up + vec34.x * this.left;
42+
double e = vec32.y * this.forwards + vec33.y * this.up + vec34.y * this.left;
43+
double l = vec32.z * this.forwards + vec33.z * this.up + vec34.z * this.left;
44+
return new Vec3(pos.x + d, pos.y + e, pos.z + l);
45+
}
46+
47+
@Override
48+
public Vec2 getRotation(FabricClientCommandSource commandSourceStack) {
49+
return Vec2.ZERO;
50+
}
51+
52+
@Override
53+
public boolean isXRelative() {
54+
return true;
55+
}
56+
57+
@Override
58+
public boolean isYRelative() {
59+
return true;
60+
}
61+
62+
@Override
63+
public boolean isZRelative() {
64+
return true;
65+
}
66+
67+
@Contract("_ -> new")
68+
public static @NotNull ClientLocalCoordinates parse(@NotNull StringReader stringReader) throws CommandSyntaxException {
69+
int i = stringReader.getCursor();
70+
double d = readDouble(stringReader, i);
71+
if (stringReader.canRead() && stringReader.peek() == ' ') {
72+
stringReader.skip();
73+
double e = readDouble(stringReader, i);
74+
if (stringReader.canRead() && stringReader.peek() == ' ') {
75+
stringReader.skip();
76+
double f = readDouble(stringReader, i);
77+
return new ClientLocalCoordinates(d, e, f);
78+
} else {
79+
stringReader.setCursor(i);
80+
throw Vec3Argument.ERROR_NOT_COMPLETE.createWithContext(stringReader);
81+
}
82+
} else {
83+
stringReader.setCursor(i);
84+
throw Vec3Argument.ERROR_NOT_COMPLETE.createWithContext(stringReader);
85+
}
86+
}
87+
88+
private static double readDouble(@NotNull StringReader stringReader, int i) throws CommandSyntaxException {
89+
if (!stringReader.canRead()) {
90+
throw WorldCoordinate.ERROR_EXPECTED_DOUBLE.createWithContext(stringReader);
91+
} else if (stringReader.peek() != '^') {
92+
stringReader.setCursor(i);
93+
throw Vec3Argument.ERROR_MIXED_TYPE.createWithContext(stringReader);
94+
} else {
95+
stringReader.skip();
96+
return stringReader.canRead() && stringReader.peek() != ' ' ? stringReader.readDouble() : 0.0;
97+
}
98+
}
99+
100+
@Override
101+
public boolean equals(Object object) {
102+
if (this == object) {
103+
return true;
104+
} else if (!(object instanceof ClientLocalCoordinates)) {
105+
return false;
106+
} else {
107+
ClientLocalCoordinates clientLocalCoordinates = (ClientLocalCoordinates) object;
108+
return this.left == clientLocalCoordinates.left && this.up == clientLocalCoordinates.up && this.forwards == clientLocalCoordinates.forwards;
109+
}
110+
}
111+
112+
@Override
113+
public int hashCode() {
114+
return Objects.hash(this.left, this.up, this.forwards);
115+
}
116+
}

0 commit comments

Comments
 (0)