Skip to content

Implement mc_format! macro for MiniMessage-style component generation #278

@Sweattypalms

Description

@Sweattypalms

Is your feature request related to a problem?

Constructing TextComponent trees using the current ComponentBuilder pattern is extremely verbose and difficult to visualize. Simple formatting changes (color, bold) require substantial boilerplate and deep nesting, making UI code hard to maintain.

Current "Behemoth" Approach:

ComponentBuilder::text("")
    .color(NamedColor::Yellow)
    .extra(
        ComponentBuilder::text("Your client is outdated!")
            .color(NamedColor::Red)
            .bold(),
    )
    .extra(ComponentBuilder::text("\n\n"))
    .extra(ComponentBuilder::text("Please use Minecraft version ").color(NamedColor::Gray))
    .extra(
        ComponentBuilder::text("1.21.8")
            .color(NamedColor::Green)
            .bold(),
    )
    .extra(ComponentBuilder::text(" to connect to this server.").color(NamedColor::Gray))
    .extra(ComponentBuilder::text("\n\n"))
    .extra(ComponentBuilder::text("Server Version: ").color(NamedColor::DarkGray))
    .extra(ComponentBuilder::text(PROTOCOL_VERSION_1_21_8.to_string()).color(NamedColor::Aqua))
    .extra(ComponentBuilder::text(" | Your Version: ").color(NamedColor::DarkGray))
    .extra(ComponentBuilder::text(client_version.to_string()).color(NamedColor::Red))
    .build()

Describe the solution / feature you'd like.

I propose implementing a mc_format! proc-macro that supports MiniMessage-style tag parsing and Rust variable interpolation. This reduces boilerplate by ~80% and improves readability.

Proposed Syntax (String Parsing):

let component = mc_format!(
    "<yellow>Your client is <red><bold>outdated!</bold></red>\n\n\
    <gray>Please use Minecraft version <green><bold>1.21.8</bold></green> to connect to this server.</gray>\n\n\
    <dark_gray>Server Version: <aqua>{}</aqua> | Your Version: <red>{}</red></dark_gray>",
    PROTOCOL_VERSION_1_21_8,
    client_version
);

Alternatives you've considered.

Token-based DSL:
If string parsing is too heavy (although not sure why? since it'd just be a compile time macro), for the implementation, a token-based macro could be used, though it is less readable than the string format.

let component = component! {
    yellow "Your client is ", red bold "outdated!", "\n\n",
    gray "Please use Minecraft version ", green bold "1.21.8", gray " to connect...", "\n\n",
    dark_gray "Server Version: ", aqua PROTOCOL_VERSION_1_21_8, 
    dark_gray " | Your Version: ", red client_version
};

Additional Context

Kyori Adventure Parity: This pattern is standard in the modern Minecraft ecosystem (MiniMessage).

Compile-time Safety: The macro can validate tags at compile time (e.g., ensuring is closed by ). Can use some code parsing library for HTML/tag based languages.

Productivity: Significantly speeds up the development of complex chat interfaces and system messages.

I have confimed that...

  • ... such a feature does not exist already.
  • ... I ticked all the boxes without reading them
  • ... such a feature request has not been submitted already.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions