Skip to content

Commit 1eb77da

Browse files
committed
Add platform pages
1 parent 8c39232 commit 1eb77da

File tree

14 files changed

+1049
-9
lines changed

14 files changed

+1049
-9
lines changed

astro.config.ts

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@ import starlightSidebarTopics from "starlight-sidebar-topics";
77
import miniMessageHighlight from "./src/assets/mm.tmLanguage.json";
88
import codeConstantsPlugin from "./src/utils/remark/code_const";
99
import javadocPlugin from "./src/utils/remark/javadoc";
10-
import { LATEST_MC_RELEASE, LATEST_PAPER_RELEASE, LATEST_VELOCITY_RELEASE } from "./src/utils/versions";
10+
import {
11+
LATEST_MC_RELEASE,
12+
LATEST_PAPER_RELEASE,
13+
LATEST_VELOCITY_RELEASE,
14+
} from "./src/utils/versions";
1115

1216
const prod = process.env.NODE_ENV === "production";
1317

@@ -50,7 +54,8 @@ export default defineConfig({
5054
Footer: "./src/components/overrides/Footer.astro",
5155
Banner: "./src/components/overrides/Banner.astro",
5256
TableOfContents: "./src/components/overrides/TableOfContents.astro",
53-
MobileTableOfContents: "./src/components/overrides/MobileTableOfContents.astro",
57+
MobileTableOfContents:
58+
"./src/components/overrides/MobileTableOfContents.astro",
5459
},
5560
plugins: [
5661
starlightLinksValidator({
@@ -69,7 +74,12 @@ export default defineConfig({
6974
items: [
7075
{
7176
label: "Getting started",
72-
items: ["paper/getting-started", "paper/adding-plugins", "paper/migration", "paper/next-steps"],
77+
items: [
78+
"paper/getting-started",
79+
"paper/adding-plugins",
80+
"paper/migration",
81+
"paper/next-steps",
82+
],
7383
},
7484
{
7585
label: "How-to guides",
@@ -186,7 +196,10 @@ export default defineConfig({
186196
{
187197
label: "Entity API",
188198
collapsed: true,
189-
items: ["paper/dev/entity-teleport", "paper/dev/display-entities"],
199+
items: [
200+
"paper/dev/entity-teleport",
201+
"paper/dev/display-entities",
202+
],
190203
},
191204
"paper/dev/data-component-api",
192205
"paper/dev/pdc",
@@ -238,7 +251,11 @@ export default defineConfig({
238251
},
239252
{
240253
label: "How-to guides",
241-
items: ["velocity/tuning", "velocity/security", "velocity/migration"],
254+
items: [
255+
"velocity/tuning",
256+
"velocity/security",
257+
"velocity/migration",
258+
],
242259
},
243260
{
244261
label: "Reference",
@@ -266,7 +283,10 @@ export default defineConfig({
266283
},
267284
{
268285
label: "How-to guides",
269-
items: ["velocity/dev/dependency-management", "velocity/dev/porting-plugins-from-velocity-1"],
286+
items: [
287+
"velocity/dev/dependency-management",
288+
"velocity/dev/porting-plugins-from-velocity-1",
289+
],
270290
},
271291
{
272292
label: "API",
@@ -301,7 +321,11 @@ export default defineConfig({
301321
items: [
302322
{
303323
label: "Reference",
304-
items: ["folia/reference/overview", "folia/reference/region-logic", "folia/faq"],
324+
items: [
325+
"folia/reference/overview",
326+
"folia/reference/region-logic",
327+
"folia/faq",
328+
],
305329
},
306330
],
307331
},
@@ -354,6 +378,22 @@ export default defineConfig({
354378
"adventure/minimessage/translator",
355379
],
356380
},
381+
"adventure/localization",
382+
{
383+
label: "Platforms",
384+
items: [
385+
"adventure/platform/index",
386+
"adventure/platform/native",
387+
"adventure/platform/bukkit",
388+
"adventure/platform/bungeecord",
389+
"adventure/platform/spongeapi",
390+
"adventure/platform/modded",
391+
"adventure/platform/fabric",
392+
"adventure/platform/neoforge",
393+
"adventure/platform/viaversion",
394+
"adventure/platform/implementing",
395+
],
396+
},
357397
],
358398
},
359399
{

src/components/adventure/data/DependencyVersions.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ const versions: Map<string, string> = new Map(
2424
"text-serializer-bungeecord": "4.3.4",
2525
"adventure-platform-fabric": "6.3.0",
2626
facet: "4.3.4",
27-
// "api": "4.3.4", -- Duplicate key?
27+
platform: "4.3.4",
2828
bungeecord: "4.3.4",
2929
viaversion: "4.3.4",
3030
neoforge: "6.3.0",
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
---
2+
title: Localization
3+
---
4+
5+
Adventure provides a way to utilize Minecraft's built-in localization system for client-side translations as well as an additional Adventure-specific system for translating text.
6+
7+
## Using Minecraft's localization
8+
9+
To send text to a player that will be translated in the language they have selected in their client settings, use a translatable component.
10+
For example, `Component.translatable("block.minecraft.diamond_block")` will render as "Block of Diamond" (or translated to another language) when viewed by the client.
11+
Some translation keys have arguments which are inserted into the translated content.
12+
For example, `Component.translatable("block.minecraft.player_head.named", Component.text("Mark"))` will render as "Mark's Head".
13+
Translatable components can have styling, hover/click events and children components just like any other component type.
14+
15+
### Resource pack language files
16+
17+
You can provide translation files in a resource pack in order to change existing translations or add new ones.
18+
For a guide on how to do that, see the [Minecraft Wiki](https://minecraft.wiki/w/Resource_pack#Language).
19+
20+
### Using Adventure's localization
21+
22+
Adventure also provides a way to handle localization in Adventure itself.
23+
This can be useful in environments where you do not have access to resource packs, or wish to do translations yourself, without relying on Minecraft's translation system.
24+
25+
Any component that is sent to a client is ran through the `GlobalTranslator` using the locale of the client.
26+
This means that if you wish to have automatic translation of components using your own translation data, you can add a `Translator` to the `GlobalTranslator`.
27+
You can either provide your own implementation of `Translator` or use one of the implementations that Adventure provides.
28+
29+
Once you have a `Translator` instance, you can register it to the `GlobalTranslator` using `GlobalTranslator.translator().addSource(myTranslator)`.
30+
This will then make it available for automatic translation across the platform.
31+
32+
:::caution
33+
34+
Some implementations may not use the `GlobalTranslator` in every area, or at all.
35+
For example, Paper does not use it for items, and Minestom does not use it unless specifically enabled.
36+
Please consult the documentation for your platform for any limitations.
37+
38+
:::
39+
40+
## Using a custom `Translator`
41+
42+
A `Translator` is a simple interface that provides two ways of translating content.
43+
44+
The first `translate` method provides the translation key and locale as an argument and expects a nullable `MessageFormat` in return.
45+
This system is comparable to Minecraft's built-in localization system, using the standard Java [message format](https://docs.oracle.com/javase/8/docs/api/java/text/MessageFormat.html) for arguments.
46+
47+
If the first `translate` method returns `null`, the second method which provides the translatable component and locale as an argument can be used.
48+
This method allows for much richer customization of the translation process as you can return an entire component.
49+
This means you can, for example, customize the color and styling of the translated component, rather than relying solely on strings for the message format system.
50+
51+
:::caution
52+
53+
If you are overriding the component `translate` method, you should be careful not to unintentionally lose the children of the translatable component.
54+
See the Javadocs for the translate method for a code example of how to avoid this common error.
55+
56+
:::
57+
58+
Below is an example of how one might implement a custom `Translator`.
59+
60+
```java title="MyTranslator.java"
61+
public class MyTranslator implements Translator {
62+
63+
@Override
64+
public @NotNull Key name() {
65+
// Every translator has a name which is used to identify this specific translator instance.
66+
return Key.key("mynamespace:mykey");
67+
}
68+
69+
@Override
70+
public @Nullable MessageFormat translate(final @NotNull String key, final @NotNull Locale locale) {
71+
// You could retrieve a string from a properties file, a config file, or some other system.
72+
// An an example, we will hard-code a check for a specific key here.
73+
if (key.equals("mytranslation.key") && locale == Locale.US) {
74+
return new MessageFormat("Hello %s!", locale);
75+
} else {
76+
// If you only want to use component translation, you can override this method and always return `null`.
77+
return null;
78+
}
79+
}
80+
81+
@Override
82+
public @Nullable Component translate(@NotNull TranslatableComponent component, @NotNull Locale locale) {
83+
// As above, we will hardcode a check here, but you should be reading this from elsewhere.
84+
if (key.equals("mytranslation.colorful") && locale == Locale.US) {
85+
return Component.text("Hello, ", NamedTextColor.GREEN)
86+
.append(component.arguments().get(0).color(NamedTextColor.RED))
87+
.append(component.children()); // Always make sure to copy the children over!
88+
} else {
89+
return null;
90+
}
91+
}
92+
}
93+
```
94+
95+
### Using a `TranslationStore`
96+
97+
A `TranslationStore` is a store of translations.
98+
It provides a simpler way creating a `Translator` without having to implement the logic for determining and storing translations yourself.
99+
You can create a translation store and then add or remove translations at will, even after registering it to the global translator.
100+
101+
Adventure provides two translation stores, one for message format translating and one for component translating.
102+
An example of how to use a translation store is below.
103+
104+
```java
105+
// As above, every translator needs an identifying name!
106+
// Could also use TranslationStore#component(Key) to work with components instead.
107+
final TranslationStore myStore = TranslationStore.messageFormat(Key.key("mynamespace:mykey"));
108+
109+
// You can add translations one-by-one, or in bulk. Consult the Javadocs for a full list of methods.
110+
myStore.register("mytranslation.key", Locale.US, new MessageFormat("Hello %s!", Locale.US));
111+
112+
// You can then register this to the global translator so the translations are available there!
113+
GlobalTranslator.translator().addSource(myStore);
114+
```
115+
116+
There are additional methods on the message format translation store to bulk register from [resource bundles](https://docs.oracle.com/javase/8/docs/api/java/util/ResourceBundle.html).
117+
You may also want to use Adventure's `UTF8ResourceBundleControl` utility class to create your bundle.
118+
119+
### Using MiniMessage for translations
120+
121+
Adventure also provides a translator that can use MiniMessage strings, with automatic support for placeholders and arguments.
122+
For more information, see [MiniMessage Translator](adventure/minimessage/translator).

src/content/docs/adventure/minimessage/format.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ Arguments
157157
* `_decorationname_`, Any decoration supported in Minecraft:
158158

159159
| Decoration | Aliases |
160-
| ------------------| --------------- |
160+
| ----------------- | --------------- |
161161
| `bold` | `b` |
162162
| `italic` | `em` or `i` |
163163
| `underlined` | `u` |
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
---
2+
title: Bukkit
3+
---
4+
5+
import AdventureDependency from "/src/components/adventure/AdventureDependency.astro";
6+
7+
The Adventure platform implementation for Bukkit targets Paper, Spigot, and Bukkit for
8+
Minecraft 1.7.10 through 1.21.5.
9+
10+
:::caution
11+
12+
This page documents only the *legacy* platform adapter for Bukkit. Most users should use [Paper](/paper)'s native implementation instead.
13+
This native implementation provides more functionality, better integration with the server, and does not require the `BukkitAudiences` adapter.
14+
15+
:::
16+
17+
<AdventureDependency artifact="adventure-platform-bukkit" project="platform" />
18+
19+
## Usage
20+
21+
You should first obtain a `BukkitAudiences` object by using `BukkitAudiences.create(plugin)`. This object is thread-safe
22+
and can be reused from different threads if needed. From here, Bukkit `CommandSender`s and `Player`s may be converted into
23+
`Audience`s using the appropriate methods on `BukkitAudiences`.
24+
25+
The audiences object should also be closed when a plugin is disabled in order to clean up resources and increase the likelihood of a successful `/reload`.
26+
27+
```java
28+
public class MyPlugin extends JavaPlugin {
29+
30+
private BukkitAudiences adventure;
31+
32+
@NonNull
33+
public BukkitAudiences adventure() {
34+
if (this.adventure == null) {
35+
throw new IllegalStateException("Tried to access Adventure when the plugin was disabled!");
36+
}
37+
return this.adventure;
38+
}
39+
40+
@Override
41+
public void onEnable() {
42+
// Initialize an audiences instance for the plugin
43+
this.adventure = BukkitAudiences.create(this);
44+
// then do any other initialization
45+
}
46+
47+
@Override
48+
public void onDisable() {
49+
if (this.adventure != null) {
50+
this.adventure.close();
51+
this.adventure = null;
52+
}
53+
}
54+
}
55+
```
56+
57+
This audience provider should be used over the serializers directly, since it will handle compatibility measures for sending messages across versions.
58+
59+
## Component serializers
60+
61+
For areas that aren't covered by the `Audience` interface, the Bukkit platform provides the `MinecraftComponentSerializer`
62+
(available on CraftBukkit-based servers), and the `BungeeComponentSerializer` (available on Spigot and Paper servers)
63+
to convert directly between Adventure [Components](/adventure/text) and other component types. For uses that don't integrate
64+
directly with native types, JSON and legacy format serializers for the running server version are exposed in `BukkitComponentSerializer`.
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
---
2+
title: BungeeCord
3+
---
4+
5+
import AdventureDependency from "/src/components/adventure/AdventureDependency.astro";
6+
7+
Adventure targets the latest version of BungeeCord and BungeeCord-compatible
8+
forks, such as Waterfall.
9+
10+
:::caution
11+
12+
The BungeeCord platform is intended for legacy environments only.
13+
Most developers will want to write plugins for [Velocity](/velocity), which natively implements the Adventure API. No adapters required!
14+
15+
:::
16+
17+
<AdventureDependency artifact="adventure-platform-bungeecord" project="platform" />
18+
19+
## Usage
20+
21+
You should first obtain a `BungeeAudiences` object by using `BungeeAudiences.create(plugin)`. This object is thread-safe
22+
and can be reused from different threads if needed. This object should also be *closed* when the plugin is disabled.
23+
24+
Note that not all functionality is available on the proxy. Sending chat messages, action bar messages, titles, and boss bars,
25+
and tab list header and footer are supported, but all other requests will fail silently.
26+
27+
A simple example of how to appropriately initialize this platform follows:
28+
29+
```java
30+
public class MyPlugin extends Plugin {
31+
32+
private BungeeAudiences adventure;
33+
34+
@NonNull
35+
public BungeeAudiences adventure() {
36+
if (this.adventure == null) {
37+
throw new IllegalStateException("Cannot retrieve audience provider while plugin is not enabled");
38+
}
39+
return this.adventure;
40+
}
41+
42+
@Override
43+
public void onEnable() {
44+
this.adventure = BungeeAudiences.create(this);
45+
}
46+
47+
@Override
48+
public void onDisable() {
49+
if (this.adventure != null) {
50+
this.adventure.close();
51+
this.adventure = null;
52+
}
53+
}
54+
}
55+
```
56+
57+
## Component serializers
58+
59+
For functionality not already supported by `Audience`, the `BungeeComponentSerializer` allows you to convert between
60+
Adventure [Components](/adventure/text) and the native BungeeCord chat component API and back.
61+
62+
:::cautions
63+
64+
For some areas of the proxy (notably, sending server list responses), the component serializer cannot be appropriately
65+
injected unless a `BungeeAudiences` instance has been initialized. Using Adventure `Component` instances **will not**
66+
work without a created `BungeeAudiences` instance.
67+
68+
:::

0 commit comments

Comments
 (0)