Skip to content

Commit

Permalink
Add built-in placeholders for comparing values
Browse files Browse the repository at this point in the history
  • Loading branch information
Almighty-Satan committed Mar 7, 2024
1 parent a4b1082 commit 9c0dbe7
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 11 deletions.
25 changes: 25 additions & 0 deletions core/src/main/java/io/github/almightysatan/slams/Placeholder.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;
import java.util.function.BiFunction;
import java.util.function.BooleanSupplier;
import java.util.function.Predicate;

Expand Down Expand Up @@ -300,6 +302,29 @@ public interface Placeholder extends PlaceholderResolver {
});
}

static @NotNull Placeholder comparison(@NotNull String key, @NotNull BiFunction<String, String, Boolean> fun) {
Objects.requireNonNull(fun);
return of(key, (context, arguments) -> {
if (arguments.size() < 2)
return "INVALID_COMPARISON";
if (fun.apply(arguments.get(0), arguments.get(1)))
return arguments.size() > 2 ? arguments.get(2) : "";
else
return arguments.size() > 3 ? arguments.get(3) : "";
});
}

static @NotNull Placeholder numberComparison(@NotNull String key, @NotNull BiFunction<BigDecimal, BigDecimal, Boolean> fun) {
Objects.requireNonNull(fun);
return comparison(key, (arg0, arg1) -> {
try {
return fun.apply(new BigDecimal(arg0), new BigDecimal(arg1));
} catch (NumberFormatException e) {
return false;
}
});
}

@FunctionalInterface
interface ValueFunction {
@NotNull String value(@Nullable Context context, @NotNull List<@NotNull String> arguments);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,10 @@ public interface PlaceholderResolver {
return of(placeholderResolvers.toArray(new PlaceholderResolver[0]));
}

static @NotNull PlaceholderResolver builtInPlaceholders() {
return builder().builtIn().build();
}

/**
* Returns a new {@link Builder Builder}.
*
Expand Down Expand Up @@ -384,5 +388,18 @@ interface Builder {
default @NotNull Builder conditional(@NotNull String key, @NotNull BooleanSupplier supplier) {
return this.add(Placeholder.conditional(key, supplier));
}

default @NotNull Builder builtIn() {
this.add(Placeholder.comparison("if_eq", String::equals));
this.add(Placeholder.comparison("if_neq", (arg0, arg1) -> !arg0.equals(arg1)));

this.add(Placeholder.numberComparison("if_num_eq", (arg0, arg1) -> arg0.compareTo(arg1) == 0));
this.add(Placeholder.numberComparison("if_num_neq", (arg0, arg1) -> arg0.compareTo(arg1) != 0));
this.add(Placeholder.numberComparison("if_num_lt", (arg0, arg1) -> arg0.compareTo(arg1) < 0));
this.add(Placeholder.numberComparison("if_num_gt", (arg0, arg1) -> arg0.compareTo(arg1) > 0));
this.add(Placeholder.numberComparison("if_num_le", (arg0, arg1) -> arg0.compareTo(arg1) <= 0));
this.add(Placeholder.numberComparison("if_num_ge", (arg0, arg1) -> arg0.compareTo(arg1) >= 0));
return this;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -175,8 +175,9 @@ public boolean has(@NotNull String name) {
}

/**
* Creates a new {@link ContextTagResolver} from the given {@link PlaceholderResolver}. Any string returned by
* placeholders will be deserialized.
* Creates a new {@link ContextTagResolver} from the given {@link PlaceholderResolver}. All tags returned by this
* {@link ContextTagResolver} will be pre-process tags and their value will therefore be parsed by MiniMessage. Do
* not use this method for placeholders that return user input!
*
* @param placeholderResolver the {@link PlaceholderResolver}
* @return a new {@link ContextTagResolver}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class ContextTagResolverImpl {
if (placeholder == null)
return null;
String value = placeholder.value(context, this.argumentQueueToList(arguments));
return Tag.selfClosingInserting(eval ? ctx.deserialize(value) : Component.text(value));
return eval ? Tag.preProcessParsed(value) : Tag.selfClosingInserting(Component.text(value));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ public void testConditionalPlaceholder() throws IOException {
}

@Test
public void testConditionalContextTagResolver() throws IOException {
public void testConditionalUnsafePlaceholder() throws IOException {
Slams langManager = Slams.create("0");
AdventureMessage entry = AdventureMessage.of("test", langManager, ContextTagResolver.of(
ContextTagResolver.ofUnsafe(Placeholder.conditional("ifn", () -> false)),
Expand All @@ -144,6 +144,19 @@ public void testConditionalContextTagResolver() throws IOException {
assertEquals("Hello <def>", component.content());
}

@Test
public void testComparisonPlaceholder() throws IOException {
Slams langManager = Slams.create("0");
AdventureMessage entry = AdventureMessage.of("test", langManager, ContextTagResolver.ofUnsafe(
PlaceholderResolver.builder().builtIn().constant("abc", "World").constant("number", "150").build()
));

langManager.load("0", values -> values.put("test", "Hello <if_num_eq:'<number>':150:'<abc>':Earth>"));

TextComponent component = (TextComponent) entry.value();
assertEquals("Hello World", component.content());
}

@Test
public void testArray() throws IOException {
Slams langManager = Slams.create("0");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,13 +96,14 @@ public void testBasicCurlyParentheses() {

@Test
public void testPlaceholders() {
PlaceholderResolver placeholderResolver = PlaceholderResolver.of(
Placeholder.constant("abc", "def"),
Placeholder.constant("a<b", "c"),
Placeholder.constant("a>b", "d"),
Placeholder.withArgs("arg", args -> args.get(0)),
Placeholder.conditional("if", () -> true),
Placeholder.conditional("ifn", () -> false));
PlaceholderResolver placeholderResolver = PlaceholderResolver.builder()
.constant("abc", "def")
.constant("a<b", "c")
.constant("a>b", "d")
.withArgs("arg", args -> args.get(0))
.conditional("if", () -> true)
.conditional("ifn", () -> false)
.builtIn().build();
Function<String, String> eval = input -> new CompositeComponent(PlaceholderStyle.ANGLE_BRACKETS, input, PlaceholderResolver.empty()).value(null, placeholderResolver);

Assertions.assertEquals("", eval.apply(""));
Expand Down Expand Up @@ -142,6 +143,11 @@ public void testPlaceholders() {
Assertions.assertEquals("Hello World", eval.apply("Hello <if:World:Earth>"));
Assertions.assertEquals("Hello Earth", eval.apply("Hello <ifn:World:Earth>"));
Assertions.assertEquals("Hello def", eval.apply("Hello <if:<abc>:fail>"));

// built-in
Assertions.assertEquals("Hello World", eval.apply("Hello <if_eq:abc:abc:World:Earth>"));
Assertions.assertEquals("Hello World", eval.apply("Hello <if_num_eq:150:150:World:Earth>"));
Assertions.assertEquals("Hello Earth", eval.apply("Hello <if_num_eq:100:150:World:Earth>"));
}

@Test
Expand Down

0 comments on commit 9c0dbe7

Please sign in to comment.