Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ org.gradle.jvmargs=-Xmx2048M

# Fabric Properties
# check these on https://fabricmc.net/develup
minecraft_version=1.21.6
yarn_mappings=1.21.6+build.1
minecraft_version=1.21.7
yarn_mappings=1.21.7+build.6
loader_version=0.16.14
loom_version=1.10-SNAPSHOT
loom_version=1.11-SNAPSHOT

# Fabric API
fabric_version=0.127.0+1.21.6
fabric_version=0.128.2+1.21.7

# Mod Properties
mod_name = Essential Commands
Expand Down
Binary file modified gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Expand Down
6 changes: 3 additions & 3 deletions gradlew

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions gradlew.bat

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

import eu.pb4.placeholders.api.PlaceholderContext;
import eu.pb4.placeholders.api.Placeholders;
import eu.pb4.placeholders.api.TextParserUtils;
import eu.pb4.placeholders.api.parsers.NodeParser;
import eu.pb4.placeholders.api.parsers.ParserBuilder;
import eu.pb4.placeholders.api.parsers.TagParser;

import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
Expand All @@ -15,17 +17,24 @@
public final class MotdCommand {
private MotdCommand() {}

private static final NodeParser NODE_PARSER = ParserBuilder.of()
.globalPlaceholders()
.add(TagParser.QUICK_TEXT_WITH_STF_SAFE)
.build();

public static int run(CommandContext<ServerCommandSource> context) throws CommandSyntaxException {
var player = context.getSource().getPlayerOrThrow();
exec(player);
return 0;
}

public static void exec(ServerPlayerEntity player) {
var message = Placeholders.parseText(
TextParserUtils.formatText(CONFIG.MOTD),
PlaceholderContext.of(player)
player.getCommandSource().sendFeedback(
() -> Placeholders.parseText(
NODE_PARSER.parseNode(CONFIG.MOTD),
PlaceholderContext.of(player)
),
false
);
player.getCommandSource().sendFeedback(() -> message, false);
}
}
108 changes: 43 additions & 65 deletions src/main/java/com/fibermc/essentialcommands/text/ECTextImpl.java
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
package com.fibermc.essentialcommands.text;

import java.util.*;
import java.util.stream.Collectors;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import com.fibermc.essentialcommands.types.ECPlaceholderApiCompat;
import com.fibermc.essentialcommands.types.IStyleProvider;
import eu.pb4.placeholders.api.*;
import eu.pb4.placeholders.api.node.TextNode;
import eu.pb4.placeholders.api.ParserContext;
import eu.pb4.placeholders.api.PlaceholderContext;
import eu.pb4.placeholders.api.parsers.NodeParser;
import eu.pb4.placeholders.api.parsers.TagLikeParser;
import org.jetbrains.annotations.Nullable;

import net.minecraft.server.MinecraftServer;
import net.minecraft.text.*;

import dev.jpcode.eccore.util.TextUtil;

public class ECTextImpl extends ECText {
private final ParserContext parserContext;

Expand Down Expand Up @@ -67,50 +68,41 @@ public MutableText getText(String key, TextFormatType textFormatType, IStyleProv
return getTextInternal(key, textFormatType, styleProvider, args);
}

private Placeholders.PlaceholderGetter placeholderGetterForContext(
private NodeParser parserForContext(
TextFormatType textFormatType,
@Nullable IStyleProvider styleProvider,
List<MutableText> args)
{
return new Placeholders.PlaceholderGetter() {
@Override
public boolean isContextOptional() {
// In some situations (Notably, unit tests), the MinecraftServer from which to init
// the PlaceholderContext will be unavailable, so we set the context to Optional.
// (At time of writing, none of EC's PlaceholderGetter tech depends on the server
// context)
return true;
}

@Override
public PlaceholderHandler getPlaceholder(String placeholderId) {
return (ctx, abc) -> {
return TagLikeParser.of(
TagLikeParser.PLACEHOLDER_USER,
TagLikeParser.Provider.placeholderText(placeholderId -> {
if (placeholderId.startsWith("l:")) {
// handling the ${l:lang.key.here} case for interpolating value from elsewhere in language files
var idxAndFormattingCode = placeholderId.split(":");
if (idxAndFormattingCode.length < 1) {
throw new IllegalArgumentException("lang string placeholder did not contain an index");
if (idxAndFormattingCode.length < 2) {
throw new IllegalArgumentException(
"Specified lang interpolation prefix ('l'), but no lang key was provided. Expected the form: 'l:lang.key.here'. Received: "
+ placeholderId);
}
if (idxAndFormattingCode.length > 3) {
throw new IllegalArgumentException("lang string placeholder had an unexpected second ':'. Received: " + placeholderId);
}

var firstToken = idxAndFormattingCode[0];
var text = switch (firstToken) {
case "l" -> {
if (idxAndFormattingCode.length < 2) {
throw new IllegalArgumentException(
"Specified lang interpolation prefix ('l'), but no lang key was provided. Expected the form: 'l:lang.key.here'. Received: "
+ placeholderId);
}
yield getTextInternal(idxAndFormattingCode[1], textFormatType, styleProvider);
}

default -> args.get(Integer.parseInt(idxAndFormattingCode[0]));
};
return PlaceholderResult.value(text);
};
}
};
}
return getTextInternal(idxAndFormattingCode[1], textFormatType, styleProvider);
}

if (placeholderId.matches("\\d+")) {
// handling the ${1} case for argument interpolation
int targetIndex = Integer.parseInt(placeholderId);
if (targetIndex > args.size()) {
throw new IllegalArgumentException("Invalid 'Argument' placeholder: targeted argument with (0-based) index '" + targetIndex + "' but only " + args.size() + " were present");
}
return args.get(targetIndex);
}

private static int hashText(Text text) {
return Objects.hash(text.getContent(), text.getStyle());
return null;
})
);
}

public MutableText getTextInternal(
Expand All @@ -120,33 +112,19 @@ public MutableText getTextInternal(
Text... args)
{
var argsList = Arrays.stream(args).map(Text::copy).toList();
var argsHashes = argsList.stream()
.map(ECTextImpl::hashText)
.collect(Collectors.toCollection(HashSet::new));

var placeholderGetter = placeholderGetterForContext(textFormatType, styleProvider, argsList);
var nodes = Placeholders.parseNodes(
TextNode.convert(Text.literal(getString(key))),
Placeholders.PREDEFINED_PLACEHOLDER_PATTERN,
placeholderGetter);
var retVal = ECPlaceholderApiCompat.toText(nodes, parserContext);

var retValSiblings = retVal.getSiblings();
var parser = parserForContext(textFormatType, styleProvider, argsList);
var parsedText = parser.parseText(
getString(key),
this.parserContext
);

var specifiedStyle = styleProvider == null
? textFormatType.getStyle()
: styleProvider.getStyle(textFormatType);

if (retValSiblings.size() == 0) {
return retVal.copy().setStyle(specifiedStyle);
}

return retValSiblings
.stream()
.map(text -> argsHashes.contains(hashText(text))
? text
: text.copy().setStyle(specifiedStyle))
.collect(TextUtil.collect());
var ret = Text.empty();
parsedText.getWithStyle(specifiedStyle).forEach(ret::append);
return ret;
Comment on lines +125 to +127

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

potentially worth checking that there was no reason I was avoiding this (e.g. prestyled text that's supposed to cascade down to children still) and that there's no reason to avoid this for the "one node" case...

}

public boolean hasTranslation(String key) {
Expand Down