use of net.kyori.adventure.text.minimessage.tag.Tag in project adventure by KyoriPowered.
the class GradientTag method create.
static Tag create(final ArgumentQueue args, final Context ctx) {
float phase = 0;
final List<TextColor> textColors;
if (args.hasNext()) {
textColors = new ArrayList<>();
while (args.hasNext()) {
final Tag.Argument arg = args.pop();
// last argument? maybe this is the phase?
if (!args.hasNext()) {
final OptionalDouble possiblePhase = arg.asDouble();
if (possiblePhase.isPresent()) {
phase = (float) possiblePhase.getAsDouble();
if (phase < -1f || phase > 1f) {
throw ctx.newException(String.format("Gradient phase is out of range (%s). Must be in the range [-1.0f, 1.0f] (inclusive).", phase), args);
}
break;
}
}
final TextColor parsedColor = ColorTagResolver.resolveColor(arg.value(), ctx);
textColors.add(parsedColor);
}
if (textColors.size() < 2) {
throw ctx.newException("Invalid gradient, not enough colors. Gradients must have at least two colors.", args);
}
} else {
textColors = Collections.emptyList();
}
return new GradientTag(phase, textColors);
}
use of net.kyori.adventure.text.minimessage.tag.Tag in project adventure by KyoriPowered.
the class MiniMessageParser method treeToComponent.
@NotNull
Component treeToComponent(@NotNull final ElementNode node, @NotNull final ContextImpl context) {
Component comp = Component.empty();
Tag tag = null;
if (node instanceof ValueNode) {
comp = Component.text(((ValueNode) node).value());
} else if (node instanceof TagNode) {
final TagNode tagNode = (TagNode) node;
tag = tagNode.tag();
// special case for gradient and stuff
if (tag instanceof Modifying) {
final Modifying modTransformation = (Modifying) tag;
// first walk the tree
this.visitModifying(modTransformation, tagNode, 0);
modTransformation.postVisit();
}
if (tag instanceof Inserting) {
comp = ((Inserting) tag).value();
}
}
if (!node.unsafeChildren().isEmpty()) {
final List<Component> children = new ArrayList<>(comp.children().size() + node.children().size());
children.addAll(comp.children());
for (final ElementNode child : node.unsafeChildren()) {
children.add(this.treeToComponent(child, context));
}
comp = comp.children(children);
}
// special case for gradient and stuff
if (tag instanceof Modifying) {
comp = this.handleModifying((Modifying) tag, comp, 0);
}
final Consumer<String> debug = context.debugOutput();
if (debug != null) {
debug.accept("==========\ntreeToComponent \n");
debug.accept(node.toString());
debug.accept("\n");
debug.accept(comp.examine(MultiLineStringExaminer.simpleEscaping()).collect(Collectors.joining("\n")));
debug.accept("\n==========\n");
}
return comp;
}
use of net.kyori.adventure.text.minimessage.tag.Tag in project adventure by KyoriPowered.
the class MiniMessageParser method parseToTree.
@NotNull
RootNode parseToTree(@NotNull final ContextImpl context) {
final TagResolver combinedResolver = TagResolver.resolver(this.tagResolver, context.extraTags());
final String processedMessage = context.preProcessor().apply(context.message());
final Consumer<String> debug = context.debugOutput();
if (debug != null) {
debug.accept("Beginning parsing message ");
debug.accept(processedMessage);
debug.accept("\n");
}
final TokenParser.TagProvider transformationFactory;
if (debug != null) {
transformationFactory = (name, args, token) -> {
try {
debug.accept("Attempting to match node '");
debug.accept(name);
debug.accept("'");
if (token != null) {
debug.accept(" at column ");
debug.accept(String.valueOf(token.startIndex()));
}
debug.accept("\n");
@Nullable final Tag transformation = combinedResolver.resolve(name, new ArgumentQueueImpl<>(context, args), context);
if (transformation == null) {
debug.accept("Could not match node '");
debug.accept(name);
debug.accept("'\n");
} else {
debug.accept("Successfully matched node '");
debug.accept(name);
debug.accept("' to tag ");
debug.accept(transformation instanceof Examinable ? ((Examinable) transformation).examinableName() : transformation.getClass().getName());
debug.accept("\n");
}
return transformation;
} catch (final ParsingException e) {
if (token != null && e instanceof ParsingExceptionImpl) {
final ParsingExceptionImpl impl = (ParsingExceptionImpl) e;
if (impl.tokens().length == 0) {
impl.tokens(new Token[] { token });
}
}
debug.accept("Could not match node '");
debug.accept(name);
debug.accept("' - ");
debug.accept(e.getMessage());
debug.accept("\n");
return null;
}
};
} else {
transformationFactory = (name, args, token) -> {
try {
return combinedResolver.resolve(name, new ArgumentQueueImpl<>(context, args), context);
} catch (final ParsingException ignored) {
return null;
}
};
}
final Predicate<String> tagNameChecker = name -> {
final String sanitized = TokenParser.TagProvider.sanitizePlaceholderName(name);
return combinedResolver.has(sanitized);
};
final String preProcessed = TokenParser.resolvePreProcessTags(processedMessage, transformationFactory);
context.message(preProcessed);
// Then, once MiniMessage placeholders have been inserted, we can do the real parse
final RootNode root = TokenParser.parse(transformationFactory, tagNameChecker, preProcessed, processedMessage, context.strict());
if (debug != null) {
debug.accept("Text parsed into element tree:\n");
debug.accept(root.toString());
}
return root;
}
use of net.kyori.adventure.text.minimessage.tag.Tag in project adventure by KyoriPowered.
the class StringResolvingMatchedTokenConsumer method accept.
@Override
public void accept(final int start, final int end, @NotNull final TokenType tokenType) {
super.accept(start, end, tokenType);
if (tokenType != TokenType.OPEN_TAG) {
// just add it normally, we don't care about other tags
this.builder.append(this.input, start, end);
} else {
// well, now we need to work out if it's a tag or a placeholder!
final String match = this.input.substring(start, end);
final String cleanup = this.input.substring(start + 1, end - 1);
final int index = cleanup.indexOf(SEPARATOR);
final String tag = index == -1 ? cleanup : cleanup.substring(0, index);
// we might care if it's a valid tag!
if (TagInternals.sanitizeAndCheckValidTagName(tag)) {
final List<Token> tokens = tokenize(match);
final List<TagPart> parts = new ArrayList<>();
final List<Token> childs = tokens.isEmpty() ? null : tokens.get(0).childTokens();
if (childs != null) {
for (int i = 1; i < childs.size(); i++) {
parts.add(new TagPart(match, childs.get(i), this.tagProvider));
}
}
// we might care if it's a pre-process!
@Nullable final Tag replacement = this.tagProvider.resolve(TokenParser.TagProvider.sanitizePlaceholderName(tag), parts, tokens.get(0));
if (replacement instanceof PreProcess) {
this.builder.append(Objects.requireNonNull(((PreProcess) replacement).value(), "PreProcess replacements cannot return null"));
return;
}
}
// if we get here, the placeholder wasn't found or was null
this.builder.append(match);
}
}
use of net.kyori.adventure.text.minimessage.tag.Tag in project adventure by KyoriPowered.
the class TransitionTag method create.
static Tag create(final ArgumentQueue args, final Context ctx) {
float phase = 0;
final List<TextColor> textColors;
if (args.hasNext()) {
textColors = new ArrayList<>();
while (args.hasNext()) {
final Tag.Argument arg = args.pop();
// last argument? maybe this is the phase?
if (!args.hasNext()) {
final OptionalDouble possiblePhase = arg.asDouble();
if (possiblePhase.isPresent()) {
phase = (float) possiblePhase.getAsDouble();
if (phase < -1f || phase > 1f) {
throw ctx.newException(String.format("Gradient phase is out of range (%s). Must be in the range [-1.0f, 1.0f] (inclusive).", phase), args);
}
break;
}
}
final String argValue = arg.value();
final TextColor parsedColor;
if (argValue.charAt(0) == '#') {
parsedColor = TextColor.fromHexString(argValue);
} else {
parsedColor = NamedTextColor.NAMES.value(arg.lowerValue());
}
if (parsedColor == null) {
throw ctx.newException(String.format("Unable to parse a color from '%s'. Please use named colors or hex (#RRGGBB) colors.", argValue), args);
}
textColors.add(parsedColor);
}
if (textColors.size() < 2) {
throw ctx.newException("Invalid transition, not enough colors. Transitions must have at least two colors.", args);
}
} else {
textColors = Collections.emptyList();
}
return new TransitionTag(phase, textColors);
}
Aggregations