Skip to content

Commit

Permalink
Implement message action replacements
Browse files Browse the repository at this point in the history
Signed-off-by: Pablo Herrera <[email protected]>
  • Loading branch information
Pablete1234 committed Nov 30, 2023
1 parent 81f4a16 commit 976aeca
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 9 deletions.
42 changes: 40 additions & 2 deletions core/src/main/java/tc/oc/pgm/action/ActionParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,14 @@
import static net.kyori.adventure.key.Key.key;
import static net.kyori.adventure.sound.Sound.sound;
import static net.kyori.adventure.text.Component.empty;
import static net.kyori.adventure.text.Component.text;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import java.lang.reflect.Method;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.List;
import java.util.Map;
import net.kyori.adventure.sound.Sound;
import net.kyori.adventure.text.Component;
Expand Down Expand Up @@ -37,6 +42,7 @@
import tc.oc.pgm.kits.Kit;
import tc.oc.pgm.regions.BlockBoundedValidation;
import tc.oc.pgm.regions.RegionParser;
import tc.oc.pgm.util.Audience;
import tc.oc.pgm.util.MethodParser;
import tc.oc.pgm.util.MethodParsers;
import tc.oc.pgm.util.inventory.ItemMatcher;
Expand All @@ -49,6 +55,8 @@

public class ActionParser {

private static final NumberFormat DEFAULT_FORMAT = NumberFormat.getIntegerInstance();

private final MapFactory factory;
private final FeatureDefinitionContext features;
private final FilterParser filters;
Expand Down Expand Up @@ -227,7 +235,8 @@ public Kit parseKitTrigger(Element el, Class<?> scope) throws InvalidXMLExceptio
}

@MethodParser("message")
public MessageAction parseChatMessage(Element el, Class<?> scope) throws InvalidXMLException {
public <T extends Filterable<?>> MessageAction<?> parseChatMessage(Element el, Class<T> scope)
throws InvalidXMLException {
Component text = XMLUtils.parseFormattedText(Node.fromChildOrAttr(el, "text"));
Component actionbar = XMLUtils.parseFormattedText(Node.fromChildOrAttr(el, "actionbar"));

Expand All @@ -245,7 +254,36 @@ public MessageAction parseChatMessage(Element el, Class<?> scope) throws Invalid
throw new InvalidXMLException(
"Expected at least one of text, title, subtitle or actionbar", el);

return new MessageAction(text, actionbar, title);
List<Element> replacements = XMLUtils.flattenElements(el, "replacements");
if (replacements.isEmpty()) {
return new MessageAction<>(Audience.class, text, actionbar, title, null);
}

scope = parseScope(el, scope);

ImmutableMap.Builder<String, MessageAction.Replacement<T>> replacementMap =
ImmutableMap.builder();
for (Element replacement : XMLUtils.flattenElements(el, "replacements")) {
replacementMap.put(
XMLUtils.parseRequiredId(replacement), parseReplacement(replacement, scope));
}
return new MessageAction<>(scope, text, actionbar, title, replacementMap.build());
}

private <T extends Filterable<?>> MessageAction.Replacement<T> parseReplacement(
Element el, Class<T> scope) throws InvalidXMLException {
// TODO: Support alternative replacement types (eg: player(s), team(s), or durations)
switch (el.getName()) {
case "decimal":
Formula<T> formula =
Formula.of(Node.fromRequiredAttr(el, "value").getValue(), variables.getContext(scope));
Node formatNode = Node.fromAttr(el, "format");
NumberFormat format =
formatNode != null ? new DecimalFormat(formatNode.getValue()) : DEFAULT_FORMAT;
return (T filterable) -> text(format.format(formula.applyAsDouble(filterable)));
default:
throw new InvalidXMLException("Unknown replacement type", el);
}
}

@MethodParser("sound")
Expand Down
50 changes: 43 additions & 7 deletions core/src/main/java/tc/oc/pgm/action/actions/MessageAction.java
Original file line number Diff line number Diff line change
@@ -1,28 +1,64 @@
package tc.oc.pgm.action.actions;

import java.util.Map;
import java.util.function.Function;
import java.util.regex.Pattern;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.ComponentLike;
import net.kyori.adventure.text.TextReplacementConfig;
import net.kyori.adventure.title.Title;
import org.jetbrains.annotations.Nullable;
import tc.oc.pgm.util.Audience;

public class MessageAction extends AbstractAction<Audience> {
public class MessageAction<T extends Audience> extends AbstractAction<T> {
private static final Pattern REPLACEMENT_PATTERN = Pattern.compile("\\{(.+?)}");

private final Component text;
private final Component actionbar;
private final Title title;
private final Map<String, Replacement<T>> replacements;

public MessageAction(
@Nullable Component text, @Nullable Component actionbar, @Nullable Title title) {
super(Audience.class);
Class<T> scope,
@Nullable Component text,
@Nullable Component actionbar,
@Nullable Title title,
@Nullable Map<String, Replacement<T>> replacements) {
super(scope);
this.text = text;
this.actionbar = actionbar;
this.title = title;
this.replacements = replacements;
}

@Override
public void trigger(Audience audience) {
if (text != null) audience.sendMessage(text);
if (title != null) audience.showTitle(title);
if (actionbar != null) audience.sendActionBar(actionbar);
public void trigger(T scope) {
if (text != null) scope.sendMessage(replace(text, scope));
if (title != null) scope.showTitle(replace(title, scope));
if (actionbar != null) scope.sendActionBar(replace(actionbar, scope));
}

private Component replace(Component component, T scope) {
if (component == null || replacements == null) {
return component;
}

return component.replaceText(
TextReplacementConfig.builder()
.match(REPLACEMENT_PATTERN)
.replacement(
(match, original) -> {
Replacement<T> r = replacements.get(match.group(1));
return r != null ? r.apply(scope) : original;
})
.build());
}

private Title replace(Title title, T scope) {
if (replacements == null) return title;
return Title.title(
replace(title.title(), scope), replace(title.subtitle(), scope), title.times());
}

public interface Replacement<T extends Audience> extends Function<T, ComponentLike> {}
}

0 comments on commit 976aeca

Please sign in to comment.