Skip to content

Commit

Permalink
Merge branch 'pr/3' into dev/forgecraft
Browse files Browse the repository at this point in the history
  • Loading branch information
sciwhiz12 committed Aug 6, 2023
2 parents b80e04f + 42e22d1 commit 269d445
Show file tree
Hide file tree
Showing 2 changed files with 133 additions and 1 deletion.
15 changes: 15 additions & 0 deletions src/main/java/tk/sciwhiz12/concord/ConcordConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ public class ConcordConfig {

public static final ForgeConfigSpec.BooleanValue USE_CUSTOM_FONT;
public static final ForgeConfigSpec.BooleanValue LAZY_TRANSLATIONS;
public static final ForgeConfigSpec.BooleanValue USE_LEGACY_FORMATTING;
public static final ForgeConfigSpec.BooleanValue USE_CUSTOM_FORMATTING;
public static final ForgeConfigSpec.EnumValue<CrownVisibility> HIDE_CROWN;
public static final ForgeConfigSpec.ConfigValue<String> WEBHOOK_AVATAR_URL;
public static final ForgeConfigSpec.BooleanValue HIDE_ROLES;
Expand Down Expand Up @@ -138,6 +140,19 @@ public static void register() {
"Set to false if you cannot ensure that all clients will have the mod installed.")
.define("lazy_translate", true);

USE_CUSTOM_FORMATTING = builder.comment("Allow Discord users to use Concord Message Formatting Codes in a message.",
"This will cause in-game messages to have color formatting.",
"To use it, send a message with a dollar sign ($) followed by either an English-language color (ie. $red), or a hex code (ie. $#FF0000).",
"Names are delimited by a space which will be consumed, so the string \"this is a $red colored text\" will be shown as \"this is a colored text\".",
"Please note that Custom Formatting will override Legacy Formatting when enabled. This is intentional.")
.define("use_custom_formatting", false);

USE_LEGACY_FORMATTING = builder.comment("Allow Discord users to put legacy-style chat formatting (&5, etc) in a message.",
"This will cause in-game messages to have color, bold, italic, strikethrough and \"obfuscated\" formatting.",
"Note however, that this only works with vanilla formatting codes, and is likely to cause weirdness.")
.define("use_legacy_formatting", false);


HIDE_CROWN = builder.comment("Configures when the Server Owner crown is visible to clients.",
"ALWAYS means the crown is always visible, NEVER means the crown is never visible.",
"WITHOUT_ADMINISTRATORS means it is only visible when there are no hoisted Administrator roles.")
Expand Down
119 changes: 118 additions & 1 deletion src/main/java/tk/sciwhiz12/concord/msg/Messaging.java
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ public static MutableComponent createMessage(boolean useIcons, ConcordConfig.Cro

public static MutableComponent createContentComponent(Message message) {
final String content = message.getContentDisplay();
final MutableComponent text = Component.literal(content).withStyle(WHITE);
final MutableComponent text = processCustomFormatting(content);

boolean skipSpace = content.length() <= 0 || Character.isWhitespace(content.codePointAt(content.length() - 1));
for (StickerItem sticker : message.getStickers()) {
Expand Down Expand Up @@ -305,4 +305,121 @@ public static IntelligentTranslator<MessageContext> versionCheckingTranslator(

private record MessageContext(boolean useIcons, ArtifactVersion version) {
}

/**
* Search a user-input string for legacy-style ChatFormatting.
* ie. the input "&5Sup?" will be sent to Minecraft as "Sup?" with a purple color.
* It is intentional that this only supports the default vanilla formatting.
*
* @param input the text from Discord
* @return a properly formatted MutableComponent to be echoed into chat.
* @author Curle
*/
private static MutableComponent processLegacyFormatting(String input) {
if(!ConcordConfig.USE_LEGACY_FORMATTING.get()) {
// Default to white if legacy formatting is disabled.
return Component.literal(input).withStyle(WHITE);
} else {
final String[] parts = input.split("(?=&)");
MutableComponent currentComponent = Component.literal("");

for (String part : parts) {
// Ensure that we only process non-empty strings
if (part.isEmpty()) continue;

final boolean partHasFormatter = part.charAt(0) == '&';
// Short circuit for strings of only "&" to avoid a temporal paradox
if (partHasFormatter && part.length() == 1) {
currentComponent = currentComponent.append(Component.literal(part).withStyle(WHITE));
continue;
}

// Parse a formatting character after the & trigger
final ChatFormatting formatting = ChatFormatting.getByCode(part.charAt(1));
// Ensure that we only process if there's a formatting code
if (partHasFormatter && formatting != null) {
currentComponent = currentComponent.append(Component.literal(part.substring(2)).withStyle(formatting));
} else {
// White by default!
currentComponent = currentComponent.append(Component.literal(part).withStyle(WHITE));
}
}

return currentComponent;
}
}

/**
* Search a user-input string for a custom chat formatting syntax.
* The custom syntax follows the format of $color or $#hex.
* ie. "$red chat" will print "chat" in red. "$#0000FF sup" will print "sup" in blue.
* There is no custom formatting for italic, strikethrough, bold, etc.
*
* @param input the text from Discord
* @return a properly formatted MutableComponent to be echoed into chat.
* @author Curle
*/
private static MutableComponent processCustomFormatting(String input) {
if (!ConcordConfig.USE_CUSTOM_FORMATTING.get()) {
// Default to white if custom formatting is disabled.
return processLegacyFormatting(input);
} else {
MutableComponent currentComponent = Component.literal("");
// Regexplanation:
// (?= \$ #? [\w \d] + )
// ^ ^ ^^ ^ ^ ^ ^ ^
// | | || | | | | |
// | | || | | | | - End group
// | | || | | | - Match at least one
// | | || | | - Match any digit
// | | || | - Match any word
// | | || - Look for any of the following
// | | |- Match 0 or 1 of the preceding
// | | - Look for a # character
// | - Look for a $ character
// - Include the result in the split strings

final String[] parts = input.split("(?=\\$#?[\\w\\d]+)");


for (String part : parts) {
// Ensure that we only process non-empty strings
if (part.isEmpty()) continue;

final boolean partHasFormatter = part.charAt(0) == '$';
final int firstSpacePosition = part.indexOf(' ');

// Short circuit for strings of only "$" to avoid a temporal paradox
if (partHasFormatter && part.length() == 1 && firstSpacePosition == -1) {
currentComponent = currentComponent.append(Component.literal(part).withStyle(WHITE));
continue;
}

// Make sure that formatting at the end of messages, or lone formatting, is dealt with.
final String formatString = firstSpacePosition == -1 ? part.substring(1) : part.substring(1, firstSpacePosition);
// Use TextColor's built-in parsing to do the heavy lifting.
final TextColor color = TextColor.parseColor(formatString);
// Assign the TextColor into a Style instance so that we can use it with a TextComponent.
final Style formatting = Style.EMPTY.withColor(color == null ? TextColor.fromLegacyFormat(WHITE) : color);

if (partHasFormatter && color != null) {

currentComponent = currentComponent.append(
// Cut the string on either the space (if there is one) or the end of the string.
Component.literal(part.substring(firstSpacePosition != -1 ? firstSpacePosition + 1 : part.length()))
.withStyle(formatting)
);
} else {
// White by default!
currentComponent = currentComponent.append(
Component.literal(part).withStyle(WHITE)
);
}

}


return currentComponent;
}
}
}

0 comments on commit 269d445

Please sign in to comment.