Skip to content

Commit

Permalink
Revamped components.md v3
Browse files Browse the repository at this point in the history
  • Loading branch information
tmvkrpxl0 committed Jul 31, 2023
1 parent 6d37f6a commit effc137
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 36 deletions.
63 changes: 27 additions & 36 deletions docs/misc/components.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,31 @@ Text Components
A `Component` is a holder for text which can be formatted and chained with other components via its subtype `MutableComponent`.
A component can be created using one of the available static helpers:

| Method Name | Description |
|----------------|-----------------------------------------------------------------------------------------------------------------------|
| `literal` | it creates component which simply wraps passed in text. |
| `nullToEmpty` | it's same as `#literal` except it creates empty component if null has been passed |
| `translatable` | it creates component which is represented as localized text to user, read [internationalization] for more details. |
| `empty` | it creates empty component |
| `keybind` | it creates component which is represented as name of current Keyboard key of passed keybind. |
| `nbt` | it creates component for representing nbt data specified by `path` inside `dataSource` |
| `score` | it creates component for representing `objective`'s score of entity specified by [entity selector][selectors] `name`. |
| `selector` | it creates component for displaying list of names of entities selected by [entity selector][selectors] `pattern`. |

These helpers create [`ComponentContents`][content] and wrap it in `MutableComponent`
| Method Name | Description |
|----------------|-------------------------------------------------------------------------------------------------------------------------|
| `literal` | it creates a component which simply wraps passed in text. |
| `nullToEmpty` | it's same as `#literal` except it creates empty component if null has been passed |
| `translatable` | it creates a component which is represented as localized text to user, read [internationalization] for more details. |
| `empty` | it creates an empty component |
| `keybind` | it creates a component which is represented as name of current Keyboard key of passed keybind. |
| `nbt` | it creates a component for representing nbt data specified by `path` inside `dataSource` |
| `score` | it creates a component for representing `objective`'s score of entity specified by [entity selector][selectors] `name`. |
| `selector` | it creates a component for displaying list of names of entities selected by [entity selector][selectors] `pattern`. |

Component's text contents are represented by `ComponentContents`, which holds data and defines how to represent it as text.
These helpers create `ComponentContents`, and wrap it in a `MutableComponent`.
Notably, subtype `TranslatableContents` not only supports [localization][internalization] but also [text formatting][formatting].

Applying Style
--------------

Components can be formatted (e.g., bold, click actions, color) via `Style`s.
They're immutable objects which create copy of themselves instead when modified.
`Style`s are immutable, creating new `Style` each time when modified.
You can reconfigure `Style.EMPTY` to your preferences.

`Style`'s configurations can have empty values and multiple styles can be merged together with `#applyTo(Style other)`,
with `other` overriding all empty configurations of `this`
Multiple styles can be merged together with `#applyTo(Style other)`, `other` will override all empty configurations of `this`

After configuring style to your preference,
you can apply it to your component with either `MutableComponent#setStyle` for overwriting,
or `#withStyle` for merging with previous one.

Here's an example of how you can stylize your component:
After configuring a style, it can be applied to a component with either `MutableComponent#setStyle` for overwriting, or `#withStyle` for merging with previous one:
```java
// Creates MutableComponent wrapping literal "Hello!"
MutableComponent text = Component.literal("Hello!");
Expand Down Expand Up @@ -60,15 +57,16 @@ text.setStyle(blueItalic);
// Overwrites blue and italic style to be red, bold, underlined, and strikethrough
text.withStyle(red).withStyle(bold).withStyle(doubleLines);
```
This results in red, bold text with two lines as shown in the [image][red_hello]
This results in red, bold text with two lines as shown in the image:
![red_hello]

Chaining Components
-------------------

`MutableComponent` can have additional components chained as siblings with `MutableComponent#append`. Chained components can be retrieved with `MutableComponent#getSiblings`.

`Component` stores its siblings like a tree and traversed in preorder; the parent style is merged with those of its siblings.
The tree is traversed in preorder.
![tree]

The code below will create a component with the same structure in the above example:
```java
Expand All @@ -91,27 +89,21 @@ red.append(first).append(blue).append(seventh);
blue.append(second).append(third).append(bold);
bold.append(fourth).append(fifth).append(sixth);
```
[Here's how it looks like in-game][style_annotated]

`ComponentContents`
-------------------

Component's text contents are handled by `ComponentContents`, it holds data and defines how to represent it as text.
Notably, subtype `TranslatableContents` not only supports localization but also text formatting.
Here's how it looks like in-game
![style_annotated]

### Text Formatting
Text Formatting
---------------

Text formatting is the process of inserting data as text into predefined larger text.
It can be used for displaying coordinate with x, y, z annotation, showing number with respectful units alongside, etc.
Usually special notation called **format specifiers** are used for indicating where a text can be inserted into.

`TranslatableContents` uses two types of format specifiers: `%s` and `%n$s`.
Its `args` are inserted in place of format specifiers.
This feature is useful as order of information in various languages varies.
`TranslatableContents` supports text formatting and uses two types of format specifiers: `%s` and `%n$s` as order of information in various languages varies.
It holds what to insert in place of format specifiers in array `args`

`%s` is replaced with elements of `args` in order they appear, i.e., First `%s` is replaced with a first element of `args`, and so on.
`%n$s` is positional specifier; they can specify which element will replace them with number `n`.
Here's an example of how format specifier works in practice:
* Formatting `x:%s y:%s z:%s` with `[1, 2, 3]` as `args` results in `x:1 y:2 z:3`
* Formatting `Time: %1$s ms` with `17` as `args` results in `Time: 17 ms`
* Formatting `Player name: %2$s, HP: %1$s` with `[10.2, Dev]` as `args` results in `Player name: Dev, HP: 10.2`
Expand All @@ -123,5 +115,4 @@ Here's an example of how format specifier works in practice:
[red_hello]: /img/component_red_hello.png
[style_annotated]: /img/component_style_annotated.png
[formatting]: #text-formatting
[tree]: /img/component_graph.png
[content]: #componentcontents
[tree]: /img/component_graph.png
Binary file modified static/img/component_red_hello.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified static/img/component_style_annotated.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

1 comment on commit effc137

@neoforged-pages-deployments
Copy link

Choose a reason for hiding this comment

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

Deploying with Cloudflare Pages

Name Result
Last commit: effc13795063b8a8d503d14b27711b1c8f526090
Status: ✅ Deploy successful!
Preview URL: https://9ae827e3.neoforged-docs-previews.pages.dev
PR Preview URL: https://pr-4.neoforged-docs-previews.pages.dev

Please sign in to comment.