diff --git a/astro.config.ts b/astro.config.ts index 770c846ec..e6f12b9a4 100644 --- a/astro.config.ts +++ b/astro.config.ts @@ -43,6 +43,11 @@ export default defineConfig({ }, starlight({ title: "PaperMC Docs", + defaultLocale: "root", + locales: { + root: { label: "English", lang: "en" }, + es: { label: "Español", lang: "es" }, + }, social: [ { icon: "github", label: "paper:GitHub", href: "https://github.com/PaperMC/Paper" }, { icon: "seti:java", label: "paper:Javadoc", href: `https://jd.papermc.io/paper` }, @@ -105,6 +110,7 @@ export default defineConfig({ starlightLinksValidator({ exclude: [ "/adventure/version-history/*", // custom pages + "/es/adventure/version-history/*", // custom pages ], errorOnInvalidHashes: false, // enable if you want to check hashes - it doesn't work with config diagrams }), @@ -112,19 +118,22 @@ export default defineConfig({ [ { id: "paper", - label: "Paper", + label: { en: "Paper", es: "Paper" }, link: "/paper/", icon: "paper", items: [ { label: "Administration", + translations: { es: "Administración" }, items: [ { label: "Getting started", + translations: { es: "Primeros pasos" }, items: ["paper/getting-started", "paper/adding-plugins", "paper/migration", "paper/next-steps"], }, { label: "How-to guides", + translations: { es: "Guías prácticas" }, items: [ "paper/aikars-flags", "paper/anti-xray", @@ -136,9 +145,11 @@ export default defineConfig({ }, { label: "Reference", + translations: { es: "Referencia" }, items: [ { label: "Configuration", + translations: { es: "Configuración" }, collapsed: true, items: [ "paper/reference/configuration", @@ -162,15 +173,18 @@ export default defineConfig({ }, { label: "Miscellaneous", + translations: { es: "Varios" }, items: ["paper/misc/update-checker", "paper/misc/paper-bug-fixes", "paper/faq"], }, ], }, { label: "Development", + translations: { es: "Desarrollo" }, items: [ { label: "Getting started", + translations: { es: "Primeros pasos" }, items: [ "paper/dev/project-setup", "paper/dev/how-do-plugins-work", @@ -181,13 +195,16 @@ export default defineConfig({ }, { label: "API", + translations: { es: "API" }, items: [ { label: "Command API", + translations: { es: "API de comandos" }, collapsed: true, items: [ { label: "Basics", + translations: { es: "Fundamentos" }, items: [ "paper/dev/command-api/basics/introduction", "paper/dev/command-api/basics/command-tree", @@ -201,6 +218,7 @@ export default defineConfig({ }, { label: "Arguments", + translations: { es: "Argumentos" }, items: [ "paper/dev/command-api/arguments/minecraft", "paper/dev/command-api/arguments/location", @@ -214,6 +232,7 @@ export default defineConfig({ }, { label: "Miscellaneous", + translations: { es: "Varios" }, items: [ "paper/dev/command-api/misc/basic-command", "paper/dev/command-api/misc/comparison-bukkit-brigadier", @@ -223,6 +242,7 @@ export default defineConfig({ }, { label: "Component API", + translations: { es: "API de componentes" }, collapsed: true, items: [ "paper/dev/component-api/introduction", @@ -233,6 +253,7 @@ export default defineConfig({ }, { label: "Event API", + translations: { es: "API de eventos" }, collapsed: true, items: [ "paper/dev/event-listeners", @@ -243,6 +264,7 @@ export default defineConfig({ }, { label: "Entity API", + translations: { es: "API de entidades" }, collapsed: true, items: [ "paper/dev/entity-teleport", @@ -253,11 +275,13 @@ export default defineConfig({ }, { label: "Inventories", + translations: { es: "Inventarios" }, collapsed: true, items: ["paper/dev/menu-type-api", "paper/dev/custom-inventory-holder"], }, { label: "Lifecycle API", + translations: { es: "API de ciclo de vida" }, collapsed: true, items: ["paper/dev/lifecycle", "paper/dev/lifecycle/datapacks"], }, @@ -276,6 +300,7 @@ export default defineConfig({ }, { label: "Miscellaneous", + translations: { es: "Varios" }, items: [ "paper/dev/using-databases", "paper/dev/debugging", @@ -287,21 +312,24 @@ export default defineConfig({ }, { label: "Contributing", + translations: { es: "Colaboración" }, items: ["paper/contributing/events"], }, ], }, { id: "velocity", - label: "Velocity", + label: { en: "Velocity", es: "Velocity" }, link: "/velocity/", icon: "velocity", items: [ { label: "Administration", + translations: { es: "Administración" }, items: [ { label: "Getting started", + translations: { es: "Primeros pasos" }, items: [ "velocity/getting-started", "velocity/why-velocity", @@ -311,10 +339,12 @@ export default defineConfig({ }, { label: "How-to guides", + translations: { es: "Guías prácticas" }, items: ["velocity/tuning", "velocity/security", "velocity/migration"], }, { label: "Reference", + translations: { es: "Referencia" }, items: [ "velocity/configuration", "velocity/reference/system-properties", @@ -328,9 +358,11 @@ export default defineConfig({ }, { label: "Development", + translations: { es: "Desarrollo" }, items: [ { label: "Getting started", + translations: { es: "Primeros pasos" }, items: [ "velocity/dev/creating-your-first-plugin", "velocity/dev/velocity-plugin-json", @@ -340,13 +372,16 @@ export default defineConfig({ }, { label: "How-to guides", + translations: { es: "Guías prácticas" }, items: ["velocity/dev/dependency-management", "velocity/dev/porting-plugins-from-velocity-1"], }, { label: "API", + translations: { es: "API" }, items: [ { label: "Component API", + translations: { es: "API de componentes" }, collapsed: true, items: [ "paper/dev/component-api/introduction", @@ -366,15 +401,17 @@ export default defineConfig({ }, { id: "folia", - label: "Folia", + label: { en: "Folia", es: "Folia" }, link: "/folia/", icon: "folia", items: [ { label: "Administration", + translations: { es: "Administración" }, items: [ { label: "Reference", + translations: { es: "Referencia" }, items: ["folia/reference/overview", "folia/reference/region-logic", "folia/faq"], }, ], @@ -383,7 +420,7 @@ export default defineConfig({ }, { id: "adventure", - label: "Adventure", + label: { en: "Adventure", es: "Adventure" }, link: "/adventure/", icon: "adventure", items: [ @@ -394,6 +431,7 @@ export default defineConfig({ "adventure/text", { label: "Text serializers", + translations: { es: "Serializadores de texto" }, items: [ "adventure/serializer", "adventure/serializer/json", @@ -402,6 +440,7 @@ export default defineConfig({ "adventure/serializer/plain", { label: "MiniMessage", + translations: { es: "MiniMessage" }, items: [ "adventure/minimessage", "adventure/minimessage/format", @@ -419,19 +458,10 @@ export default defineConfig({ "adventure/book", "adventure/tablist", "adventure/resource-pack", - { - label: "MiniMessage", - items: [ - "adventure/minimessage", - "adventure/minimessage/format", - "adventure/minimessage/api", - "adventure/minimessage/dynamic-replacements", - "adventure/minimessage/translator", - ], - }, "adventure/localization", { label: "Platforms", + translations: { es: "Plataformas" }, items: [ "adventure/platform", "adventure/platform/native", @@ -447,6 +477,7 @@ export default defineConfig({ }, { label: "Version history", + translations: { es: "Historial de versiones" }, items: [ { label: "adventure", link: "/adventure/version-history/adventure" }, { label: "adventure-platform", link: "/adventure/version-history/adventure-platform" }, @@ -458,6 +489,7 @@ export default defineConfig({ }, { label: "Migration", + translations: { es: "Migración" }, items: [ "adventure/migration", "adventure/migration/bungeecord-chat-api", @@ -469,14 +501,14 @@ export default defineConfig({ }, { id: "waterfall", - label: "Waterfall", + label: { en: "Waterfall", es: "Waterfall" }, link: "/waterfall/", icon: "waterfall", items: ["waterfall/getting-started", "waterfall/configuration"], }, { id: "misc", - label: "Miscellaneous", + label: { en: "Miscellaneous", es: "Misceláneos" }, link: "/misc/", icon: "random", items: [ @@ -487,6 +519,7 @@ export default defineConfig({ "misc/java-install", { label: "Tools", + translations: { es: "Herramientas" }, items: [ "misc/tools/start-script-gen", "misc/tools/item-command-converter", @@ -520,6 +553,25 @@ export default defineConfig({ "/paper/dev/api/event-api", "/paper/dev/misc", "/paper/contributing", + "/es/paper/admin", + "/es/paper/admin/getting-started", + "/es/paper/admin/how-to", + "/es/paper/admin/misc", + "/es/paper/admin/reference", + "/es/paper/dev", + "/es/paper/dev/getting-started", + "/es/paper/dev/api", + "/es/paper/dev/api/command-api", + "/es/paper/dev/api/command-api/arguments", + "/es/paper/dev/api/command-api/basics", + "/es/paper/dev/api/command-api/misc", + "/es/paper/dev/api/component-api", + "/es/paper/dev/api/entity-api", + "/es/paper/dev/api/inventories", + "/es/paper/dev/api/lifecycle", + "/es/paper/dev/api/event-api", + "/es/paper/dev/misc", + "/es/paper/contributing", ], velocity: [ "/velocity/admin", @@ -530,11 +582,19 @@ export default defineConfig({ "/velocity/dev/getting-started", "/velocity/dev/how-to", "/velocity/dev/api", + "/es/velocity/admin", + "/es/velocity/admin/getting-started", + "/es/velocity/admin/how-to", + "/es/velocity/admin/reference", + "/es/velocity/dev", + "/es/velocity/dev/getting-started", + "/es/velocity/dev/how-to", + "/es/velocity/dev/api", ], - folia: ["/folia/admin", "/folia/admin/reference"], - adventure: ["/adventure/version-history"], - waterfall: ["/waterfall"], - misc: ["/misc", "/misc/tools"], + folia: ["/folia/admin", "/folia/admin/reference", "/es/folia/admin", "/es/folia/admin/reference"], + adventure: ["/adventure/version-history", "/es/adventure/version-history"], + waterfall: ["/waterfall", "/es/waterfall"], + misc: ["/misc", "/misc/tools", "/es/misc", "/es/misc/tools"], }, } ), diff --git a/src/content/docs/es/adventure/audiences.md b/src/content/docs/es/adventure/audiences.md new file mode 100644 index 000000000..9fe3a7cc4 --- /dev/null +++ b/src/content/docs/es/adventure/audiences.md @@ -0,0 +1,127 @@ +--- +title: Audiencias +slug: es/adventure/audiences +description: Guía sobre las audiencias de Adventure. +--- + +En esencia, una audiencia es un grupo de cero o más destinatarios de cierto contenido. +El concepto de audiencia es la diferencia más clara entre Adventure y otras plataformas de Minecraft. + +Como API, `Audience` está diseñada como una interfaz universal para cualquier jugador, +emisor de comandos, consola u otro destinatario que pueda recibir texto, títulos, barras de jefe +y otros medios de Minecraft. Esto permite ampliar las audiencias para que incluyan a más de +un destinatario individual: una «audiencia» podría ser un equipo, servidor, +mundo o todos los jugadores que cumplan una condición (por ejemplo, tener cierto +permiso). La interfaz universal también reduce el código repetitivo al degradar +con elegancia las funciones que no sean aplicables. Por ejemplo, no tiene mucho sentido +enviar una barra de jefe a un emisor de comandos, y no se pueden enviar títulos a clientes de Minecraft 1.7. + +Normalmente obtendrás instancias de audiencia desde una de las [Plataformas](/es/adventure/platform). +La propia API de Adventure incluye dos implementaciones de audiencia: una que no +admite ninguna acción (y, por tanto, no hace nada), `Audience.empty()`, y otra que +reenvía cada acción a todos los miembros de la audiencia, mediante `Audience.audience()` y métodos relacionados, +junto con `ForwardingAudience`, que implementa por ti la lógica de reenvío. + +La mayoría de los usuarios empleará esta API principalmente para mostrar contenido creado por otras partes +de la API. + +## Audiencias de reenvío + +Una [](jd:adventure:net.kyori.adventure.audience.ForwardingAudience) reenvía a otras audiencias +todas las acciones que recibe. Su único método abstracto es `audiences()`, +así que basta con implementarlo para convertir uno de tus tipos en una audiencia: + +```java title=GameTeam.java +public class GameTeam implements ForwardingAudience { + private final List players = new ArrayList<>(); + + // ... + + @Override + public Iterable audiences() { + return this.players; + } +} +``` + +Ahora puedes enviar al equipo completo todo lo que se pueda enviar a una audiencia: + +```java +final GameTeam team = /* ... */; +team.sendMessage(Component.text("¡La partida empieza en 10 segundos!")); +team.playSound(Sound.sound(Key.key("block.note_block.pling"), Sound.Source.MASTER, 1F, 1F)); +``` + +`audiences()` se llama cada vez que se reenvía una acción, así que los miembros que se añadan +o eliminen de la colección subyacente se tendrán en cuenta automáticamente. + +Si no necesitas un tipo propio, +[`Audience.audience(Iterable)`](jd:adventure:net.kyori.adventure.audience.Audience#audience(java.lang.Iterable)), +[`Audience.audience(Audience...)`](jd:adventure:net.kyori.adventure.audience.Audience#audience(net.kyori.adventure.audience.Audience...)), +y el colector [`Audience.toAudience()`](jd:adventure:net.kyori.adventure.audience.Audience#toAudience()) +pueden crear por ti una `ForwardingAudience`. + +Una audiencia de reenvío formada por varios miembros no tiene punteros propios, así que +`get(Identity.UUID)` en el `GameTeam` anterior devolvería un `Optional` vacío. + +### Envolver una sola audiencia + +Para envolver exactamente una audiencia, implementa en su lugar +[](jd:adventure:net.kyori.adventure.audience.ForwardingAudience$Single). Reenvía tanto los punteros como las acciones: + +```java title=GamePlayer.java +public class GamePlayer implements ForwardingAudience.Single { + private final Audience audience; + private int score; + + public GamePlayer(final Audience audience) { + this.audience = audience; + } + + @Override + public Audience audience() { + return this.audience; + } +} +``` + +Esto resulta especialmente útil en proyectos compatibles con más de una plataforma. Si el código común +solo trabaja con `GamePlayer`, cada módulo de plataforma puede proporcionar la audiencia de +su propio tipo de jugador. Consulta [Plataformas](/es/adventure/platform) para obtener más información. + +### Cambiar qué se reenvía + +Muchos métodos de `Audience` son sobrecargas de conveniencia que terminan llamando a un conjunto reducido +de métodos. `sendMessage(ComponentLike)` llama a `sendMessage(Component)` y +`showTitle(Title)` llama a `sendTitlePart` una vez por cada parte del título. +`ForwardingAudience` solo sobrescribe ese conjunto reducido, así que basta con sobrescribir esos métodos +para cambiar el comportamiento de la audiencia: + +```java title=GameTeam.java +public class GameTeam implements ForwardingAudience { + private static final Component PREFIX = Component.text("[Team] "); + + // ... + + @Override + public void sendMessage(final Component message) { + // También se aplica a sendMessage(ComponentLike) + ForwardingAudience.super.sendMessage(PREFIX.append(message)); + } +} +``` + +## Punteros + +Las audiencias también pueden proporcionar información arbitraria, como el nombre visible o el UUID. +Esto se hace mediante el sistema de punteros. + +Ejemplos: + +```java +// Obtener el UUID de un miembro de la audiencia; devuelve un Optional +audience.get(Identity.UUID); + +// Obtener el nombre visible o, si no está definido, un valor predeterminado +audience.getOrDefault(Identity.DISPLAY_NAME, Component.text("sin nombre visible")); +``` diff --git a/src/content/docs/es/adventure/book.md b/src/content/docs/es/adventure/book.md new file mode 100644 index 000000000..c5f43743c --- /dev/null +++ b/src/content/docs/es/adventure/book.md @@ -0,0 +1,34 @@ +--- +title: Libros +slug: es/adventure/book +description: Guía sobre los libros de Adventure. +--- + +## Crear un libro + +Los libros se componen de: + * Un componente para el título del libro + * Un componente para el autor del libro + * Una colección de componentes para las páginas del libro + +**Ejemplo:** + +```java +// Crear y abrir para la audiencia destinataria un libro sobre gatos +public void openMyBook(final Audience target) { + final Component bookTitle = Component.text("Enciclopedia de los gatos"); + final Component bookAuthor = Component.text("kashike"); + final Collection bookPages = Cats.getCatKnowledge(); + + final Book myBook = Book.book(bookTitle, bookAuthor, bookPages); + target.openBook(myBook); +} +``` + +## Información adicional sobre los libros + +Los libros de Adventure no están necesariamente vinculados a un objeto de libro con el que se pueda interactuar en el cliente. +En la versión actual, esa conexión debe implementarse fuera de Adventure. + +Cualquier componente que supere el límite de texto por página del juego se truncará en el cliente; lo mismo se aplica +a la cantidad de componentes (páginas). Puedes leer más sobre estos límites en la [Minecraft Wiki](https://minecraft.wiki/w/Book_and_Quill#Writing). diff --git a/src/content/docs/es/adventure/bossbar.md b/src/content/docs/es/adventure/bossbar.md new file mode 100644 index 000000000..a2549ac8a --- /dev/null +++ b/src/content/docs/es/adventure/bossbar.md @@ -0,0 +1,61 @@ +--- +title: Barras de jefe +slug: es/adventure/bossbar +description: Guía sobre las barras de jefe de Adventure. +--- + +## Crear una barra de jefe + +Las barras de jefe se componen de: + * Un componente para el título de la barra de jefe + * Un número de 0 a 1 que determina cuánto se llena la barra de jefe + * Un color, que se reducirá a una paleta compatible en clientes <1.9 + * Una superposición que determina el número de segmentos visuales de la barra de jefe + + +**Ejemplos:** + +```java +private @Nullable BossBar activeBar; + +public void showMyBossBar(final Audience target) { + final Component name = Component.text("Barra de jefe increíble"); + // Crear una barra de jefe roja, vacía y sin segmentos + final BossBar emptyBar = BossBar.bossBar(name, 0, BossBar.Color.RED, BossBar.Overlay.PROGRESS); + // Crear una barra de jefe verde, con un 50 % de progreso y 10 segmentos + final BossBar halfBar = BossBar.bossBar(name, 0.5F, BossBar.Color.GREEN, BossBar.Overlay.NOTCHED_10); + // etc. + final BossBar fullBar = BossBar.bossBar(name, 1, BossBar.Color.BLUE, BossBar.Overlay.NOTCHED_20); + + // Enviar una barra de jefe a la audiencia + target.showBossBar(fullBar); + + // Guardarla localmente para poder ocultarla manualmente más adelante + this.activeBar = fullBar; +} + +public void hideActiveBossBar(final Audience target) { + target.hideBossBar(this.activeBar); + this.activeBar = null; +} +``` + +## Cambiar una barra de jefe activa + +Las barras de jefe son mutables y reaccionan a los cambios en su objeto: +la vista del juego se actualizará automáticamente, ¡sin necesidad de refrescarla manualmente! + +Por tanto, si esta barra de jefe está activa: + +```java +final BossBar bossBar = BossBar.bossBar(Component.text("Contador de gatos"), 0, BossBar.Color.RED, BossBar.Overlay.PROGRESS); +``` + +y se llama a `BossBar.name()` con un componente + +```java +final Component newText = Component.text("Contador de patos"); +bossBar.name(newText); +``` + +la barra de jefe se actualizará automáticamente. Lo mismo ocurre con `progress`, `color` y `overlay`. diff --git a/src/content/docs/es/adventure/community-libraries.mdx b/src/content/docs/es/adventure/community-libraries.mdx new file mode 100644 index 000000000..9c70a9573 --- /dev/null +++ b/src/content/docs/es/adventure/community-libraries.mdx @@ -0,0 +1,73 @@ +--- +title: Bibliotecas de la comunidad +slug: es/adventure/community-libraries +description: Bibliotecas que utilizan la API de Adventure. +--- + +Adventure busca proporcionar las bibliotecas básicas necesarias para interactuar con componentes del chat. +Sin embargo, dado el tiempo y los recursos limitados del equipo de Adventure, y la enorme cantidad de casos de uso posibles, no podemos ofrecer soluciones directas para todos los problemas. + +Por suerte, muchos miembros de nuestra comunidad han creado bibliotecas que complementan Adventure y ofrecen funciones adicionales e integraciones con otros programas. + +:::note + +Esta lista de bibliotecas se ofrece únicamente como referencia. +El equipo de Adventure no respalda ninguna biblioteca en particular ni puede proporcionar información o asistencia más allá de los enlaces incluidos. + +Si quieres que se incluya una biblioteca, abre una solicitud de cambios en el repositorio [PaperMC/docs](https://github.com/PaperMC/docs). + +::: + +{/* Los elementos de todas estas tablas deben ordenarse alfabéticamente */} + +## Serializadores + +Estas bibliotecas se centran en ofrecer formatos de serialización adicionales para componentes del chat. +Normalmente no dependen de una plataforma concreta, sino solo de Adventure y, posiblemente, de alguna biblioteca con la que se integren. + +{/* spellchecker:off */} +Nombre | Descripción | Enlace +----------------------------|-----------------------------------------------------------------------|----------------------------------------------------------------------------------------------------- +EnhancedLegacyText | Formato de entrada alternativo compatible con las nuevas funciones del formato antiguo | [Vankka/EnhancedLegacyText](https://github.com/Vankka/EnhancedLegacyText) +MCDiscordReserializer | Serializadores para convertir entre Minecraft y Discord | [Vankka/MCDiscordReserializer](https://github.com/Vankka/MCDiscordReserializer) +Minedown | Formato de estilo Markdown para representar componentes | [Phoenix616/MineDown](https://github.com/Phoenix616/MineDown) +{/* spellchecker:on */} + +## Plataformas + +Estas bibliotecas proporcionan implementaciones de Adventure en distintas plataformas que no están integradas oficialmente en el software ni mantenidas por el equipo de Adventure. + +{/* spellchecker:off */} +Nombre | Descripción | Enlace +----------------------------|-----------------------------------------------|----------------------------------------------------------------------------------------------------- +adventure-platform-hytale | Implementación de la plataforma Adventure para Hytale | [ArikSquad/adventure-platform-hytale](https://github.com/ArikSquad/adventure-platform-hytale) +{/* spellchecker:on */} + +## Ampliaciones + +Estas bibliotecas amplían la API principal de Adventure con funciones independientes de la plataforma que no se incluyen en el proyecto principal o no son adecuadas para incluirse en él. + +{/* spellchecker:off */} +Nombre | Descripción | Enlace +--------------------|-----------------------------------------------------------------------|---------------------------------------------------- +MiniPlaceholders | Biblioteca de marcadores de posición basada en componentes MiniMessage e independiente de la plataforma | [MiniPlaceholders/MiniPlaceholders](https://github.com/MiniPlaceholders/MiniPlaceholders) +{/* spellchecker:on */} + +## Bibliotecas adicionales de interfaz de usuario + +Estas bibliotecas usan Adventure en su API, pero se centran en aspectos distintos a los componentes del chat. +Permiten usar Adventure en elementos de interfaz de usuario que no admiten las bibliotecas principales de Adventure. +Entre ellos se incluyen los comandos, los marcadores y los inventarios. +A menudo, estas bibliotecas dependen de una o varias plataformas concretas para ofrecer su funcionalidad. + +{/* spellchecker:off */} +Nombre | Descripción | Enlace +--------------------|-----------------------------------------------------------------------|---------------------------------------------------- +Cloud | Despachador de comandos y marco de trabajo de propósito general para Java | [Incendo/cloud](https://github.com/Incendo/cloud) +Creative | Biblioteca de paquetes de recursos para Minecraft: Java Edition | [unnamed/creative](https://github.com/unnamed/creative) +Inventory Framework | Marco de trabajo de inventarios para administrar interfaces gráficas | [stefvanschie/IF](https://github.com/stefvanschie/IF) +LiteCommands | Marco de trabajo de comandos basado en anotaciones para Velocity, Bukkit y BungeeCord | [Rollczi/LiteCommands](https://github.com/Rollczi/LiteCommands) +ProtocolSidebar | Biblioteca de barras laterales fácil de usar para servidores Paper/Spigot | [CatCoderr/ProtocolSidebar](https://github.com/CatCoderr/ProtocolSidebar) +ScoreboardLibrary | Biblioteca de marcadores para servidores Paper/Spigot | [MegavexNetwork/scoreboard-library](https://github.com/MegavexNetwork/scoreboard-library) +Triumph GUI | Biblioteca que simplifica la creación de interfaces gráficas de inventario | [TriumphTeam/triumph-gui](https://github.com/TriumphTeam/triumph-gui) +{/* spellchecker:on */} diff --git a/src/content/docs/es/adventure/faq.md b/src/content/docs/es/adventure/faq.md new file mode 100644 index 000000000..3d2945823 --- /dev/null +++ b/src/content/docs/es/adventure/faq.md @@ -0,0 +1,73 @@ +--- +title: Preguntas frecuentes +slug: es/adventure/faq +description: Preguntas frecuentes. +--- + +Hemos observado que hay algunos problemas que se presentan con relativa frecuencia al usar la biblioteca Adventure en ciertos contextos. Puede que no estén directamente relacionados con Adventure, pero publicamos aquí estas respuestas para quienes las necesiten: + +## ¿Por qué el texto descriptivo aparece en cursiva? + +Los componentes heredan el estilo de su componente padre. Por ejemplo, en el siguiente fragmento de código, cada palabra será roja, aunque el color rojo no se establezca explícitamente en el componente añadido: `text("hi", RED).append(text("also red!"))`. + +En Minecraft vanilla, algunos lugares donde se muestran componentes tienen estilos propios. Por ejemplo, el texto descriptivo tiene un estilo padre que pone todo el texto en cursiva. Por tanto, si no quieres que los componentes de la descripción aparezcan en cursiva, debes establecer italic en false. El método `Component.decorationIfAbsent()` permite aplicarlo a componentes existentes sin sobrescribir el formato establecido explícitamente por los usuarios. + +## ¿No se envían los mensajes? ¿No funcionan los colores hexadecimales? ¿No aparecen los eventos? ¿Hay problemas con las fuentes? + +- Prueba con un cliente vanilla, sin mods ni paquetes de recursos. Los clientes modificados (como Badlion), los mods del cliente e incluso los paquetes de recursos pueden interrumpir muchos elementos del formato JSON moderno del chat y alterar los paquetes de chat entrantes, lo que provoca numerosos problemas. +- Prueba sin otros plugins o mods. Si otro plugin o mod modifica los paquetes salientes o el formato de los mensajes del chat, puede eliminar el formato de los mensajes que envías. Prueba sin otros plugins para comprobar si alguno causa el problema. +- Para los colores RGB, prueba con un cliente de la versión *1.16* o posterior. Mojang añadió compatibilidad con RGB en esa versión. El formato JSON de los mensajes ha evolucionado y ha incorporado muchas funciones desde su introducción hace ya muchos años. Consulta el historial completo de versiones en [Minecraft Wiki](https://minecraft.wiki/w/Text_component_format). + +## ¿Cómo puedo admitir tanto MiniMessage como el formato antiguo (códigos §)? + +Si tienes texto con formato antiguo en archivos de configuración u otros lugares, te recomendamos migrarlo una sola vez: usa el deserializador antiguo para convertirlo en un componente y luego MiniMessage para serializarlo al formato MiniMessage adecuado. + +No existe —ni existirá— una forma funcional, recomendada o compatible de usar MiniMessage y los códigos de color antiguos a la vez. Ni siquiera funcionan las técnicas sencillas de buscar y reemplazar, pues no tienen en cuenta las particularidades del reinicio de estilos en el formato antiguo. + +## ¿Cómo puedo usar PlaceholderAPI de Bukkit en mensajes MiniMessage? + +MiniMessage no admite los marcadores de posición de PlaceholderAPI. Sin embargo, puedes crear fácilmente un resolvedor de etiquetas personalizado para permitir que se usen esos marcadores en cadenas MiniMessage, como en el siguiente ejemplo: + +
+ Ejemplo + Método de ejemplo para crear un marcador de posición MiniMessage que analice marcadores de PlaceholderAPI para un jugador. + + La etiqueta añadida tiene el formato ``. Por ejemplo, ``. + + Agradecimientos a `mbaxter`. + + ```java + /** + * Crea un resolvedor de etiquetas capaz de resolver etiquetas de PlaceholderAPI para un jugador. + * + * @param player el jugador + * @return el resolvedor de etiquetas + */ + public TagResolver papiTag(final Player player) { + return TagResolver.resolver("papi", (argumentQueue, context) -> { + // Obtener el marcador de posición de texto que se quiere usar. + final String papiPlaceholder = argumentQueue.popOr("papi tag requires an argument").value(); + + // Pedir a PAPI que analice el marcador de posición para el jugador indicado. + final String parsedPlaceholder = PlaceholderAPI.setPlaceholders(player, '%' + papiPlaceholder + '%'); + + // Convertir esta cadena antigua, poco práctica, en un componente. + final Component componentPlaceholder = LegacyComponentSerializer.legacySection().deserialize(parsedPlaceholder); + + // Por último, devolver la instancia de etiqueta que insertará el marcador. + return Tag.selfClosingInserting(componentPlaceholder); + }); + } + ``` +
+ +## ¿Por qué aparece un `NoSuchFieldError`, `NoSuchMethodError`, `ClassNotFoundException` o similar al actualizar o usar `adventure-platform-*`, `adventure-text-minimessage`, `adventure-api` u otras bibliotecas o herramientas relacionadas? + +En el caso de `adventure-platform-fabric`, asegúrate de incluir correctamente el mod mediante `include()`. Para las implementaciones de plataformas antiguas, asegúrate de sombrear y reubicar correctamente las dependencias correspondientes. Entre los problemas concretos se incluyen: + +- No sombrear la versión correcta de `adventure-api`. Comprueba el árbol de dependencias para averiguar por qué tu herramienta de compilación no incluye la versión correcta de la API, compatible con la versión de plataforma que usas. +- No reubicar las dependencias. Si ejecutas la aplicación en una plataforma que incluye una versión anterior de la API, o si otro mod o plugin tampoco reubica correctamente sus dependencias, acabarás usando su versión desactualizada de la API y se producirán errores. +- Compilar o ejecutar contra una implementación nativa de `adventure-api`. Si la plataforma incluye una versión antigua de la API, la biblioteca podría depender de funciones nuevas que no están disponibles en esa versión; por ello, no encontrará esos métodos y generará errores. +- Reubicar `adventure-api` e intentar usar métodos nativos o de bibliotecas. Si reubicas la API, no podrás usar métodos que dependan de ella en implementaciones nativas o bibliotecas, porque las firmas de los métodos serán distintas. Sombrea y reubica ese software o no uses métodos nativos. También puedes sombrear y reubicar una biblioteca y seguir usando la API, siempre que solo reubiques los paquetes que estás sombreando. + +Consulta la documentación de tu herramienta de compilación para obtener más información sobre cómo sombrear, reubicar y administrar dependencias. No ofrecemos asistencia individual para este tipo de problemas: hay demasiadas variables específicas de cada proyecto como para aislarlos con facilidad. diff --git a/src/content/docs/es/adventure/getting-started.mdx b/src/content/docs/es/adventure/getting-started.mdx new file mode 100644 index 000000000..1f3f34a31 --- /dev/null +++ b/src/content/docs/es/adventure/getting-started.mdx @@ -0,0 +1,61 @@ +--- +title: Primeros pasos +slug: es/adventure/getting-started +description: Guía para empezar a usar Adventure. +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components"; + +import Dependency from "/src/components/Dependency.astro"; +import { LATEST_ADVENTURE_API_RELEASE } from "/src/utils/versions"; + +Para usar Adventure en tu proyecto, debes añadir la siguiente dependencia (y el repositorio si usas Gradle): + +Declaración de la dependencia: + + + +¿Necesitas compilaciones de desarrollo o snapshots? [Uso de compilaciones snapshot](#uso-de-compilaciones-snapshot) + +Algunas plataformas ya usan Adventure de forma nativa. +En ese caso, no es necesario añadir Adventure como dependencia. +Para ver la lista de plataformas que incluyen Adventure, consulta [Compatibilidad nativa](/es/adventure/platform/native). + +Para usar Adventure con otras plataformas, puedes consultar los adaptadores específicos de cada plataforma. +Encontrarás la lista de plataformas con adaptadores compatibles en [Plataformas](/es/adventure/platform). + +## Uso de compilaciones snapshot + +Para usar compilaciones snapshot, debes añadir el siguiente repositorio: + + + + ```kotlin title="build.gradle.kts" + repositories { + maven(url = "https://central.sonatype.com/repository/maven-snapshots/") { + name = "central-snapshots" + } + } + ``` + + + ```groovy title="build.gradle" + repositories { + maven { + name = 'central-snapshots' + url = 'https://central.sonatype.com/repository/maven-snapshots/' + } + } + ``` + + + ```xml title="pom.xml" + + + central-snapshots + https://central.sonatype.com/repository/maven-snapshots/ + + + ``` + + diff --git a/src/content/docs/es/adventure/index.mdx b/src/content/docs/es/adventure/index.mdx new file mode 100644 index 000000000..08d59a0ea --- /dev/null +++ b/src/content/docs/es/adventure/index.mdx @@ -0,0 +1,11 @@ +--- +title: Adventure +slug: es/adventure +description: Una descripción general de la biblioteca Adventure. +--- + +import PageCards from "/src/components/PageCards.astro"; + +Documentación de Adventure y sus numerosas bibliotecas. + + diff --git a/src/content/docs/es/adventure/localization.md b/src/content/docs/es/adventure/localization.md new file mode 100644 index 000000000..d5784c669 --- /dev/null +++ b/src/content/docs/es/adventure/localization.md @@ -0,0 +1,125 @@ +--- +title: Localización +slug: es/adventure/localization +description: Uso de la localización en Adventure. +--- + +Adventure permite usar el sistema de localización integrado de Minecraft para las traducciones en el cliente, además de ofrecer un sistema propio para traducir texto. + +## Usar la localización de Minecraft + +Para enviar a un jugador texto que se traduzca al idioma seleccionado en los ajustes de su cliente, usa un componente traducible. +Por ejemplo, `Component.translatable("block.minecraft.diamond_block")` se mostrará como «Block of Diamond» (o traducido a otro idioma) en el cliente. +Algunas claves de traducción admiten argumentos que se insertan en el contenido traducido. +Por ejemplo, `Component.translatable("block.minecraft.player_head.named", Component.text("Mark"))` se mostrará como «Mark's Head». +Los componentes traducibles pueden tener estilos, eventos de desplazamiento o clic y componentes secundarios, igual que cualquier otro tipo de componente. + +### Archivos de idioma de paquetes de recursos + +Puedes incluir archivos de traducción en un paquete de recursos para cambiar las traducciones existentes o añadir otras nuevas. +Encontrarás una guía en [Minecraft Wiki](https://minecraft.wiki/w/Resource_pack#Language). + +### Usar la localización de Adventure + +Adventure también permite gestionar la localización desde la propia biblioteca. +Esto puede resultar útil en entornos donde no tienes acceso a paquetes de recursos o quieres realizar las traducciones por tu cuenta, sin depender del sistema de traducción de Minecraft. + +Todo componente que se envía a un cliente pasa por `GlobalTranslator` usando la configuración regional del cliente. +Por tanto, si quieres traducir componentes automáticamente con tus propios datos de traducción, puedes añadir un `Translator` a `GlobalTranslator`. +Puedes proporcionar tu propia implementación de `Translator` o usar una de las que ofrece Adventure. + +Cuando tengas una instancia de `Translator`, puedes registrarla en `GlobalTranslator` mediante `GlobalTranslator.translator().addSource(myTranslator)`. +Así estará disponible para la traducción automática en toda la plataforma. + +:::caution + +Es posible que algunas implementaciones no usen `GlobalTranslator` en todos los contextos, o que no lo usen en absoluto. +Por ejemplo, Paper no lo usa para los objetos, y Minestom no lo usa salvo que se habilite explícitamente. +Consulta la documentación de tu plataforma para conocer sus limitaciones. + +::: + +## Usar un `Translator` personalizado + +`Translator` es una interfaz sencilla que ofrece dos formas de traducir contenido. + +El primer método `translate` recibe la clave de traducción y la configuración regional como argumentos, y espera que se devuelva un `MessageFormat` anulable. +Este sistema es comparable al sistema de localización integrado de Minecraft y usa el formato estándar de mensajes de Java +[formato de mensajes](jd:java:java.text.MessageFormat) para los argumentos. + +Si el primer método `translate` devuelve `null`, se puede usar el segundo, que recibe el componente traducible y la configuración regional. +Este método permite personalizar mucho más el proceso de traducción, ya que puedes devolver un componente completo. +Por ejemplo, puedes personalizar el color y el estilo del componente traducido en lugar de depender únicamente de cadenas con el formato de mensajes. + +:::caution + +Si sobrescribes el método `translate` para componentes, ten cuidado de no perder accidentalmente los componentes secundarios del componente traducible. +Consulta los Javadocs del método `translate` para ver un ejemplo de código que evita este error común. + +::: + +A continuación se muestra un ejemplo de implementación de un `Translator` personalizado. + +```java title="MyTranslator.java" +public class MyTranslator implements Translator { + + @Override + public Key name() { + // Cada traductor tiene un nombre que identifica esta instancia concreta. + return Key.key("mynamespace:mykey"); + } + + @Override + public @Nullable MessageFormat translate(final String key, final Locale locale) { + // Podrías obtener una cadena de un archivo de propiedades, de configuración o de otro sistema. + // A modo de ejemplo, aquí comprobaremos una clave concreta directamente en el código. + if (key.equals("mytranslation.key") && Locale.US.equals(locale)) { + return new MessageFormat("Hello {0}!", locale); + } else { + // Si solo quieres traducir componentes, puedes sobrescribir este método y devolver siempre `null`. + return null; + } + } + + @Override + public @Nullable Component translate(final TranslatableComponent component, final Locale locale) { + // Como antes, aquí comprobaremos una clave directamente, pero lo ideal es obtenerla de otra fuente. + if (component.key().equals("mytranslation.colorful") && Locale.US.equals(locale)) { + return Component.text("Hello, ", NamedTextColor.GREEN) + .append(component.arguments().stream().map(it -> it.asComponent().color(NamedTextColor.RED)).toList()) + .append(component.children()) // Asegúrate siempre de copiar también los componentes secundarios. + .applyFallbackStyle(component.style()); + } else { + return null; + } + } +} +``` + +### Usar un `TranslationStore` + +Un `TranslationStore` es un almacén de traducciones. +Permite crear un `Translator` de forma más sencilla, sin tener que implementar por tu cuenta la lógica para buscar y almacenar traducciones. +Puedes crear un almacén de traducciones y añadir o quitar traducciones cuando quieras, incluso después de registrarlo en el traductor global. + +Adventure proporciona dos almacenes de traducciones: uno para traducciones con formato de mensajes y otro para traducciones de componentes. +A continuación se muestra un ejemplo de uso. + +```java +// Como antes, todos los traductores necesitan un nombre identificador. +// También puedes usar TranslationStore#component(Key) para trabajar con componentes. +final TranslationStore.StringBased myStore = TranslationStore.messageFormat(Key.key("mynamespace:mykey")); + +// Puedes añadir traducciones una a una o en bloque. Consulta los Javadocs para ver todos los métodos. +myStore.register("mytranslation.key", Locale.US, new MessageFormat("Hello {0}!", Locale.US)); + +// Después puedes registrarlo en el traductor global para que las traducciones estén disponibles. +GlobalTranslator.translator().addSource(myStore); +``` + +El almacén de traducciones con formato de mensajes incluye métodos adicionales para registrar traducciones en bloque desde [paquetes de recursos](jd:java:java.util.ResourceBundle). + +### Usar MiniMessage para las traducciones + +Adventure también proporciona un traductor que puede usar cadenas MiniMessage y admite automáticamente marcadores de posición y argumentos. +Para obtener más información, consulta [Traductor MiniMessage](/es/adventure/minimessage/translator). diff --git a/src/content/docs/es/adventure/migration/adventure-4.x.md b/src/content/docs/es/adventure/migration/adventure-4.x.md new file mode 100644 index 000000000..efa15ed6b --- /dev/null +++ b/src/content/docs/es/adventure/migration/adventure-4.x.md @@ -0,0 +1,138 @@ +--- +title: Migrar de Adventure 4.x a 5.x +slug: es/adventure/migration/adventure-4.x +description: Migración de Adventure 4.x a 5.x. +--- + +Con el lanzamiento de Adventure 5.0, se han introducido algunos cambios incompatibles con la serie Adventure 4.x. +Esta página documenta los cambios y explica cómo puedes migrar tu código. + +## Una base de código moderna + +Uno de los principales objetivos de Adventure 5.0 era migrar a una base de código más moderna. +Ahora se requiere como mínimo Java 21 para usar Adventure. + +Al actualizar a Java 21, Adventure ha aprovechado las clases y las interfaces selladas. +Casi todas las interfaces y clases anotadas con `@ApiStatus.NonExtendable` ahora son selladas. +Esto significa que ya no puedes extender estas clases, aunque no deberías haberlo hecho de todos modos. +Un uso incorrecto relativamente común era crear implementaciones personalizadas de `Component`. +Ahora ya no es posible; en su lugar, debes usar la API `VirtualComponent`. + +Otro efecto de la modernización de la base de código es que se ha eliminado el módulo `adventure-extra-kotlin`. +En el futuro, se volverá a introducir en un repositorio independiente como un nuevo módulo. +Esto permitirá más flexibilidad para adaptarse a las actualizaciones más frecuentes de Kotlin. + +También se ha eliminado el módulo `adventure-text-serializer-gson-legacy-impl`. +Se ha reemplazado por el módulo independiente de la implementación `adventure-text-serializer-json-legacy-impl`. + +Por último, Adventure ahora incluye archivos `module-info.java` adecuados para quienes usan el sistema de módulos de Java 9 o posterior. + +## Dependencias actualizadas + +Se han actualizado muchas dependencias sin cambios incompatibles. +A continuación se documentan algunos cambios importantes o incompatibles. + +Adventure ha migrado a JSpecify para las anotaciones de nulabilidad. +Se aplican a nivel de paquete o clase, así que, salvo que se indique lo contrario, todo debe considerarse no nulo. + +Como la mayor parte de la implementación interna de Adventure ahora usa records, ya no necesitamos la biblioteca Examination para generar `toString`. +Examination se ha eliminado por completo de Adventure y ya no es una dependencia transitiva. + +El módulo `adventure-text-logger-slf4j` se ha actualizado para usar SLF4J 2.0. + +La biblioteca GSON se ha actualizado a 2.13.2. +Aunque esta versión es posterior a la que se usa en la mayoría de las versiones de Minecraft compatibles con Adventure, no tenemos intención de dejar de admitir esas versiones antiguas. +Procuraremos no usar funciones nuevas de GSON que interrumpan la compatibilidad con las versiones antiguas de GSON usadas en versiones anteriores de Minecraft. + +## Cambios incompatibles + +### Cambios en los eventos de clic + +La clase `ClickEvent` ahora es una interfaz tipada. +El argumento de tipo de este evento de clic es el tipo de carga. +Esto no cambia la forma de construir eventos de clic, pero facilita la serialización y la deserialización. + +Este cambio también se aplica a `ClickEvent$Action`, que ya no es un enum, sino una interfaz tipada. + +Además, el campo `nbt` de las cargas personalizadas de eventos de clic ahora admite valores nulos. +Esto permite crear eventos de clic personalizados sin NBT y se ajusta mejor al comportamiento de Minecraft vanilla. + +### Cambios en el renderizador de componentes + +Con la incorporación del nuevo componente de objeto, la interfaz `AbstractComponentRenderer` se ha actualizado para incluir un método que renderiza componentes de objeto. +Este es un cambio incompatible, ya que será necesario implementar el método. +En adelante, añadiremos métodos a esta clase cada vez que Mojang incorpore nuevos tipos de componentes. +Este cambio incompatible se documenta en los Javadocs de `AbstractComponentRenderer`. + +### Sellado de la interfaz `TextFormat` + +Aunque nunca se recomendó extender `TextFormat`, antes era posible hacerlo. +La API ya no lo permite y la interfaz ahora es sellada. +Si extendías esta interfaz, considera extender `StyleBuilderApplicable`, una alternativa más potente y ampliamente utilizada. + +### Cambios en los tipos de chat + +Debido a cambios en el sistema de chat, especialmente en la creación de tipos de chat dinámicos, es posible que los tipos de chat no tengan una clave. +Por este cambio interno, `ChatType#key` ahora admite valores nulos. +Además, la clase ya no implementa `Keyed`. + +## Eliminación de métodos y clases obsoletos + +Se han marcado como obsoletos varios métodos y clases a lo largo de la serie Adventure 4.x. +En esta sección se documentan las eliminaciones realizadas y cómo puedes migrar el código, si corresponde. + +* **Se ha eliminado `BuildableComponent`.**\ + Ahora puedes obtener un `ComponentBuilder` directamente de un `Component` mediante `Component#toBuilder`. + Un efecto incompatible de este cambio es que `NBTComponent` ahora solo acepta un argumento de tipo, en lugar de dos. +* **Se han eliminado los métodos antiguos para firmar o identificar mensajes de chat.**\ + Aunque las versiones antiguas todavía usan estas funciones, su uso no era lo bastante extendido como para justificar que siguieran en Adventure. + En general, si tienes previsto enviar mensajes identificados o de chat, debes migrar a los mensajes firmados. + * **Se ha eliminado por completo el enum `MessageType`.**\ + Ahora los mensajes de chat se identifican al enviar un mensaje firmado. + Todos los demás mensajes son mensajes del sistema. + * **Se han eliminado todos los métodos `Audience#sendMessage` que aceptan `Identity` o `Identified`.**\ + En su lugar, es preferible enviar mensajes firmados. +* **Se ha eliminado el porcentaje de la barra de jefe.**\ + Esto incluye las constantes de porcentaje máximo y mínimo y los métodos para cambiar u obtener el porcentaje. + En su lugar, debes usar las constantes y los métodos de progreso. +* **Se han eliminado los métodos estáticos del estilo `of`.**\ + Estos métodos llevaban tiempo marcados como obsoletos y cada uno tiene alternativas con nombre. +* **Se han eliminado los datos de carga personalizados de eventos de clic.**\ + Como las cargas personalizadas de clic contienen NBT, debes usar el método `nbt`. + Esto incluye los métodos constructores de eventos de clic personalizados que aceptan cadenas en lugar de NBT. +* **Se ha eliminado `ClickEvent#create(Action, String)`.**\ + Como los eventos de clic ahora pueden contener datos distintos de cadenas, se ha eliminado este método. + Si lo usabas, migra al método `create` que acepta una carga o usa los métodos de construcción directa (por ejemplo, `ClickEvent#openUrl(String)`). +* **Se ha eliminado `ClickEvent#value`.**\ + Como se ha indicado, los eventos de clic ahora pueden contener datos distintos de cadenas. + Por tanto, este método se ha eliminado en favor del método `payload`. +* **Se ha eliminado `AbstractComponent`.**\ + Como esta clase era principalmente un detalle de implementación, se ha eliminado sin reemplazo. +* **Se ha eliminado la combinación de componentes sin constructor.**\ + Esto incluye la familia de métodos `Component#join` que no acepta un `JoinConfiguration`. + En su lugar, debes usar `Component#textOfChildren` o los métodos `join` que aceptan un `JoinConfiguration`. +* **Se ha eliminado `Component#detectCycle(Component)`.**\ + Como los componentes son inmutables, este método no es necesario y se ha eliminado sin reemplazo. +* **Se ha eliminado el reemplazo de texto de componentes sin constructor.**\ + Esto incluye la familia de métodos `Component#replace[First]Text` que no acepta un `TextReplacementConfig`. + En su lugar, debes usar los métodos `replaceText` que aceptan un `TextReplacementConfig`. +* **Se ha eliminado `TranslationRegistry`.**\ + Los registros se han reemplazado por `TranslationStore`, que ofrece más funciones. + Consulta los métodos estáticos de `TranslationStore` para encontrar una alternativa compatible. +* **Se ha eliminado `JSONComponentConstants`.**\ + Se ha reemplazado por `ComponentTreeConstants`, del módulo `adventure-text-serializer-commons`. +* **Se ha eliminado `PlainComponentSerializer`.**\ + Se ha reemplazado por la clase equivalente `PlainTextComponentSerializer`. +* **Se ha eliminado `ClickEvent$Action#payloadType`.**\ + Como las acciones de eventos de clic ahora están tipadas, este campo ya no es necesario. +* **Se ha eliminado `UTF8ResourceBundleControl`.**\ + Desde Java 9, los paquetes de recursos se cargan con UTF-8 de forma predeterminada. + Por tanto, esta clase ya no es necesaria. + En lugar de esta clase, puedes cargar archivos de propiedades sin un control de paquetes de recursos. +* **Se han eliminado métodos de `GSONComponentSerializer`.**\ + Desde que se añadió el sistema de opciones para personalizar los serializadores JSON, se eliminaron las opciones `downsampleColors` y `emitLegacyHoverEvent` de `GSONComponentSerializer`. + En su lugar, debes usar los campos `EMIT_RGB` y `EMIT_HOVER_EVENT_TYPE` de `JSONOptions`, respectivamente. + Además, se eliminó `legacyHoverEventSerializer`, que acepta un `LegacyHoverEventSerializer` del módulo GSON, en favor de la alternativa genérica del módulo JSON. +* **Se han corregido errores tipográficos.**\ + Se han eliminado algunos métodos con nombres mal escritos, como `Argument#numeric` y `ComponentSerializer#deseializeOrNull`. + Estos métodos estaban obsoletos y sus alternativas con la ortografía correcta ya estaban disponibles desde hacía tiempo. diff --git a/src/content/docs/es/adventure/migration/bungeecord-chat-api.md b/src/content/docs/es/adventure/migration/bungeecord-chat-api.md new file mode 100644 index 000000000..b26e3d4fd --- /dev/null +++ b/src/content/docs/es/adventure/migration/bungeecord-chat-api.md @@ -0,0 +1,145 @@ +--- +title: Migrar desde la API de chat de BungeeCord +slug: es/adventure/migration/bungeecord-chat-api +description: Migración de la API de chat de BungeeCord a la API de Adventure. +--- + +La API de texto de Adventure y la API de chat de BungeeCord se diseñaron con metodologías muy +distintas. Esta página repasa algunas diferencias importantes. + +## Audiencias + +Te recomendamos encarecidamente leer primero sobre las [audiencias](/es/adventure/audiences). A diferencia de BungeeCord, +que limita las funciones a tipos de usuario específicos, Adventure solo permite realizar +las operaciones aplicables a cada audiencia. + +## Decoración y estilos + +La API de chat de BungeeCord almacena todas las decoraciones en `BaseComponent`. Adventure separa +los estilos en su propia clase `Style`. + +BungeeCord permite combinar los estilos de un componente con otro. Adventure ofrece +métodos equivalentes para combinar estilos, o permite reemplazar los estilos de un +componente por los de otro. + +## Colores del chat + +La jerarquía de colores y estilos del chat de Adventure difiere de la API `ChatColor` +de BungeeCord. Probablemente sea aquí donde se aprecie el contraste más marcado entre la API de Adventure y BungeeCord/Bukkit. + +### Alternativa a `ChatColor` + +Los equivalentes de `ChatColor` en Adventure se dividen en tres tipos: + +* Los tipos de formato (como `BOLD` o `ITALIC`) pertenecen a `TextDecoration` y se pueden establecer + en un componente o estilo mediante el método `decoration`. Las decoraciones también usan un valor de tres estados + para indicar si están activadas, desactivadas o sin definir (en cuyo caso el componente hereda + el ajuste de su componente padre). +* Los colores con nombre (también llamados códigos de color antiguos de Mojang) ahora pertenecen a la clase + `NamedTextColor`. +* Los colores RGB se crean mediante los métodos `TextColor.color()` (equivalentes al método + `ChatColor.of()` de la API `ChatColor` de BungeeCord 1.16). + +### No se pueden construir cadenas antiguas + +La API `ChatColor` de BungeeCord proviene de la API de Bukkit. A su vez, la API `ChatColor` de Bukkit +se remonta a los primeros días de Minecraft (Beta 1.0), cuando la forma habitual y aceptada de enviar +mensajes con formato al cliente consistía en concatenar cadenas especiales que le indicaban qué formato aplicar. Un mensaje +de chat con formato se enviaba al cliente de esta manera: + +```java +player.sendMessage(ChatColor.GREEN + "¡Hola a todos! " + ChatColor.BOLD + "Este mensaje está en verde y negrita" + ChatColor.RESET + ChatColor.GREEN + "!"); +``` + +Esta forma de enviar mensajes ha perdurado hasta hoy, incluso después de que Mojang introdujera componentes de chat enriquecido +en Minecraft 1.7.2. Bukkit conservó este comportamiento por compatibilidad con versiones anteriores, y BungeeCord incorporó el +cambio para ser compatible con la clase `ChatColor` de Bukkit. + +En Adventure, no puedes concatenar códigos de formato especiales. El equivalente de `ChatColor` en Adventure, +`TextColor`, devuelve texto descriptivo sobre el color cuando se llama a `toString()`. La +alternativa recomendada es convertir todos los mensajes antiguos en componentes. + +### `ChatColor.stripColor()` + +`ChatColor.stripColor()` no existe en Adventure. Una alternativa sería usar +`PlainTextComponentSerializer.plainText().serialize(LegacyComponentSerializer.legacySection().deserialize(input))`. + +### `ChatColor.translateAlternateColorCodes()` + +`ChatColor.translateAlternateColorCodes()` no existe en Adventure. En su lugar, al deserializar una +cadena antigua debes usar `LegacyComponentSerializer.legacy(altChar).deserialize(input)`. + +## Diferencias en `ComponentBuilder` + +`ComponentBuilder` de BungeeCord trata cada componente de forma independiente y permite +transferir manualmente los estilos de un componente anterior. Adventure dispone de varios +constructores de componentes. El equivalente más cercano a `ComponentBuilder` de BungeeCord es +añadir componentes a un componente vacío de nivel superior usando `Component.text()` +como base. Para reproducir el comportamiento de `ComponentBuilder`, puedes hacer lo siguiente: + +* Usa la clase `Style` para almacenar estilos comunes y los métodos `mergeStyle` y `style` + para combinar y reemplazar estilos en un componente. +* Usa el constructor `TextComponent` de Adventure para crear un componente a la vez y + luego añádelo a un constructor de componentes de texto vacío de nivel superior. + +Por ejemplo, este componente de BungeeCord: + +```java +new ComponentBuilder("hola") + .color(ChatColor.GOLD) + .append(" mundo", FormatRetention.NONE) + .build() +``` + +se convierte en este equivalente de Adventure: + +```java +Component.text() + .append(Component.text("hola", NamedTextColor.GOLD)) + .append(Component.text(" mundo")) + .build() +``` + +Del mismo modo, + +```java +new ComponentBuilder("hola") + .color(ChatColor.GOLD) + .bold(true) + .append(" mundo") + .build() +``` + +se convierte en + +```java +final Style style = Style.style(NamedTextColor.GOLD, TextDecoration.BOLD); +Component.text() + .append(Component.text("hola", style)) + .append(Component.text(" mundo", style)) + .build() +``` + +## Inmutabilidad + +En la API de chat de BungeeCord, todos los componentes son mutables. En cambio, los componentes de texto +de Adventure son inmutables: cualquier intento de modificar un componente crea uno nuevo, +que es una copia del original con el cambio solicitado. + +## Serializadores + +La API de chat de BungeeCord incluye tres serializadores. Los tres tienen equivalentes en Adventure: + +* El método de deserialización `TextComponent.fromLegacyText()` equivale al método + `deserialize` del serializador de texto [antiguo](/es/adventure/serializer/legacy). Del mismo modo, el método de serialización + `BaseComponent.toLegacyText()` equivale al método `serialize` del serializador de texto antiguo. +* El método de serialización `TextComponent.toPlainText()` equivale al método + `serialize` del serializador de texto [sin formato](/es/adventure/serializer/plain). Se puede crear un componente + a partir de una cadena de texto sin formato mediante `Component.text(string)`. +* El equivalente de Adventure a `ComponentSerializer` es el serializador de texto [Gson](/es/adventure/serializer/gson). + +## Compatibilidad con versiones anteriores + +`BungeeCordComponentSerializer` permite convertir componentes de Adventure ([Component](/es/adventure/text)) +a la API nativa de componentes de chat de BungeeCord y viceversa. Se puede usar cuando no hay +compatibilidad nativa con la plataforma. El serializador está disponible en el artefacto `adventure-platform-text-serializer-bungeecord`. diff --git a/src/content/docs/es/adventure/migration/index.md b/src/content/docs/es/adventure/migration/index.md new file mode 100644 index 000000000..29308e1fb --- /dev/null +++ b/src/content/docs/es/adventure/migration/index.md @@ -0,0 +1,29 @@ +--- +title: Migración +slug: es/adventure/migration +description: Actualización a la versión más reciente de Adventure. +tableOfContents: false +sidebar: + label: Resumen +--- + +Estas guías ofrecen consejos y alternativas útiles para migrar a la versión más reciente de Adventure. +Incluyen la migración desde versiones anteriores de Adventure y desde otras bibliotecas. + +* [Migrar de Adventure 4.x a 5.x](/es/adventure/migration/adventure-4.x) + * [Una base de código moderna](/es/adventure/migration/adventure-4.x#una-base-de-código-moderna) + * [Dependencias actualizadas](/es/adventure/migration/adventure-4.x#dependencias-actualizadas) + * [Cambios incompatibles](/es/adventure/migration/adventure-4.x#cambios-incompatibles) + * [Eliminación de métodos y clases obsoletos](/es/adventure/migration/adventure-4.x#eliminación-de-métodos-y-clases-obsoletos) +* [Migrar desde la API de chat de BungeeCord](/es/adventure/migration/bungeecord-chat-api) + * [Audiencias](/es/adventure/migration/bungeecord-chat-api#audiencias) + * [Decoración y estilos](/es/adventure/migration/bungeecord-chat-api#decoración-y-estilos) + * [Colores del chat](/es/adventure/migration/bungeecord-chat-api#colores-del-chat) + * [Diferencias en `ComponentBuilder`](/es/adventure/migration/bungeecord-chat-api#diferencias-en-componentbuilder) + * [Inmutabilidad](/es/adventure/migration/bungeecord-chat-api#inmutabilidad) + * [Serializadores](/es/adventure/migration/bungeecord-chat-api#serializadores) + * [Compatibilidad con versiones anteriores](/es/adventure/migration/bungeecord-chat-api#compatibilidad-con-versiones-anteriores) +* [Migrar desde text 3.x](/es/adventure/migration/text-3.x) + * [Una advertencia](/es/adventure/migration/text-3.x#una-advertencia) + * [Cambios incompatibles de text 3.x](/es/adventure/migration/text-3.x#cambios-incompatibles-de-text-3x) + * [Serializador](/es/adventure/migration/text-3.x#serializador) diff --git a/src/content/docs/es/adventure/migration/text-3.x.md b/src/content/docs/es/adventure/migration/text-3.x.md new file mode 100644 index 000000000..7e3c8365a --- /dev/null +++ b/src/content/docs/es/adventure/migration/text-3.x.md @@ -0,0 +1,60 @@ +--- +title: Migrar desde text 3.x +slug: es/adventure/migration/text-3.x +description: Migración de text 3.x a Adventure. +--- + +Adventure es una evolución de la API text 3.x. Si ya has trabajado con +la API text, el cambio a Adventure debería ser relativamente rápido. +En general, solo tendrás que añadir como dependencia la API de Adventure +y la [plataforma](/es/adventure/platform) correspondiente, y reemplazar las referencias +a las clases de `net.kyori.text` por `net.kyori.adventure.text`. No obstante, consulta +a continuación los principales cambios incompatibles. + +## Una advertencia + +Antes de continuar, te recomendamos encarecidamente leer sobre las +[audiencias](/es/adventure/audiences). A diferencia de text, Adventure define una interfaz estándar para +enviar contenido (incluidos mensajes de chat) a los destinatarios. Además, Adventure +define interfaces para otras mecánicas de juego que se pueden enviar a los jugadores de forma arbitraria. + +## Cambios incompatibles de text 3.x + +### Cambio de nombre de los métodos de fábrica +En text 3.x, los componentes se podían crear con métodos `Component.of()`. +En Adventure, usamos métodos del tipo `Component.(/*...*/)` para facilitar +las importaciones estáticas. + +Del mismo modo, `Style.of(/*...*/)` cambia a `Style.style(/*...*/)` . + +### `.builder()` +Los constructores ahora se crean llamando sin parámetros a los métodos de fábrica mencionados. +Por ejemplo, `TextComponent.builder()` pasa a ser `Component.text()`. + +Ten en cuenta que el equivalente de `TextComponent.builder("hello")` es `Component.text().content("hello")`. + +### `.append()` con un argumento String +Los constructores de componentes de 3.x ofrecían una forma abreviada de añadir un componente de texto: `builder.append("wow")`. +En Adventure debes escribirlo completo: en este caso, `builder.append(Component.text("wow"))`. + +### `LegacyComponentSerializer` + +En text 3.x, para deserializar un componente que usara un prefijo de código de color distinto del símbolo de sección habitual, se usaba `LegacyComponentSerializer.legacy().deserialize(string, altChar)`. +En Adventure, debes usar `LegacyComponentSerializer.legacy(altChar).deserialize(string)`. + +Para crear un serializador que convierta los enlaces, debes usar el constructor. +Cambia `LegacyComponentSerializer.legacyLinking(style)` +por `LegacyComponentSerializer.builder().extractUrl(style).build()`. + +### Cambio de nombre de `TextColor` a `NamedTextColor` + +Para admitir los nuevos colores RGB introducidos en 1.16, todos los colores de texto con nombre +se trasladaron a la clase `NamedTextColor`. Actualiza las referencias a la antigua clase `TextColor` +para que apunten a `NamedTextColor`. + +## Serializador + +Si necesitas interoperar con clientes que usan la antigua API text 3.x, puedes +usar el artefacto `adventure-text-serializer-legacy-text3`, que incluye +`LegacyText3ComponentSerializer` para convertir componentes de Adventure a text 3.x +y viceversa. Ten en cuenta que los colores RGB se reducirán a una paleta compatible. diff --git a/src/content/docs/es/adventure/minimessage/api.mdx b/src/content/docs/es/adventure/minimessage/api.mdx new file mode 100644 index 000000000..a68208105 --- /dev/null +++ b/src/content/docs/es/adventure/minimessage/api.mdx @@ -0,0 +1,239 @@ +--- +title: API de MiniMessage +slug: es/adventure/minimessage/api +description: Guía para usar MiniMessage en tu código. +--- + +import Dependency from "/src/components/Dependency.astro"; +import { LATEST_ADVENTURE_API_RELEASE } from "/src/utils/versions"; + +## Dependencia + +Declaración de la dependencia: + + + +:::note + +Algunas plataformas ya proporcionan MiniMessage de forma nativa. En ese caso, no es necesario añadir MiniMessage como dependencia. + +::: + +## Primeros pasos + +MiniMessage ofrece una API sencilla mediante la clase `MiniMessage`. + +Se puede obtener una instancia estándar del serializador mediante el método `miniMessage()`. Usa el conjunto predeterminado de etiquetas y no está en modo estricto. + +MiniMessage se puede personalizar más mediante el [constructor](#constructor). + +MiniMessage permite serializar componentes como cadenas MiniMessage y analizar o deserializar cadenas MiniMessage para convertirlas en componentes. + +A continuación se muestra un breve ejemplo para probarlo: + +```java +final Audience player = ...; +final MiniMessage mm = MiniMessage.miniMessage(); + +final Component parsed = mm.deserialize("Hola mundo, ¿no es divertido MiniMessage?"); + +player.sendMessage(parsed); +``` + +Para usos más avanzados, se pueden registrar resolvedores de etiquetas adicionales, que generarán una instancia `Tag` al recibir el nombre de una etiqueta y sus argumentos. Se describen con más detalle a continuación. + +### Preajustes + +MiniMessage también proporciona un conjunto de preajustes que se pueden usar en lugar de la instancia principal de MiniMessage. +Estos preajustes permiten a los desarrolladores evitar fácilmente que los usuarios usen por accidente funciones de componentes susceptibles de abuso, como el evento de clic para ejecutar comandos. + +A continuación se muestra una lista de los preajustes disponibles y sus funciones: +* **`DEFAULT`**\ + El preajuste predeterminado, que incluye todas las funciones de MiniMessage. + Equivale a `MiniMessage.miniMessage()`. +* **`NON_INTERACTABLE`**\ + Un preajuste que desactiva todas las funciones de componentes que permiten la interacción. + Incluye eventos de clic, eventos de desplazamiento e inserción de texto. + También incluye un posprocesador personalizado que elimina del componente resultante cualquier elemento interactivo. + Por tanto, también se puede usar con resolvedores de etiquetas personalizados que podrían generar componentes interactivos. +* **`FORMATTED_TEXT`**\ + Un preajuste que solo permite componentes de texto y el formato asociado. + Incluye color, sombra, fuente y decoración de texto (por ejemplo, negrita y cursiva). + También incluye un posprocesador personalizado que elimina del componente resultante cualquier componente que no sea de texto o elemento interactivo. + Por tanto, también se puede usar con resolvedores de etiquetas personalizados. + +```java +// Puedes obtener una instancia de MiniMessage preconfigurada con cualquiera de los preajustes. +final MiniMessage miniMessage = MiniMessage.miniMessage(MiniMessage.Preset.NON_INTERACTABLE); + +// Como alternativa, puedes obtener un constructor preconfigurado... +final MiniMessage.Builder builder = MiniMessage.builder(MiniMessage.Preset.NON_INTERACTABLE); + +// ...y añadir tus propias etiquetas o cambiar otros ajustes si hace falta... +builder.editTags(tags -> { + tags + .resolver(new MyCustomTagResolver()) + .resolver(fetchExternalTags()); +}); + +// ...y, por último, crear tu instancia de MiniMessage. +final MiniMessage myCustomMiniMessageInstance = builder.build(); +``` + +### Constructor + +Para facilitar la personalización de MiniMessage, ofrecemos un constructor. Los métodos específicos se explican en los Javadocs. + +```java +final MiniMessage mm = MiniMessage.builder() + .tags(TagResolver.builder() + .resolver(StandardTags.color()) + .resolver(StandardTags.decorations()) + .resolver(this.someResolvers) + .build() + ) + .build(); +``` + +:::tip + +Es recomendable inicializar una instancia de MiniMessage una sola vez en un lugar central y usarla para todos los mensajes. +La excepción sería que quisieras personalizar MiniMessage en función de los permisos del usuario (por ejemplo, permitir que los administradores usen colores y decoraciones en sus mensajes, pero no los usuarios normales). + +::: + +### Gestión de errores + +De forma predeterminada, MiniMessage nunca lanza una excepción causada por la entrada del usuario. En su lugar, trata las etiquetas no válidas como texto normal. El modo `MiniMessage.Builder#strict(true)` habilita el modo estricto, +que lanza excepciones cuando hay etiquetas sin cerrar, pero sigue permitiendo las etiquetas especificadas incorrectamente. + +Para obtener información sobre los motivos por los que puede haber fallado el análisis, se puede proporcionar `MiniMessage.Builder#debug(Consumer)`, que recibirá los mensajes de depuración de una cadena de entrada. + + +## Resolvedores de etiquetas + +Toda resolución de etiquetas pasa por resolvedores de etiquetas. Hay un resolvedor global que describe las etiquetas disponibles en una instancia de `MiniMessage`, además de resolvedores específicos de cada análisis que pueden proporcionar etiquetas adicionales para una entrada concreta. + +Los resolvedores de etiquetas vinculan un nombre y sus argumentos con la lógica que genera el `Component` contenido en una instancia `Tag`. Se pueden combinar, por lo que un `TagResolver` puede generar cualquier cantidad de instancias `Tag`. El nombre de etiqueta que reciben los resolvedores siempre estará en minúsculas para que las búsquedas no distingan entre mayúsculas y minúsculas. + +Los nombres de etiquetas solo pueden contener los caracteres a-z, 0-9, `_` y `-`. Además, pueden empezar opcionalmente por cualquiera de estos caracteres: `!?#`. + +Puedes crear tu propio `TagResolver` mediante los métodos de fábrica estáticos de `TagResolver`. Para reemplazar etiquetas dinámicamente por texto, MiniMessage incluye `Placeholder` y `Formatter`. +Siempre que sea posible, conviene usar estos resolvedores integrados, ya que MiniMessage puede aplanar sus combinaciones para obtener un formato más eficiente. +Consulta [aquí](/es/adventure/minimessage/dynamic-replacements) los reemplazos dinámicos integrados. + +Para combinar varios resolvedores, consulta el constructor de resolvedores de etiquetas: `TagResolver.builder()`. + +El constructor de `MiniMessage` permite proporcionar un resolvedor de etiquetas personalizado en lugar del predeterminado (`StandardTags.all()`). + +MiniMessage también ofrece métodos de conveniencia para hacerlo: + +```java +final MiniMessage serializer = MiniMessage.builder() + .tags(TagResolver.builder() + .resolver(StandardTags.color()) + .build() + ) + .build(); + +Component parsed = serializer.deserialize("Hola"); + +// La aserción se cumple. +assertEquals(Component.text("Hola", NamedTextColor.GREEN), parsed); +``` + +Como la etiqueta `` no está habilitada en este constructor, se interpreta como texto literal. + +### Gestionar argumentos + +Los resolvedores de etiquetas reciben un parámetro `ArgumentQueue`, que proporciona los argumentos de etiqueta presentes en la entrada. Los métodos auxiliares de `Tag.Argument` pueden facilitar la conversión de la etiqueta. + +Las excepciones que lanzan los métodos `popOr()` interrumpen la ejecución, pero por ahora solo se exponen a los usuarios en la salida de depuración. Tenemos previsto añadir una función de autocompletado que pueda +mostrar parte de esta información al usuario; por eso, procura redactar mensajes de error útiles en los resolvedores de etiquetas personalizados. + +## Etiquetas + +Una vez que un resolvedor de etiquetas ha procesado los argumentos, devuelve un objeto `Tag`. Estos objetos implementan la lógica para generar o modificar un árbol de componentes. Hay tres tipos principales de `Tag`; todas las implementaciones personalizadas deben implementar una de estas interfaces. + +### Preprocesamiento + +Estas etiquetas implementan la interfaz `PreProcess` y contienen una cadena MiniMessage sin procesar que se inserta en la entrada del usuario antes de continuar con el análisis. + +Debido a las limitaciones de la implementación actual del analizador, ten en cuenta que las etiquetas de preprocesamiento alteran los desplazamientos de los mensajes de error y pueden impedir el autocompletado. Sin embargo, actualmente son la única forma de integrar fragmentos de marcado en un mensaje. + +### Inserción + +Estas etiquetas son bastante sencillas: representan un `Component` literal. La mayoría de las implementaciones de `Tag` deberían +ser etiquetas `Inserting`. Estas etiquetas también pueden ser autocerradas opcionalmente; de forma predeterminada, solo ocurre con las etiquetas creadas por `Placeholder.unparsed(String)` y `Placeholder.component(Component)`, +para que los marcadores de posición sean autónomos. + +La mayoría de las `etiquetas estándar <./format>` son `Inserting`. Estas etiquetas insertan directamente un componente o usan el método auxiliar `Tag.styling(StyleBuilderApplicable...)` para aplicar estilos a los componentes. + +Este método auxiliar permite aplicar de forma eficiente una colección de estilos con una sola etiqueta. Por ejemplo, para crear una etiqueta `Título` que convierta ese texto en un enlace que abra una URL con el estilo tradicional de los enlaces, se puede usar lo siguiente: + +```java +Component aTagExample() { + final String input = "Hola, ¡haz clic aquí!, pero no aquí."; + final MiniMessage extendedInstance = MiniMessage.builder() + .editTags(b -> b.tag("a", MiniMessageTest::createA)) + .build(); + + return extendedInstance.deserialize(input); +} + +static Tag createA(final ArgumentQueue args, final Context ctx) { + final String link = args.popOr("La etiqueta requiere exactamente un argumento: el enlace que se abrirá").value(); + + return Tag.styling( + NamedTextColor.BLUE, + TextDecoration.UNDERLINED, + ClickEvent.openUrl(link), + HoverEvent.showText(Component.text("Abrir " + link)) + ); +} +``` + +Esto permite generar estilos enriquecidos con relativa rapidez. + + +### Modificación + +Las etiquetas de modificación son las más complejas y especializadas. Reciben el árbol de nodos y pueden analizarlo antes de +crear los componentes; después reciben cada componente secundario generado y pueden modificarlo. Se usan para las etiquetas integradas `` y ``, +pero también sirven para transformaciones complejas similares. + +Primero, las etiquetas de modificación pueden recorrer cada nodo del árbol en profundidad. Si una instancia `Modifying` almacena estado durante este recorrido, su resolvedor debe devolver una instancia nueva cada vez para evitar que se corrompa el estado. + +:::note + +La API `Node` de 4.10.0 todavía no está muy desarrollada: la mayoría de sus elementos siguen siendo internos. Se puede exponer información adicional según las necesidades de quienes desarrollen etiquetas. + +::: + +Una vez recorrido todo el árbol de análisis, se llama al método `postVisit()`. Se puede sobrescribir opcionalmente si es necesario realizar cálculos adicionales. + +A continuación, la instancia `Modifying` entra en la fase de aplicación, en la que se presenta el árbol de componentes a la etiqueta para su transformación. Esto permite que la etiqueta *modifique* el contenido de los componentes, de ahí su nombre. + +### Directivas del analizador + +Las directivas del analizador son un tipo especial de etiqueta: son instrucciones para el analizador y, por tanto, los usuarios finales no pueden implementarlas. + +Actualmente solo hay una, pero se pueden añadir más en cualquier momento. + +| Directiva | Descripción | +|-----------|----------------------------------------------------------------------------------| +| RESET | Indica al analizador que esta etiqueta debe cerrar todas las etiquetas que estén abiertas. | + +Esto permite ofrecer la funcionalidad de una etiqueta `` con otro nombre. Por ejemplo: + +```java +final var clearTag = TagResolver.resolver("clear", ParserDirective.RESET); + +final var parser = MiniMessage.builder() + .editTags(t -> t.resolver(clearTag)) + .build(); + +final Component parsed = parser.deserialize("hola mundo, ¿cómo estás?"); +``` + +Este código añade una etiqueta `` que se comporta igual que la etiqueta `` predeterminada: el texto `, ¿cómo estás?` no aparecería en negrita ni en rojo. diff --git a/src/content/docs/es/adventure/minimessage/dynamic-replacements.md b/src/content/docs/es/adventure/minimessage/dynamic-replacements.md new file mode 100644 index 000000000..e88961bfb --- /dev/null +++ b/src/content/docs/es/adventure/minimessage/dynamic-replacements.md @@ -0,0 +1,150 @@ +--- +title: Reemplazos dinámicos +slug: es/adventure/minimessage/dynamic-replacements +description: Guía sobre los resolvedores de etiquetas. +--- + +MiniMessage incluye algunos `TagResolver` que pueden reemplazar etiquetas dinámicamente durante el análisis. Estos resolvedores pueden sustituir una etiqueta por contenido dinámico, como una cadena o un número con formato. + +## Marcadores de posición + +Los marcadores de posición sustituyen la etiqueta por un texto concreto. Son los reemplazos más básicos: + +### Insertar un componente + +Puedes insertar directamente un componente para la etiqueta mediante el marcador de posición de componente. + +```java +MiniMessage.miniMessage().deserialize("Hola :)", Placeholder.component("name", Component.text("PRUEBA", NamedTextColor.RED))); +``` + +Esto insertará el componente de texto rojo «PRUEBA» en la posición de la etiqueta. + +### Insertar texto sin analizar + +A veces es mejor no analizar texto dinámico, como las entradas de usuario. Para esos casos, MiniMessage proporciona el marcador de posición sin analizar. +Este método permite sanear la entrada del usuario sin tener que escapar directamente las etiquetas. + +```java +MiniMessage.miniMessage().deserialize("Hola ", Placeholder.unparsed("name", "PRUEBA :)")); +``` + +Esto insertará el texto sin analizarlo. El resultado será texto gris con `Hola PRUEBA :)`. + +### Insertar y analizar texto + +Si quieres insertar texto y permitir que MiniMessage analice las etiquetas, puedes usar el marcador de posición analizado. +Este marcador inserta el reemplazo antes de analizar la cadena. Las etiquetas del marcador pueden afectar al resultado analizado después del marcador. + +```java +MiniMessage.miniMessage().deserialize("Hola :)", Placeholder.parsed("name", "PRUEBA")); +// Devuelve Component.text("Hola ", NamedTextColor.GRAY).append(Component.text("PRUEBA :)", NamedTextColor.RED)); +``` + +Esto insertará y analizará el texto. + +### Insertar un estilo + +Si quieres crear tu propia etiqueta de estilo, puedes usar el marcador de posición de estilo. + +```java +MiniMessage.miniMessage().deserialize("Hola :) ¿Cómo estás?", + Placeholder.styling("my_style", ClickEvent.suggestCommand("/say hello"), NamedTextColor.RED, TextDecoration.BOLD)); +// Aplicará al texto un evento de clic, el color rojo y la decoración en negrita. +``` + +Esto insertará el estilo con un evento de clic y texto rojo. Los marcadores de posición de estilo se pueden usar con cualquier estilo, como colores, decoraciones de texto y eventos. + +Crear etiquetas de estilo propias: + +```java +Placeholder.styling("fancy", TextColor.color(150, 200, 150)); // Cambiará el color del texto entre "" y "". +Placeholder.styling("my_hover", HoverEvent.showText(Component.text("prueba"))); // Mostrará el texto personalizado al pasar el cursor. +Placeholder.styling("my_cmd", ClickEvent.runCommand("/mycmd es genial")); // Creará un texto en el que se puede hacer clic para ejecutar el comando indicado. +``` + +:::tip + +Los marcadores de posición de estilo se pueden usar para sanear la entrada de los jugadores en eventos de clic. En lugar de usar un marcador analizado, se puede usar la cadena directamente. + +::: + + +## Formateadores + +No todo es texto; a veces resulta útil mostrar un número o una fecha. +Para ello, puedes usar los formateadores que proporciona MiniMessage. + +### Insertar un número + +Puedes insertar un `Number` usando el formateador numérico de MiniMessage. + +Para especificar la configuración regional y el formato del número, el formateador acepta argumentos opcionales de etiqueta. +Puedes especificar la configuración regional y el formato numérico. Es posible pasar ambos como argumentos de la etiqueta, pero debes indicar primero la configuración regional. + +```java +MiniMessage.miniMessage().deserialize("Hola, mi número es .", Formatter.number("no", 250.25)); +MiniMessage.miniMessage().deserialize("Hola, mi número es .", Formatter.number("no", 250.25)); +MiniMessage.miniMessage().deserialize("Hola, mi número es .", Formatter.number("no", 250.25)); +MiniMessage.miniMessage().deserialize("Hola, mi número es .", Formatter.number("no", 250.25)); +``` + +Todos estos ejemplos son válidos e insertarán el número como etiqueta. + +Consulta `Locale` y `DecimalFormat` para ver etiquetas de configuración regional válidas y patrones que se pueden usar. + +:::tip + +Puedes cambiar el estilo, como el color, mediante un patrón más complejo: + +```java +MiniMessage.miniMessage().deserialize("Tu saldo actual es #.00;-#.00'>.", Formatter.number("no", 250.25)); +``` + +Esto mostrará el saldo en rojo si es negativo; de lo contrario, el número aparecerá en verde. + +::: + + +### Insertar una fecha + +Para insertar una instancia de `TemporalAccessor`, como `LocalDateTime`, puedes usar el formateador de fechas. + +El resolvedor de etiquetas requiere un argumento de etiqueta para el formato. Consulta `DateTimeFormatter` para ver patrones válidos. + +```java +MiniMessage.miniMessage().deserialize("La fecha actual es: .", Formatter.date("date", LocalDateTime.now(ZoneId.systemDefault())); +``` + +Esto mostrará la fecha actual con el formato especificado, por ejemplo, `2022-05-27 11:30:25`. + +### Insertar una opción + +Para insertar un número y dar formato a un texto según su valor, puedes usar el formateador de opciones. + +Este formateador acepta un patrón `ChoiceFormat`. + +```java +MiniMessage.miniMessage().deserialize("Conocí a .", Formatter.choice("choice", 5)); +``` + +Esto dará formato a la entrada según el `ChoiceFormat` proporcionado. En este caso, el resultado será `Conocí a muchos desarrolladores.`. + + +## Marcadores de posición complejos + +Puedes crear tus propios marcadores de posición. Consulta las clases [Formatter](https://github.com/PaperMC/adventure/blob/main/5/text-minimessage/src/main/java/net/kyori/adventure/text/minimessage/tag/resolver/Formatter.java) y [Placeholder](https://github.com/PaperMC/adventure/blob/main/5/text-minimessage/src/main/java/net/kyori/adventure/text/minimessage/tag/resolver/Placeholder.java) de MiniMessage para ver ejemplos. + +### Ejemplos + +Crea una etiqueta personalizada que permita hacer clic en su contenido: + +```java replace +TagResolver.resolver("click_by_version", (args, context) -> { + final String version = args.popOr("se esperaba una versión").value(); + return Tag.styling(ClickEvent.openUrl("https://jd.papermc.io/adventure/" + version + "/")); +}); +// Crea una etiqueta para abrir los Javadocs de Adventure de la versión indicada: +``` + +Puedes crear tus propios marcadores de posición complejos con varios argumentos y lógica propia. diff --git a/src/content/docs/es/adventure/minimessage/format.mdx b/src/content/docs/es/adventure/minimessage/format.mdx new file mode 100644 index 000000000..665642ba8 --- /dev/null +++ b/src/content/docs/es/adventure/minimessage/format.mdx @@ -0,0 +1,578 @@ +--- +title: Formato +slug: es/adventure/minimessage/format +description: Documentación sobre el formato MiniMessage. +--- + +import { Image } from "astro:assets"; +import { Badge } from "@astrojs/starlight/components"; +import Shadow1 from "../../../adventure/minimessage/assets/shadow_1.png"; +import Shadow2 from "../../../adventure/minimessage/assets/shadow_2.png"; +import Shadow3 from "../../../adventure/minimessage/assets/shadow_3.png"; +import Color1 from "../../../adventure/minimessage/assets/color_1.png"; +import Color2 from "../../../adventure/minimessage/assets/color_2.png"; +import ColorVerbose1 from "../../../adventure/minimessage/assets/color_verbose_1.png"; +import ColorVerbose2 from "../../../adventure/minimessage/assets/color_verbose_2.png"; +import Decoration1 from "../../../adventure/minimessage/assets/decoration_1.png"; +import Reset1 from "../../../adventure/minimessage/assets/reset_1.png"; +import Click1 from "../../../adventure/minimessage/assets/click_1.png"; +import Hover1 from "../../../adventure/minimessage/assets/hover_1.png"; +import Hover2 from "../../../adventure/minimessage/assets/hover_2.png"; +import Key1 from "../../../adventure/minimessage/assets/key_1.png"; +import Translatable1 from "../../../adventure/minimessage/assets/translatable_1.png"; +import Translatable2 from "../../../adventure/minimessage/assets/translatable_2.png"; +import Insertion1 from "../../../adventure/minimessage/assets/insertion_1.png"; +import Rainbow1 from "../../../adventure/minimessage/assets/rainbow_1.png"; +import Gradient1 from "../../../adventure/minimessage/assets/gradient_1.png"; +import Transition1 from "../../../adventure/minimessage/assets/transition_1.png"; +import Font1 from "../../../adventure/minimessage/assets/font_1.png"; +import Newline1 from "../../../adventure/minimessage/assets/newline_1.png"; +import Selector1 from "../../../adventure/minimessage/assets/selector_1.png"; + +El lenguaje MiniMessage usa etiquetas. Todo lo que hagas se define mediante etiquetas. Las etiquetas tienen una etiqueta de apertura y otra de cierre (la etiqueta `` es una excepción). +Las etiquetas de apertura son obligatorias, pero las de cierre solo lo son en el modo `strict`. Los siguientes ejemplos se ven exactamente iguales: +```mm +Hola mundo. +Hola mundo. +Hola mundo. +``` + +Las etiquetas sin contenido se pueden cerrar automáticamente con el formato ``. Con este formato, ni siquiera en el modo estricto hay que proporcionar una etiqueta de cierre independiente. + +Los nombres de etiquetas no distinguen entre mayúsculas y minúsculas, para reducir la posibilidad de conflictos, pero recomendamos escribirlos siempre en minúsculas (o, como mínimo, ser coherentes). + +Algunas etiquetas tienen argumentos. Su formato es el siguiente: `content`. +Por ejemplo: +```mm +prueba:PRUEBA">PRUEBA +PRUEBA +``` + +Como puedes ver, a veces contienen componentes y otras veces solo números, cadenas u otros tipos. Consulta la documentación detallada a continuación. + +Se pueden intercambiar las comillas simples (`'`) y dobles (`"`). Recomendamos mantener la coherencia, aunque para reducir los escapes puede resultar conveniente cambiar el tipo de comillas en algunos argumentos. + +Se puede escapar cualquier token significativo en los lugares donde tenga efecto. En texto sin formato, los caracteres de apertura de etiqueta (`<`) se pueden escapar anteponiendo una barra invertida (`\`). Dentro de cadenas entre comillas, +se puede escapar el carácter de comillas de apertura (`'` o `"`). En ambos casos, se puede escapar el carácter de escape cuando tenga efecto. Por simplicidad, los argumentos de etiqueta sin comillas no admiten escapes. +En los lugares donde no se admiten escapes, el carácter de escape literal se conserva. En los lugares donde sí se admiten escapes, pero se quiere incluir un carácter de escape literal, se puede escapar ese carácter para producir una `\`. + +Las etiquetas predeterminadas intentan representar componentes de forma compatible con Vanilla, aunque simplifican algunos elementos. Puede resultar útil +consultar [Minecraft Wiki](https://minecraft.wiki/w/Text_component_format) como referencia del sistema de componentes de Vanilla, sobre todo +para elementos como las acciones y los valores de los eventos de clic y de desplazamiento. + +El [visor web de MiniMessage](https://webui.advntr.dev) permite probar texto MiniMessage localmente, sin tener que iniciar una instancia de Minecraft. +Mientras aprendes, puede ser útil copiar en el visor los ejemplos de esta documentación. + +## Modo estricto + +De forma predeterminada, MiniMessage es muy permisivo e ignora las etiquetas no válidas. Las etiquetas que queden abiertas al final de una cadena de entrada se cerrarán automáticamente. + +Las aplicaciones pueden habilitar el *modo estricto*, que prohíbe el uso de `` y exige que todas las etiquetas se cierren en el orden inverso al de apertura. Toda aplicación +que use MiniMessage debe indicar claramente a los usuarios finales qué variante del lenguaje se está usando. + +## Etiquetas estándar + +Estas son las etiquetas que MiniMessage incluye y habilita de forma predeterminada. Algunos analizadores de MiniMessage pueden añadir etiquetas personalizadas a esta lista o limitar las disponibles a un subconjunto. Consulta la documentación de la aplicación para obtener más detalles. + +### Color + +{/* spellchecker:off */} +Colorea las siguientes partes. + +Etiqueta + * `<_colorname_>` + +Argumentos + * `_colorname_`, cualquier constante de color de Minecraft: `black`, `dark_blue`, `dark_green`, `dark_aqua`, `dark_red`, `dark_purple`, `gold`, `gray`, `dark_gray`, `blue`, `green`, `aqua`, `red`, `light_purple`, `yellow` o `white`. + + + Se puede usar `dark_grey` en lugar de `dark_gray`, y también `grey` en lugar de `gray`. + También se admiten colores hexadecimales con el formato `#RRGGBB`. +{/* spellchecker:on */} + +Ejemplos +```mm +Hola mundo! +Esto es una prueba. +<#00ff00>R G B! +``` + +
+ +Resultado del análisis de `<yellow>Hola <blue>mundo</blue>!`, mostrado en la ventana de chat del cliente de Minecraft +Resultado del análisis de `<red>Esto es una <green>prueba.`, mostrado en la ventana de chat del cliente de Minecraft + +### Color (forma detallada) + +Una forma más detallada de definir colores. + +Etiqueta + * `` + +{/* spellchecker:off */} +Alias + * `colour`, `c` +{/* spellchecker:on */} + +Argumentos + * `_colorNameOrHex_`, puede ser cualquiera de los valores anteriores (colores con nombre o colores hexadecimales) + +Ejemplos +```mm +Hola mundo! +Esto es una prueba. +``` + +
+ +Resultado del análisis de `<color:yellow>Hola <color:blue>mundo</color:blue>!`, mostrado en la ventana de chat del cliente de Minecraft +Resultado del análisis de `<color:#FF5555>Esto es una <color:#55FF55>prueba.`, mostrado en la ventana de chat del cliente de Minecraft + +### Color de sombra + +Colorea la sombra de las siguientes partes. + +Etiqueta + * `` + * `` como alias para desactivar la sombra (equivalente a ``) + +Argumentos + * `_colorNameOrHex_`, un color con nombre o una cadena de color hexadecimal con el formato `#RRGGBB` o `#RRGGBBAA` + * `[alpha_as_float]`, un valor de punto flotante entre 0 y 1 que representa el valor alfa de la sombra. Es opcional y su valor predeterminado es 0.25. No tiene efecto si la cadena de color hexadecimal ya incluye un valor alfa. + +Ejemplos +```mm +Hola mundo! +Esto es una prueba. +Grueso +``` + +
+ +Resultado del análisis de `<shadow:yellow>Hola <shadow:aqua:0.5>mundo</shadow>!`, mostrado en la ventana de chat del cliente de Minecraft +Resultado del análisis de `<shadow:#FF5555>Esto es una <shadow:#55FF55>prueba.`, mostrado en la ventana de chat del cliente de Minecraft +Resultado del análisis de `<shadow:#000000FF><b>Grueso`, mostrado en la ventana de chat del cliente de Minecraft + +### Decoración + +Decora las siguientes partes. + +Etiqueta + * `<_decorationname_[:false]>` o `` como alias para invertir la decoración. + +Argumentos + * `_decorationname_`, cualquier decoración compatible con Minecraft: + +| Decoración | Alias | +| ----------------- | --------------- | +| `bold` | `b` | +| `italic` | `em` o `i` | +| `underlined` | `u` | +| `strikethrough` | `st` | +| `obfuscated` | `obf` | + +Ejemplos +```mm +Esto es importante. +``` + +
+Resultado del análisis de `<underlined>Esto es <bold>importante</bold>.`, mostrado en la ventana de chat del cliente de Minecraft + +### Reinicio + +Cierra todas las etiquetas abiertas y restablece el color, la decoración, etc. La etiqueta de reinicio no se puede cerrar. + +En el modo estricto, las etiquetas de reinicio están prohibidas. + +Etiqueta + * `` + +Argumentos + * ninguno + +Ejemplos +```mm +Hola mundo. +``` + +
+Resultado del análisis de `<yellow><bold>Hola <reset>mundo.`, mostrado en la ventana de chat del cliente de Minecraft + +### Clic + +Permite realizar varias acciones al hacer clic en el componente. + +Etiqueta + * `` + +Argumentos + * `_action_`, el tipo de evento de clic; debe ser uno de los elementos de [esta lista](jd:adventure:net.kyori.adventure.text.event.ClickEvent$Action#field-summary) + * `_value_`, el argumento de ese evento; consulta [Minecraft Wiki](https://minecraft.wiki/w/Text_component_format#Click_events) + +Ejemplos +```mm +Haz clic para ver la semilla del mundo. +Haz clic aquí para copiar tu puntuación. +``` + +
+Resultado del análisis de `<click:run_command:/seed>Haz clic</click> para ver la semilla del mundo.`, mostrado en la ventana de chat del cliente de Minecraft + +:::caution + +Desde que se introdujeron las firmas de chat en 1.19.1, el cliente ya no ejecuta comandos que requieren argumentos firmados, +como `/say` o `/tell`, para impedir que el servidor envíe mensajes firmados en nombre del cliente. + +::: + +### Desplazamiento + +Permite realizar varias acciones al pasar el cursor sobre el componente. + +Etiqueta + * `` + +Argumentos + * `_action_`, el tipo de evento de desplazamiento; debe ser uno de los elementos de [esta lista](jd:adventure:net.kyori.adventure.text.event.HoverEvent$Action#field-summary) + * `_value_`, los argumentos específicos de cada acción del evento: + +[//]: # (FIXME: El relleno de Starlight no se aplica a las celdas combinadas, así que se añade manualmente) +| Acción | Valor | Descripción | +|---------------|------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `show_text` | `_text_` | una cadena MiniMessage | +| `show_item` | `_type_[:_count_[(:_componentKey_:_componentValue_)...]]` | una `Key` del tipo de objeto, seguida opcionalmente de la cantidad (un entero) y una lista de pares clave-valor de [componentes de datos](https://minecraft.wiki/w/Data_component_format) | +| ^ | `_type_[:_count_[:tag]]` | una `Key` del tipo de objeto, seguida opcionalmente de la cantidad (un entero) y una etiqueta (una cadena [SNBT](https://minecraft.wiki/w/NBT_format#SNBT_format)) | +| `show_entity` | `_type_:_uuid_[:_name_]` | una `Key` con el ID del tipo de entidad, el UUID de la entidad y un nombre personalizado opcional | + +:::caution +El formato de valor `_type_[:_count_[:tag]]` de la acción `show_item` se considera antiguo y es posible que se deje de admitir. +El formato recomendado es `_type_[:_count_[(:_componentKey_:_componentValue_)...]]`. +::: + +Ejemplos +```mm +prueba'>PRUEBA +``` +
+Resultado del análisis de `<hover:show_text:'<red>prueba'>PRUEBA`, mostrado en la ventana de chat del cliente de Minecraft + +```mm +¡Espada muy afilada! +``` +
+Resultado de `<hover:show_item:diamond_sword:1:enchantments:'{sharpness:3,knockback:2}'>¡Espada muy afilada!</hover> + +### Asignación de teclas + +Permite mostrar la tecla configurada para las acciones. + +Etiqueta + * `` + +Argumentos + * `_key_`, el identificador de asignación de teclas de la acción + +Ejemplos +```mm +Pulsa para saltar. +``` + +
+Resultado del análisis de `Pulsa <red><key:key.jump> para saltar.`, mostrado en la ventana de chat del cliente de Minecraft + +### Traducible + +Permite mostrar mensajes de Minecraft usando la configuración regional del jugador. + +Etiqueta + * `` + +Alias + * `tr`, `translate` + +Argumentos + * `_key_`, la clave de traducción + * `_valueX_`, valores opcionales que se usan como marcadores de posición en la clave (se incluirán en la etiqueta `with` del JSON) + +Ejemplos +```mm +Deberías conseguir un . +1':'Piedra'>. +``` + +
+Resultado del análisis de una etiqueta de traducción de Minecraft, con el resultado en inglés en la ventana de chat del cliente +Resultado del análisis de una etiqueta de traducción de Minecraft con argumentos, en la ventana de chat del cliente + +### Alternativa + +:::note + +La opción de alternativa solo está disponible desde Minecraft 1.19.4. + +::: + +Permite mostrar mensajes de Minecraft usando la configuración regional del jugador o un texto alternativo si no hay una traducción disponible. + +Etiqueta + * `` + +Alias + * `tr_or`, `translate_or` + +Argumentos + * `_key_`, la clave de traducción + * `_fallback_`, el texto alternativo que se mostrará + * `_valueX_`, valores opcionales que se usan como marcadores de posición en la clave (se incluirán en la etiqueta `with` del JSON) + +Ejemplos +```mm +Deberías conseguir un . +``` + +### Inserción + +Permite insertar texto en el chat mediante Mayús + clic. + +Etiqueta + * `` + +Argumentos + * `_text_`, el texto que se insertará + +Ejemplos +```mm +Pulsa Mayús y haz clic en este texto para insertarlo. +``` + +
+Resultado del análisis de `Pulsa Mayús y haz clic en <insert:prueba>este texto</insert> para insertarlo.`, mostrado en la ventana de chat del cliente de Minecraft + +### Arcoíris + +¿Texto con los colores del arcoíris? + +Etiqueta + * `` + +Argumentos + * phase, opcional + * `!`, valor literal opcional que invierte el arcoíris + +Ejemplos +```mm +Woo: ||||||||||||||||||||||||! +Woo: ||||||||||||||||||||||||
! +Woo: ||||||||||||||||||||||||! +Woo: ||||||||||||||||||||||||! +``` + +
+Resultado del análisis de los cuatro ejemplos en serie, mostrado en la ventana de chat del cliente de Minecraft + +### Degradado + +Texto con colores en degradado. + +Etiqueta + * `` + +Argumentos + * Una lista de 1 a n colores, que pueden ser hexadecimales o con nombre, y un parámetro de fase opcional (rango de -1 a 1) que permite desplazar el degradado para crear animaciones. + +Ejemplos +```mm +Woo: ||||||||||||||||||||||||! +Woo: ||||||||||||||||||||||||! +Woo: ||||||||||||||||||||||||! +Woo: ||||||||||||||||||||||||! +``` + +
+Resultado del análisis de los ejemplos de la etiqueta de degradado, mostrado en la ventana de chat del cliente de Minecraft + +### Transición + +Transición entre colores. +Es similar a un degradado, pero todo el texto tiene el mismo color y la fase determina cuál. + +Etiqueta + * `` +Argumentos + * Una lista de 1 a n colores, que pueden ser hexadecimales o con nombre, y un parámetro de fase opcional (rango de -1 a 1) que permite desplazar la transición para crear animaciones. +Ejemplos +```mm +||||||||| +Hola mundo [phase] +``` + +
+Resultado del análisis de `<transition:white:black:red:[phase]>Hola mundo [phase]</transition>`, mostrado en la ventana de chat del cliente de Minecraft + +### Fuente + +Permite cambiar la fuente del texto. + +Etiqueta + * `` + +Argumentos + * La clave con espacio de nombres de la fuente; el valor predeterminado es `minecraft` + +Ejemplos +```mm +Nada Uniforme Alternativa Uniforme +Usa una fuente personalizada de un paquete de recursos +``` + +
+Resultado del análisis de `Nada <font:uniform>Uniforme <font:alt>Alternativa  </font> Uniforme`, mostrado en la ventana de chat del cliente de Minecraft + +### Salto de línea + +Inserta un carácter de salto de línea. + +Etiqueta + * `` + +Alias + * `br` + +Argumentos + * ninguno + +Ejemplos +```mm +Inserta aquí unsalto de línea. +Texto emergente con unsalto de línea'>Texto consalto de línea +``` + +
+Resultado del análisis de `<hover:show_text:'<red>Texto emergente con un<newline><green>salto de línea'>Texto con<newline>salto de línea</hover>`, mostrado en la ventana de chat del cliente de Minecraft + +### Selector + +*(desde v4.11.0)* Inserta un componente selector. + +Etiqueta + * `` + +Alias + * `sel` + +Argumentos + * `_sel_`, el patrón del selector que se insertará + * `_separator_` (opcional), el separador que se insertará entre los valores que coincidan con el selector + +Ejemplos +```mm +Hola , soy . +``` + +
+Resultado del análisis de `Hola <selector:@e[limit=5]>, soy <selector:@s>.`, mostrado en la ventana de chat del cliente de Minecraft + +### Puntuación + +*(desde v4.13.0)* Inserta un componente de puntuación. + +:::note + +El componente de puntuación requiere *renderizado* en el servidor para que los clientes puedan verlo. Esta operación depende de la plataforma. + +::: + +Etiqueta + * `` + +Argumentos: + * `_name_`, el nombre del titular de la puntuación en el marcador del servidor, o un selector que se resuelve en el contexto del destinatario + * `_objective_`, el nombre del objetivo cuyo valor de puntuación se obtendrá para `name` + +Ejemplos +```mm +Has ganado partidas. +``` + +### NBT + +*(desde v4.13.0)* Inserta un componente NBT. La sintaxis de esta etiqueta está pensada para resultar familiar a quienes usan el comando `/data` de Minecraft vanilla. + +:::note + +El componente NBT generado requiere *renderizado* en el servidor para que los clientes puedan verlo. Esta operación depende de la plataforma. + +::: + +Etiqueta + * `` + +Alias + * `data` + +Argumentos: + * `block|entity|storage`, el tipo de origen de datos del que se leerá: una entidad `block`, un selector `entity` o el contenedor persistente de comandos `storage` + * `_id_`, la posición para un componente NBT de bloque, un selector para uno de entidad o una clave (ubicación de recurso) para uno de almacenamiento + * `_path_`, la ruta NBT que se resolverá dentro del origen de datos + * `_separator_`, el separador entre varios valores, si el origen devuelve más de uno (principalmente para NBT de entidades) + * `interpret`, el texto literal `interpret` si el resultado debe analizarse como JSON de componentes + +Ejemplos +```mm +Tu salud es +``` + +### Orgullo + +*(desde v4.18.0)* Colorea el texto entre las etiquetas con un degradado correspondiente a una bandera del orgullo. + +Etiqueta + * `` + +Argumentos + * `flag`, la bandera que se usará: pride, progress, trans, bi, pan, nb, lesbian, ace, agender, demisexual, genderqueer, genderfluid, intersex, aro, baker, philly, queer, gay, bigender, demigender, femboy o intersex inclusive. + * `phase`, fase opcional, un número entre -1 y 1 + +Ejemplos +```mm +¡Feliz mes del orgullo! +Kyori apoya los derechos trans. +``` + +### Sprite + +*(desde v4.25.0)* Inserta un sprite. + +Etiqueta + * `` + +Argumentos + * `atlas`, el atlas que se usará, por ejemplo, `minecraft:blocks` o `items`. + * `sprite`, el sprite que se usará, por ejemplo, `item/emerald` o `custom:item/ruby`. + +Ejemplos +```mm +Mira mi . +Este objeto cuesta 10 × . +Esta es una textura personalizada de un espacio de nombres: +``` + +### Cabeza + +*(desde v4.25.0)* Inserta una cabeza de jugador. + +Etiqueta + * `` + +Argumentos + * `name|uuid|texture`, el nombre, UUID o ruta a la textura de la skin que se usará para dibujar la cabeza. + * `outer_layer`, `true` o `false`; determina si se dibuja la capa exterior (o capa del «sombrero»). + El valor predeterminado es `true`. + +Ejemplos +```mm +Mi desarrollador favorito es . +¿Prefieres a Steve o a Alex? +¡Gracias por la documentación! +``` diff --git a/src/content/docs/es/adventure/minimessage/index.md b/src/content/docs/es/adventure/minimessage/index.md new file mode 100644 index 000000000..fd53568bf --- /dev/null +++ b/src/content/docs/es/adventure/minimessage/index.md @@ -0,0 +1,21 @@ +--- +title: MiniMessage +slug: es/adventure/minimessage +description: Documentación de MiniMessage. +tableOfContents: false +sidebar: + label: Resumen +--- + +El formato MiniMessage es una representación sencilla de los componentes del chat mediante cadenas, diseñada para que los usuarios finales puedan aprenderla fácilmente y los desarrolladores ampliarla. + +```mm +Hola mundo, ¿no es divertido MiniMessage? +``` + +Si quieres escribir mensajes con MiniMessage, consulta el [formato MiniMessage](/es/adventure/minimessage/format); si quieres desarrollar software que use MiniMessage, consulta la [descripción general de la API](/es/adventure/minimessage/api). + +- [Formato](/es/adventure/minimessage/format) +- [API](/es/adventure/minimessage/api) +- [Reemplazos dinámicos](/es/adventure/minimessage/dynamic-replacements) +- [Traductor MiniMessage](/es/adventure/minimessage/translator) diff --git a/src/content/docs/es/adventure/minimessage/translator.md b/src/content/docs/es/adventure/minimessage/translator.md new file mode 100644 index 000000000..f1f8f3102 --- /dev/null +++ b/src/content/docs/es/adventure/minimessage/translator.md @@ -0,0 +1,71 @@ +--- +title: Traductor MiniMessage +slug: es/adventure/minimessage/translator +description: Guía sobre el traductor MiniMessage. +--- + +:::note + +Para obtener más información sobre los sistemas de localización de Minecraft y Adventure, consulta [localización](/es/adventure/localization). + +::: + +MiniMessage proporciona una implementación de `Translator` que permite usar MiniMessage como cadenas de traducción. +También admite automáticamente marcadores de posición de argumentos, lo que permite usar componentes traducibles sencillos en todo el código. + +## Crear un traductor MiniMessage + +Para empezar, crea una implementación de `MiniMessageTranslator` y regístrala en `GlobalTranslator`. +Puedes hacerlo mediante `GlobalTranslator.translator().addSource(myMiniMessageTranslator)`. +Consulta el siguiente bloque de código para ver un ejemplo de cómo crear tu propio +`MiniMessageTranslator`. + +```java title="MyMiniMessageTranslator.java" +public class MyMiniMessageTranslator extends MiniMessageTranslator { + + public MyMiniMessageTranslator() { + // De forma predeterminada, se usará la instancia estándar de MiniMessage. + // Puedes especificar una personalizada en el constructor de la superclase. + super(MiniMessage.miniMessage()); + } + + @Override + public Key name() { + // Cada traductor tiene un nombre que identifica esta instancia concreta. + return Key.key("mynamespace:mykey"); + } + + @Override + public @Nullable String getMiniMessageString(final String key, final Locale locale) { + // Para crear un traductor MiniMessage personalizado, basta con sobrescribir este método. + // Solo tienes que devolver una cadena MiniMessage para la clave y la configuración regional indicadas. + // En este ejemplo el valor está escrito directamente en el código, pero podrías obtenerlo de un paquete de recursos, un archivo de propiedades o de configuración, o de otra fuente. + if (key.equals("mykey") && locale.equals(Locale.forLanguageTag("es"))) { + return "¡Hola, ! Hoy es ."; + } else { + // Devolver null hace que se «ignore» esta traducción. + return null; + } + } +} +``` + +### Almacén de traducciones MiniMessage + +Para facilitar la administración de un `MiniMessageTranslator`, también ofrecemos una implementación de `TranslationStore` que usa cadenas MiniMessage. +Consulta `localization` para obtener documentación sobre el uso de almacenes de traducciones. + +Ten en cuenta que `MiniMessageTranslationStore` incluye los mismos métodos que el almacén de traducciones con formato de mensajes para rellenar un almacén de traducciones usando paquetes de recursos. + +## Usar un traductor MiniMessage + +El traductor MiniMessage convierte automáticamente los argumentos de componentes traducibles en etiquetas personalizadas. +La etiqueta será `` o ``, donde `index` es la posición del argumento, empezando por cero. +Por ejemplo, el componente `Component.translatable(key, Component.text("Kezz"))` con la cadena MiniMessage `¡Hola, !` producirá «¡Hola, Kezz!». + +También puedes usar la clase `Argument` para crear etiquetas con nombre y facilitar su uso. +Por ejemplo, el componente `Component.translatable(key, Argument.component("name", Component.text("Kezz"))` producirá la cadena «¡Hola, Kezz!» +si se usa con `¡Hola, !` o con `¡Hola, !`. + +Por último, puedes añadir etiquetas o resolvedores de etiquetas completamente personalizados durante la deserialización usando los demás métodos de `Argument`. +Consulta los Javadocs de la clase `Argument` para ver la lista completa. diff --git a/src/content/docs/es/adventure/platform/bukkit.mdx b/src/content/docs/es/adventure/platform/bukkit.mdx new file mode 100644 index 000000000..947d4293d --- /dev/null +++ b/src/content/docs/es/adventure/platform/bukkit.mdx @@ -0,0 +1,70 @@ +--- +title: Bukkit +slug: es/adventure/platform/bukkit +description: Implementación de Adventure para Bukkit. +--- + +import Dependency from "/src/components/Dependency.astro"; +import { LATEST_ADVENTURE_PLATFORM_BUKKIT_SUPPORTED_MC, LATEST_ADVENTURE_PLATFORM_RELEASE } from "/src/utils/versions"; + +La implementación de la plataforma Adventure para Bukkit es compatible con Paper, Spigot y Bukkit desde +Minecraft 1.7.10 hasta {LATEST_ADVENTURE_PLATFORM_BUKKIT_SUPPORTED_MC}. + +:::danger + +La implementación de la plataforma Adventure para Bukkit/Spigot y los serializadores de componentes de Minecraft/Bungeecord ya no se mantienen. +El equipo de Adventure ya no ofrece asistencia para estas bibliotecas. + +Recomendamos que quienes usan estas bibliotecas migren a programas modernos con [compatibilidad nativa con Adventure](/es/adventure/platform/native) (por ejemplo, [Paper](/es/paper)). + +::: + +Declaración de la dependencia: + + + +## Uso + +Primero debes obtener un objeto `BukkitAudiences` mediante `BukkitAudiences.create(plugin)`. Este objeto es seguro para subprocesos +y, si es necesario, se puede reutilizar desde distintos subprocesos. A partir de ahí, puedes convertir los `CommandSender` y `Player` de Bukkit en +`Audience` usando los métodos correspondientes de `BukkitAudiences`. + +También debes cerrar el objeto de audiencias cuando se desactive un plugin para liberar recursos y aumentar las probabilidades de que `/reload` se complete correctamente. + +```java title="MyPlugin.java" +public class MyPlugin extends JavaPlugin { + + private BukkitAudiences adventure; + + public BukkitAudiences adventure() { + if (this.adventure == null) { + throw new IllegalStateException("Tried to access Adventure when the plugin was disabled!"); + } + return this.adventure; + } + + @Override + public void onEnable() { + // Inicializar una instancia de audiencias para el plugin + this.adventure = BukkitAudiences.create(this); + // y realizar el resto de la inicialización + } + + @Override + public void onDisable() { + if (this.adventure != null) { + this.adventure.close(); + this.adventure = null; + } + } +} +``` + +Es preferible usar este proveedor de audiencias en lugar de los serializadores directamente, ya que se encarga de las medidas de compatibilidad necesarias para enviar mensajes entre versiones. + +## Serializadores de componentes + +Para los casos que no cubre la interfaz `Audience`, la plataforma Bukkit proporciona `MinecraftComponentSerializer` +(disponible en servidores basados en CraftBukkit) y `BungeeComponentSerializer` (disponible en servidores Spigot y Paper) +para convertir directamente entre los [componentes](/es/adventure/text) de Adventure y otros tipos de componentes. Para los usos que no se integran +directamente con tipos nativos, `BukkitComponentSerializer` expone serializadores JSON y de formato antiguo para la versión del servidor en ejecución. diff --git a/src/content/docs/es/adventure/platform/bungeecord.mdx b/src/content/docs/es/adventure/platform/bungeecord.mdx new file mode 100644 index 000000000..fbacceacb --- /dev/null +++ b/src/content/docs/es/adventure/platform/bungeecord.mdx @@ -0,0 +1,74 @@ +--- +title: BungeeCord +slug: es/adventure/platform/bungeecord +description: Implementación de Adventure para BungeeCord. +--- + +import Dependency from "/src/components/Dependency.astro"; +import { LATEST_ADVENTURE_PLATFORM_RELEASE } from "/src/utils/versions"; + +Adventure es compatible con la versión más reciente de BungeeCord y con derivados compatibles +con BungeeCord, como Waterfall. + +:::danger + +La implementación de la plataforma Adventure para BungeeCord y el serializador de componentes de BungeeCord ya no se mantienen. +El equipo de Adventure ya no ofrece asistencia para estas bibliotecas. + +Recomendamos que quienes usan estas bibliotecas migren a programas modernos con [compatibilidad nativa con Adventure](/es/adventure/platform/native) (por ejemplo, [Velocity](/es/velocity)). + +::: + +Declaración de la dependencia: + + + +## Uso + +Primero debes obtener un objeto `BungeeAudiences` mediante `BungeeAudiences.create(plugin)`. Este objeto es seguro para subprocesos +y, si es necesario, se puede reutilizar desde distintos subprocesos. También debes *cerrar* este objeto al desactivar el plugin. + +Ten en cuenta que no todas las funciones están disponibles en el proxy. Se admiten los mensajes de chat, los mensajes de la barra de acción, los títulos, las barras de jefe +y los encabezados y pies de la lista de jugadores; las demás solicitudes fallarán silenciosamente. + +A continuación se muestra un ejemplo sencillo de inicialización correcta de esta plataforma: + +```java title="MyPlugin.java" +public class MyPlugin extends Plugin { + + private BungeeAudiences adventure; + + public BungeeAudiences adventure() { + if (this.adventure == null) { + throw new IllegalStateException("Cannot retrieve audience provider while plugin is not enabled"); + } + return this.adventure; + } + + @Override + public void onEnable() { + this.adventure = BungeeAudiences.create(this); + } + + @Override + public void onDisable() { + if (this.adventure != null) { + this.adventure.close(); + this.adventure = null; + } + } +} +``` + +## Serializadores de componentes + +Para las funciones que `Audience` no admite, `BungeeComponentSerializer` permite convertir entre +los [componentes](/es/adventure/text) de Adventure y la API nativa de componentes de chat de BungeeCord, y viceversa. + +:::cautions + +En algunas áreas del proxy (en particular, al enviar respuestas de la lista de servidores), no se puede inyectar correctamente el serializador de componentes +a menos que se haya inicializado una instancia de `BungeeAudiences`. El uso de instancias de `Component` de Adventure **no** +funcionará sin una instancia de `BungeeAudiences`. + +::: diff --git a/src/content/docs/es/adventure/platform/fabric.mdx b/src/content/docs/es/adventure/platform/fabric.mdx new file mode 100644 index 000000000..6c6be05b5 --- /dev/null +++ b/src/content/docs/es/adventure/platform/fabric.mdx @@ -0,0 +1,218 @@ +--- +title: Fabric +slug: es/adventure/platform/fabric +description: Implementación de Adventure para Fabric. +--- + +import Dependency from "/src/components/Dependency.astro"; +import { LATEST_ADVENTURE_PLATFORM_MOD_RELEASE, LATEST_ADVENTURE_PLATFORM_MOD_SUPPORTED_MC_RANGE } from "/src/utils/versions"; + +Adventure admite Fabric en *Minecraft: Java Edition* 1.16 y versiones posteriores, tanto en el servidor como en el cliente. Por lo general, cada versión principal de Minecraft +requiere una nueva versión de la plataforma. + +La plataforma admite todas las funciones, incluidas la localización y los renderizadores personalizados. + +Desde la versión 5.3.0, esta plataforma ofrece una experiencia *casi nativa* mediante la implementación directa de interfaces Adventure en las clases de Minecraft cuando es posible. + +:::danger[Atención] + +La versión 6.x de adventure-platform-fabric, que usa una implementación compartida con NeoForge (consulta [Con mods (API compartida de Fabric y NeoForge)](/es/adventure/platform/modded)), +no se publica para Minecraft 1.20-1.21.1. Así se evitan conflictos con los mods existentes que usan 5.x. +Desde Minecraft 1.21.2, se publica la versión 6.x para ambas plataformas. + +::: + +## Dependencia + +La plataforma Fabric se empaqueta como mod y está diseñada para incluirse en otros mods mediante el empaquetado jar-in-jar. +Como los demás proyectos de Adventure, las versiones se distribuyen en Maven Central y las compilaciones snapshot en Sonatype OSS: + +El siguiente ejemplo usa el plugin sin remapeo `net.fabricmc.fabric-loom` para Minecraft 26.1 y versiones posteriores. +Usa `implementation` para la dependencia de desarrollo y `include` para empaquetar la plataforma en tu mod: + + + +La versión actual de la plataforma, {LATEST_ADVENTURE_PLATFORM_MOD_RELEASE}, está destinada a Minecraft {LATEST_ADVENTURE_PLATFORM_MOD_SUPPORTED_MC_RANGE}. +Para Minecraft 1.21.11 y versiones anteriores, usa una versión compatible de la plataforma con Loom con remapeo +(`net.fabricmc.fabric-loom-remap` o el plugin antiguo `fabric-loom`) y `modImplementation` en lugar de `implementation`. + +La plataforma Fabric necesita *fabric-api-base* para proporcionar el evento de cambio de configuración regional y *fabric-command-api-v2* para el evento de clic de devolución de llamada. +También puede usar [Colonel](https://gitlab.com/stellardrift/colonel) (o *fabric-networking-api-v1*) de forma opcional para permitir que se usen los tipos de argumento `Component` y `Key` +en clientes que no tengan instalado el mod. No hay otras dependencias. + +:::danger[Atención] + +Cada versión principal de Minecraft requiere distintas versiones de la plataforma. Para versiones anteriores de Minecraft, consulta la siguiente tabla. +Para Minecraft 1.21.2 y posteriores, consulta la tabla de [Con mods (API compartida de Fabric y NeoForge)](/es/adventure/platform/modded). + +
+ Versiones anteriores + | Versión de Minecraft | Versión de Adventure | Versión de `adventure-platform-fabric` | + |-------------------|-------------------|-------------------------------------| + | 1.16.2-1.16.4 | 4.9.3 | 4.0.0 | + | 1.17.x | 4.9.3 | 4.1.0 | + | 1.18, 1.18.1 | 4.10.0 | 5.1.0 | + | 1.18.2 | 4.11.0 | 5.3.1 | + | 1.19 | 4.11.0 | 5.4.0 | + | 1.19.1-1.19.2 | 4.12.0 | 5.5.2 | + | 1.19.3 | 4.13.0 | 5.7.0 | + | 1.19.4 | 4.13.0 | 5.8.0 | + | 1.20-1.20.1 | 4.14.0 | 5.9.0 | + | 1.20.2 | 4.14.0 | 5.10.1 | + | 1.20.4 | 4.16.0 | 5.12.0 | + | 1.20.5-1.20.6 | 4.17.0 | 5.13.0 | + | 1.21-1.21.1 | 4.17.0 | 5.14.1 | +
+ +::: + +## Uso básico + +La forma más sencilla de empezar a usar esta plataforma es trabajar con los objetos del juego de Minecraft que implementan directamente las interfaces de Adventure mediante la inyección de interfaces de Loom. + +Esto cubre casi todos los casos en los que se usa el renderizador predeterminado. + +Se implementan directamente las siguientes interfaces de Adventure: + +`Audience` + - `net.minecraft.commands.CommandSourceStack`, `net.minecraft.server.MinecraftServer`, `net.minecraft.server.rcon.RconConsoleSource`, + - `net.minecraft.server.level.ServerPlayer`, `net.minecraft.client.player.LocalPlayer` + +`AdventureCommandSourceStack` + - `net.minecraft.commands.CommandSourceStack` + +`Sound.Emitter` + - `net.minecraft.world.entity.Entity` + +`Sound.Type` + - `net.minecraft.sounds.SoundEvent` + +`Identified` + - `net.minecraft.world.entity.player.Player` + +`ComponentLike` + - `net.minecraft.network.chat.Component` + +`Key` + - `net.minecraft.resources.Identifier` + +`Keyed` + - `net.minecraft.resources.ResourceKey` + +`HoverEventSource` + - `net.minecraft.world.entity.Entity`, + - `net.minecraft.world.item.ItemStack`, `net.minecraft.world.item.ItemStackTemplate` + +`SignedMessage` + - `net.minecraft.network.chat.PlayerChatMessage` + +Además, todas las `Key` creadas serán instancias de `Identifier`. + +Con estas inyecciones, empezar a usar la plataforma es tan sencillo como: + +```java +void greet(final ServerPlayer player) { + final Component message = Component.text() + .content("Hola ") + .append(player.get(Identity.DISPLAY_NAME) + .get() + .color(NamedTextColor.RED) + ) + .build(); + player.sendMessage(message); +} +``` + +Para casos de uso más complejos, `MinecraftServerAudiences` o `MinecraftClientAudiences` proporcionan API adicional. + +## Servidor + +Se puede acceder al lado del servidor lógico de la plataforma Fabric siempre que haya un servidor disponible, mediante una instancia `MinecraftServerAudiences`. De forma predeterminada, los componentes traducibles se renderizan con el traductor global, aunque se puede pasar un renderizador personalizado al inicializar la plataforma. + +Se admiten todos los métodos de la interfaz `AudienceProvider`. El método `permission` requiere *fabric-permissions-api* para filtrar jugadores por permiso. + +Para empezar a usar Adventure, configura un proveedor de audiencias como este: + +```java title="MyMod.java" +public class MyMod implements ModInitializer { + + private volatile MinecraftServerAudiences adventure; + + public MinecraftServerAudiences adventure() { + if (this.adventure == null) { + throw new IllegalStateException("Tried to access Adventure without a running server!"); + } + return this.adventure; + } + + @Override + public void onInitialize() { + // Registrar las devoluciones de llamada del ciclo de vida del servidor. + // Así se garantiza que se borren los datos de la plataforma entre instancias del juego. + // Esto es importante en el servidor integrado, donde puede haber varias + // instancias del servidor durante la inicialización de un mismo mod. + ServerLifecycleEvents.SERVER_STARTING.register(server -> this.adventure = MinecraftServerAudiences.of(server)); + ServerLifecycleEvents.SERVER_STOPPED.register(server -> this.adventure = null); + } +} +``` + +Desde aquí, se pueden obtener audiencias para jugadores y cualquier otro `CommandSource`. También hay instancias especializadas de serializadores que permiten usar +información del juego al serializar componentes. + +### Localización + +Como parte de la compatibilidad de traducción de la plataforma, se llamará a la devolución de llamada `PlayerLocales.CHANGED_EVENT` cada vez que un jugador del servidor reciba del cliente un idioma +actualizado; esto permite acceder a la configuración regional actual del jugador. + +### Comandos + +La plataforma Fabric proporciona tipos de argumento personalizados para especificar parámetros `Key` y `Component` en comandos Brigadier y métodos auxiliares para obtener fácilmente una +`Audience` a partir de una instancia `CommandSourceStack`. + +:::caution + +Si se usan estos tipos de argumento personalizados (antes de 1.19), los clientes vanilla no podrán unirse a menos que el mod [Colonel](https://gitlab.com/stellardrift/colonel) +esté instalado en el servidor. Al igual que la plataforma, es pequeño y se puede incluir fácilmente en el archivo jar del mod. + +::: + +Por ejemplo, este comando sencillo repetirá lo que se proporcione como entrada: + +```java +// Posible método para la clase de inicialización del mod mostrada arriba +private static final String ARG_MESSAGE = "message"; + +void registerCommands(final CommandDispatcher dispatcher, final boolean isDedicated) { + dispatcher.register(literal("echo").then(argument(ARG_MESSAGE, component()).executes(context -> { + final Component message = component(context, ARG_MESSAGE); + context.getSource().sendMessage(Component.text("Has dicho: ").append(message)); + }))); +} +``` + +## Cliente + +Una particularidad de la plataforma Fabric es que admite operaciones exclusivamente del lado del cliente. La configuración es más sencilla que la del servidor, +ya que el cliente es un singleton y solo hay un sujeto sobre el que actuar: el jugador del cliente. + +Esto significa que la mayoría de los usuarios puede tratar el objeto `MinecraftClientAudiences` como un singleton. La única excepción son quienes usan un +renderizador personalizado. Así, usar audiencias de Adventure es bastante sencillo, como muestra este ejemplo de código: + +```java +void doThing() { + // Obtener la audiencia + final Audience client = MinecraftClientAudiences.of().audience(); + + // Hacer algo. Esto solo funcionará cuando el jugador esté dentro de la partida. + client.sendMessage(Component.text("meow", NamedTextColor.DARK_PURPLE)); +} +``` + +Está disponible toda la funcionalidad de la interfaz `Audience`, incluida la localización. + +## Trabajar con tipos nativos + +Por desgracia, Adventure no puede proporcionar una API para todos los lugares del juego donde se usan componentes del chat. Sin embargo, en los casos que no cubre la API de `Audience`, +es posible convertir componentes entre tipos nativos y de Adventure. Consulta los tipos nativos que implementan +interfaces de Adventure y los métodos de `MinecraftAudiences` para ver otras conversiones disponibles. diff --git a/src/content/docs/es/adventure/platform/implementing.md b/src/content/docs/es/adventure/platform/implementing.md new file mode 100644 index 000000000..39d3c6165 --- /dev/null +++ b/src/content/docs/es/adventure/platform/implementing.md @@ -0,0 +1,64 @@ +--- +title: Implementar plataformas +slug: es/adventure/platform/implementing +description: Implementación de Adventure para tu propia plataforma. +--- + +La mayoría de los usuarios consultará aquí información sobre implementaciones de plataformas existentes, pero esta página también está dirigida a quienes quieran crear sus propias integraciones de plataforma. + +Aunque en esencia Adventure «solo» proporciona estructuras de datos y serializadores, la evolución del juego y la incorporación de nuevas funciones requieren más opciones ajustables y puntos de extensión de plataforma +para generar la salida correcta para cada versión del juego. Esto ha llevado a introducir varios servicios que las plataformas pueden implementar mediante el mecanismo +`ServiceLoader` de Java. También se esperan algunos comportamientos por convención. Como no hay muchas plataformas que se integren con Adventure, esta página intenta +cubrir los aspectos comunes. No dudes en hacernos preguntas; podemos completar esta página entre todos. + +## Servicios + +### Servicios `ComponentSerializer` + +La mayoría de los serializadores (Gson, antiguo, etc.) tienen SPI `Provider` que permiten personalizar su comportamiento predeterminado. Son especialmente útiles para Gson y otros serializadores JSON, +cuyas estructuras de datos han cambiado con el tiempo, aunque también puede interesar consultar las opciones del serializador antiguo. Consulta los Javadocs de cada serializador para obtener más información. + +En los subtipos de `JSONComponentSerializer`, hemos intentado agrupar las opciones ajustables pertinentes en un único sistema, identificado por la +[data version](https://minecraft.wiki/w/Data_version). Para gestionar eventos de desplazamiento en versiones del juego anteriores a 1.16, existe la interfaz adicional `LegacyHoverEventSerializer`. +Ofrecemos una implementación que usa `adventure-nbt` como submódulo independiente, aunque las plataformas pueden preferir una biblioteca NBT nativa. +Ambas opciones deben configurarse en los constructores de la implementación `Provider` correspondiente. + +### Valores de componentes de datos + +Para almacenar datos específicos de la plataforma en eventos de desplazamiento `show_item`, exponemos objetos de datos opacos en la API. Las plataformas deben proporcionar la lógica de conversión entre implementaciones +mediante una implementación de `DataComponentValueConverterRegistry.Provider`. En general, solo hay que convertir entre tipos específicos de la plataforma +y los tipos genéricos `TagSerializable` y `Removed`, pero las plataformas deben incluir conversores a `GsonDataComponentValue` (tanto desde los tipos de la plataforma +*como* desde el tipo genérico `TagSerializable`, que requiere analizar SNBT para realizar la conversión). + +### Devoluciones de llamada de clic + +Como las devoluciones de llamada son una función muy solicitada, Adventure proporciona un tipo de evento de clic «virtual» para funciones de devolución de llamada. Esta acción no persiste entre ejecuciones y requiere +que las plataformas registren un comando que active la ejecución de las devoluciones de llamada. Esto se implementa mediante el SPI `ClickCallback.Provider`. El comando no debe enviarse como parte del +árbol de comandos que reciben los clientes para evitar saturarlos. + +Las plataformas que implementen el proveedor de devoluciones de llamada de clic deben registrar el comando en el momento adecuado y mantener un registro de devoluciones de llamada activas, al que se añada cada una cuando se solicite un +comando de devolución de llamada. La plataforma es responsable de garantizar las condiciones de ejecución e implementar los efectos de cualquier `Option` que se establezca en la devolución de llamada. + +### Registro de componentes + +`ComponentLogger`, como parte del módulo `adventure-text-logger-slf4j`, proporciona una interfaz de registro que amplía SLF4J y envuelve cualquier registrador SLF4J existente (compatible con +las versiones 1 y 2). Las plataformas deben proporcionar el adaptador que busca el registrador adecuado por nombre y serializa los componentes a texto. + +Esto debe incluir las traducciones que sean necesarias. De forma predeterminada, el registrador serializa a texto sin formato, pero las plataformas pueden usar el serializador +[ANSI](/es/adventure/serializer/ansi) para obtener una salida en color. + +### Barras de jefe + +Las barras de jefe son algo complicadas desde el punto de vista operativo. Como son uno de los pocos elementos de la biblioteca que mantienen un estado mutable, deben volver a sincronizar con sus destinatarios todos los cambios de estado. +Para hacer un seguimiento de los destinatarios y vincularlos con el estado interno, el SPI `BossBarImplementation.Provider` permite que las plataformas proporcionen sus propios puntos de implementación para cada barra. + +## Comportamientos convencionales + +Además de lo que se exige explícitamente al implementar determinadas interfaces, se espera que las plataformas sigan algunos comportamientos: + +* Al implementar `Audience`, las operaciones no admitidas deben fallar silenciosamente. +* Antes de enviar componentes a un jugador, deben pasar por `GlobalTranslator` para realizar las traducciones que correspondan (nota: `GlobalTranslator` solo sirve para + las traducciones personalizadas; no debe contener las traducciones de paquetes de recursos vanilla, que usan una sintaxis de interpolación distinta a la de `GlobalTranslator`). +* No hay una lista obligatoria de módulos de Adventure que debas distribuir con tu plataforma, pero recomendamos `adventure-api`, `adventure-text-minimessage`, + `adventure-text-logger-slf4j` y los serializadores que necesite la integración. En concreto, no recomendamos distribuir el módulo + `adventure-text-serializer-legacy`, salvo que sea necesario para mantener la compatibilidad con versiones anteriores de tu plataforma. diff --git a/src/content/docs/es/adventure/platform/index.md b/src/content/docs/es/adventure/platform/index.md new file mode 100644 index 000000000..c80edf138 --- /dev/null +++ b/src/content/docs/es/adventure/platform/index.md @@ -0,0 +1,72 @@ +--- +title: Plataformas +slug: es/adventure/platform +description: Documentación sobre distintas implementaciones de la API de Adventure. +tableOfContents: false +sidebar: + label: Resumen +--- + +Adventure se integra con muchas plataformas de Minecraft. Algunas admiten +Adventure de forma nativa, mientras que otras plataformas antiguas tienen sus propios tipos y necesitan un adaptador para gestionar los tipos de Adventure. Para que puedas usar Adventure con estas plataformas, Adventure ofrece varios adaptadores específicos que +permiten obtener instancias `Audience` a partir de tipos de usuario nativos. + +:::note[Preguntas frecuentes] + +**¿Por qué adventure-platform no envía mensajes o no funciona correctamente?** + +Primero, asegúrate de usar la versión estable más reciente. Puedes encontrarla en [Maven Central](https://central.sonatype.com/search?q=g%3Anet.kyori+adventure-platform*). + +Después, comprueba que la función que usas esté disponible en la versión del cliente que recibe la acción. +Por ejemplo, los códigos de color hexadecimales no funcionan en clientes anteriores a 1.16, por lo que se convertirán al color compatible más cercano. + +Si aún no funciona, puede ser útil habilitar el modo de depuración estableciendo en `true` la propiedad del sistema `net.kyori.adventure.debug` y +consultando la salida. Ahí se mostrarán las facetas seleccionadas, lo que ayudará a identificar el motivo del problema. +Si no consigues resolverlo por tu cuenta, siempre puedes preguntar en el canal +[`#adventure-platform-help`](https://discord.com/channels/289587909051416579/1342379165663363112) del servidor de Discord de PaperMC. + +::: + +### Contenido: +* [Compatibilidad nativa](/es/adventure/platform/native) +* [Con mods (API compartida de Fabric y NeoForge)](/es/adventure/platform/modded) + * [Dependencia](/es/adventure/platform/modded#dependencia) + * [Uso básico](/es/adventure/platform/modded#uso-básico) + * [Trabajar con tipos nativos](/es/adventure/platform/modded#trabajar-con-tipos-nativos) +* [Fabric](/es/adventure/platform/fabric) + * [Dependencia](/es/adventure/platform/fabric#dependencia) + * [Uso básico](/es/adventure/platform/fabric#uso-básico) + * [Servidor](/es/adventure/platform/fabric#servidor) + * [Cliente](/es/adventure/platform/fabric#dependencia) + * [Trabajar con tipos nativos](/es/adventure/platform/fabric#trabajar-con-tipos-nativos) +* [NeoForge](/es/adventure/platform/neoforge) + * [Dependencia](/es/adventure/platform/neoforge#dependencia) + * [Uso básico](/es/adventure/platform/neoforge#uso-básico) + * [Servidor](/es/adventure/platform/neoforge#servidor) + * [Comandos](/es/adventure/platform/neoforge#comandos) + * [Cliente](/es/adventure/platform/neoforge#dependencia) +* [Implementar plataformas](/es/adventure/platform/implementing) + * [Servicios](/es/adventure/platform/implementing#servicios) + * [Comportamientos convencionales](/es/adventure/platform/implementing#comportamientos-convencionales) + +### Plataformas antiguas + +:::danger + +Las implementaciones de la plataforma Adventure para Bungeecord, Bukkit/Spigot y Sponge API 7, así como sus serializadores asociados, ya no se mantienen. +El equipo de Adventure ya no ofrece asistencia para estas bibliotecas. + +Recomendamos que quienes usan estas bibliotecas migren a plataformas modernas con [compatibilidad nativa con Adventure](/es/adventure/platform/native) (por ejemplo, Velocity, Paper y Sponge API 8 o posterior). +Si desarrollas para plataformas con mods, te recomendamos usar [adventure-platform-mod](/es/adventure/platform/modded) para obtener compatibilidad casi nativa con Fabric y NeoForge. + +::: + +* [Bukkit](/es/adventure/platform/bukkit) + * [Uso](/es/adventure/platform/bukkit#uso) + * [Serializadores de componentes](/es/adventure/platform/bukkit#serializadores-de-componentes) +* [BungeeCord](/es/adventure/platform/bungeecord) + * [Uso](/es/adventure/platform/bungeecord#uso) + * [Serializadores de componentes](/es/adventure/platform/bungeecord#serializadores-de-componentes) +* [SpongeAPI](/es/adventure/platform/spongeapi) + * [Uso](/es/adventure/platform/spongeapi#uso) +* [ViaVersion](/es/adventure/platform/viaversion) diff --git a/src/content/docs/es/adventure/platform/modded.mdx b/src/content/docs/es/adventure/platform/modded.mdx new file mode 100644 index 000000000..9482ec2c6 --- /dev/null +++ b/src/content/docs/es/adventure/platform/modded.mdx @@ -0,0 +1,189 @@ +--- +title: Con mods (API compartida de Fabric y NeoForge) +slug: es/adventure/platform/modded +description: Implementación compartida de Adventure para Fabric y NeoForge. +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components"; + +Desde *Minecraft: Java Edition* 1.21.2, Adventure se implementa principalmente con código compartido entre NeoForge y Fabric. +Por lo general, cada versión principal de Minecraft requiere una nueva versión de la plataforma. + +La plataforma admite todas las funciones, incluidas la localización y los renderizadores personalizados. + +## Dependencia + +Al crear mods para varios cargadores, a menudo queremos trasladar la mayor cantidad de código posible a una parte de nuestros proyectos independiente del cargador. + +Adventure lo facilita mediante el artefacto `net.kyori:adventure-platform-mod-shared`. + +Para Minecraft 26.1 y versiones posteriores, usa este artefacto tanto con Loom como con ModDevGradle. Los proyectos Loom deben usar el +plugin sin remapeo `net.fabricmc.fabric-loom` y la configuración estándar `compileOnly`. + +Para Minecraft 1.21.11 y versiones anteriores, los módulos comunes administrados por Loom con remapeo (`net.fabricmc.fabric-loom-remap` o el +plugin antiguo `fabric-loom`) deben usar `net.kyori:adventure-platform-mod-shared-fabric-repack` con `modCompileOnly`. + +:::caution[Nota] + Estos artefactos son para el módulo común de mods multiplataforma. Para plataformas concretas, consulta las páginas de + [Fabric](/es/adventure/platform/fabric) o [NeoForge](/es/adventure/platform/neoforge). Si estás creando un mod + exclusivo para Fabric o NeoForge, o no necesitas usar la API de plataforma en el código compartido, no hace falta que uses + este artefacto explícitamente, ya que ambas plataformas dependen de él de forma transitiva. +::: + +Como los demás proyectos de Adventure, las versiones se distribuyen en Maven Central y las compilaciones snapshot en Sonatype OSS: + + + + + ```kotlin title="build.gradle.kts" replace + repositories { + // Para compilaciones de desarrollo + maven(url = "https://central.sonatype.com/repository/maven-snapshots/") { + name = "central-snapshots" + mavenContent { snapshotsOnly() } + } + // Para versiones publicadas + mavenCentral() + } + + dependencies { + // Módulo común (Loom o ModDevGradle) + compileOnly("net.kyori:adventure-platform-mod-shared:\{LATEST_ADVENTURE_PLATFORM_MOD_RELEASE}") // Para Minecraft \{LATEST_ADVENTURE_PLATFORM_MOD_SUPPORTED_MC_RANGE} + } + ``` + + + ```groovy title="build.gradle" replace + repositories { + // Para compilaciones de desarrollo + maven { + name = 'central-snapshots' + url = 'https://central.sonatype.com/repository/maven-snapshots/' + mavenContent { snapshotsOnly() } + } + // Para versiones publicadas + mavenCentral() + } + + dependencies { + // Módulo común (Loom o ModDevGradle) + compileOnly('net.kyori:adventure-platform-mod-shared:\{LATEST_ADVENTURE_PLATFORM_MOD_RELEASE}') // Para Minecraft \{LATEST_ADVENTURE_PLATFORM_MOD_SUPPORTED_MC_RANGE} + } + ``` + + + + +:::note[Atención] + +Cada versión principal de Minecraft requiere distintas versiones de la plataforma. Para las versiones anteriores de Minecraft, consulta la siguiente tabla. + +
+ Versiones anteriores + + | Versión de Minecraft | Versión de Adventure | Versión de `adventure-platform-(mod-shared/fabric/neoforge)` | + |-------------------|-------------------|-----------------------------------------------------------| + | 26.2 | 5.2.0 | 7.1.1 | + | 26.1-26.1.2 | 4.26.1 | 6.9.0 | + | 1.21.11 | 4.25.0 | 6.8.0 | + | 1.21.9-1.21.10 | 4.25.0 | 6.7.0 | + | 1.21.6-1.21.8 | 4.24.0 | 6.6.0 | + | 1.21.5 | 4.21.0 | 6.4.0 | + | 1.21.2-1.21.4 | 4.20.0 | 6.3.0 | + | 1.21-1.21.1 | 4.17.0 | 6.0.0 | + +
+ +::: + +## Uso básico + +La forma más sencilla de empezar a usar esta plataforma es trabajar con los objetos del juego de Minecraft que implementan directamente las interfaces de Adventure. + +Esto cubre casi todos los casos en los que se usa el renderizador predeterminado. + +En Fabric, Loom aplica la inyección de interfaces, por lo que puedes llamar directamente a los métodos de interfaz en los objetos de Minecraft. + +En NeoForge, debes hacer una conversión de tipo manual o usar los métodos auxiliares de `MinecraftAudiences`. + +Se implementan directamente las siguientes interfaces de Adventure: + +`Audience` + - `net.minecraft.commands.CommandSourceStack`, `net.minecraft.server.MinecraftServer`, `net.minecraft.server.rcon.RconConsoleSource`, + - `net.minecraft.server.level.ServerPlayer`, `net.minecraft.client.player.LocalPlayer` + +`AdventureCommandSourceStack` + - `net.minecraft.commands.CommandSourceStack` + +`Sound.Emitter` + - `net.minecraft.world.entity.Entity` + +`Sound.Type` + - `net.minecraft.sounds.SoundEvent` + +`Identified` + - `net.minecraft.world.entity.player.Player` + +`ComponentLike` + - `net.minecraft.network.chat.Component` + +`Key` + - `net.minecraft.resources.Identifier` + +`Keyed` + - `net.minecraft.resources.ResourceKey` + +`HoverEventSource` + - `net.minecraft.world.entity.Entity`, + - `net.minecraft.world.item.ItemStack`, `net.minecraft.world.item.ItemStackTemplate` + +`SignedMessage` + - `net.minecraft.network.chat.PlayerChatMessage` + + +Con estas inyecciones, empezar a usar la plataforma es tan sencillo como: + +```java +void greet(final ServerPlayer player) { + Component message = Component.text() + .content("Hola ") + .append(player.get(Identity.DISPLAY_NAME) + .get() + .color(NamedTextColor.RED) + ) + .build(); + player.sendMessage(message); +} +``` + +Para casos de uso más complejos, `MinecraftServerAudiences` o `MinecraftClientAudiences` proporcionan API adicional. + +### Comandos + +La plataforma proporciona tipos de argumento personalizados para especificar parámetros `Key` y `Component` en comandos Brigadier. + +:::caution + +Consulta la documentación específica de la plataforma para obtener detalles sobre el registro y la sincronización de estos tipos de argumento. + +::: + +Por ejemplo, este comando sencillo repetirá lo que se proporcione como entrada: + +```java +// Posible método para la clase de inicialización del mod mostrada arriba +private static final String ARG_MESSAGE = "message"; + +void registerCommands(final CommandDispatcher dispatcher, final boolean isDedicated) { + dispatcher.register(literal("echo").then(argument(ARG_MESSAGE, component()).executes(context -> { + final Component message = component(context, ARG_MESSAGE); + ((Audience) context.getSource()).sendMessage(Component.text("Has dicho: ").append(message)); + }))); +} +``` + +## Trabajar con tipos nativos + +Por desgracia, Adventure no puede proporcionar una API para todos los lugares del juego donde se usan componentes del chat. Sin embargo, en los casos que no cubre la API de `Audience`, +es posible convertir componentes entre tipos nativos y de Adventure. Consulta los tipos nativos que implementan +interfaces de Adventure y los métodos de `MinecraftAudiences` para ver otras conversiones disponibles. diff --git a/src/content/docs/es/adventure/platform/native.md b/src/content/docs/es/adventure/platform/native.md new file mode 100644 index 000000000..d5cd1ca4d --- /dev/null +++ b/src/content/docs/es/adventure/platform/native.md @@ -0,0 +1,20 @@ +--- +title: Compatibilidad nativa +slug: es/adventure/platform/native +description: Todos los programas con compatibilidad nativa. +--- + +Las plataformas nativas integran Adventure directamente con la API que proporcionan y la incluyen automáticamente. +Esto les permite integrar Adventure mejor con el resto del juego y evita que los usuarios tengan que encargarse de distribuir +Adventure y algún adaptador de plataforma. + +Los siguientes programas ofrecen compatibilidad nativa con Adventure. + +| Plataforma | Versión mínima | Notas adicionales | +|------------|--------------------------------------|------------------------------------------------------------------------------------------------------------------| +| Sponge | Sponge 8 (1.16.5) | | +| Velocity | 1.1.0 build 158 | Para obtener más información, consulta la [documentación de Velocity](/es/velocity/dev/pitfalls#audience-operations-are-not-fully-supported) | +| Paper | 1.16.5 build 473 | | +| Minestom | Build 7494725 | Para obtener más información, consulta [Minestom Wiki](https://minestom.net/docs/feature/adventure) | +| Fabric | `adventure-platform-fabric` 5.3.0 | No es totalmente nativo, pero las interfaces inyectadas ofrecen una experiencia casi nativa | +| Fidorial | 0.1.0 | Para obtener más información, consulta el [repositorio de Fidorial en GitHub](https://github.com/Fidorial/Fidorial) | diff --git a/src/content/docs/es/adventure/platform/neoforge.mdx b/src/content/docs/es/adventure/platform/neoforge.mdx new file mode 100644 index 000000000..e85506a55 --- /dev/null +++ b/src/content/docs/es/adventure/platform/neoforge.mdx @@ -0,0 +1,105 @@ +--- +title: NeoForge +slug: es/adventure/platform/neoforge +description: Implementación de Adventure para NeoForge. +--- + +import Dependency from "/src/components/Dependency.astro"; +import { LATEST_ADVENTURE_PLATFORM_MOD_RELEASE, LATEST_ADVENTURE_PLATFORM_MOD_SUPPORTED_MC_RANGE } from "/src/utils/versions"; + +Adventure admite NeoForge en *Minecraft: Java Edition* 1.21 y versiones posteriores, tanto en el servidor como en el cliente. Por lo general, cada versión principal de Minecraft requiere +una nueva versión de la plataforma. + +La plataforma admite todas las funciones, incluidas la localización y los renderizadores personalizados. + +## Dependencia + +La plataforma NeoForge se empaqueta como mod y está diseñada para incluirse en otros mods mediante el empaquetado jar-in-jar. Como los demás proyectos de Adventure, +las versiones se distribuyen en Maven Central y las compilaciones snapshot en Sonatype OSS: + +El siguiente ejemplo usa ModDevGradle (`net.neoforged.moddev`). Usa `implementation` para la dependencia de desarrollo +y `jarJar` para empaquetar la plataforma en tu mod: + + + +La versión actual de la plataforma, {LATEST_ADVENTURE_PLATFORM_MOD_RELEASE}, está destinada a Minecraft {LATEST_ADVENTURE_PLATFORM_MOD_SUPPORTED_MC_RANGE}. + +:::danger[Atención] + +Cada versión principal de Minecraft requiere distintas versiones de la plataforma. Para versiones anteriores de Minecraft, consulta la tabla +de [Con mods (API compartida de Fabric y NeoForge)](/es/adventure/platform/modded). + +::: + +## Uso básico + +Consulta [Con mods (API compartida de Fabric y NeoForge)](/es/adventure/platform/modded) para obtener información de uso común a NeoForge y Fabric. + +## Servidor + +Se puede acceder al lado del servidor lógico de la plataforma con mods siempre que haya un servidor disponible, mediante una instancia `MinecraftServerAudiences`. +De forma predeterminada, los componentes traducibles se renderizan con el traductor global, aunque se puede pasar un renderizador personalizado al inicializar la plataforma. + +Se admiten todos los métodos de la interfaz `AudienceProvider`. + +Para empezar a usar Adventure, configura un proveedor de audiencias como este: + +```java +@Mod("my_mod") +public class MyMod { + + private volatile MinecraftServerAudiences adventure; + + public MinecraftServerAudiences adventure() { + if (this.adventure == null) { + throw new IllegalStateException("Tried to access Adventure without a running server!"); + } + return this.adventure; + } + + public MyMod() { + // Registrar las devoluciones de llamada del ciclo de vida del servidor. + // Así se garantiza que se borren los datos de la plataforma entre instancias del juego. + // Esto es importante en el servidor integrado, donde puede haber varias + // instancias del servidor durante la inicialización de un mismo mod. + NeoForge.EVENT_BUS.addListener((ServerStartingEvent e) -> + this.adventure = MinecraftServerAudiences.of(e.getServer()) + ); + NeoForge.EVENT_BUS.addListener((ServerStoppedEvent e) -> + this.adventure = null + ); + } +} +``` + +Desde aquí, se pueden obtener audiencias para jugadores y cualquier otro `CommandSource`. También hay instancias especializadas de serializadores que permiten usar +información del juego al serializar componentes. + +## Comandos + +La plataforma NeoForge incluye un método para registrar `KeyArgumentType` y `ComponentArgumentType`: + - `AdventureArgumentTypes.register();` + +Debes llamarlo desde el constructor de la clase anotada con `@Mod`. +Si registras los tipos de argumento en el servidor, todos los clientes que se unan también deberán tenerlos +registrados. + +## Cliente + +Una particularidad de la plataforma con mods es que admite operaciones exclusivamente del lado del cliente. La configuración es más sencilla que la del servidor, ya que el cliente es un singleton y +solo hay un sujeto sobre el que actuar: el jugador del cliente. + +Esto significa que la mayoría de los usuarios puede tratar el objeto `MinecraftClientAudiences` como un singleton. La única excepción son quienes usan un renderizador personalizado. Así, usar audiencias de Adventure +es bastante sencillo, como muestra este ejemplo de código: + +```java +void doThing() { + // Obtener la audiencia + final Audience client = MinecraftClientAudiences.of().audience(); + + // Hacer algo. Esto solo funcionará cuando el jugador esté dentro de la partida. + client.sendMessage(Component.text("meow", NamedTextColor.DARK_PURPLE)); +} +``` + +Está disponible toda la funcionalidad de la interfaz `Audience`, incluida la localización. diff --git a/src/content/docs/es/adventure/platform/spongeapi.mdx b/src/content/docs/es/adventure/platform/spongeapi.mdx new file mode 100644 index 000000000..db6c595e4 --- /dev/null +++ b/src/content/docs/es/adventure/platform/spongeapi.mdx @@ -0,0 +1,47 @@ +--- +title: SpongeAPI +slug: es/adventure/platform/spongeapi +description: Implementación de Adventure para SpongeAPI. +--- + +import Dependency from "/src/components/Dependency.astro"; +import { LATEST_ADVENTURE_PLATFORM_RELEASE } from "/src/utils/versions"; + +Adventure ofrece una plataforma para SpongeAPI 7 en *Minecraft: Java Edition* 1.12. + +:::danger + +La implementación de la plataforma Adventure para SpongeAPI 7 ya no se mantiene. +El equipo de Adventure ya no ofrece asistencia para estas bibliotecas. + +Recomendamos que quienes usan estas bibliotecas migren a programas modernos con [compatibilidad nativa con Adventure](/es/adventure/platform/native) (por ejemplo, SpongeAPI 8 o posterior). + +::: + +Declaración de la dependencia: + + + +## Uso + +La plataforma SpongeAPI se puede crear mediante la inyección de dependencias de Guice o directamente. Recomendamos usar la inyección, ya que requiere menos código repetitivo. + +Un plugin de ejemplo es bastante sencillo: + +```java +@Plugin(/* [...] */) +public class MyPlugin { + private final SpongeAudiences adventure; + + @Inject + MyPlugin(final SpongeAudiences adventure) { + this.adventure = adventure; + } + + public SpongeAudiences adventure() { + return this.adventure; + } +} +``` + +Esto configura una instancia de `SpongeAudiences` que puede proporcionar audiencias para los jugadores o cualquier `MessageReceiver`. diff --git a/src/content/docs/es/adventure/platform/viaversion.md b/src/content/docs/es/adventure/platform/viaversion.md new file mode 100644 index 000000000..8016e177b --- /dev/null +++ b/src/content/docs/es/adventure/platform/viaversion.md @@ -0,0 +1,22 @@ +--- +title: ViaVersion +slug: es/adventure/platform/viaversion +description: Uso de Adventure con ViaVersion. +--- + +:::danger + +La implementación de la plataforma Adventure para ViaVersion ya no se mantiene. +El equipo de Adventure ya no ofrece asistencia para estas bibliotecas. + +Recomendamos que quienes usan estas bibliotecas migren a plataformas modernas con [compatibilidad nativa con Adventure](/es/adventure/platform/native) (por ejemplo, Velocity, Paper y Sponge API 8 o posterior). + +::: + +En las plataformas compatibles (Sponge 7 y Bukkit), Adventure puede ampliar su funcionalidad +usando la API de [ViaVersion](https://hangar.papermc.io/ViaVersion/ViaVersion) +para enviar paquetes directamente al cliente. Por ejemplo, esto permite que un plugin de un servidor de Minecraft +1.7 envíe mensajes de chat y títulos RGB a clientes que usan versiones más recientes de Minecraft. + +Si incluyes las plataformas Sponge o Bukkit, no tienes que hacer nada más: ViaVersion +se detectará y se habilitará su compatibilidad. diff --git a/src/content/docs/es/adventure/resource-pack.md b/src/content/docs/es/adventure/resource-pack.md new file mode 100644 index 000000000..e6f16c6a7 --- /dev/null +++ b/src/content/docs/es/adventure/resource-pack.md @@ -0,0 +1,70 @@ +--- +title: Paquetes de recursos +slug: es/adventure/resource-pack +description: Guía para usar paquetes de recursos con Adventure. +--- + +Además de los paquetes de recursos que cada jugador controla en su cliente, el juego permite que los servidores envíen a los clientes URL de paquetes de recursos que los jugadores pueden aceptar. Esto permite a los servidores ofrecer estilos personalizados. + +Al principio solo se podía enviar un paquete de recursos, pero desde *Minecraft 1.20.3* el servidor puede enviar varios paquetes para apilarlos y, si hace falta, quitarlos individualmente. + +## Enviar paquetes de recursos + +Un paquete de recursos se identifica mediante: + * su UUID + * un URI al archivo ZIP del paquete de recursos + * el hash SHA-1 del archivo ZIP del paquete de recursos, como cadena hexadecimal + +Esto se conoce como `ResourcePackInfo`. + +Cada lote de paquetes de recursos que se envía mediante un `ResourcePackRequest` incluye: + * uno o más paquetes de recursos + * una devolución de llamada para realizar acciones según las respuestas del cliente + * una opción para reemplazar los paquetes existentes proporcionados por el servidor o apilar encima los más recientes + * si estos paquetes de recursos son obligatorios + * un mensaje para mostrar al usuario si aún no ha decidido si permite los paquetes de recursos del servidor + +## Ejemplos + +Envía a un cliente un único paquete de recursos obligatorio, con un UUID calculado a partir de su nombre. + +```java +private static final ResourcePackInfo PACK_INFO = ResourcePackInfo.resourcePackInfo() + .uri(URI.create("https://example.com/resourcepack.zip")) + .hash("2849ace6aa689a8c610907a41c03537310949294") + .build(); + +public void sendResourcePack(final Audience target) { + final ResourcePackRequest request = ResourcePackRequest.resourcePackRequest() + .packs(PACK_INFO) + .prompt(Component.text("¡Descarga el paquete de recursos!")) + .required(true) + .build(); + + // Enviar la solicitud del paquete de recursos a la audiencia destinataria + target.sendResourcePacks(request); +} + +public void sendOptionalResourcePack(final Audience target) { + final ResourcePackRequest request = ResourcePackRequest.resourcePackRequest() + .packs(PACK_INFO) + .prompt(Component.text("¡Descarga el paquete de recursos!")) + .required(false) + .build(); + + // Enviar la solicitud del paquete de recursos a la audiencia destinataria + target.sendResourcePacks(request); +} +``` + +## Devoluciones de llamada + +La función de devolución de llamada permite que los servidores respondan a la información sobre la descarga del paquete que envía el cliente. Las versiones más recientes del juego proporcionan más información sobre las distintas fases, pero todas ofrecen información básica sobre el estado de la descarga y la aplicación. Ten en cuenta que las respuestas dependen por completo del cliente, así que los clientes modificados pueden enviar información incorrecta (por ejemplo, indicar que se aplicó un paquete obligatorio cuando no es así), no enviar nada o enviar información incoherente (actualizaciones de estado después de recibir una actualización final). Por tanto, cualquier acción basada en una devolución de llamada debe diseñarse de forma defensiva para tolerar cualquier comportamiento del cliente. + +En el caso de audiencias envolventes, la audiencia proporcionada en la devolución de llamada pretende ser exactamente la misma a la que se envió el paquete de recursos; cuando sea necesario, volverá a envolver cualquier valor subyacente devuelto. + +## Quitar paquetes de recursos + +Los paquetes de recursos se pueden quitar en cantidades determinadas mediante `Audience.removeResourcePacks()` o todos a la vez mediante `Audience.clearResourcePacks()`. + +Los métodos para quitar paquetes tienen varias sobrecargas: permiten quitarlos usando únicamente un UUID o reutilizando las estructuras de datos usadas para aplicarlos. diff --git a/src/content/docs/es/adventure/serializer/ansi.mdx b/src/content/docs/es/adventure/serializer/ansi.mdx new file mode 100644 index 000000000..6a054a3e7 --- /dev/null +++ b/src/content/docs/es/adventure/serializer/ansi.mdx @@ -0,0 +1,80 @@ +--- +title: ANSI +slug: es/adventure/serializer/ansi +description: Serialización de componentes a ANSI. +--- + +import Dependency from "/src/components/Dependency.astro"; +import { LATEST_ANSI_RELEASE, LATEST_ADVENTURE_API_RELEASE } from "/src/utils/versions"; + +El serializador de texto ANSI es un codificador que convierte componentes en texto con +[códigos de escape ANSI](https://en.wikipedia.org/wiki/ANSI_escape_code), que permite mostrar texto con estilo en una terminal. Así, por ejemplo, se pueden generar registros del servidor +con componentes y conservar sus colores y estilos. + +Ten en cuenta que, al ser un codificador, solo puede serializar componentes y no puede +deserializar texto para convertirlo de nuevo en componentes. + +Declaración de la dependencia: + + + +## Uso + +Existen distintos tipos de códigos de escape ANSI que permiten diferentes niveles de precisión de color, +pero no todas las terminales admiten las secuencias de escape más recientes. +De forma predeterminada, `ANSIComponentSerializer` intentará deducir los tipos de +secuencias de escape compatibles a partir de las variables de entorno del sistema. + +Esto se puede anular para una instancia concreta del serializador mediante el método +`colorLevel` del constructor. + +También se puede anular globalmente mediante propiedades del sistema. La propiedad +`net.kyori.ansi.colorLevel` se puede establecer al iniciar la JVM mediante la +opción de línea de comandos `-Dnet.kyori.ansi.colorLevel=value`. Se pueden establecer +4 valores diferentes: + +* `none`: Evita que se emita cualquier secuencia de escape ANSI. +* `indexed16`: Conjunto original de 16 colores. +* `indexed256`: Conjunto algo más reciente de 256 colores. +* `truecolor`: Espectro completo de colores de 24 bits. + +También se pueden desactivar las secuencias de escape ANSI estableciendo en `false` +la propiedad del sistema `terminal.ansi`. + +## Biblioteca ANSI + +:::note + +Esta sección trata sobre la biblioteca independiente de componentes. Si solo te interesa +la implementación específica para componentes de Adventure, no necesitas leerla. + +::: + +`AnsiComponentSerializer` se basa en una biblioteca ANSI independiente, que gestiona +la lógica de bajo nivel de las secuencias de escape ANSI y también permite crear un conversor ANSI +para cualquier tipo de componente, no solo los de Adventure. + +Declaración de la dependencia: + + + +### Uso de la implementación + +Para empezar, debes crear una clase que implemente `StyleOps`, donde `S` es +el tipo de estilo de tu tipo de componente. Esta clase adaptadora permite que la lógica ANSI +acceda a las propiedades del estilo. + +Para iniciar la conversión, crea una instancia de `ANSIComponentRenderer` usando +uno de los métodos estáticos. El más sencillo es `ANSIComponentRenderer.toString()`; +pásale una instancia del adaptador `StyleOps` descrito anteriormente. + +Después, debes recorrer la estructura del árbol de componentes usando los métodos +`pushStyle()`, `text()` y `popStyle()` de la instancia del renderizador. + +Por último, llama a `complete()` cuando termines de recorrer el árbol. El trabajo del renderizador +habrá concluido. En el caso del renderizador `ToString`, puedes acceder al resultado +mediante el método `asString()`. + +Como se describe en la sección [Uso de ANSI](#uso), la biblioteca intentará deducir de forma predeterminada +los colores compatibles con el entorno actual. Esto se puede anular pasando un `ColorLevel` personalizado +al crear el renderizador o usando las propiedades del sistema descritas anteriormente. diff --git a/src/content/docs/es/adventure/serializer/gson.mdx b/src/content/docs/es/adventure/serializer/gson.mdx new file mode 100644 index 000000000..b8654ee1d --- /dev/null +++ b/src/content/docs/es/adventure/serializer/gson.mdx @@ -0,0 +1,50 @@ +--- +title: Gson +slug: es/adventure/serializer/gson +description: Serialización de componentes a JSON con Gson. +--- + +import Dependency from "/src/components/Dependency.astro"; +import { LATEST_ADVENTURE_API_RELEASE } from "/src/utils/versions"; + +El serializador de texto Gson convierte componentes de chat a su representación JSON +y viceversa mediante la biblioteca Gson. Si quieres enviar un componente de chat para +mostrarlo en un cliente de Minecraft o admitir funciones avanzadas de componentes de chat, +debes usar el serializador de texto Gson. + +Normalmente, quienes usan este serializador de texto solo necesitan deserializar un +componente de una fuente externa; las [plataformas](/es/adventure/platform) se encargan automáticamente de serializarlo +cuando se envía al usuario. + +Declaración de la dependencia: + + + +## Uso + +En Minecraft 1.16, Mojang introdujo varios cambios importantes en el formato JSON del chat: añadió +colores RGB y modificó la serialización de los eventos de desplazamiento. Los componentes generados para +versiones anteriores de Minecraft seguirán mostrándose en un cliente 1.16, +pero los componentes serializados para un cliente 1.16 no se podrán mostrar en +un cliente de Minecraft 1.15.2 o anterior. + +Para obtener un serializador compatible con clientes 1.16 y posteriores, usa +`GsonComponentSerializer.gson()`. Para obtener un serializador compatible con todas las versiones +de Minecraft que admiten componentes de texto, usa `GsonComponentSerializer.colorDownsamplingGson()`. +Este serializador reduce los colores RGB al color antiguo de Mojang más cercano y serializa +los eventos de desplazamiento de forma compatible con clientes anteriores. + +### ¿Qué serializador debo usar? + +Si solo vas a cargar y guardar componentes en un archivo de configuración o una base de datos, +probablemente quieras usar el serializador predeterminado para 1.16. + +Si quieres enviar un componente a un cliente, primero considera si puedes usar alguna de las +plataformas disponibles. Si no puedes usar una plataforma, en general es preferible usar el serializador predeterminado +para deserializar componentes (ya que es compatible con versiones anteriores) y decidir +si usas el serializador predeterminado o el que reduce los colores según la versión del cliente. + +### Uso avanzado + +El serializador Gson expone tanto la instancia `Gson` subyacente como un cargador que permite +registrar serializadores Adventure en cualquier instancia de `GsonBuilder`. diff --git a/src/content/docs/es/adventure/serializer/index.md b/src/content/docs/es/adventure/serializer/index.md new file mode 100644 index 000000000..9d028717d --- /dev/null +++ b/src/content/docs/es/adventure/serializer/index.md @@ -0,0 +1,58 @@ +--- +title: Serializadores de texto +slug: es/adventure/serializer +description: Todo lo que necesitas saber sobre los serializadores de texto y componentes. +sidebar: + label: Resumen +--- + +Los serializadores son la forma más básica de convertir datos de Adventure a otros formatos. +Algunos convierten a formatos estándar, mientras que otros +convierten a formatos propios de Adventure. + +- [JSON](/es/adventure/serializer/json) +- [Gson](/es/adventure/serializer/gson) +- [Formato antiguo](/es/adventure/serializer/legacy) +- [Texto sin formato](/es/adventure/serializer/plain) +- [MiniMessage](/es/adventure/minimessage) + +Los componentes se pueden convertir mediante cualquiera de estos serializadores: + +```java +// Crear un componente de texto +final TextComponent textComponent = Component.text() + .content("Hola ") + .color(NamedTextColor.GOLD) + .append(Component.text("mundo", NamedTextColor.AQUA, TextDecoration.BOLD)) + .append(Component.text("!", NamedTextColor.RED)) + .build(); + +// Convertir textComponent al formato JSON que Minecraft usa para la serialización. +final String json = JSONComponentSerializer.json().serialize(textComponent); + +// Convertir textComponent a una cadena antigua: "&6Hola &b&lmundo&c!" +final String legacy = LegacyComponentSerializer.legacyAmpersand().serialize(textComponent); + +// Convertir textComponent a una cadena sin formato: "Hola mundo" +final String plain = PlainTextComponentSerializer.plainText().serialize(textComponent); +``` + +Por supuesto, también es posible hacer lo mismo a la inversa para deserializar. + +```java +// Convertir el JSON usado por Minecraft para la serialización en un Component. +final Component component = JSONComponentSerializer.json().deserialize(json); + +// Convertir una cadena antigua (con códigos de formato) en un TextComponent. +final Component component = LegacyComponentSerializer.legacyAmpersand().deserialize("&6Hola &b&lmundo&c!"); + +// Convertir una cadena sin formato en un TextComponent. +final Component component = PlainTextComponentSerializer.plainText().deserialize("Hola mundo"); +``` + +## Codificadores de texto + +Los codificadores de texto son similares a los serializadores, pero solo ofrecen +operaciones unidireccionales: permiten serializar, pero no deserializar. + +- [ANSI](/es/adventure/serializer/ansi) diff --git a/src/content/docs/es/adventure/serializer/json.md b/src/content/docs/es/adventure/serializer/json.md new file mode 100644 index 000000000..2d87c355e --- /dev/null +++ b/src/content/docs/es/adventure/serializer/json.md @@ -0,0 +1,27 @@ +--- +title: JSON +slug: es/adventure/serializer/json +description: Serialización de componentes a su representación JSON. +--- + +El serializador JSON ofrece una interfaz común para las implementaciones de serializadores que convierten entre un componente y cadenas JSON. Así, una biblioteca puede admitir cualquier biblioteca JSON subyacente que una aplicación quiera usar. + +## Uso + +El serializador JSON funciona como los demás y ofrece las operaciones básicas de serialización y deserialización: + +```java +// Convertir un componente a texto +final String json = JSONComponentSerializer.json().serialize(Component.text("Hola mundo", NamedTextColor.LIGHT_PURPLE)); + +// Convertir una cadena JSON en un componente +final Component component = JSONComponentSerializer.json().deserialize(json); +``` + +Además, para usos avanzados que requieran configurar opciones de compatibilidad con formatos antiguos, se puede usar `JSONComponentSerializer.builder()`. + +## Implementaciones conocidas + +| Nombre | Descripción | +| ------------------------------------------------------------ | ------------------------------------------------------- | +| [adventure-text-serializer-gson](/es/adventure/serializer/gson) | Un serializador consolidado que usa la biblioteca Gson de Google. | diff --git a/src/content/docs/es/adventure/serializer/legacy.mdx b/src/content/docs/es/adventure/serializer/legacy.mdx new file mode 100644 index 000000000..b8abe424e --- /dev/null +++ b/src/content/docs/es/adventure/serializer/legacy.mdx @@ -0,0 +1,49 @@ +--- +title: Antiguo +slug: es/adventure/serializer/legacy +description: (Obsoleto) Serialización de componentes al formato antiguo. +--- + +import Dependency from "/src/components/Dependency.astro"; +import { LATEST_ADVENTURE_API_RELEASE } from "/src/utils/versions"; + +El serializador de texto antiguo convierte texto al formato de chat tradicional usado +en Minecraft antes de la versión 1.7 y todavía se usa por ser familiar para los propietarios de servidores. + +El serializador de texto antiguo no admite la mayoría de las funciones avanzadas, incluidos los eventos +de desplazamiento y clic, los componentes que no sean de texto y las inserciones. Sí admite los colores RGB +(consulta la sección [Compatibilidad con RGB](#compatibilidad-con-rgb)) y, si se solicita explícitamente, puede convertir las URL +en componentes en los que se pueda hacer clic (ten en cuenta que los eventos de clic +que contienen una URL *no* se serializan). Si necesitas funciones avanzadas, considera +usar [MiniMessage](/es/adventure/minimessage). + +Declaración de la dependencia: + + + +## Uso + +Se accede al serializador de texto antiguo mediante `LegacyComponentSerializer`. Los serializadores predeterminados +incluyen uno que usa el símbolo de sección (§) (para mostrar texto en clientes antiguos) y otro que usa el signo «&», que suele emplearse en configuraciones y +comandos para indicar códigos de color. + +La configuración predeterminada del serializador de texto antiguo deserializa los tres formatos +RGB que admite Adventure, pero solo serializa los colores antiguos de Mojang +(reduciéndolos al color más cercano cuando sea necesario) y no convierte las URL del texto en +enlaces. Puedes configurar una instancia para que añada automáticamente eventos de clic a las URL de +los componentes y permitir que el serializador codifique colores RGB con el formato RGB de Adventure o el de BungeeCord mediante el constructor. + +## Compatibilidad con RGB + +El serializador antiguo admite la deserialización de tres formatos distintos: + +* Códigos antiguos de color y formato de Mojang (como `§a` o `§l`). +* Un formato RGB específico de Adventure, diseñado para que sea fácil de editar + (por ejemplo, `§#a25981`). +* Un formato de código de color RGB de BungeeCord, compatible con rutinas de deserialización + antiguas, pero difícil de manipular y que deja al usuario la responsabilidad de asignar + un valor alternativo para clientes sin compatibilidad con RGB (como `§x§a§2§5§9§8§1`). + +El serializador antiguo reduce los colores RGB de forma predeterminada, pero puedes crear un serializador +que los codifique con el formato RGB de Adventure o de BungeeCord mediante el +constructor. diff --git a/src/content/docs/es/adventure/serializer/plain.mdx b/src/content/docs/es/adventure/serializer/plain.mdx new file mode 100644 index 000000000..83d033288 --- /dev/null +++ b/src/content/docs/es/adventure/serializer/plain.mdx @@ -0,0 +1,29 @@ +--- +title: Texto sin formato +slug: es/adventure/serializer/plain +description: Obtener el contenido de texto sin formato de los componentes. +--- + +import Dependency from "/src/components/Dependency.astro"; +import { LATEST_ADVENTURE_API_RELEASE } from "/src/utils/versions"; + +El serializador de texto sin formato convierte los componentes del chat a su representación de texto sin formato +y viceversa. Por ello, es el serializador de texto más sencillo de Adventure. Resulta +útil para admitir clientes antiguos, generar registros, eliminar el formato de un componente +de origen externo y ofrecer un ejemplo pequeño e independiente de un serializador de texto. + +Por su naturaleza, el serializador de texto sin formato no admite funciones avanzadas como +colores, eventos de desplazamiento o clic, enlaces URL o inserciones. Si necesitas funciones avanzadas, +considera usar [MiniMessage](/es/adventure/minimessage). + +Declaración de la dependencia: + + + +## Uso + +Esto crea una instancia predeterminada que ignora silenciosamente los componentes de asignación de teclas y los traducibles. También puedes crear tu propio +`PlainTextComponentSerializer` para asignar los componentes a alguna representación de texto sin formato. + +La deserialización de texto sin formato equivale a `Component.text(string)`. No se +preprocesa la entrada. La deserialización se implementa para mantener la coherencia de la API. diff --git a/src/content/docs/es/adventure/sound.md b/src/content/docs/es/adventure/sound.md new file mode 100644 index 000000000..acd572cff --- /dev/null +++ b/src/content/docs/es/adventure/sound.md @@ -0,0 +1,84 @@ +--- +title: Sonido +slug: es/adventure/sound +description: Guía para reproducir sonidos con Adventure. +--- + +Adventure incluye una API para reproducir cualquier sonido integrado o proporcionado por un paquete de recursos. Ten en cuenta que +no todas las plataformas implementan la reproducción de sonido. + +## Crear un sonido + +Los sonidos se componen de: + * Una `Key` (también conocida como `Identifier` o `ResourceLocation`) que determina qué sonido se reproduce. Se pueden usar sonidos personalizados de cualquier paquete de recursos. Si el cliente no reconoce un sonido, lo ignorará (aunque mostrará una advertencia en el registro del cliente). + * Una fuente de sonido, que indica al cliente qué tipo de sonido escucha. Los ajustes de sonido del cliente también se asocian a una fuente. + * Un número que determina el radio en el que se puede oír el sonido + * Un número de 0 a 2 que determina el tono del sonido + +**Ejemplos:** + +```java +// Crear un sonido integrado con el volumen y el tono estándar +Sound musicDisc = Sound.sound(Key.key("music_disc.13"), Sound.Source.MUSIC, 1F, 1F); + +// Crear un sonido del paquete de recursos con un tono más alto +Sound myCustomSound = Sound.sound(Key.key("adventure", "rawr"), Sound.Source.AMBIENT, 1F, 1.1F); +``` + +## Reproducir un sonido + +:::caution + +El cliente puede reproducir varios sonidos a la vez, pero desde la versión 1.16 el límite es de 8 sonidos simultáneos. + +En las versiones 1.15.2-1.16.5, debido a [`MC-138832`](https://mojira.dev/MC-138832), se ignoran el volumen y el tono de los sonidos reproducidos con un emisor. + +Como se documenta en [`MC-146721`](https://mojira.dev/MC-146721), los sonidos estéreo no se reproducen en una posición concreta ni siguen a una entidad; por ello, se ignoran los parámetros de ubicación o emisor. + +::: + +Una vez creado el sonido, puedes reproducirlo para una audiencia mediante varios métodos: + +```java +// Reproducir un sonido en la ubicación de la audiencia +audience.playSound(sound); + +// Reproducir un sonido en una ubicación concreta +audience.playSound(sound, 100, 0, 150); + +// Reproducir un sonido que siga al miembro de la audiencia +audience.playSound(sound, Sound.Emitter.self()); + +// Reproducir un sonido que siga a otro emisor (normalmente, una entidad) +audience.playSound(sound, someEntity); +``` + +## Detener sonidos + +La detención de sonidos detiene los sonidos seleccionados, desde todos los que reproduce el cliente hasta sonidos concretos identificados por nombre. + +```java +public void stopMySound(final Audience target) { + // Detener un sonido para el destinatario + target.stopSound(SoundStop.named(Key.key("music_disc.13"))); + // Detener todos los sonidos del clima para el destinatario + target.stopSound(SoundStop.source(Sound.Source.WEATHER)); + // Detener todos los sonidos para el destinatario + target.stopSound(SoundStop.all()); +} +``` + +Los objetos para detener sonidos se pueden crear con los métodos del ejemplo anterior. +También pueden construirse directamente a partir de un sonido. + +```java +// Obtener una instrucción para detener un sonido concreto +mySound.asStop(); + +// También se pueden detener sonidos directamente con el método stopSound +audience.stopSound(mySound); +``` + +## Crear un sonido personalizado + +Usa el archivo `sounds.json` para definir sonidos en un paquete de recursos. Encontrarás más información sobre estos límites en [Minecraft Wiki](https://minecraft.wiki/w/Sounds.json). diff --git a/src/content/docs/es/adventure/tablist.md b/src/content/docs/es/adventure/tablist.md new file mode 100644 index 000000000..da0f25432 --- /dev/null +++ b/src/content/docs/es/adventure/tablist.md @@ -0,0 +1,37 @@ +--- +title: Lista de jugadores / lista de pestañas +slug: es/adventure/tablist +description: Configuración de la lista de jugadores con Adventure. +--- + +Adventure solo permite cambiar el encabezado (encima de los jugadores) y el pie (debajo de los jugadores) de la lista de jugadores. + +![Imagen de una lista de jugadores de un servidor multijugador, con el encabezado y el pie resaltados, vista en el cliente vanilla de Minecraft](../../adventure/assets/tablist.png) + +**Uso** + +En cualquier `Audience`, usa `Audience.sendPlayerListHeader(Component)`, `Audience.sendPlayerListFooter(Component)` +y/o `Audience.sendPlayerListHeaderAndFooter(Component, Component)`. + +El hecho de que enviar solo el encabezado o el pie conserve el otro elemento existente depende de la plataforma +que uses. Lo más probable es que los servidores permitan conservarlos al enviarlos por separado, mientras que los proxies +probablemente solo permitan enviar ambos a la vez. + +**Ejemplos** + +```java +public void onPlayerJoin(final Audience player) { + final Component header = Component.text("Mi servidor genial", NamedTextColor.BLUE); + final Component footer = Component.text("Hoy es hoy"); + player.sendPlayerListHeaderAndFooter(header, footer); +} +``` + +Según la plataforma, el siguiente ejemplo también podría mostrar un encabezado existente. + +```java +public void onDayChange(final Audience server) { + final Component footer = Component.text("Mañana será mañana"); + server.sendPlayerListFooter(footer); +} +``` diff --git a/src/content/docs/es/adventure/text.md b/src/content/docs/es/adventure/text.md new file mode 100644 index 000000000..0104251b2 --- /dev/null +++ b/src/content/docs/es/adventure/text.md @@ -0,0 +1,94 @@ +--- +title: Texto (componentes del chat) +slug: es/adventure/text +description: Todo lo que necesitas saber sobre los componentes. +--- + +Los componentes representan los componentes del chat de Minecraft. + +## Crear componentes + +```java +// Crear una línea de texto que diga «¡Eres un conejo! Pulsa para saltar», con colores y estilos. +final TextComponent textComponent = Component.text("¡Eres un ") + .color(TextColor.color(0x443344)) + .append(Component.text("conejo", NamedTextColor.LIGHT_PURPLE)) + .append(Component.text(". Pulsa ")) + .append( + Component.keybind("key.jump") + .color(NamedTextColor.LIGHT_PURPLE) + .decoration(TextDecoration.BOLD, true) + ) + .append(Component.text(" para saltar.")); +// Ahora puedes enviar `textComponent` a un destinatario, como un cliente. +``` + +También puedes usar un constructor, que es mutable y crea un único +componente final con los componentes secundarios. + +```java +// Crear una línea de texto que diga «¡Eres un conejo! Pulsa para saltar», con colores y estilos. +final TextComponent textComponent2 = Component.text() + .content("¡Eres un ") + .color(TextColor.color(0x443344)) + .append(Component.text().content("conejo").color(NamedTextColor.LIGHT_PURPLE)) + .append(Component.text(". Pulsa ")) + .append( + Component.keybind().keybind("key.jump") + .color(NamedTextColor.LIGHT_PURPLE) + .decoration(TextDecoration.BOLD, true) + .build() + ) + .append(Component.text(" para saltar.")) + .build(); +// Ahora puedes enviar `textComponent2` a un destinatario, como un cliente. +``` + +## Aplicar estilos a los componentes + +Los estilos amplían `TextColor` y `TextDecoration`, y se pueden aplicar a componentes de texto. +`TextColor` representa cualquier color del espectro RGB. +También puedes usar `NamedTextColor` para elegir un color de la paleta predeterminada. +Están disponibles las siguientes decoraciones de texto: + +* *Cursiva* +* **Negrita** +* Tachado +* Subrayado +* Ofuscado + +## Eventos + +Actualmente hay dos tipos de eventos disponibles para los componentes de texto. +Los eventos de desplazamiento permiten mostrar otro componente, objeto o entidad cuando el usuario pasa el cursor sobre el texto. +Al hacer clic en un componente de texto, se activa un evento de clic que puede realizar una de las siguientes acciones: + +* Abrir una URL +* Abrir un archivo +* Ejecutar un comando +* Sugerir un comando +* Cambiar la página de un libro +* Copiar una cadena al portapapeles +* Abrir un diálogo +* Enviar una carga personalizada al servidor + +## Serializar y deserializar componentes + +También se admite la serialización a representaciones JSON, antiguas y de texto sin formato. + +Los componentes se pueden serializar con los [serializadores de texto](/es/adventure/serializer). + +## Usar componentes en tu aplicación + +La forma de usar componentes en tu aplicación dependerá, por supuesto, +de lo que quieras conseguir. + +Sin embargo, la tarea más habitual probablemente sea enviar un componente a +algún cliente de Minecraft. El método dependerá de la plataforma donde se ejecute +tu programa, pero probablemente implique serializar el componente al formato JSON de Minecraft y luego enviar +el JSON mediante otro método que proporcione la plataforma. + +La biblioteca de texto es independiente de la plataforma y, por tanto, no ofrece +ninguna forma de enviar componentes a los clientes. Algunas plataformas implementan [Adventure de forma nativa](/es/adventure/platform/native), por lo que puedes usar `Components` +directamente con su API. Para otras plataformas (Spigot/Bukkit, BungeeCord y SpongeAPI 7), +ofrecemos puentes de compatibilidad como [Plataformas](/es/adventure/platform), que puedes distribuir con tus propios plugins. diff --git a/src/content/docs/es/adventure/titles.md b/src/content/docs/es/adventure/titles.md new file mode 100644 index 000000000..3c6da4474 --- /dev/null +++ b/src/content/docs/es/adventure/titles.md @@ -0,0 +1,37 @@ +--- +title: Títulos +slug: es/adventure/titles +description: Mostrar títulos a los jugadores. +--- + +## Crear un título + +Los títulos se componen de: + * Un componente para el título principal + * Un componente para el subtítulo + * Opcionalmente, se puede usar un objeto `Title.Times` para determinar la duración de la aparición gradual, la permanencia en pantalla y la desaparición gradual + + +**Ejemplos:** + +```java +public void showMyTitle(final Audience target) { + final Component mainTitle = Component.text("Este es el título principal", NamedTextColor.WHITE); + final Component subtitle = Component.text("Este es el subtítulo", NamedTextColor.GRAY); + + // Crear un título sencillo con los valores predeterminados de aparición, permanencia y desaparición gradual + final Title title = Title.title(mainTitle, subtitle); + + // Enviar el título a la audiencia + target.showTitle(title); +} + +public void showMyTitleWithDurations(final Audience target) { + final Title.Times times = Title.Times.times(Duration.ofMillis(500), Duration.ofMillis(3000), Duration.ofMillis(1000)); + // Este título usará el objeto times para aparecer en 500 ms, permanecer 3000 ms y desaparecer en 1000 ms + final Title title = Title.title(Component.text("¡Hola!"), Component.empty(), times); + + // Enviar el título; también puedes usar Audience#clearTitle() para quitarlo en cualquier momento + target.showTitle(title); +} +``` diff --git a/src/content/docs/es/adventure/version-history/index.mdx b/src/content/docs/es/adventure/version-history/index.mdx new file mode 100644 index 000000000..2cb1df534 --- /dev/null +++ b/src/content/docs/es/adventure/version-history/index.mdx @@ -0,0 +1,16 @@ +--- +title: Historial de versiones +slug: es/adventure/version-history +description: Páginas dedicadas a mostrar los registros de cambios más recientes. +tableOfContents: false +--- + +import { CardGrid, LinkCard } from "@astrojs/starlight/components"; + +Estos registros de cambios de cada proyecto reproducen los publicados en la página de versiones de GitHub de su repositorio. + + + + + + diff --git a/src/content/docs/es/folia/admin/index.mdx b/src/content/docs/es/folia/admin/index.mdx new file mode 100644 index 000000000..8370163c2 --- /dev/null +++ b/src/content/docs/es/folia/admin/index.mdx @@ -0,0 +1,13 @@ +--- +title: Administración +tableOfContents: false +--- + +import PageCards from "/src/components/PageCards.astro"; + +¡Te damos la bienvenida a la guía de administración de Folia! Esta guía incluye información y tutoriales +sobre la administración de un servidor Folia. + +#### Referencia + + diff --git a/src/content/docs/es/folia/admin/reference/faq.md b/src/content/docs/es/folia/admin/reference/faq.md new file mode 100644 index 000000000..278e64c1e --- /dev/null +++ b/src/content/docs/es/folia/admin/reference/faq.md @@ -0,0 +1,72 @@ +--- +title: Preguntas frecuentes +description: Respondemos a las preguntas más frecuentes de nuestra comunidad. +slug: es/folia/faq +--- + +## ¿Qué tipos de servidores pueden beneficiarse de Folia? +Los tipos de servidores en los que los jugadores suelen repartirse por el mundo, +como skyblock o SMP, son los que más se beneficiarán de Folia. Además, el servidor +debería tener una cantidad considerable de jugadores. + +## ¿En qué hardware funciona mejor Folia? +Lo ideal es contar con al menos 16 _núcleos_ (no hilos). + +## ¿Cuál es la mejor forma de configurar Folia? +En primer lugar, se recomienda pregenerar el mundo para reducir considerablemente +la cantidad de hilos de trabajo necesarios para el sistema de chunks. + +La siguiente es una estimación _muy aproximada_ basada en las pruebas +realizadas antes de publicar Folia en nuestro servidor de pruebas, que +alcanzó un máximo de ~330 jugadores. Por tanto, no es exacta y requerirá ajustes: +úsala solo como punto de partida. + +Ten en cuenta la cantidad total de núcleos disponibles en la máquina. Después, asigna hilos para: +- E/S de Netty: ~4 por cada 200-300 jugadores +- Hilos de E/S del sistema de chunks: ~3 por cada 200-300 jugadores +- Hilos de trabajo del sistema de chunks si el mundo está pregenerado: ~2 por cada 200-300 jugadores +- No hay una estimación fiable para los hilos de trabajo del sistema de chunks si el mundo no está pregenerado. En + nuestro servidor de pruebas asignamos 16 hilos, pero la generación de chunks seguía siendo + lenta con ~300 jugadores. +- Configuración del GC: ???? La configuración del GC sí asigna hilos simultáneos y debes + saber exactamente cuántos. Normalmente se hace mediante la opción `-XX:ConcGCThreads=n`. No + la confundas con `-XX:ParallelGCThreads=n`, ya que los hilos paralelos del GC solo se ejecutan cuando + la aplicación está pausada por el GC y, por tanto, no deben incluirse en el cálculo. + +Después de esas asignaciones, puedes destinar a los hilos de tick los núcleos restantes hasta +llegar al 80 % de uso (el total de hilos asignados debe ser < 80 % de las CPU disponibles). +Esto se configura en la configuración global, mediante `threaded-regions.threads`. + +No deberías asignar más del 80 % de los núcleos porque los plugins e incluso el servidor pueden +utilizar hilos adicionales que no puedes configurar ni prever. + +Además, todo lo anterior es una estimación aproximada basada en la cantidad de jugadores. +Es muy probable que la asignación de hilos no sea ideal y tengas que ajustarla según el uso +de los hilos que observes. + +## ¿Qué comandos desactiva Folia? +Actualmente, Folia desactiva algunos comandos. Son los siguientes: +- Bossbar commands +- Clone commands +- Data commands +- Datapack +- Debug +- Function +- Item commands +- Loot +- Reload +- Return +- Ride +- Rotate +- Schedule +- Scoreboard +- Spectate +- SpreadPlayers +- Tag +- Team +- TeamMsg +- Tick +- Trigger +- Perf +- SaveAll +- Restart diff --git a/src/content/docs/es/folia/admin/reference/index.mdx b/src/content/docs/es/folia/admin/reference/index.mdx new file mode 100644 index 000000000..57af22c36 --- /dev/null +++ b/src/content/docs/es/folia/admin/reference/index.mdx @@ -0,0 +1,10 @@ +--- +title: Referencia +tableOfContents: false +--- + +import PageCards from "/src/components/PageCards.astro"; + +Referencia sobre el funcionamiento de Folia. + + diff --git a/src/content/docs/es/folia/admin/reference/overview.md b/src/content/docs/es/folia/admin/reference/overview.md new file mode 100644 index 000000000..336708cc4 --- /dev/null +++ b/src/content/docs/es/folia/admin/reference/overview.md @@ -0,0 +1,288 @@ +--- +title: Descripción general +description: Descripción general del funcionamiento de Folia. +slug: es/folia/reference/overview +--- + +Este documento presenta una descripción abstracta de los cambios realizados por Folia. Folia divide los chunks de todos los mundos cargados +en regiones que funcionan de forma independiente, de modo que estas se ejecutan +independientemente y en paralelo. Primero se describen las operaciones dentro de una región +y después las operaciones entre regiones. + +## Reglas para regiones independientes + +Para garantizar que las regiones sean independientes, las reglas de mantenimiento deben asegurar que una región que está ejecutando ticks +no tenga regiones vecinas directamente adyacentes que también estén ejecutándolos. +Las siguientes reglas garantizan este invariante: +1. Una región que está ejecutando ticks no puede crecer mientras lo hace. +2. Al inicio, cada región que ejecuta ticks debe poseer un pequeño margen de chunks fuera + de su perímetro. +3. Las regiones no pueden _empezar_ a ejecutar ticks si tienen una región vecina adyacente. +4. Las regiones adyacentes deben fusionarse finalmente para formar una sola región. + +Además, para garantizar que una región no esté compuesta por varias regiones independientes +(lo que limitaría el paralelismo), las regiones que contengan más de +un área independiente deben dividirse finalmente en regiones independientes +cuando sea posible. + +Por último, para que las regiones que ejecutan ticks puedan almacenar y mantener datos +sobre la región actual (por ejemplo, el recuento de ticks, las entidades y chunks de la región, +las listas de ticks de bloques y fluidos, entre otros), cada región tiene +su propio objeto de datos. Solo puede accederse a él mientras se ejecutan ticks en la región y +desde el hilo que los ejecuta. También hay callbacks para fusionar +o dividir regiones y actualizar correctamente el objeto de datos. + +La implementación de estas reglas se describe en [Lógica de regiones](/es/folia/reference/region-logic). + +El resultado de aplicar estas reglas es que una región que ejecuta ticks puede garantizar que +solo el hilo actual tenga acceso de escritura a los datos de la región +y que, en todo momento, la cantidad de regiones independientes se acerque al máximo posible. + +## Operaciones dentro de una región + +Las operaciones dentro de una región son las que solo usan datos +de una única región desde la propia región, o corresponden a la lógica de fusión y división. + +### Ejecución de ticks en regiones independientes + +Las regiones independientes ejecutan ticks de forma independiente y en paralelo. Esto significa +que cada región mantiene sus propios plazos para programar el siguiente tick. Por +ejemplo, supongamos que las regiones A y B tienen el inicio del próximo tick programado para t=15ms +y t=0ms, respectivamente. Considera la siguiente secuencia: +1. En t = 0ms, B empieza a ejecutar un tick. +2. En t = 15ms, A empieza a ejecutar un tick. +3. En t = 20ms, B termina su tick y se programa el siguiente para t = 50ms. +4. En t = 50ms, B empieza su segundo tick. +5. En t = 70ms, B termina su segundo tick y se programa el siguiente para t = 100ms. +6. En t = 95ms, A termina su _primer_ tick. Se programa el siguiente para t = 95ms. + +Es importante observar que el retraso de A respecto al objetivo de 20 TPS nunca afectó al programa de B. + +Para implementar este comportamiento, cada región mantiene una tarea repetitiva en un ejecutor programado (consulta `SchedulerThreadPool`) que programa +tareas mediante un algoritmo de planificación que prioriza el inicio más temprano. El +algoritmo es similar a EDF, pero programa según la hora de inicio. Sin embargo, +como el plazo de cada tick es 50ms + la hora de inicio, se comporta +igual que el algoritmo EDF. + +Se elige este algoritmo similar a EDF para que, mientras el grupo de hilos no esté +completamente ocupado, todas las regiones cuyos ticks duren <= 50ms +mantengan 20 TPS. Sin embargo, el algoritmo de planificación no tiene en cuenta NUMA +ni los núcleos de la CPU: no intenta (cuando hay n regiones > m hilos) +asignar regiones a núcleos específicos. + +Como las regiones ejecutan ticks de forma independiente, cada una mantiene sus propios contadores. Las +implicaciones se describen en la siguiente sección. + +### Contadores de ticks + +En Vanilla estándar hay varios contadores de ticks importantes: Current Tick, +Game Time Tick y Daylight Time Tick. Current Tick se usa +para determinar cuántos ticks han transcurrido desde que se inició el servidor. Game Time +se mantiene por mundo y se usa para programar ticks de bloques +de redstone, fluidos y otros eventos de física. Daylight Time +simplemente cuenta los ticks transcurridos desde el mediodía y se mantiene por mundo. + +En Folia, Current Tick se mantiene por región. Game Time +se divide en dos contadores: Redstone Time y Global Game Time. +Redstone Time se mantiene por región. Global Game Time y +Daylight Time se mantienen en la «región global». + +Al inicio de cada tick de región, los contadores globales de Game Time y +Daylight Time se copian desde la región global. Cada vez que la región actual consulta esos valores, +obtendrá la copia recibida al inicio del tick. Así se garantiza que dos llamadas para consultar el número de tick durante el mismo tick +devuelvan el mismo valor. + +Se mantiene el tiempo global del juego por un par de motivos: +1. Se necesita un contador que indique cuántos ticks lleva existiendo un mundo, + ya que el juego registra la cantidad total de días transcurridos. +2. Una parte considerable del código nuevo de IA de entidades usa el tiempo del juego (por + motivos que desconozco) para guardar plazos absolutos de tareas. + Es posible escribir código para ajustar los plazos de todas + estas tareas, pero supondría una cantidad considerable de trabajo. + +#### Región global + +La región global es una única tarea programada para ejecutarse siempre a 20 TPS, responsable de mantener datos que no +pertenecen a ninguna región específica: reglas del juego, tiempo global, hora del día, +gestión de comandos de consola, borde del mundo, clima y otros. A diferencia de las demás +regiones, no necesita lógica especial para fusionarse o dividirse, ya que nunca se divide ni se fusiona: +en todo momento hay una sola región global. No posee +datos específicos de ninguna región. + +#### Fusionar y dividir los tiempos de tick de las regiones + +Como los ticks de redstone y los ticks actuales se mantienen por región, se necesita +lógica para ajustar los plazos del planificador de ticks de bloques y fluidos +y de cualquier otro componente que programe usando el tiempo absoluto de redstone o el tick actual, +de modo que el plazo relativo no se vea afectado. + +Al fusionar la región x (origen) en la región y (destino), +podemos ajustar los plazos de ambas regiones o solo los de una. +Es más sencillo ajustar una sola, así que elegimos arbitrariamente la región x. +Después, ajustamos sus plazos para que, teniendo en cuenta los ticks actuales +de y, los plazos relativos se mantengan sin cambios. + +Considera el plazo d1 = tick de origen + plazo relativo en la región x. +Queremos que el plazo ajustado d2 sea d2 = tick de destino + plazo relativo +en la región y, de modo que se mantenga el plazo relativo del tick. Podemos +lograrlo aplicando a d1 un desplazamiento o, de modo que d1 + o = d2, donde +o = tick de destino - tick de origen. Este desplazamiento debe calcularse +por separado para los ticks de redstone y los actuales, ya que el campo `Level#tickTime` +puede desactivar el incremento de los ticks de redstone. + +Por último, el caso de división es sencillo: cuando se produce, las regiones independientes resultantes +heredan de la región principal los ticks de redstone y los actuales. Por tanto, se mantienen los plazos relativos, ya que +el número de ticks no cambia. + +En todos los casos, los eventos de redstone y cualquier otro evento programado según el tick actual +no se ven afectados por la división o fusión de regiones, ya que el plazo relativo +se mantiene aplicando un desplazamiento al fusionar y copiando +el número de ticks al dividir. + +## Operaciones entre regiones + +Las operaciones entre regiones son las que interactúan con regiones distintas de la región actual que ejecuta ticks, +cuyo estado es completamente desconocido. Estas regiones +pueden ser transitorias, estar ejecutando ticks o ni siquiera existir. + +### Utilidades para facilitar las operaciones + +Para facilitar las operaciones entre regiones, se proporcionan varias utilidades. +En NMS, estas utilidades son `EntityScheduler`, `RegionizedTaskQueue`, +la cola de tareas de la región global y el proveedor de datos local a la región +`RegionizedData`. La API de Folia ofrece equivalentes similares, pero no dispone +de un proveedor de datos local a la región, ya que el proveedor de NMS mantiene +bloqueos críticos y se invoca en secciones críticas del código al ejecutar +callbacks. Por ello, es muy vulnerable a errores graves de plugins +que impliquen operaciones de E/S prolongadas o modificaciones del estado del mundo. + +#### `EntityScheduler` + +`EntityScheduler` permite programar tareas para que se ejecuten en la +región propietaria de la entidad. Esto resulta especialmente útil al teletransportar +entidades, porque, una vez que una entidad inicia un teletransporte asíncrono, +no puede ejecutar ticks hasta que termine, y el momento en que esto ocurra no está definido. + +#### `RegionizedTaskQueue` + +`RegionizedTaskQueue` permite programar tareas para que se ejecuten en +el siguiente tick de la región propietaria de una ubicación específica, o crear +dicha región si aún no existe. Resulta útil para tareas que necesiten +modificar o consultar datos del mundo, bloques o chunks fuera de la región actual. + +#### Cola de tareas de la región global + +La cola de tareas de la región global se usa para modificar datos +propiedad de la región global, como las reglas del juego, la hora del día o el clima, +o para ejecutar comandos mediante el emisor de comandos de la consola. + +#### `RegionizedData` + +La clase `RegionizedData` permite que las regiones definan datos locales, +para almacenarlos sin tener que considerar el acceso concurrente +desde otras regiones. Por ejemplo, las listas actuales de ticks de entidades, +chunks, bloques y fluidos se mantienen por región, de modo que las regiones no +tienen que preocuparse por el acceso concurrente a esos conjuntos de datos. + +Estas utilidades permiten resolver fácilmente distintos problemas entre regiones, +por ejemplo, modificar el estado de bloques, entidades o del mundo desde cualquier región +mediante colas de tareas, o evitar problemas de concurrencia usando +`RegionizedData`. Operaciones más avanzadas, como el teletransporte, +la reaparición de jugadores y el uso de portales, también recurren a estas utilidades +para garantizar la seguridad entre hilos. + +### Teletransportes de entidades entre regiones y dimensiones + +Las entidades necesitan una lógica especial para teletransportarse de forma segura entre +regiones o dimensiones. En todos los casos, la llamada para teletransportar o colocar una entidad +debe invocarse en la región propietaria de esta. +`EntityScheduler` permite programar fácilmente código para ejecutarlo en ese contexto. + +#### Teletransporte simple + +En un teletransporte simple, la entidad ya existe en una ubicación del mundo +y se conocen la ubicación y la dimensión de destino. +La operación se divide en dos partes: transformación y colocación asíncrona. +En este caso, la transformación elimina la entidad del mundo actual y después ajusta su posición. +La colocación asíncrona programa una tarea en la ubicación de destino +mediante `RegionizedTaskQueue` para añadir la entidad a +la dimensión de destino en la posición indicada. + +Se omiten varios detalles de implementación, como la copia de entidades que no son jugadores +durante la transformación, ya que no son relevantes para esta descripción general. + +El inicio de sesión y la reaparición de jugadores suelen considerarse +teletransportes simples. El inicio de sesión solo se diferencia porque el jugador +no existe en ningún mundo al principio y la transformación asíncrona también +debe encontrar un lugar donde aparezca. La reaparición es similar al inicio +de sesión, pero el jugador ya está en el mundo cuando reaparece. + +#### Teletransporte por portal + +El teletransporte por portal se diferencia del teletransporte simple porque no +se conoce la ubicación exacta del destino. Por ello, el paso de transformación +no actualiza la posición de la entidad. En su lugar, se intercala una nueva operación +entre la transformación y la colocación asíncrona: una búsqueda o creación asíncrona, +responsable de encontrar o crear el portal de salida. + +Además, el código actual de Vanilla puede rechazar un teletransporte si la +entidad no es un jugador y el portal de salida del Nether aún no existe. Sin embargo, +como la ubicación del portal solo se determina durante la colocación asíncrona, +ya es demasiado tarde para cancelar la operación. Por eso se reescribió la lógica +de los portales para que no haya diferencias entre jugadores y entidades. Ahora ambos +crean portales de salida, tanto para el Nether como para el End. + +#### Apagado durante un teletransporte + +Como el teletransporte se realiza en varios pasos, el proceso de apagado +del servidor debe gestionar manualmente los teletransportes que no se hayan completado. + +## Proceso de apagado del servidor + +El proceso de apagado crea un hilo independiente, +que ejecuta la lógica de cierre: +1. Detener el planificador de ticks de regiones para impedir más ticks. +2. Detener el procesamiento de métricas. +3. Desactivar los plugins. +4. Dejar de aceptar conexiones nuevas. +5. Enviar paquetes de desconexión a todos los jugadores (sin eliminarlos). +6. Detener los sistemas de chunks de todos los mundos. +7. Ejecutar la lógica de apagado de todos los mundos: completar todos los teletransportes pendientes + de todas las regiones, guardar todos los chunks del mundo y, por último, + guardar los datos del nivel (level.dat y otros archivos .dat). +8. Guardar a todos los jugadores. +9. Apagar el gestor de recursos. +10. Liberar el bloqueo del nivel. +11. Detener los ejecutores restantes (el ejecutor Util, los hilos de E/S de regiones, etc.). + + +La diferencia principal con Vanilla es que la lógica para expulsar a los jugadores y +guardar el mundo se sustituye por los pasos 5-8. + +En el paso 5, no se puede expulsar a los jugadores antes de completar los teletransportes, +porque expulsarlos guardaría el archivo de datos del jugador. Por eso, el guardado se traslada a después. + +En el paso 6, los sistemas de chunks se detienen antes de guardar para detener +la generación de chunks. Esto reduce la carga del servidor durante el apagado, +lo que puede ser crucial cuando hay poca memoria disponible. + +En el paso 7, los teletransportes se completan de forma distinta según su tipo: +simple o por portal. + +Los teletransportes simples se completan garantizando que la entidad que se teletransporta +se añada al chunk de destino especificado. Así, la entidad se puede guardar en la posición +de destino, como si el teletransporte se hubiera completado antes del apagado. + +Los teletransportes por portal se completan forzando la incorporación +de la entidad al chunk de origen, desde el que debía haberse teletransportado. +Como no se conoce la ubicación de destino, la entidad solo puede volver al origen +(sin teletransportarse). Aunque este comportamiento no es ideal, la lógica de apagado +_debe_ contemplar cualquier estado incoherente del mundo, lo que significa que quizá +no sea posible encontrar o crear el portal de salida de destino. + +El teletransporte debe completarse antes de guardar el mundo para que +se guarden las entidades cuyo teletransporte se haya completado. + +En el paso 8, los jugadores solo se guardan una vez completados los teletransportes. + +Los pasos restantes son los de Vanilla. diff --git a/src/content/docs/es/folia/admin/reference/region-logic.md b/src/content/docs/es/folia/admin/reference/region-logic.md new file mode 100644 index 000000000..615aab3e4 --- /dev/null +++ b/src/content/docs/es/folia/admin/reference/region-logic.md @@ -0,0 +1,264 @@ +--- +title: Lógica de regiones +description: Descripción general del funcionamiento del regionizador de Folia. +slug: es/folia/reference/region-logic +--- + +## Lógica fundamental de regionalización + +## Región + +Una región es simplemente un conjunto de posiciones de chunks propias y un objeto de datos único, definido por la implementación, +asociado a esa región. Es importante +señalar que, para cualquier región x que no esté muerta y cada posición de chunk y +que posea, no existe otra región z no muerta que +posea la posición de chunk y. + +## Regionizador + +Cada mundo tiene su propio regionizador. El término regionizador +describe la lógica que ejecuta la clase `ThreadedRegionizer` +para crear, mantener y destruir regiones. El mantenimiento de regiones se +realiza fusionando regiones cercanas, marcando cuáles pueden +ejecutar ticks y, finalmente, dividiendo las regiones +en otras independientes más pequeñas. En esencia, esta lógica +garantiza que los grupos de chunks cercanos se consideren +una única región independiente. + +## Garantías que ofrece el regionizador + +El regionizador proporciona varios invariantes importantes que permiten +que las regiones ejecuten ticks en paralelo sin condiciones de carrera: + +### Primer invariante + +El primer invariante establece simplemente que cada chunk holder existente +tiene una única región correspondiente. + +### Segundo invariante + +El segundo invariante establece que para cada chunk holder x _existente_ +incluido en una región, todas las posiciones de chunk dentro del +«radio de fusión» de x pertenecen a esa región. En la práctica, este invariante +garantiza que la región no esté cerca de otra, lo que permite +suponer que, mientras ejecuta ticks, puede crear datos para los chunk holders cercanos. + +### Tercer invariante + +El tercer invariante establece que una región que ejecuta ticks _no puede_ ampliar +las posiciones de chunks que posee mientras ejecuta ticks. Este invariante +es importante porque evita que las regiones que ejecutan ticks «compitan» +por chunks cercanos que no poseen, y garantiza que realmente ejecuten ticks +en paralelo, independientemente de las cargas de chunks que soliciten durante +la ejecución. + +Para cumplir el primer invariante, el regionizador crea regiones "transient" +_alrededor_ de las regiones que ejecutan ticks. En este contexto, «alrededor» +significa lo bastante cerca como para requerir una fusión, pero no tanto como +para considerarlas independientes. Las regiones "transient" creadas en estos casos +se fusionan con la región que ejecuta ticks cuando esta termina. + +La combinación del segundo y el tercer invariante permite que +el regionizador garantice que una región que ejecuta ticks pueda crear +y después acceder a los chunk holders cercanos (es decir, realizar cargas síncronas) +sin interferir con otra región. + +### Cuarto invariante + +El cuarto invariante establece que una región solo puede estar en uno de estos cuatro +estados: "transient", "ready", "ticking" o "dead". + +El estado "ready" permite pasar al estado "ticking", +mientras que "transient" se usa para las regiones que quizá +no ejecuten ticks. El estado "dead" marca regiones que no deben +utilizarse. + +Las transiciones entre estados se explican más adelante, ya que están relacionadas +con la lógica de fusión y división del regionizador. + +## Implementación del regionizador + +La implementación del regionizador describe cómo la clase +`ThreadedRegionizer` cumple los cuatro invariantes descritos anteriormente. + +### División del mundo en secciones + +El regionizador no opera con coordenadas de chunks, sino con «coordenadas de sección de región». +Estas coordenadas representan grupos de NxN chunks en una cuadrícula, donde N es una potencia +de dos. El valor concreto no se especifica, ya que las coordenadas de sección de región +son un detalle interno de la agrupación de chunks. +Por ejemplo, con N=16, la sección de región (0,0) abarca todos los +chunks con x entre 0 y 15 y z entre 0 y 15. El concepto es similar al de la +coordenada de chunk (0,0), que abarca todos los bloques con x entre 0 y 15 +y z entre 0 y 15. Otro ejemplo: con N=16, el chunk (17, -5) está +contenido en la sección de región (1, -1). + +Las coordenadas de sección de región se usan como una optimización de rendimiento +del regionizador: al aproximar las coordenadas de los chunks a sus coordenadas de región, +puede tratar NxN chunks como una sola unidad al regionalizar. Esto significa que las regiones +no poseen posiciones de chunks, sino posiciones de secciones de región. La agrupación de NxN chunks +permite ejecutar la lógica de regionalización solo cuando se crean o destruyen secciones de región. +Por ejemplo, con N=16, esto puede reducir hasta NxN-1=255 operaciones en áreas como +addChunk y el recálculo de regiones, suponiendo que las secciones de región estén siempre completas. + +### Variables de implementación + +Las variables de implementación controlan la intensidad con la que el +regionizador mantiene las regiones y las fusiona. + +#### Cantidad de recálculos + +La cantidad de recálculos es el número mínimo de secciones de región que +una región debe poseer para poder recalcularse. La operación de recálculo +simplemente calcula el conjunto de regiones independientes que hay dentro de una región +para comprobar si se puede dividir. +Este parámetro permite desactivar la lógica de división para regiones pequeñas, +ya que es poco probable que estas puedan dividirse. + +#### Porcentaje máximo de secciones inactivas + +El porcentaje máximo de secciones inactivas es el porcentaje mínimo de secciones inactivas +que debe haber en una región para que esta pueda ejecutar la lógica de recálculo. + +#### Radio de creación de secciones vacías + +La variable del radio de creación de secciones vacías determina +cuántas secciones de región vacías deben existir alrededor de _cualquier_ +sección de región que contenga al menos un chunk. + +Internamente, el regionizador hace cumplir el tercer invariante al +impedir que las regiones que ejecutan ticks posean nuevas secciones de región. +La creación de secciones vacías alrededor de cualquier sección no vacía +hace cumplir el segundo invariante. + +#### Radio de fusión de secciones de región + +La variable del radio de fusión garantiza que, para cualquier sección de región existente x, +cualquier otra sección de región y dentro del radio de fusión pertenezca a la región propietaria de x, +esté pendiente de fusionarse con dicha región, o que la región propietaria de x +esté pendiente de fusionarse con la región propietaria de y. + +#### Desplazamiento de chunk de la sección de región + +El desplazamiento de chunk de la sección de región es simplemente log2(N), donde N es el tamaño de la cuadrícula. Por tanto, +N = 1 << region section chunk shift. La conversión +de una posición de chunk a una sección de región se define como: +coordenada de región = coordenada de chunk >> desplazamiento de chunk de la sección de región. + +### Funcionamiento + +El regionizador funciona invocando `ThreadedRegionizer#addChunk(x, z)` +o `ThreadedRegionizer#removeChunk(x, z)` cuando se crea +o destruye un chunk holder. + +Además, el código que intenta pasar una región del estado "ready" al estado "ticking" +puede utilizar `ThreadedRegion#tryMarkTicking`. Es importante tener en cuenta que esta función devuelve false si +la región no está en el estado "ready", ya que incluso una región que antes se consideraba +"ready" (es decir, estaba programada para ejecutar ticks) puede marcarse inesperadamente como "transient". +Por tanto, el código que llama a la función debe gestionar estos casos. Quien marque +correctamente una región como activa debe volver a marcarla como inactiva mediante +`ThreadedRegion#markNotTicking`. + +La función ThreadedRegion#markNotTicking devuelve true si la región +pasó del estado "ticking" al estado "ready", y false en cualquier +otro caso. En la práctica, indica si la región actual podrá ejecutar ticks de nuevo más adelante. + +### Estado de las secciones de región + +El estado de una sección de región puede ser "dead" o "alive". Además, se considera +"non-empty" si contiene al menos una posición de chunk, y "empty" en caso contrario. + +Una sección de región se considera "dead" si, y solo si, también está "empty" +y no hay otras secciones "empty" dentro del radio de creación de secciones vacías. + +La existencia del estado "dead" responde únicamente a motivos de rendimiento, ya que +permite aplazar la lógica de recálculo de una región hasta que contenga suficientes secciones +"dead". Sin embargo, estas secciones siguen considerándose parte de la región que las posee, +igual que las secciones "alive". + +### Adición de chunks (`addChunk`) + +La adición de chunks al regionizador se reduce a dos casos: + +#### La sección de región de destino ya existe y no está vacía + +En este caso, simplemente se añade el chunk a la sección y se termina. + +#### La sección de región de destino no existe o está vacía + +En este caso, se crea la sección de región si aún no existe. +También se crean las secciones de región incluidas en el «radio de creación de secciones vacías». + +Después, se recopilan en un conjunto X todas las regiones que estén dentro +del radio de creación de secciones vacías más el radio de fusión. Este conjunto representa +las regiones que habrá que fusionar para cumplir el segundo invariante. + +Si el conjunto X está vacío, se crea una región en estado "ready" +para que posea todas las secciones creadas. + +Si el conjunto X contiene una sola región, no es necesario fusionar regiones +ni modificar el estado de ninguna región; las secciones se añaden a esa región. + +La lógica de fusión se ejecuta cuando el conjunto X contiene más de una región. +Se selecciona del conjunto una región x que no esté ejecutando ticks. Si no hay +ninguna, se crea una región x. Todas las secciones de región creadas se añaden +a x, ya que se sabe que no está ejecutando ticks; así se cumple el tercer invariante. + +Cada región y del conjunto X que no sea x se fusiona con x si y no está en estado +"ticking"; de lo contrario, x aplica a y la lógica de fusión diferida. + +### Lógica de fusión diferida + +Una operación de fusión diferida solo puede realizarse desde +una región x que no esté ejecutando ticks ni esté "dead" hacia una región y que esté ejecutando ticks. +Esta lógica mantiene, para cada región, un conjunto de regiones con las que debe fusionarse más adelante +y otro conjunto de regiones que se espera que se fusionen con ella. +En la práctica, una fusión diferida de x hacia y añade y al conjunto de x +de fusiones pendientes y añade x al conjunto de y de fusiones esperadas. + +Cuando la región que ejecuta ticks termina, ejecuta la lógica de fusión +para todas las fusiones esperadas. + +### Lógica de fusión + +Una operación de fusión solo puede realizarse entre una región x en estado "dead" +y otra región y, que puede estar en estado "transient" o "ready". +En la práctica, x se absorbe en y, ya que sus secciones se trasladan a esta última. + +Las fusiones diferidas también se transfieren a la región y, +de modo que esta pase a fusionarse más adelante con las regiones con las que x tenía previsto hacerlo. + +Además, si la región x contiene datos específicos de la implementación, +se invoca la función de callback de la región para fusionar esos datos con los de y. + +El estado de la región y puede actualizarse al finalizar una fusión. +Por ejemplo, si la región x estaba en estado "transient", la región y también debe +degradarse a "transient". En concreto, y debe marcarse como "transient" si x contenía +destinos de fusión diferida distintos de y. Esta degradación es necesaria +para cumplir el segundo invariante. + +### Eliminación de chunks (`removeChunk`) + +La eliminación de chunks de las secciones de región simplemente actualiza +el estado de estas secciones a "dead" o "alive", así como el de las secciones +dentro del radio de creación de secciones vacías. No actualiza ningún estado +de región ni elimina secciones de región. + +### Inicio del tick de una región (`tryMarkTicking`) + +Al comenzar el tick, simplemente se cambia el estado a "ticking" para cumplir +los invariantes #2 y #3. + +### Fin del tick de una región (`markNotTicking`) + +Al terminar un tick, todavía no se conoce el nuevo estado de la región. + +Primero, la región debe procesar las fusiones pendientes. + +Después de procesarlas, debe comprobar si ahora está pendiente de fusionarse +con otra región. Si es así, pasa al estado "transient". + +De lo contrario, procesa la eliminación de las secciones inactivas e intenta dividirse +en regiones más pequeñas. Si una región puede dividirse, necesariamente debe eliminar +las secciones inactivas; de lo contrario, se contradirían las reglas utilizadas +para construirla. diff --git a/src/content/docs/es/folia/index.mdx b/src/content/docs/es/folia/index.mdx new file mode 100644 index 000000000..25c0d4458 --- /dev/null +++ b/src/content/docs/es/folia/index.mdx @@ -0,0 +1,16 @@ +--- +title: Documentación de Folia +tableOfContents: false +--- + +import { CardGrid, LinkCard } from "@astrojs/starlight/components"; + +Folia es una bifurcación de Paper que añade multihilo por regiones al servidor dedicado. + + + + diff --git a/src/content/docs/es/index.mdx b/src/content/docs/es/index.mdx new file mode 100644 index 000000000..f94364b20 --- /dev/null +++ b/src/content/docs/es/index.mdx @@ -0,0 +1,48 @@ +--- +title: Bienvenido +description: Documentación de todos los proyectos de PaperMC, incluidos Paper, Velocity y Folia. +template: splash +editUrl: false +lastUpdated: false +hero: + title: Documentación de PaperMC + tagline: Documentación de todos los proyectos de PaperMC, incluidos Paper, Velocity y Folia. + image: + file: "https://assets.papermc.io/brand/papermc_logo.min.svg" + alt: Logotipo de PaperMC +--- + +import { CardGrid } from "@astrojs/starlight/components"; +import { ContributorList } from "astro-contributors"; +import LinkCard from "/src/components/LinkCard.astro"; + + + + Servidor de Minecraft de alto rendimiento que busca corregir inconsistencias en la jugabilidad y las mecánicas. + + + Proxy de servidor de Minecraft moderno y de última generación. + + + Fork de Paper que añade multihilo por regiones al servidor dedicado. + + + Biblioteca Java para crear elementos de interfaz controlados por el servidor en Minecraft: Java Edition. + + + Bifurcación abandonada del proxy BungeeCord que buscaba mejorar el rendimiento y la estabilidad. + + + Otra documentación y herramientas. + + + +
+ +## [Colabora](https://github.com/PaperMC/docs) + +Queremos agradecer sinceramente a todas las personas que han contribuido a esta documentación. +Ya sea escribiendo código, enviando comentarios, corrigiendo erratas o compartiendo sus conocimientos, agradecemos cada aporte. +Este proyecto es un esfuerzo colectivo y nos alegra contar contigo. + + diff --git a/src/content/docs/es/misc/assets.md b/src/content/docs/es/misc/assets.md new file mode 100644 index 000000000..924732a10 --- /dev/null +++ b/src/content/docs/es/misc/assets.md @@ -0,0 +1,76 @@ +--- +title: Recursos gráficos +description: Logotipos oficiales de PaperMC y Velocity y condiciones de uso. +slug: es/misc/assets +--- + + + +Esta página ofrece los logotipos oficiales de PaperMC y Velocity, así como las condiciones de uso. + +Las imágenes de esta página están disponibles en nuestra CDN. Te recomendamos (aunque no es obligatorio) +usar las URL proporcionadas al hacer referencia a estos recursos en tus proyectos, siempre que respetes las pautas de uso indicadas a continuación. + +:::caution + +Los logotipos están sujetos a sus propias condiciones de licencia y no heredan las de los +proyectos que representan. + +::: + +## PaperMC + +Puedes: + + - Usar el logotipo de PaperMC para representar el proyecto en publicaciones de blog y otros espacios, con el fin de + dar visibilidad al proyecto. +- Usar el logotipo de PaperMC para representar Paper-Server en descargas, selectores de servidores y lugares similares. +- Recortar el espacio transparente sobrante alrededor del logotipo de PaperMC para que encaje mejor junto a + otros contenidos. + +No puedes: + +- Modificar los colores del logotipo de PaperMC. +- Cambiar las dimensiones del logotipo de PaperMC. +- Crear versiones modificadas del logotipo de PaperMC o trabajos derivados. +- Añadir imágenes o elementos de marca de tu proyecto al logotipo de PaperMC. +- Afirmar que el logotipo es obra tuya o usarlo para representar tus propios proyectos. +- Vender el logotipo de PaperMC por sí solo o como parte de otros productos sin permiso explícito. +- Modificar la transparencia de cualquier elemento del logotipo de PaperMC. + +| Image | URL | +|----------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------| +|
![](https://assets.papermc.io/brand/papermc_combination_mark_dark.min.svg)
| `https://assets.papermc.io/brand/papermc_combination_mark_dark.min.svg` | +|
![](https://assets.papermc.io/brand/papermc_combination_mark_light.min.svg)
| `https://assets.papermc.io/brand/papermc_combination_mark_light.min.svg` | +| ![](https://assets.papermc.io/brand/papermc_logo.min.svg) | `https://assets.papermc.io/brand/papermc_logo.min.svg` | +| ![](https://assets.papermc.io/brand/papermc_logo.256.png) | `https://assets.papermc.io/brand/papermc_logo.256.png` | +| ![](https://assets.papermc.io/brand/papermc_logo.512.png) | `https://assets.papermc.io/brand/papermc_logo.512.png` | + +## Velocity + +No edites, cambies los colores, reorganices ni deformes el logotipo de Velocity. Se permite cambiar su tamaño +y recortar el espacio vacío. + +El logotipo no debe usarse de forma que sugiera que el proyecto Velocity respalda oficialmente +un producto o servicio. Por ejemplo, puedes anunciar que un plugin es compatible con Velocity, +pero no puedes destacar el logotipo de Velocity en ese anuncio. + +| Image | URL | +|-----------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------| +| ![](https://assets.papermc.io/brand/velocity_combination_mark_blue.min.svg) | `https://assets.papermc.io/brand/velocity_combination_mark_blue.min.svg` | +|
![](https://assets.papermc.io/brand/velocity_combination_mark_white.min.svg)
| `https://assets.papermc.io/brand/velocity_combination_mark_white.min.svg` | +| ![](https://assets.papermc.io/brand/velocity_logo_blue.min.svg) | `https://assets.papermc.io/brand/velocity_logo_blue.min.svg` | +|
![](https://assets.papermc.io/brand/velocity_logo_white.min.svg)
| `https://assets.papermc.io/brand/velocity_logo_white.min.svg` | diff --git a/src/content/docs/es/misc/contact.md b/src/content/docs/es/misc/contact.md new file mode 100644 index 000000000..981c0fa82 --- /dev/null +++ b/src/content/docs/es/misc/contact.md @@ -0,0 +1,29 @@ +--- +title: Contacto +description: Hay muchas formas de ponerse en contacto con nosotros; aquí encontrarás más información. +slug: es/misc/contact +--- + +## Discord + +El proyecto PaperMC gestiona la mayor parte de la comunicación a través de Discord. Usa esta invitación: https://discord.gg/papermc + +## Foros + +:::caution +Tras considerarlo detenidamente y debido a su uso limitado, hemos decidido cerrar los foros de PaperMC. +En adelante, recomendamos usar Hangar para subir plugins. Para cualquier otro debate o solicitud de ayuda de la comunidad, +únete a nuestro Discord. +::: + +- [Foros](https://forums.papermc.io) + +## Twitter/X + +Publicamos con frecuencia notas de lanzamiento, avisos de actualizaciones y otra información en nuestra página +de Twitter. + +- [@PaperPowered](https://x.com/PaperPowered) + +No envíes mensajes directos ni menciones esta cuenta para solicitar ayuda. No la revisamos con tanta frecuencia como los +canales anteriores. diff --git a/src/content/docs/es/misc/downloads-service.mdx b/src/content/docs/es/misc/downloads-service.mdx new file mode 100644 index 000000000..fad67741f --- /dev/null +++ b/src/content/docs/es/misc/downloads-service.mdx @@ -0,0 +1,310 @@ +--- +title: Servicio de descargas +description: Paper ofrece un servicio de descargas que puedes usar para acceder a las compilaciones. +slug: es/misc/downloads-service +--- + +PaperMC ofrece un servicio de descargas para facilitar el acceso automatizado a las descargas. Puedes encontrar la documentación completa en +[la documentación del servicio de descargas](https://fill.papermc.io/swagger-ui/index.html#/). + +:::danger + +**No recomendamos en absoluto** usar compilaciones inestables ni actualizadores automáticos en entornos de producción. + +::: + +Todas las solicitudes deben incluir ahora un encabezado User-Agent válido que: +- Identifique claramente tu software o empresa +- No sea genérico (por ejemplo, curl, wget o valores predeterminados similares) +- Incluya una URL o dirección de correo electrónico de contacto (por ejemplo, una página de inicio, información del bot o un correo de soporte) + +**Algunos ejemplos:** +``` +mc-image-helper/1.39.11 (https://github.com/itzg/docker-minecraft-server) +nodecraft/packifier/1.0.0 (staff@nodecraft.com) +``` + +## Ejemplos de la API REST + +:::note + +Para los siguientes ejemplos, es necesario tener instalado `jq`. Puedes instalarlo con `sudo apt-get install jq` en Debian/Ubuntu. + +::: + +### Obtener la última versión + +```shell +#!/usr/bin/env sh + +PROJECT="paper" +USER_AGENT="cool-project/1.0.0 (contact@me.com)" + +LATEST_VERSION=$(curl -s -H "User-Agent: $USER_AGENT" https://fill.papermc.io/v3/projects/${PROJECT} | \ + jq -r '.versions | to_entries[0] | .value[0]') + +echo "La última versión es $LATEST_VERSION" +``` + +Esto obtiene la última versión disponible de Minecraft para el proyecto indicado. + +### Obtener el número de la última compilación estable + +```shell replace +#!/usr/bin/env sh + +PROJECT="paper" +MINECRAFT_VERSION="\{LATEST_PAPER_RELEASE}" +USER_AGENT="cool-project/1.0.0 (contact@me.com)" + +LATEST_BUILD=$(curl -s -H "User-Agent: $USER_AGENT" https://fill.papermc.io/v3/projects/${PROJECT}/versions/${MINECRAFT_VERSION}/builds | \ + jq -r 'map(select(.channel == "STABLE")) | .[0] | .id') + +if [ "$LATEST_BUILD" != "null" ]; then + echo "La última compilación estable es $LATEST_BUILD" +else + echo "No se encontró ninguna compilación estable para la versión $MINECRAFT_VERSION :(" +fi +``` + +Esto obtiene la última compilación estable disponible para el proyecto y la versión de Minecraft indicados. + +### Descargar la última compilación estable + +```shell replace +#!/usr/bin/env sh + +PROJECT="paper" +MINECRAFT_VERSION="\{LATEST_PAPER_RELEASE}" +USER_AGENT="cool-project/1.0.0 (contact@me.com)" + +# Primero comprueba si la versión solicitada tiene una compilación estable +BUILDS_RESPONSE=$(curl -s -H "User-Agent: $USER_AGENT" https://fill.papermc.io/v3/projects/${PROJECT}/versions/${MINECRAFT_VERSION}/builds) + +# Comprueba si la API devolvió un error +if echo "$BUILDS_RESPONSE" | jq -e '.ok == false' > /dev/null 2>&1; then + ERROR_MSG=$(echo "$BUILDS_RESPONSE" | jq -r '.message // "Unknown error"') + echo "Error: $ERROR_MSG" + exit 1 +fi + +# Intenta obtener la URL de una compilación estable para la versión solicitada +PAPERMC_URL=$(echo "$BUILDS_RESPONSE" | jq -r 'first(.[] | select(.channel == "STABLE") | .downloads."server:default".url) // "null"') +FOUND_VERSION="$MINECRAFT_VERSION" + +# Si no hay una compilación estable para la versión solicitada, busca la última versión con una compilación estable +if [ "$PAPERMC_URL" == "null" ]; then + echo "No hay compilación estable para la versión $MINECRAFT_VERSION; se busca la última versión con compilación estable..." + + # Obtén todas las versiones del proyecto (usando la misma estructura del endpoint que el ejemplo "Obtener la última versión") + # Las versiones están organizadas por grupos; por eso necesitamos extraer todas las versiones de todos los grupos + # Luego las ordenamos correctamente como versiones semánticas (las más nuevas primero) + VERSIONS=$(curl -s -H "User-Agent: $USER_AGENT" https://fill.papermc.io/v3/projects/${PROJECT} | \ + jq -r '.versions | to_entries[] | .value[]' | \ + sort -V -r) + + # Recorre las versiones para encontrar una con una compilación estable + for VERSION in $VERSIONS; do + VERSION_BUILDS=$(curl -s -H "User-Agent: $USER_AGENT" https://fill.papermc.io/v3/projects/${PROJECT}/versions/${VERSION}/builds) + + # Comprueba si esta versión tiene una compilación estable + STABLE_URL=$(echo "$VERSION_BUILDS" | jq -r 'first(.[] | select(.channel == "STABLE") | .downloads."server:default".url) // "null"') + + if [ "$STABLE_URL" != "null" ]; then + PAPERMC_URL="$STABLE_URL" + FOUND_VERSION="$VERSION" + echo "Se encontró una compilación estable para la versión $VERSION" + break + fi + done +fi + +if [ "$PAPERMC_URL" != "null" ]; then + # Descarga la última versión de Paper + curl -o server.jar $PAPERMC_URL + echo "Descarga completada (versión: $FOUND_VERSION)" +else + echo "No hay compilaciones estables disponibles para ninguna versión :(" + exit 1 +fi +``` + +Este es el uso más habitual de la API. Descargará la última compilación estable del proyecto y la +versión de Minecraft indicados. Siempre debes publicar y usar compilaciones estables. Las compilaciones experimentales pueden contener errores y +no reciben soporte. + +## Ejemplos de la API GraphQL + +Fill también admite una API GraphQL, disponible en `https://fill.papermc.io/graphql`. +La API GraphQL de Fill usa paginación estándar; puedes obtener más información [aquí](https://graphql.org/learn/pagination/). + +Hay un entorno de pruebas GraphQL integrado en https://fill.papermc.io/graphiql?path=/graphql. +Herramientas habituales para API, como Postman, inspeccionan la API y ofrecen una interfaz para crear consultas. + +### Obtener la última versión +```graphql +query LatestVersion { + project(key: "paper") { + key + versions(first: 1, orderBy: {direction: DESC}) { + edges { + node { + key + } + } + } + } +} +``` + +
+Respuesta de ejemplo + +```json +{ + "data": { + "project": { + "key": "paper", + "versions": { + "edges": [ + { + "node": { + "key": "1.21.11" + } + } + ] + } + } + } +} +``` + +
+ +### Obtener el número de la última compilación estable +```graphql +query LatestStableBuild { + project(key: "paper") { + key + versions(first: 1, orderBy: {direction: DESC}) { + edges { + node { + key + builds(filterBy: { channel: STABLE }, first: 1, orderBy: { direction: DESC }) { + edges { + node { + number + } + } + } + } + } + } + } +} +``` + +
+Respuesta de ejemplo + +```json +{ + "data": { + "project": { + "key": "paper", + "versions": { + "edges": [ + { + "node": { + "key": "1.21.10", + "builds": { + "edges": [ + { + "node": { + "number": 48 + } + } + ] + } + } + } + ] + } + } + } +} +``` + +
+ +### Obtener la URL de descarga de la última compilación estable +```graphql +query LatestStableBuildDownloadURL { + project(key: "paper") { + key + versions(first: 1, orderBy: {direction: DESC}) { + edges { + node { + key + builds(filterBy: { channel: STABLE }, first: 1, orderBy: { direction: DESC }) { + edges { + node { + number + download(key: "server:default") { + name + url + checksums { + sha256 + } + size + } + } + } + } + } + } + } + } +} +``` + +
+Respuesta de ejemplo + +```json +{ + "data": { + "project": { + "key": "paper", + "versions": { + "edges": [ + { + "node": { + "key": "1.21.10", + "builds": { + "edges": [ + { + "node": { + "number": 48, + "download": { + "name": "paper-1.21.10-48.jar", + "url": "https://fill-data.papermc.io/v1/objects/bfca155b4a6b45644bfc1766f4e02a83c736e45fcc060e8788c71d6e7b3d56f6/paper-1.21.10-48.jar", + "checksums": { + "sha256": "bfca155b4a6b45644bfc1766f4e02a83c736e45fcc060e8788c71d6e7b3d56f6" + }, + "size": 54185955 + } + } + } + ] + } + } + } + ] + } + } + } +} +``` + +
diff --git a/src/content/docs/es/misc/hangar-publishing.md b/src/content/docs/es/misc/hangar-publishing.md new file mode 100644 index 000000000..f44c147d2 --- /dev/null +++ b/src/content/docs/es/misc/hangar-publishing.md @@ -0,0 +1,255 @@ +--- +title: Publicación automática en Hangar +description: Cómo publicar automáticamente tu plugin en Hangar al crear confirmaciones. +slug: es/misc/hangar-publishing +--- + +Si quieres publicar automáticamente tu plugin en [Hangar](https://hangar.papermc.io/) al enviar cambios, puedes usar +nuestro [plugin de Gradle](https://github.com/HangarMC/hangar-publish-plugin). + +Después de añadir la configuración necesaria de `hangarPublish`, puedes publicarlo manualmente ejecutando +`./gradlew build publishPluginPublicationToHangar`, o configurar GitHub Actions para publicar una versión automáticamente con +cada confirmación. + +## Requisitos previos + +### Gradle + +Tu proyecto de plugin debe usar Gradle como herramienta de compilación. + +:::tip + +Si usas +Maven, [cambiar a Gradle es sencillo](https://docs.gradle.org/current/userguide/migrating_from_maven.html) y, en +general, se recomienda por su mayor capacidad de configuración y compatibilidad con otros plugins, por ejemplo, +al [compilar contra un servidor de Minecraft sin ofuscar](/es/paper/dev/userdev). + +Los ejemplos proporcionados usan Kotlin DSL, pero también puedes hacer lo mismo con Groovy. Los conversores en línea (incluso ChatGPT) +pueden convertir el código de ejemplo. + +::: + +### Crear el canal de publicación `Snapshot` + +El script de compilación siguiente publicará las compilaciones que no sean de lanzamiento en el canal `Snapshot`. Primero debes crear este canal en +la página de canales de tu proyecto de Hangar. + +![Crear un canal Snapshot](../../misc/assets/hangar-create-snapshot-channel.png) + +### Añadir el secreto del repositorio `HANGAR_API_TOKEN` + +Primero, debes crear un token de API de Hangar. Ve a la configuración de Hangar desde el menú desplegable del perfil y haz clic en "Api keys" a la izquierda. Luego, marca +el permiso `create_version`, asigna un nombre a la clave y créala. **En la parte superior** aparecerá tu token secreto de API. +**No lo compartas con nadie**; lo necesitarás en el siguiente paso. + +El flujo de trabajo de GitHub Actions proporcionado usa un secreto del repositorio para almacenar tu clave de API de Hangar. Ve a la configuración de tu proyecto de GitHub, +haz clic en "Actions" en la pestaña Security y luego en el botón "New repository secret". Asigna al +secreto el nombre `HANGAR_API_TOKEN` y pega en el campo Secret el token de API de Hangar del paso anterior. + +![Secretos de Actions](../../misc/assets/github-secrets-actions.png) + +## Archivos del proyecto + +Los siguientes archivos son ejemplos sencillos que requieren pocos cambios manuales para poder usarlos, aunque puedes adaptarlos +según tus necesidades. Revisa los comentarios y, en especial, los TODO para saber qué debes +cambiar. + +### `gradle.properties` + +Si aún no existe, crea un archivo `gradle.properties` en el directorio raíz del proyecto. Allí defines las +versiones de las plataformas con las que es compatible tu plugin. Simplemente elimina las plataformas que no necesites y añade las versiones +correctas. + +Hangar permite intervalos de versiones (como `1.19-1.20.2`) y comodines (como `1.20.x`). + +```properties +# Especifica las versiones de la plataforma para Paper y Velocity. +# Hangar también permite intervalos de versiones (como 1.19-1.20.2) y comodines (como 1.20.x). +# TODO: Elimina las plataformas que no necesites y pon las versiones correctas. +paperVersion=1.12.2, 1.16.5, 1.19-1.20.2 +velocityVersion=3.2 +waterfallVersion=1.20 +``` + +### `build.gradle.kts` + +En el bloque de plugins del script de compilación `build.gradle.kts`, añade el plugin de publicación: + +```kotlin title="build.gradle.kts" +plugins { + id("io.papermc.hangar-publish-plugin") version "0.1.2" +} +``` + +Después solo tienes que añadir el bloque de configuración `hangarPublish` y asegurarte de hacer lo siguiente: + +- Si tu plugin no es un plugin de Paper o también es compatible con Velocity/Waterfall, copia el bloque register con una plataforma diferente + y cambia la propiedad usada en lugar de `paperVersion` (tal como se declara en el archivo `gradle.properties`). +- Introduce el espacio de nombres correcto del proyecto. +- Añade las dependencias del plugin, si las hay. +- Si usas el archivo de Actions siguiente, debes configurar el secreto del repositorio `HANGAR_API_TOKEN`; de lo contrario, añade la + clave de API de otra forma. + +```kotlin +import io.papermc.hangarpublishplugin.model.Platforms + +// ... + +hangarPublish { + publications.register("plugin") { + version.set(project.version as String) + channel.set("Snapshot") // Estamos usando el canal "Snapshot" + // TODO: Edita el nombre del proyecto para que coincida con tu proyecto de Hangar + id.set("hangar-project") + apiKey.set(System.getenv("HANGAR_API_TOKEN")) + platforms { + // TODO: Usa la(s) plataforma(s) correcta(s) para tu plugin + register(Platforms.PAPER) { + // TODO: Si usas ShadowJar, sustituye las líneas del JAR por la tarea adecuada: + // jar.set(tasks.shadowJar.flatMap { it.archiveFile }) + // Establece el archivo JAR a cargar + jar.set(tasks.jar.flatMap { it.archiveFile }) + + // Establece las versiones de la plataforma desde el archivo gradle.properties + val versions: List = (property("paperVersion") as String) + .split(",") + .map { it.trim() } + platformVersions.set(versions) + + // TODO: Configura las dependencias de tu plugin, si las hay + dependencies { + // Ejemplo de una dependencia que se encuentra en Hangar + hangar("Maintenance") { + required.set(false) + } + // Ejemplo de una dependencia externa + url("Debuggery", "https://github.com/PaperMC/Debuggery") { + required.set(true) + } + } + } + } + } +} +``` + +## Flujo de trabajo de GitHub Actions + +No es imprescindible publicar mediante GitHub Actions, pero es una forma sencilla de hacerlo. Si quieres usarlo, crea +un archivo `publish.yml` en el directorio `.github/workflows` de la raíz del proyecto y asegúrate de +[añadir el secreto del repositorio](#añadir-el-secreto-del-repositorio-hangar_api_token). + +Puedes añadir o quitar ramas que se publicarán editando la sección `branches`. + +```yaml +name: Publish to Hangar +on: + push: + branches: + # Añade cualquier rama adicional desde la que quieras publicar automáticamente + - main # Suponiendo que tu rama principal se llama 'main' + +jobs: + publish: + # TODO: Opcional; asegúrate de que la tarea solo se ejecute al hacer push a tu repositorio y no falle en forks. Descomenta la línea de abajo y escribe el propietario del repositorio entre comillas + # if: github.repository_owner == '' + runs-on: ubuntu-latest + steps: + - name: Checkout Repository + uses: actions/checkout@v7 + - name: Set up JDK 25 + uses: actions/setup-java@v5 + with: + distribution: 'temurin' + java-version: 25 + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v6 + - name: Publish + env: + # Asegúrate de haber añadido un secreto del repositorio en la configuración del repositorio + HANGAR_API_TOKEN: ${{ secrets.HANGAR_API_TOKEN }} + run: ./gradlew build publishPluginPublicationToHangar --stacktrace +``` + +## Opcional: gestionar varios canales y un registro de cambios automático + +Con el siguiente código, cualquier versión que contenga un guion (`-`) se publicará en el canal `Snapshot` +(que debes crear en Hangar), y las demás, en el canal `Release`. +Puedes cambiarlo por cualquier otro canal editando la línea `channel.set(...)`. +Por ejemplo, también podrías dividir las compilaciones según la rama actual y usar compilaciones `Alpha`. + +:::caution + +Asegúrate de no publicar nunca compilaciones de desarrollo en curso en el canal `Release`. + +::: + +```kotlin +import java.io.ByteArrayOutputStream + +// ... + +// Helper methods +fun executeGitCommand(vararg command: String): String { + val byteOut = ByteArrayOutputStream() + exec { + commandLine = listOf("git", *command) + standardOutput = byteOut + } + return byteOut.toString(Charsets.UTF_8.name()).trim() +} + +fun latestCommitMessage(): String { + return executeGitCommand("log", "-1", "--pretty=%B") +} + +val versionString: String = version as String +val isRelease: Boolean = !versionString.contains('-') + +val suffixedVersion: String = if (isRelease) { + versionString +} else { + // Dale a la versión un nombre único usando el número de ejecución de GitHub Actions + versionString + "+" + System.getenv("GITHUB_RUN_NUMBER") +} + +// Usa la descripción del commit para el registro de cambios +val changelogContent: String = latestCommitMessage() + +// Si quieres publicar releases con sus changelogs adecuados de forma manual, simplemente añade una instrucción if con la variable `isRelease` aquí. +hangarPublish { + publications.register("plugin") { + version.set(suffixedVersion) + channel.set(if (isRelease) "Release" else "Snapshot") + changelog.set(changelogContent) + // ... (ver arriba) + } +} +``` + +## Opcional: actualizar la página del recurso + +Al publicar una versión nueva, quizá quieras actualizar la página del recurso (por ejemplo, la página de inicio del plugin) con contenido nuevo del repositorio del plugin. + +En este ejemplo usamos un archivo README, pero puedes usar cualquier texto, siempre que tenga formato Markdown. + +```kotlin +val pageContent = project.file("README.md").readText() + +hangarPublish { + publications.register("plugin") { + // ... (ver arriba) + pages.resourcePage(pageContent) + } +} +``` + +Puedes ejecutar la tarea `syncPluginPublicationMainResourcePagePageToHangar` para actualizar la página del recurso en Hangar. +Esto no publicará una nueva versión; solo actualizará el contenido de la página en Hangar. + +Si usas un flujo de trabajo de GitHub Actions, también deberías añadir la invocación de la tarea al paso `Publish` del flujo: +```yaml +- name: Publish + # ... + run: ./gradlew build publishPluginPublicationToHangar syncPluginPublicationMainResourcePagePageToHangar --stacktrace +``` diff --git a/src/content/docs/es/misc/index.mdx b/src/content/docs/es/misc/index.mdx new file mode 100644 index 000000000..17bc9fd0d --- /dev/null +++ b/src/content/docs/es/misc/index.mdx @@ -0,0 +1,10 @@ +--- +title: Varios +tableOfContents: false +--- + +import PageCards from "/src/components/PageCards.astro"; + +Documentación que no encaja claramente en ninguna otra categoría. + + diff --git a/src/content/docs/es/misc/java-install.md b/src/content/docs/es/misc/java-install.md new file mode 100644 index 000000000..ec74eca88 --- /dev/null +++ b/src/content/docs/es/misc/java-install.md @@ -0,0 +1,186 @@ +--- +title: Instalar o actualizar Java +description: Cómo instalar o actualizar a Java 25 en Linux (apt/rpm), Windows o Mac. +slug: es/misc/java-install +--- + +Instalar Java es un primer paso fundamental para usar o desarrollar plugins para Paper y Velocity. +Esta guía explica los pasos de instalación recomendados para la mayoría de las principales +plataformas. + +:::caution[¡No uses las variantes headless de Java!] + +Hay variantes `headless` de Java cuyo paquete suele tener el sufijo `-headless`. +Estas variantes no incluyen dependencias necesarias para Paper. Por eso, no se recomienda usarlas. + +::: + +:::tip + +Esta guía se centra en la distribución OpenJDK Corretto de Amazon porque ofrece la mejor +experiencia de instalación en la mayoría de las plataformas. Sin embargo, Corretto no es el único proveedor de OpenJDK +disponible. Hay muchas alternativas, como [Eclipse Adoptium](https://adoptium.net/), +[Microsoft](https://www.microsoft.com/openjdk) y +[Azul Zulu](https://www.azul.com/downloads/?package=jdk). Ten en cuenta que no recomendamos el JDK distribuido por Oracle, aunque sea funcionalmente idéntico, +debido a que su instalador es muy poco amigable y a sus anteriores condiciones de licencia restrictivas. + +::: + +## Linux + +### Ubuntu/Debian + +Instalar Java 25 en distribuciones Linux basadas en Debian es muy sencillo. Primero, asegúrate de que el sistema tenga +todas las herramientas necesarias para instalar Java correctamente. + +```bash +sudo apt-get update +sudo apt-get install ca-certificates apt-transport-https gnupg wget +``` + +Después, importa la clave pública y el repositorio apt de Amazon Corretto. + +```bash +wget -O - https://apt.corretto.aws/corretto.key | sudo gpg --dearmor -o /usr/share/keyrings/corretto-keyring.gpg && \ +echo "deb [signed-by=/usr/share/keyrings/corretto-keyring.gpg] https://apt.corretto.aws stable main" | sudo tee /etc/apt/sources.list.d/corretto.list +``` + +Luego, instala Java 25 y otras dependencias con el siguiente comando: + +```bash +sudo apt-get update +sudo apt-get install -y java-25-amazon-corretto-jdk libxi6 libxtst6 libxrender1 +``` + +Continúa con [verificar la instalación](#verificar-la-instalación). + +### Basado en RPM + +Para instalar Java 25 en CentOS, RHEL, Fedora, openSUSE, SLES u otra distribución Linux basada en RPM, +ejecuta los siguientes comandos según el gestor de paquetes. Cuando termines, +continúa con [verificar la instalación](#verificar-la-instalación). + +#### DNF + +DNF se usa en Fedora, CentOS/RHEL 7 y distribuciones relacionadas. + +```bash +sudo rpm --import https://yum.corretto.aws/corretto.key +sudo curl -Lo /etc/yum.repos.d/corretto.repo https://yum.corretto.aws/corretto.repo +sudo dnf -y install java-25-amazon-corretto-devel +``` + +#### Zypper + +Zypper se usa en openSUSE, SLES y distribuciones relacionadas. + +```bash +sudo zypper addrepo https://yum.corretto.aws/corretto.repo +sudo zypper refresh +sudo zypper install java-25-amazon-corretto-devel +``` + +#### YUM + +YUM se usa en versiones antiguas de CentOS/RHEL y en versiones muy antiguas de Fedora. + +```bash +sudo rpm --import https://yum.corretto.aws/corretto.key +sudo curl -Lo /etc/yum.repos.d/corretto.repo https://yum.corretto.aws/corretto.repo +sudo yum -y install java-25-amazon-corretto-devel +``` + +## Windows 10 y 11 + +En Windows 10 u 11, instalar Java es igual que instalar cualquier otro programa. Descarga +el instalador de Amazon Corretto desde +[su sitio web](https://corretto.aws/downloads/latest/amazon-corretto-25-x64-windows-jdk.msi). + +Después de ejecutar el instalador, puedes hacer clic en «siguiente» durante todo el proceso. No se instalarán +programas no deseados ni barras de herramientas, y todas las funciones necesarias vienen habilitadas de forma predeterminada. + +Ahora, abre una línea de comandos y continúa con [verificar la instalación](#verificar-la-instalación). + +## macOS/OS X + +En macOS, la mejor forma de gestionar las instalaciones de Java es mediante una herramienta llamada +[Homebrew](https://brew.sh). Sigue las instrucciones de su página de inicio para instalarla. Después, ejecuta el siguiente comando en la +terminal: + +```bash +brew install openjdk@25 +``` + +Cuando termine este comando, continúa con [verificar la instalación](#verificar-la-instalación). + +## Pterodactyl + +:::note + +En versiones de Pterodactyl anteriores a `1.2.0`, se necesita una cuenta de administrador para cambiar la versión de Java. +Estas instrucciones no serán aplicables. + +::: + +Si iniciaste un servidor Paper con una versión de Java incorrecta, Pterodactyl te pedirá automáticamente +que la actualices de esta forma: + +![Aviso automático de Pterodactyl](../../misc/assets/pterodactyl-prompt.png) + +Si no aparece este aviso, puedes cambiar la versión de Java manualmente. Ve a la pestaña +"Inicio" del servidor y selecciona `Java 25` en el menú desplegable "Imagen de Docker", +como se muestra en la imagen siguiente. + +![Cambio manual de la versión de Java en Pterodactyl](../../misc/assets/pterodactyl-manual.png) + +:::note + +Si no ves `Java 25` en el menú desplegable, se necesita una cuenta de administrador para actualizar el egg de Paper. + +::: + +## Pufferpanel (Docker) + +:::note + +Necesitarás permisos de **Admin** en el panel para cambiar la versión de Java. + +::: + +En el servidor cuya versión de Java quieras cambiar, ve a la pestaña **Admin** y abre +**Editar la definición del servidor**. En la pestaña **Entorno**, el campo **Imagen de Docker** te permite +editar la imagen de Docker utilizada. + +![Pestaña Entorno de Pufferpanel](../../misc/assets/pufferpanel-environment.png) + +En este caso, basta con reemplazar la versión (el número después de ":") por `25`. +Puedes encontrar imágenes de Docker alternativas del JDK en +[Docker Hub](https://hub.docker.com/search?badges=official). + +## Verificar la instalación + +:::note + +Esta sección no se aplica al usar Pterodactyl o Pufferpanel. + +::: + +Ahora que instalaste Java 25, ejecuta este comando en la terminal para comprobar que el proceso se +completó correctamente. + +```bash +java -version +``` + +El resultado debería parecerse al siguiente. Comprueba que empiece por +`openjdk 25` y que la última línea incluya `64-Bit`. Si el resultado es parecido a +`java: command not found`, prueba a abrir una sesión nueva de la terminal. + +``` +openjdk version "25" 2025-09-16 +OpenJDK Runtime Environment (build 25+36-3489) +OpenJDK 64-Bit Server VM (build 25+36-3489, mixed mode, sharing) +``` + +Si la instalación falla, no dudes en pedir ayuda en el canal `#paper-help` de nuestro +[Discord](https://discord.gg/papermc). diff --git a/src/content/docs/es/misc/tools/diff-viewer.md b/src/content/docs/es/misc/tools/diff-viewer.md new file mode 100644 index 000000000..c4d48e56d --- /dev/null +++ b/src/content/docs/es/misc/tools/diff-viewer.md @@ -0,0 +1,19 @@ +--- +title: Visor de diferencias +description: Visor enriquecido de diferencias entre varios archivos de GitHub y archivos diff/patch. +slug: es/misc/tools/diff-viewer +--- + +Visor enriquecido de diferencias entre varios archivos, compatible con confirmaciones, solicitudes de cambios y comparaciones de GitHub, así como +con archivos diff y patch. +El visor de diferencias de GitHub es excelente para la mayoría de los casos, pero tiene varias limitaciones, +especialmente al trabajar con diferencias grandes, en las que puede funcionar mal o incluso bloquearse. +El visor de diffs.dev busca resolver este problema y ofrecer funciones adicionales +útiles para PaperMC y en general, como el tratamiento especial de diferencias de segundo orden. También +hemos creado una extensión para Firefox y Chrome que facilita abrir diferencias de GitHub en el +visor. + +- https://diffs.dev - El visor de diferencias +- [Chrome Extension](https://chromewebstore.google.com/detail/patch-roulette/feaaoepdocmiibjilhoahgldkaajfnhb) +- [Firefox Add-on](https://addons.mozilla.org/en-US/firefox/addon/patch-roulette/) +- https://github.com/PaperMC/diff-viewer - Repositorio de GitHub diff --git a/src/content/docs/es/misc/tools/index.mdx b/src/content/docs/es/misc/tools/index.mdx new file mode 100644 index 000000000..e8029564c --- /dev/null +++ b/src/content/docs/es/misc/tools/index.mdx @@ -0,0 +1,10 @@ +--- +title: Herramientas +tableOfContents: false +--- + +import PageCards from "/src/components/PageCards.astro"; + +Colección de herramientas útiles para administradores de servidores y desarrolladores de plugins. + + diff --git a/src/content/docs/es/misc/tools/item-command-converter.mdx b/src/content/docs/es/misc/tools/item-command-converter.mdx new file mode 100644 index 000000000..61ec12262 --- /dev/null +++ b/src/content/docs/es/misc/tools/item-command-converter.mdx @@ -0,0 +1,21 @@ +--- +title: Conversor de comandos de objetos +description: Herramienta para actualizar comandos del antiguo formato de objetos basado en NBT a componentes de objetos. +slug: es/misc/tools/item-command-converter +tableOfContents: false +--- + +import ItemCommandConverter from "/src/components/tools/ItemCommandConverter.svelte"; + +En la versión 1.20.5, Mojang pasó del NBT no estructurado a los llamados componentes de objetos. Aunque Minecraft +actualizará automáticamente todos los objetos existentes, solo Paper actualizará, cuando sea posible, los comandos y +componentes de texto que contengan objetos. Esta herramienta permite convertir externamente los comandos antiguos de objetos al +nuevo formato. + + +Ten en cuenta que debes seleccionar el modo *Argumento de entidad* si quieres convertir datos de entidades fuera del +comando summon, ya que necesitamos el tipo de entidad para convertir los datos correctamente. + +
+ + diff --git a/src/content/docs/es/misc/tools/minimessage-web-editor.md b/src/content/docs/es/misc/tools/minimessage-web-editor.md new file mode 100644 index 000000000..c77801ef7 --- /dev/null +++ b/src/content/docs/es/misc/tools/minimessage-web-editor.md @@ -0,0 +1,12 @@ +--- +title: Editor web de MiniMessage +description: Editor web para crear y previsualizar texto con formato MiniMessage. +slug: es/misc/tools/minimessage-web-editor +--- + +El editor web de MiniMessage permite crear y previsualizar texto con formato MiniMessage. + + +Está disponible aquí: [Editor web de MiniMessage](https://webui.advntr.dev/). + +![Imagen de la interfaz web de Adventure](../../../misc/tools/assets/adventure-webui.png) diff --git a/src/content/docs/es/misc/tools/start-script-gen.mdx b/src/content/docs/es/misc/tools/start-script-gen.mdx new file mode 100644 index 000000000..ab8a84fde --- /dev/null +++ b/src/content/docs/es/misc/tools/start-script-gen.mdx @@ -0,0 +1,23 @@ +--- +title: Generador de scripts de inicio +description: Generador de scripts de inicio para proyectos de PaperMC. +slug: es/misc/tools/start-script-gen +tableOfContents: false +--- + +import StartScriptGenerator from "/src/components/tools/StartScriptGenerator.svelte"; + +
+ ¿Qué opciones debo elegir? + Si usas una JVM moderna, por ejemplo la 17, 21 o superior, primero prueba sin opciones. + Las JVM modernas gestionan muy bien distintas aplicaciones con la configuración predeterminada del GC. + + Si tienes problemas con el GC o ejecutas una versión antigua de Minecraft o Java, + prueba las [opciones de Aikar](/es/paper/aikars-flags), optimizadas específicamente para Minecraft. + + Si generas un script para iniciar [Velocity](https://papermc.io/software/velocity), selecciona "Velocity". +
+ +
+ + diff --git a/src/content/docs/es/paper/admin/getting-started/adding-plugins.md b/src/content/docs/es/paper/admin/getting-started/adding-plugins.md new file mode 100644 index 000000000..a92df9bf9 --- /dev/null +++ b/src/content/docs/es/paper/admin/getting-started/adding-plugins.md @@ -0,0 +1,123 @@ +--- +title: Añadir plugins +description: Los plugins son la forma más potente de ampliar las funciones de Paper más allá de los archivos de configuración. +slug: es/paper/adding-plugins +--- + +Los plugins son la forma más potente de ampliar las funciones de Paper más allá de los archivos de configuración. +Las funciones que añaden pueden ir desde hacer que la leche restaure el hambre o que crezcan los arbustos secos, +hasta incorporar modos de juego o artículos totalmente nuevos y originales. + +:::danger[Plugins maliciosos] + +Asegúrate de confiar plenamente en el origen de cualquier plugin antes de instalarlo. Los plugins obtienen acceso +**completo y sin restricciones** no solo a tu servidor, sino también a la máquina en la que se ejecuta. Por eso, +es imprescindible instalar plugins únicamente desde fuentes de confianza. ¡Ten cuidado! + +::: + +## Buscar plugins + +Antes de instalar un plugin, tendrás que encontrar el que quieres. El mejor lugar para buscar +plugins es [Hangar](https://hangar.papermc.io), el repositorio de plugins de Paper, aunque también puedes encontrarlos +en [Modrinth](https://modrinth.com/discover/plugins?g=categories:paper) o +[BukkitDev](https://dev.bukkit.org/bukkit-plugins). Muchos plugins también se publican en [GitHub](https://github.com). +En vez de revisar cada sitio por separado, puedes usar un motor de búsqueda. A menudo encontrarás buenos resultados +si buscas la función que necesitas seguida de `Paper plugin`. + +## Instalar plugins + +1. Cuando encuentres el plugin que quieres instalar, descárgalo. Asegúrate de que el archivo + descargado termine en `.jar`. Algunos plugins también se distribuyen como archivos `.zip`; en ese caso, + tendrás que extraer el archivo y localizar el `.jar` correspondiente a tu plataforma, normalmente etiquetado como `bukkit` o + `paper`. +2. Una vez descargado el plugin en tu equipo, busca la carpeta `plugins` en el directorio raíz + de tu servidor Paper. +3. Arrastra el archivo del plugin (`.jar`) hasta la carpeta `plugins`. Si usas un servicio de alojamiento compartido, + puede que tengas que subir el plugin mediante su panel web o SFTP; el procedimiento será el mismo. +4. Reinicia el servidor. El plugin debería cargarse. +5. Comprueba que todo haya funcionado. Cuando termine de cargarse el servidor, ejecuta el comando `/plugins` dentro del juego o escribe + `plugins` en la consola. El plugin recién instalado debería aparecer en verde. Si no aparece o figura en rojo, + continúa con la [solución de problemas](#solucion-de-problemas). Un plugin en rojo no está habilitado. Si acabas de instalarlo, + normalmente significa que no se pudo cargar. + +## Solución de problemas + +### Revisar los registros + +El primer paso para resolver problemas al instalar plugins es revisar el registro del servidor. Los +registros más recientes se guardan en el archivo `logs/latest.log`. Puede que tengas que desplazarte +cerca del principio del archivo para ver cuándo se cargaron los plugins. + +#### Dependencias faltantes + +Si ves algo parecido a esto: + +```log +[00:00:00] [Server thread/WARN] Could not load 'plugins/MyAwesomePlugin-1.0.0.jar' in folder 'plugins' +[00:00:00] [Server thread/WARN] org.bukkit.plugin.UnknownDependencyException: Unknown/missing dependency plugins: [Vault]. Please download and install these plugins to run 'MyAwesomePlugin'. +``` + +Esto significa que al plugin que intentaste instalar le falta una dependencia. En este caso, una dependencia +es otro plugin que debes instalar para que funcione el primero. Aunque aparezca un error alarmante, +la línea importante es: + +```log +[00:00:00] [Server thread/WARN] Unknown/missing dependency plugins: [Vault]. Please download and install these plugins to run 'MyAwesomePlugin'. +``` + +El mensaje indica que primero debes instalar `Vault` para poder cargar `MyAwesomePlugin`. + +#### `plugin.yml` no válido + +Si ves algo más parecido a esto: + +```log +[00:00:00] [Server thread/WARN] Could not load 'plugins/MyAwesomePlugin-1.0.0.jar' in folder 'plugins' +[00:00:00] [Server thread/WARN] org.bukkit.plugin.InvalidDescriptionException: Invalid plugin.yml +``` + +Esto significa que lo que descargaste no es un plugin válido de Paper. Suele deberse a una de estas causas: + +1. Lo que descargaste no es un plugin, sino un mod para Forge, Fabric o una plataforma similar. + Estos no se ejecutan en Paper. +2. La descarga del plugin no se completó correctamente. En especial, al usar herramientas como `curl` o `wget`, + es fácil descargar páginas de error en vez del plugin esperado. También puede deberse a un problema de red. + Intenta descargar el plugin otra vez. Si usas FTP (no SFTP ni un panel web) para subir el plugin a un servicio de alojamiento compartido, + asegúrate de que el cliente FTP esté en modo `binary` y no en modo `ASCII`. Consulta la documentación del cliente FTP para obtener más detalles. + +#### Nombre de plugin ambiguo + +Si ves algo parecido a esto: + +```log +[00:00:00] [Server thread/WARN] Ambiguous plugin name `Essentials' for files `plugins/EssentialsX-2.19.4.jar' and `plugins/Essentialsx-2.20.0-dev.jar' in `plugins' +``` + +Esto significa que tienes dos plugins con el mismo nombre, algo que no se admite. En este caso, hay instaladas dos +versiones de EssentialsX: la versión estable `2.19.4` y una compilación de desarrollo de +`2.20.0`. Asegúrate de tener instalada solo una versión de cada plugin a la vez. Elimina +la versión más antigua del plugin duplicado y reinicia el servidor. + +Para evitar instalar accidentalmente dos versiones del mismo plugin durante una actualización, puedes usar +la carpeta `update`, tal como se explica en la [guía de actualización](/es/paper/updating#paso-2-actualizar-plugins). + +#### Otro problema + +Si ves un error distinto de los anteriores, intenta leerlo. Aunque el mensaje completo pueda ser extenso e intimidante, +probablemente baste con leer las primeras una o dos líneas para entender qué ocurre. Si tienes dudas, no dudes en pedir ayuda +en nuestro [Discord](https://discord.gg/papermc), en el canal `#paper-help`. + +### Si no se registra nada + +Si no se registra nada, es probable que el servidor ni siquiera esté intentando cargar plugins. Para que el servidor cargue un plugin, deben cumplirse estas condiciones: + +1. El archivo está en la raíz de la carpeta `plugins`, relativa al directorio de trabajo. Normalmente es + la misma carpeta que contiene el archivo JAR del servidor. **No se revisarán las subcarpetas de `plugins`.** + Todos los plugins deben estar en la carpeta raíz. +2. El archivo termina en `.jar`. Si el archivo del plugin no termina en `.jar`, puede que lo que descargaste + no sea un plugin. Ten en cuenta que algunos plugins distribuyen varios JAR dentro de archivos `.zip`. En ese + caso, debes extraerlos antes de instalar el plugin. + +Si se cumplen ambas condiciones y aun así no aparece ningún registro, pide ayuda en nuestro servidor de +[Discord](https://discord.gg/papermc), en el canal `#paper-help`. Estaremos encantados de ayudarte. diff --git a/src/content/docs/es/paper/admin/getting-started/getting-started.mdx b/src/content/docs/es/paper/admin/getting-started/getting-started.mdx new file mode 100644 index 000000000..763f0d6b4 --- /dev/null +++ b/src/content/docs/es/paper/admin/getting-started/getting-started.mdx @@ -0,0 +1,71 @@ +--- +title: Primeros pasos +description: Cómo empezar a descargar y configurar un servidor Paper. +slug: es/paper/getting-started +--- + +## Requisitos + +:::tip + +Paper requiere al menos **Java 25** para ejecutarse; [descargarlo e instalarlo es sencillo](/es/misc/java-install). + +::: + +| Versión de Paper | Versión recomendada de Java | +|-------------------|--------------------------| +| 1.7.10 to 1.11 | Java 8 | +| 1.12 to 1.16.4 | Java 11 | +| 1.16.5 | Java 16 | +| 1.17 to 1.19 | Java 17 | +| 1.20 to 1.21.11 | Java 21 | +| 26.1+ | Java 25 | + +## Descargar Paper + +Paper ofrece archivos JAR de servidor ejecutables directamente desde la +[página de descargas de nuestro sitio web](https://papermc.io/downloads/paper). + +Haz clic en el número de compilación para descargar un archivo. + +## Ejecutar el servidor + +Para ejecutar el servidor, tendrás que crear un script de inicio +o ejecutar un comando en el terminal. + +Puedes generar un script de inicio con nuestro [Generador de scripts de inicio](/es/misc/tools/start-script-gen). +También puedes obtener allí el comando optimizado para ejecutar el servidor desde el terminal. + +Si solo buscas un comando breve: +```bash +java -Xms4G -Xmx4G -jar paper.jar --nogui +``` +Asegúrate de que el terminal esté situado en el directorio de tu servidor +y de haber sustituido `paper.jar` por el nombre del archivo JAR que descargaste. + +Puedes establecer la cantidad de RAM cambiando los valores de los argumentos `Xmx` y `Xms`. +`--nogui` desactiva la interfaz gráfica de Vanilla para evitar que aparezcan dos interfaces al usar la línea de comandos. + +Para configurar el servidor, consulta las páginas de [Configuración global](/es/paper/reference/global-configuration) y +[Configuración por mundo](/es/paper/reference/world-configuration). + +## Actualizar el servidor + +¡Actualizar Paper es sencillo! Consulta nuestro [tutorial de actualización](/es/paper/updating) para obtener más información. + +## Migrar a Paper + +### Desde Vanilla + +La migración desde Vanilla es sencilla, pero hay algunas diferencias, sobre todo en los datos guardados de los mundos. Paper permite que las dimensiones tengan datos independientes (como las reglas del juego). + +Paper realizará esta conversión automáticamente. No hace falta ningún paso adicional. + +### Desde CraftBukkit o Spigot + +Paper sustituye directamente tanto a CraftBukkit como a Spigot, así que no necesitas hacer ningún cambio. + +## Próximos pasos + +Consulta nuestra guía de [próximos pasos](/es/paper/next-steps) para poner en marcha tu servidor con el mejor rendimiento y las mejores +funciones. diff --git a/src/content/docs/es/paper/admin/getting-started/index.mdx b/src/content/docs/es/paper/admin/getting-started/index.mdx new file mode 100644 index 000000000..73120cac2 --- /dev/null +++ b/src/content/docs/es/paper/admin/getting-started/index.mdx @@ -0,0 +1,10 @@ +--- +title: Primeros pasos +tableOfContents: false +--- + +import PageCards from "/src/components/PageCards.astro"; + +Guías para empezar a ejecutar un servidor Paper. + + diff --git a/src/content/docs/es/paper/admin/getting-started/migration.md b/src/content/docs/es/paper/admin/getting-started/migration.md new file mode 100644 index 000000000..7d87d4b9d --- /dev/null +++ b/src/content/docs/es/paper/admin/getting-started/migration.md @@ -0,0 +1,132 @@ +--- +title: Migrar a Paper o desde Paper +description: Migrar tu servidor a Paper o desde Paper es sencillo. Esta página te ayudará a empezar. +slug: es/paper/migration +--- + +Migrar tu servidor a Paper o desde Paper es sencillo. Los pasos siguientes te ayudarán a empezar. + +:::caution[¡Haz una copia de seguridad de tus datos antes de empezar!] + +Antes de empezar, asegúrate de tener una copia de seguridad completa del servidor. + +Consulta nuestra [guía de copias de seguridad](/es/paper/updating#paso-1-crear-una-copia-de-seguridad) para obtener más información. + +::: + +## Migrar a Paper + +### Desde Vanilla + +Al migrar de Vanilla a Paper, cambiará automáticamente la forma en que se almacenan los mundos. +Si alguna vez quieres volver a Vanilla, sigue atentamente la [guía de migración a Vanilla](#a-vanilla), +ya que tendrás que realizar algunos cambios manualmente. + +1. Si el servidor Vanilla está en ejecución, detenlo y crea una copia de seguridad completa. +2. Descarga Paper desde [nuestra página de descargas](https://papermc.io/downloads) y sustituye el JAR + del servidor Vanilla por el JAR de Paper que acabas de descargar. +3. Cambia el nombre del archivo descargado para que coincida con el indicado en + el [comando de inicio](/es/paper/getting-started#ejecutar-el-servidor). +4. Inicia el nuevo servidor Paper. + +Ya has migrado a Paper correctamente. Si tienes algún problema, no dudes en pedir ayuda +en [nuestro servidor de Discord](https://discord.gg/papermc), en el canal `#paper-help`. + +### Desde Fabric/Forge + +Como Fabric y Forge usan la estructura de directorios de mundos de Vanilla, puedes seguir los mismos pasos que en la +[guía de migración desde Vanilla](#desde-vanilla), con una salvedad. Si el servidor Fabric o Forge +usaba mods que añadían bloques, artículos u otros datos al juego, Paper no podrá +cargar esas funciones. + +Además, ten en cuenta que Paper no admite mods de Fabric ni de Forge. Tendrás que buscar plugins +que los sustituyan. Las plataformas híbridas que intentan admitir tanto mods como plugins tienen defectos fundamentales y +no se recomienda usarlas. + +### Desde Spigot/CraftBukkit + +Spigot y CraftBukkit modifican la estructura de directorios de mundos de Vanilla, por lo que, a partir de `26.1`, +la migración directa es fundamentalmente imposible. Si aun así quieres migrar desde Spigot/CraftBukkit, +primero tendrás que **migrar de Spigot/CraftBukkit a Vanilla** y, después, podrás seguir sin problemas +la [guía de migración desde Vanilla](#desde-vanilla). Para obtener instrucciones, consulta la documentación de Spigot. + +## Migrar desde Paper + +### A Vanilla + +Como Paper comparte una estructura de mundos similar a la de Vanilla, solo tendrás que mover algunos archivos. +La siguiente lista indica qué archivos debes mover y a dónde. **Antes de moverlos, +asegúrate de que el servidor esté completamente detenido**. + +:::note + +Estos pasos presuponen que `level-name` (definido en `server.properties`) tiene el valor `world`. Si no es así, +sustituye `world` por el valor de `level-name` en todos los pasos siguientes. + +::: + +Los siguientes archivos deben moverse **desde** `world/dimensions/minecraft/overworld/data/minecraft/` +**a** `world/data/minecraft/`: + +- `game_rules.dat` +- `scheduled_events.dat` +- `wandering_trader.dat` +- `weather.dat` +- `world_gen_settings.dat` + +Cuando hayas movido estos archivos, podrás sustituir el JAR del servidor Paper por un JAR del servidor Vanilla +y poner en marcha el servidor Vanilla. + +### A Fabric/Forge + +Como Fabric y Forge usan la misma estructura de directorios de almacenamiento de mundos que Vanilla, sigue +la [guía de migración a Vanilla](#a-vanilla). Ten en cuenta que ni Fabric ni Forge admiten plugins de Paper. +Tendrás que buscar mods que los sustituyan. + +## Otras migraciones + +:::caution + +Las guías siguientes contienen información obsoleta que ya no es pertinente para los servidores Paper actuales. Se +conservan por motivos históricos y para quienes aún usan versiones antiguas. Ten en cuenta que +**no recibirás asistencia si usas versiones obsoletas**. + +::: + +### A Vanilla (anterior a 26.1) + +Como Paper almacena los mundos de manera ligeramente distinta a Vanilla, la migración requiere algunos pasos manuales. +Si no los sigues, parecerá que el Nether y el End se han reiniciado. ¡No te preocupes! +Aunque esto ocurra, no habrás perdido datos: el servidor Vanilla simplemente no sabe dónde +encontrarlos. + +La tabla siguiente muestra la diferencia entre la forma en que Vanilla y Paper almacenan los mundos. + +| Software del servidor | Mundo superior | Nether | End | +|-----------------|-----------|-----------------------|-----------------------| +| Vanilla | `/world` | `/world/DIM-1` | `/world/DIM1` | +| Paper | `/world` | `/world_nether/DIM-1` | `/world_the_end/DIM1` | + +Sigue estos pasos para migrar de Paper a Vanilla: + +:::note + +Estos pasos presuponen que `level-name` (definido en `server.properties`) tiene el valor `world`. Si no es así, +sustituye `world` por el valor de `level-name` en todos los pasos siguientes. + +::: + +1. Detén el servidor Paper si está en ejecución. +2. Si ya iniciaste el servidor con Vanilla, abre la carpeta `world` y elimina las carpetas `DIM-1` y `DIM1`. + Este paso solo es necesario si ya iniciaste el servidor con Vanilla. +3. Copia la carpeta `/world_nether/DIM-1` dentro de la carpeta `/world`. +4. Copia la carpeta `/world_the_end/DIM1` dentro de la carpeta `/world`. +5. Elimina las carpetas `/world_nether` y `/world_the_end`. +6. Sustituye el JAR de Paper por un JAR del servidor Vanilla. +7. Inicia el servidor Vanilla. + +### A CraftBukkit o Spigot + +Paper **no admite** la migración a CraftBukkit ni a Spigot. +Aunque puede que consigas hacerlo, **no** solicites asistencia +si tienes problemas y ten en cuenta que podrías perder datos. diff --git a/src/content/docs/es/paper/admin/getting-started/next-steps.md b/src/content/docs/es/paper/admin/getting-started/next-steps.md new file mode 100644 index 000000000..25756191e --- /dev/null +++ b/src/content/docs/es/paper/admin/getting-started/next-steps.md @@ -0,0 +1,63 @@ +--- +title: Próximos pasos +description: Qué hacer después de iniciar el servidor. +slug: es/paper/next-steps +--- + +Ahora que tu servidor está en funcionamiento, hay algunas cosas que deberías hacer para asegurarte de que funcione sin problemas. + +## Configuración + +Una de las primeras cosas que deberías hacer es asegurarte de que el servidor esté configurado según tus preferencias. +Paper ofrece muchas opciones de configuración que puedes adaptar a tus necesidades. En la guía de +[configuración](/es/paper/reference/configuration) explicamos dónde encontrar estos ajustes. + +## Plugins + +Una de las principales razones para usar Paper es aprovechar los numerosos plugins que utilizan nuestra +amplia API. Tenemos nuestro propio repositorio de plugins, [Hangar](https://hangar.papermc.io/), donde puedes +encontrar muchos plugins para tu servidor. También tenemos una guía sobre cómo instalarlos +[aquí](/es/paper/adding-plugins). + +![Hangar](../../../../paper/admin/getting-started/assets/hangar.png) + +## Seguridad + +### Lista de permitidos + +Si quieres restringir quién puede entrar en tu servidor, puedes usar la lista de permitidos. Esta función te permite +indicar quién puede entrar e impide el acceso a cualquier otra persona. Puedes administrar la lista desde +la consola del servidor o editando el archivo `whitelist.json` en el directorio del servidor. + +### Permisos + +Los permisos permiten controlar lo que los jugadores pueden y no pueden hacer en tu servidor. Puedes usarlos +para restringir quién puede ejecutar determinados comandos o acceder a ciertas zonas. Es habitual que los plugins +usen permisos para controlar quién puede utilizar sus funciones. Puedes administrar los permisos que se conceden +a los jugadores con plugins como [LuckPerms](https://luckperms.net/). + +## Copias de seguridad + +Es importante conservar copias de seguridad del servidor. Si algo sale mal, podrás restaurarlo a un +estado anterior. Explicamos cómo hacerlo en la guía de [actualización](/es/paper/updating). + +## Optimización + +Paper viene optimizado para ofrecer un buen rendimiento. Aun así, puedes hacer muchas cosas para optimizarlo +aún más. Una de las más habituales es asegurarte de que el servidor se ejecute con los indicadores de inicio +adecuados. Tenemos una herramienta que genera automáticamente un script de inicio con los indicadores correctos. +Puedes encontrarla +[aquí](/es/misc/tools/start-script-gen). Además, una guía como [esta](https://paper-chan.moe/paper-optimization/) +te ayudará a optimizar aún más tu servidor. + +## Hacer público tu servidor + +Si quieres hacer público tu servidor, tendrás que configurar el reenvío de puertos. Esto permite que personas +ajenas a tu red se conecten al servidor. [NordVPN](https://nordvpn.com/blog/open-ports-on-router/) ofrece una guía +que explica qué es el reenvío de puertos y cómo configurarlo para tu servidor Paper. + +## Solución de problemas + +Si tienes algún problema con el servidor, puedes seguir nuestra guía de [solución de problemas](/es/paper/basic-troubleshooting) +para diagnosticarlo y resolverlo. Si no consigues solucionarlo, puedes pedir ayuda en nuestro servidor de +[Discord](https://discord.gg/papermc). diff --git a/src/content/docs/es/paper/admin/how-to/aikars-flags.md b/src/content/docs/es/paper/admin/how-to/aikars-flags.md new file mode 100644 index 000000000..3889df476 --- /dev/null +++ b/src/content/docs/es/paper/admin/how-to/aikars-flags.md @@ -0,0 +1,164 @@ +--- +title: Indicadores de Aikar +description: Los indicadores de Aikar son un conjunto de indicadores de JVM diseñados para mejorar el rendimiento de tu servidor Paper. +slug: es/paper/aikars-flags +--- + +## Indicadores de inicio de JVM recomendados + +:::caution[Generador de scripts] + +**Esta página solo sirve como explicación.** Si quieres generar un script de inicio, visita +nuestro **[Generador de scripts](/es/misc/tools/start-script-gen)**. + +::: + +```bash +java -Xms10G -Xmx10G -XX:+UseG1GC -XX:+ParallelRefProcEnabled -XX:MaxGCPauseMillis=200 -XX:+UnlockExperimentalVMOptions -XX:+DisableExplicitGC -XX:+AlwaysPreTouch -XX:G1NewSizePercent=30 -XX:G1MaxNewSizePercent=40 -XX:G1HeapRegionSize=8M -XX:G1ReservePercent=20 -XX:G1HeapWastePercent=5 -XX:G1MixedGCCountTarget=4 -XX:InitiatingHeapOccupancyPercent=15 -XX:G1MixedGCLiveThresholdPercent=90 -XX:G1RSetUpdatingPauseTimePercent=5 -XX:SurvivorRatio=32 -XX:+PerfDisableSharedMem -XX:MaxTenuringThreshold=1 -Dusing.aikars.flags=https://mcflags.emc.gs -Daikars.new.flags=true -jar paper.jar --nogui +``` + +:::danger[¡No asignes toda la memoria disponible en un alojamiento compartido!] + +Al definir los valores de `Xms` y `Xmx`, si tu proveedor indica que tienes 8 GB de memoria, **¡no uses 8 GB!** + +Minecraft (y Java) necesitan memoria adicional además de la indicada por el parámetro `Xmx`. Se recomienda +**reducir `Xmx` y `Xms` en unos 1000-1500 MB** para evitar quedarte sin memoria o que `OOMKiller` cierre +el servidor. Así también dejas memoria disponible para el sistema operativo. + +¿Tienes 8 GB de memoria? Por seguridad, usa 6500 MB. +_También puedes preguntar a tu proveedor si cubre esta sobrecarga y +te asigna 9500M. ¡Algunos lo hacen! Solo tienes que preguntar._ + +::: + +## Memoria recomendada + +**Recomendamos usar al menos entre 6 y 10 GB**, aunque haya pocos jugadores. Si no puedes permitirte 10 GB de +memoria, asigna tanta como puedas, pero asegúrate de dejar memoria para el sistema operativo. G1GC +funciona mejor con más memoria. + +Sin embargo, a partir de cierto punto, más memoria no significa un mejor rendimiento. Llegarás a +un punto de rendimientos decrecientes. Comprar 32 GB de RAM para un servidor solo será un gasto +con beneficios mínimos. + +## Registro de GC de Java + +¿Tienes problemas con la generación antigua al usar estos indicadores? Añade los siguientes indicadores según tu versión de Java +para habilitar el registro de GC: + +**Java 8-10** + +```bash +-Xloggc:gc.log -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps +-XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=1M +``` + +**Java 11+** + +```bash +-Xlog:gc*:logs/gc.log:time,uptime:filecount=5,filesize=1M +``` + +El registro de GC no afecta al rendimiento y puede permanecer activado en todo momento. Los archivos no ocuparán +mucho espacio (5 MB). + +## Explicación técnica de los indicadores + +1. **Por qué hacer coincidir -Xms con -Xmx:** Nunca deberías ejecutar el servidor con una configuración en la que `Xmx` pueda + agotar toda la memoria del sistema. Debes asumir que el servidor podría usar todo el valor de + `Xmx`. Asegúrate de que el sistema operativo tenga memoria adicional a la de `Xmx` para procesos ajenos a Minecraft o al propio sistema. + Por tanto, no ejecutes Minecraft con un valor de `Xmx` que no puedas asumir que Java usará por completo. + Esto significa que **si `Xms` es menor que `Xmx`, tienes memoria sin usar**. La memoria sin usar + se desperdicia. G1 funciona mejor cuanta más memoria tiene. G1 elige de forma adaptativa cuánta memoria asignar a cada región + para optimizar las pausas. Si tiene más memoria de la necesaria para alcanzar un tiempo de pausa óptimo, + simplemente destinará el exceso a la generación antigua, sin efectos perjudiciales. La idea fundamental para mejorar el comportamiento del GC + es garantizar que los objetos de corta duración mueran jóvenes y nunca se promuevan. Cuanta más memoria tenga G1, + más probable será que los objetos no se promuevan prematuramente a la generación antigua. G1 funciona de forma distinta + a los recolectores anteriores y puede gestionar heaps grandes con mayor eficiencia. + + Si no necesita la memoria asignada, no la utilizará. Todo el motor funciona de otra manera y no sufre por heaps demasiado grandes; + es una recomendación ampliamente aceptada en el sector que, con G1, se mantengan iguales Xms y Xmx. + +2. **UnlockExperimentalVMOptions:** necesario para algunas de las opciones siguientes. + +3. **G1NewSizePercent:** Estos son algunos de los ajustes más importantes. Ahora puedes especificar porcentajes de + un intervalo total deseado para la generación nueva. Con estos ajustes, indicamos a G1 que no use el + 5 % predeterminado para la generación nueva, sino el 40 %. **Minecraft tiene una tasa de asignación de memoria extremadamente + alta**: puede llegar al menos a 800 MB por segundo en un servidor con 30 jugadores. La mayoría corresponde a objetos de corta duración (posiciones de bloques). + + Por eso, Minecraft necesita **realmente** dar más prioridad a la generación nueva para admitir esta tasa + de asignación. Si la generación nueva es demasiado pequeña, se ejecutarán recolecciones de esa generación una o más veces + por segundo, lo cual es muy perjudicial. Habrá tantas pausas que los TPS podrían verse afectados + y el servidor no podrá asumir el costo de las recolecciones de basura. Además, los objetos se promoverán más rápido y la generación antigua crecerá con mayor rapidez. Con más espacio para la generación nueva, + podemos ampliar los intervalos entre recolecciones de objetos jóvenes, dando más tiempo para que los objetos de corta duración mueran jóvenes y mejorando la eficiencia general del GC. + +4. **G1MixedGCLiveThresholdPercent:** Controla cuándo se incluyen regiones en las recolecciones mixtas de GC durante + la recolección de la generación joven. Así se mantiene limpia la generación antigua sin ejecutar una recolección normal de esa generación. Si el uso de + memoria está por debajo de este porcentaje, la generación antigua ni siquiera se incluirá en las recolecciones mixtas. Estas + son menos costosas que una recolección completa de la generación antigua, así que las limpiezas incrementales pequeñas mantienen + bajo el uso de memoria. + + El valor predeterminado varía entre 65 y 85 según la versión de Java. Lo establecemos en 90 para recuperar los residuos + de la generación antigua lo más rápido posible y conservar tantas regiones libres como podamos. + +5. **G1ReservePercent=20:** En las versiones actuales, la tasa de asignación de memoria de Minecraft es extraordinariamente alta. Existe + el riesgo de sufrir la temida «falta de espacio de destino» por no tener suficiente memoria libre para mover los datos. + Este ajuste reserva más memoria para esa operación. El valor predeterminado es 10, así que añadimos otros 10 puntos. + +6. **MaxTenuringThreshold=1:** Minecraft tiene una tasa de asignación de memoria muy alta. La mayor parte + de esa memoria se recupera en la generación eden. Sin embargo, los datos transitorios pasan a la + generación survivor. Al principio probamos a eliminar por completo survivor y obtuvimos resultados aceptables, pero esto + hace que los datos transitorios pasen a la generación antigua, lo cual no es conveniente. Max Tenuring 1 garantiza que no + promovamos datos transitorios a la generación antigua; se supondrá que todo lo que sobreviva a dos ciclos de GC + tiene una vida útil más larga. + + Esto reduce considerablemente las pausas en las recolecciones jóvenes, ya que copiar los datos de un objeto tenured hasta 15 veces en + el espacio survivor lleva mucho tiempo cuando se trata de memoria realmente antigua. Lo ideal sería que el motor del GC + registrara la edad media de los objetos y los promoviera antes, pero no funciona así. + + Como la frecuencia media del GC va de 10 segundos a varios minutos por recolección joven, esto no + provoca que se promueva «basura»; solo retrasa la recolección de la memoria de mayor duración hasta las recolecciones mixtas. + +7. **SurvivorRatio=32:** Como hemos reducido drásticamente MaxTenuringThreshold, también reduciremos + considerablemente el uso del espacio survivor. Así liberamos más regiones para que las use eden. + +8. **AlwaysPreTouch:** AlwaysPreTouch prepara y reserva la memoria al iniciar el proceso y garantiza + que sea contigua, lo que mejora aún más su eficiencia. Esto aumenta la velocidad de acceso a memoria del sistema operativo. + Es obligatorio usar Transparent Huge Pages. + +9. **+DisableExplicitGC:** Muchos plugins creen saber cómo administrar la memoria e intentan iniciar + la recolección de basura. Esto provoca una recolección completa y un pico enorme + de retraso. Este indicador impide que los plugins lo intenten y te protege de ese código + defectuoso. + +10. **MaxGCPauseMillis=200:** Este ajuste controla cuánta memoria se usa dentro de los límites mínimo + y máximo especificados para la generación nueva. Es un «objetivo» para la duración de las pausas de recolección del servidor. + Un valor de 200 supone perder como máximo 4 ticks. Esto provocará una breve caída de TPS, pero el servidor podrá recuperarla al instante, + por lo que no tendrá un efecto significativo en los TPS. Los jugadores no perciben una pausa de 200 ms. En + las pruebas, limitar este valor aún más impide que G1 recupere memoria lo bastante rápido y podría agotar la generación antigua, lo que desencadenaría una recolección completa. + Que este valor sea 200 no significa que cada recolección dure 200 ms. Significa que puede tardar hasta + 200 ms si realmente lo necesita, y debemos dejar que haga su trabajo cuando haya memoria que recuperar. + +11. **+ParallelRefProcEnabled:** Optimiza el proceso de GC para usar varios hilos al comprobar referencias débiles. + No se sabe por qué no está habilitado de forma predeterminada... + +12. **G1RSetUpdatingPauseTimePercent=5:** El valor predeterminado destina el 10 % del tiempo de pausa a actualizar los RSets; + lo reducimos al 5 % para que una mayor parte se ejecute de forma concurrente y las pausas sean más cortas. + +13. **G1MixedGCCountTarget=4:** El valor predeterminado es 8. Como buscamos hacer recolecciones más pausadas con menos uso de la generación antigua, + intentamos recuperar su memoria más rápido para evitar agotarla. + +14. **G1HeapRegionSize=8M+:** El valor predeterminado se calcula automáticamente. Es muy importante para Minecraft, especialmente + en la versión 1.15, porque con poca memoria el cálculo predeterminado suele ser demasiado bajo. Cualquier + asignación de memoria que ocupe la mitad de este tamaño (4 MB) se tratará como «Humongous», pasará directamente a + la generación antigua y será más difícil de liberar. Si permites que Java use el valor predeterminado, una parte considerable de la memoria se tratará como Humongous. + +15. **+PerfDisableSharedMem:** Hace que el GC escriba en el sistema de archivos, lo que puede causar mucha latencia si + la E/S del disco es alta. Consulta https://www.evanjones.ca/jvm-mmap-pause.html. + +### Páginas enormes transparentes + +Es una función controvertida, pero puede servir si no puedes configurar HugeTLBFS real en tu alojamiento. Prueba +a añadir `-XX:+UseTransparentHugePages`, pero es imprescindible que también tengas establecido `AlwaysPreTouch`. +De lo contrario, es probable que THP afecte negativamente al rendimiento. No hemos medido cómo funciona THP con Minecraft ni su impacto junto con +`AlwaysPreTouch`, así que esta sección está dirigida a usuarios avanzados que quieran experimentar. diff --git a/src/content/docs/es/paper/admin/how-to/anti-xray.mdx b/src/content/docs/es/paper/admin/how-to/anti-xray.mdx new file mode 100644 index 000000000..07a2f6f7d --- /dev/null +++ b/src/content/docs/es/paper/admin/how-to/anti-xray.mdx @@ -0,0 +1,467 @@ +--- +title: Configurar Anti-Xray +description: Paper incluye de forma predeterminada un sistema Anti-Xray basado en ofuscación. Aquí aprenderás a configurarlo. +slug: es/paper/anti-xray +--- + +> Escrito y mantenido originalmente por [stonar96](https://github.com/stonar96). + +Paper incluye Anti-Xray basado en ofuscación, con tres modos que se pueden configurar por mundo. + +:::note[Configuración por mundo] + +Si aún no conoces la configuración por mundo, dedica un momento a familiarizarte con la +[guía de configuración](/es/paper/reference/configuration). + +::: + +Esta guía explica paso a paso cómo configurar Anti-Xray. Para consultar la documentación de referencia, +visita la sección de Anti-Xray de la +[referencia de configuración por mundo](/es/paper/reference/world-configuration#anticheat_anti_xray). + +Anti-Xray tiene tres modos. `engine-mode: 1` sustituye los bloques especificados en `hidden-blocks` por +otros bloques «falsos»: `stone` (`deepslate` si y < 0), `netherrack` o `end_stone`, según la +dimensión. En cambio, `engine-mode: 2` sustituye tanto los bloques de `hidden-blocks` como los de `replacement-blocks` +por bloques de `hidden-blocks` generados aleatoriamente. `engine-mode: 3` funciona de forma similar a `engine-mode: 2`, pero en vez de +aleatorizar cada bloque, aleatoriza el bloque de cada capa de un chunk. + +Las imágenes siguientes[^1] muestran cómo se ve cada modo para un jugador que usa Xray con la configuración +recomendada, tanto en el Overworld como en el Nether. + +[^1]: + Diseño de la imagen por `Oberfail`, publicada originalmente en el + [PaperMC Discord](https://discord.gg/papermc). + +{/* + +Seed: -7943468717341609647 + +# Overworld: +/tp @p -581.976 67.85076 -4924.106 47 36 + +# Nether: +/tp @p 789.437 117.38012 -319.064 -137.4 28 +*/} + +![Comparación de Anti-Xray en el Overworld](../../../../paper/admin/how-to/assets/anti-xray-overworld.png) +![Comparación de Anti-Xray en el Nether](../../../../paper/admin/how-to/assets/anti-xray-nether.png) + +Especialmente en el cliente, `engine-mode: 1` requiere muchos menos recursos de cómputo, mientras que +`engine-mode: 2` puede impedir mejor el uso de Xray. Con `engine-mode: 1`, solo se ocultan los minerales completamente cubiertos +por bloques sólidos. No se ocultan los minerales expuestos al aire en cuevas ni al agua de un lago. +Con `engine-mode: 2`, los minerales falsos ocultan los bloques reales. Si añades `air` a +`hidden-blocks`, `engine-mode: 2` ocultará prácticamente todos los minerales, incluso los expuestos al aire. `engine-mode: 3` puede reducir aproximadamente a la mitad la carga de red al entrar y ayuda a comprimir los paquetes de chunks. + +:::caution[Formas de eludir Anti-Xray] + +**Ampliación del alcance**: Aunque Anti-Xray por sí solo impedirá que la mayoría de los usuarios usen Xray en tu +servidor, no es infalible en absoluto. Debido a la forma en que Anti-Xray está implementado (y debe implementarse), +en un servidor predeterminado es posible ampliar de forma considerable el alcance al que se pueden ver minerales reales. +Un plugin antitrampas competente puede mitigar esto; sin embargo, no se incluye de forma predeterminada. + +**Inversión de la seed**: Otro vector de ataque es el carácter determinista de la generación de mundos de Minecraft. +Si el cliente consigue obtener la seed del mundo, puede conocer la ubicación real de +cada mineral generado y eludir por completo Anti-Xray. Se puede dificultar parcialmente esta inversión de la seed con la +[configuración `feature-seeds`](/es/paper/reference/world-configuration#feature_seeds), junto con +las opciones de seed de estructuras de `spigot.yml`. Ten en cuenta que no es una solución completa: el cliente +aún podría obtener la seed del mundo del servidor. También puede ser útil usar una seed distinta +para cada mundo. + +**Minerales expuestos al aire**: En `engine-mode: 1`, `engine-mode: 2` y `engine-mode: 3`, el cliente puede +ver los minerales expuestos al aire. En `engine-mode: 2` y `engine-mode: 3`, esto se puede mitigar añadiendo `air` a +la lista `hidden-blocks`. Sin embargo, esto puede provocar problemas de rendimiento en el cliente (caídas de FPS) a +algunos jugadores. + +::: + +## Configuración recomendada + +La configuración recomendada para `engine-mode: 1`, `engine-mode: 2` y `engine-mode: 3` es la siguiente: + +:::tip[Espaciado] + +¡YAML distingue los espacios en blanco! El ejemplo de configuración siguiente ya tiene el formato correcto. Para mantener +el formato y la sangría, usa el botón «copiar» situado en la esquina superior derecha de cada +ejemplo. Asegúrate especialmente de no insertar tabuladores por accidente. Comprueba las opciones del editor +para usar espacios en lugar de tabuladores en la sangría. Si el archivo de configuración ya contiene +otros cambios importantes, se recomienda hacer una copia de seguridad antes de editarlo. + +::: + +### `engine-mode: 1` + +
+ Configuración predeterminada del mundo + +Sustituye el bloque `anticheat.anti-xray` existente en `paper-world-defaults.yml` por el siguiente: + +```yaml title="paper-world-defaults.yml" +anticheat: + anti-xray: + enabled: true + engine-mode: 1 + hidden-blocks: + # No hay forma de ocultar los cofres de las mazmorras, ya que están completamente rodeados de aire; los tesoros enterrados sí se ocultarán. + - chest + - coal_ore + - deepslate_coal_ore + - copper_ore + - deepslate_copper_ore + - raw_copper_block + - diamond_ore + - deepslate_diamond_ore + - emerald_ore + - deepslate_emerald_ore + - gold_ore + - deepslate_gold_ore + - iron_ore + - deepslate_iron_ore + - raw_iron_block + - lapis_ore + - deepslate_lapis_ore + - redstone_ore + - deepslate_redstone_ore + lava-obscures: false + # Desde la versión 1.18, algunos minerales se generan a mucha más altura. + # Ajusta el valor de max-block-height según lo necesites. + # Puede serte útil consultar https://minecraft.wiki/w/Ore. + max-block-height: 64 + # La lista replacement-blocks no se usa en engine-mode: 1. Cambiarla no tendrá efecto. + replacement-blocks: [] + update-radius: 2 + use-permission: false +``` + +
+ +
+ Configuración del Nether + +Copia y pega esto en el archivo `paper-world.yml` de la carpeta del mundo Nether. Consulta la +[guía de configuración](/es/paper/reference/configuration) para obtener más información. + +```yml title="world/dimensions/minecraft/the_nether/paper-world.yml" +anticheat: + anti-xray: + enabled: true + engine-mode: 1 + hidden-blocks: + - ancient_debris + - nether_gold_ore + - nether_quartz_ore + lava-obscures: false + max-block-height: 128 + # La lista replacement-blocks no se usa en engine-mode: 1. Cambiarla no tendrá efecto. + replacement-blocks: [] + update-radius: 2 + use-permission: false +``` + +
+ +
+ Configuración del End + +Copia y pega esto en el archivo `paper-world.yml` de la carpeta del mundo End. Consulta la +[guía de configuración](/es/paper/reference/configuration) para obtener más información. + +```yml title="world/dimensions/minecraft/the_end/paper-world.yml" +anticheat: + anti-xray: + enabled: false +``` + +
+ +### `engine-mode: 2` + +
+ Configuración predeterminada del mundo + +Sustituye el bloque `anticheat.anti-xray` existente en `paper-world-defaults.yml` por el siguiente: + +```yaml title="paper-world-defaults.yml" +anticheat: + anti-xray: + enabled: true + engine-mode: 2 + hidden-blocks: + # Puedes añadir aire aquí para que se generen muchos agujeros. + # Esto funciona bien contra quienes buscan cuevas, pero puede reducir los FPS del cliente de todos los jugadores. + - air + - copper_ore + - deepslate_copper_ore + - raw_copper_block + - diamond_ore + - deepslate_diamond_ore + - gold_ore + - deepslate_gold_ore + - iron_ore + - deepslate_iron_ore + - raw_iron_block + - lapis_ore + - deepslate_lapis_ore + - redstone_ore + - deepslate_redstone_ore + lava-obscures: false + # Desde la versión 1.18, algunos minerales se generan a mucha más altura. + # Ajusta el valor de max-block-height según lo necesites. + # Puede serte útil consultar https://minecraft.wiki/w/Ore. + max-block-height: 64 + replacement-blocks: + # Chest es una entidad de bloque y no se puede añadir a hidden-blocks en engine-mode: 2. + # Sin embargo, si aumentas max-block-height, añadir chest aquí ocultará los tesoros enterrados. + - chest + - amethyst_block + - andesite + - budding_amethyst + - calcite + - coal_ore + - deepslate_coal_ore + - deepslate + - diorite + - dirt + - emerald_ore + - deepslate_emerald_ore + - granite + - gravel + - oak_planks + - smooth_basalt + - stone + - tuff + update-radius: 2 + use-permission: false +``` + +
+ +
+ Configuración del Nether + +Copia y pega esto en el archivo `paper-world.yml` de la carpeta del mundo Nether. Consulta la +[guía de configuración](/es/paper/reference/configuration) para obtener más información. + +```yml title="world/dimensions/minecraft/the_nether/paper-world.yml" +anticheat: + anti-xray: + enabled: true + engine-mode: 2 + hidden-blocks: + # Consulta la nota anterior sobre el aire y los posibles problemas de rendimiento del cliente. + - air + - ancient_debris + - bone_block + - glowstone + - magma_block + - nether_bricks + - nether_gold_ore + - nether_quartz_ore + - polished_blackstone_bricks + lava-obscures: false + max-block-height: 128 + replacement-blocks: + - basalt + - blackstone + - gravel + - netherrack + - soul_sand + - soul_soil + update-radius: 2 + use-permission: false + +``` + +
+ +
+ Configuración del End + +Copia y pega esto en el archivo `paper-world.yml` de la carpeta del mundo End. Consulta la +[guía de configuración](/es/paper/reference/configuration) para obtener más información. + +```yml title="world/dimensions/minecraft/the_end/paper-world.yml" +anticheat: + anti-xray: + enabled: false +``` +
+ + +### `engine-mode: 3` + +
+ Configuración predeterminada del mundo + +Sustituye el bloque `anticheat.anti-xray` existente en `paper-world-defaults.yml` por el siguiente: + +```yaml title="paper-world-defaults.yml" +anticheat: + anti-xray: + enabled: true + engine-mode: 3 + hidden-blocks: + # Puedes añadir aire aquí para que se generen muchos agujeros. + # Esto funciona bien contra quienes buscan cuevas, pero puede reducir los FPS del cliente de todos los jugadores. + - air + - copper_ore + - deepslate_copper_ore + - raw_copper_block + - diamond_ore + - deepslate_diamond_ore + - gold_ore + - deepslate_gold_ore + - iron_ore + - deepslate_iron_ore + - raw_iron_block + - lapis_ore + - deepslate_lapis_ore + - redstone_ore + - deepslate_redstone_ore + lava-obscures: false + # Desde la versión 1.18, algunos minerales se generan a mucha más altura. + # Ajusta el valor de max-block-height según lo necesites. + # Puede serte útil consultar https://minecraft.wiki/w/Ore. + max-block-height: 64 + replacement-blocks: + # Chest es una entidad de bloque y no se puede añadir a hidden-blocks en engine-mode: 2. + # Sin embargo, si aumentas max-block-height, añadir chest aquí ocultará los tesoros enterrados. + - chest + - amethyst_block + - andesite + - budding_amethyst + - calcite + - coal_ore + - deepslate_coal_ore + - deepslate + - diorite + - dirt + - emerald_ore + - deepslate_emerald_ore + - granite + - gravel + - oak_planks + - smooth_basalt + - stone + - tuff + update-radius: 2 + use-permission: false +``` + +
+ +
+ Configuración del Nether + +Copia y pega esto en el archivo `paper-world.yml` de la carpeta del mundo Nether. Consulta la +[guía de configuración](/es/paper/reference/configuration) para obtener más información. + +```yml title="world/dimensions/minecraft/the_nether/paper-world.yml" +anticheat: + anti-xray: + enabled: true + engine-mode: 3 + hidden-blocks: + # Consulta la nota anterior sobre el aire y los posibles problemas de rendimiento del cliente. + - air + - ancient_debris + - bone_block + - glowstone + - magma_block + - nether_bricks + - nether_gold_ore + - nether_quartz_ore + - polished_blackstone_bricks + lava-obscures: false + max-block-height: 128 + replacement-blocks: + - basalt + - blackstone + - gravel + - netherrack + - soul_sand + - soul_soil + update-radius: 2 + use-permission: false +``` + +
+ +
+ Configuración del End + +Copia y pega esto en el archivo `paper-world.yml` de la carpeta del mundo End. Consulta la +[guía de configuración](/es/paper/reference/configuration) para obtener más información. + +```yml title="world/dimensions/minecraft/the_end/paper-world.yml" +anticheat: + anti-xray: + enabled: false +``` + +
+ +## Preguntas frecuentes, errores comunes y asistencia + +
+ Aún puedo ver algunos minerales o usar Xray + +Como se describió anteriormente, hay varios motivos por los que quizá aún puedas ver algunos minerales aunque hayas +activado Anti-Xray: + +* Los minerales están por encima del valor configurado en `max-block-height`. +* Anti-Xray no puede ocultar minerales expuestos al aire o a otros bloques transparentes (por ejemplo, en cuevas). En + principio, esto también ocurre con `engine-mode: 2` y `engine-mode: 3`; sin embargo, normalmente los minerales falsos ocultan + los bloques reales. Para ocultar también esos minerales expuestos se necesitan plugins adicionales. +* La opción `use-permission` está habilitada y tienes el permiso para eludir Anti-Xray (`paper.antixray.bypass`) o tienes + estado de operador. +* Falta el tipo de bloque en las listas de bloques configuradas. Esto puede deberse a que se usa un + archivo de configuración obsoleto. + +
+ +
+ Añadí bloques falsos, pero Xray no los muestra + +Si usas `engine-mode: 2` o `engine-mode: 3` y añadiste bloques falsos a la lista `hidden-blocks`, pero no puedes +verlos dentro del juego con Xray, puede deberse a lo siguiente: + +* Los tipos de bloque añadidos son entidades de bloque. Anti-Xray puede ocultar (sustituir) entidades de bloque, como + cofres, siempre que no estén expuestas al aire ni a otros bloques transparentes. Sin embargo, Anti-Xray + no puede colocar entidades de bloque falsas en el chunk. +* El bloque está desactivado en el mod Xray de tu cliente o tu paquete de recursos Xray no lo muestra. + +
+ +
+ No funciona por debajo de y = 0 ni en ciertos otros lugares + +* Es probable que tu archivo de configuración esté obsoleto y que falten bloques importantes en la lista + `replacement-blocks`, como `deepslate` o bloques específicos de biomas, como `basalt`. También + podrías comprobar si la lista `hidden-blocks` incluye todos los minerales importantes y sus + variantes de `deepslate`. +* Si no funciona por encima de cierta altura Y, comprueba el ajuste `max-block-height`. + +
+ +
+ Sigue sin funcionar: más pasos para solucionar problemas + +* Asegúrate de reiniciar siempre el servidor después de cambiar la configuración de Anti-Xray. + Los cambios no se aplican automáticamente. +* No uses el comando `/reload`. Es necesario reiniciar el servidor para aplicar los cambios de configuración de Anti-Xray. +* Después de reiniciar el servidor, comprueba que la configuración se haya aplicado correctamente inspeccionando las + secciones de configuración con timings o spark. + +
+ +
+ ¿Cómo y dónde puedo pedir ayuda si sigue sin funcionar? + +Si los puntos anteriores no resuelven el problema o tienes más preguntas sobre +Anti-Xray, no dudes en consultarnos en el [Discord de PaperMC](https://discord.gg/papermc), +en el canal #paper-help. Procura describir el problema con el mayor detalle posible. +Decir «no funciona» no ayuda mucho a quienes prestan asistencia. Explica qué quieres conseguir, +qué has intentado, qué esperabas y qué observas. Lo ideal es incluir un enlace de timings o spark +y una captura de lo que ves en el juego. + +
diff --git a/src/content/docs/es/paper/admin/how-to/basic-troubleshooting.mdx b/src/content/docs/es/paper/admin/how-to/basic-troubleshooting.mdx new file mode 100644 index 000000000..2536f601f --- /dev/null +++ b/src/content/docs/es/paper/admin/how-to/basic-troubleshooting.mdx @@ -0,0 +1,233 @@ +--- +title: Solución básica de problemas +description: Esta guía te ayudará a diagnosticar los problemas del servidor antes de comunicarlos a PaperMC o al autor del plugin. +slug: es/paper/basic-troubleshooting +--- + +Esta guía te ayudará a diagnosticar los problemas del servidor antes de comunicarlos a PaperMC o al autor del plugin. + +:::caution[Detén el servidor y haz una copia de seguridad] + +Antes de seguir esta guía, detén el servidor. Modificar sus archivos mientras está en ejecución los dañará. Solo un apagado completo del servidor puede evitarlo. + +Además, si no sigues esta guía con atención o cometes un error al hacerlo, podrías dañar el servidor. Se recomienda encarecidamente crear una copia de seguridad antes de seguirla. Basta con archivar la carpeta del servidor como archivo .zip o, si lo prefieres, usar programas de copia de seguridad como [borg](https://www.borgbackup.org/) o [kopia](https://kopia.io/). Lo ideal sería crear un servidor de prueba copiando los archivos del servidor de producción, aunque no siempre es posible. + +::: + +Si se produce un problema, el servidor imprimirá un mensaje de error en la consola, generará un informe de fallo y se cerrará, o hará ambas cosas. +Si el servidor falla, el informe se guardará en el directorio crash-report. Si no se ha cerrado, los mensajes de error se guardarán en el directorio de registros junto con los demás mensajes. + +Ten en cuenta que los registros anteriores al más reciente se comprimen y no se guardan como archivos de texto sin formato. + +Lo primero que debes hacer es diagnosticar esos mensajes. + +Casi todos los problemas que encuentres mostrarán en la consola del servidor líneas de mensaje de error llamadas «stack trace» (traza de pila). Examinar la traza de pila te ayudará a averiguar qué causa los problemas del servidor. + +La traza de pila empieza con el mensaje de error, el tipo de excepción y el mensaje de la excepción. + +Los mensajes de error y de excepción los añadió el desarrollador de tu plugin o de Paper. Estos mensajes indican qué problema tuvo el servidor. Un tipo de excepción como `java.lang.RuntimeException` señala la clase de excepción y ayudará al desarrollador (y a ti) a comprender el problema. Un buen punto de partida es buscar el tipo y el mensaje de la excepción en el [Discord de Paper](https://discord.gg/papermc). + +Debajo del mensaje de excepción pueden aparecer muchas líneas que empiezan con `at`. Estas forman el cuerpo de la traza de pila e indican dónde empieza el problema. La primera línea del cuerpo señala exactamente dónde ocurrió y, si es posible, muestra su origen. + +Los problemas suelen deberse a plugins, así que eso es lo primero que deberías comprobar. + +# Problemas comunes + +## Problemas causados por plugins +Si encuentras el nombre de algún plugin en una traza de pila de los registros, ve a [Comprobar las actualizaciones de plugins](#comprobar-las-actualizaciones-de-plugins) y sigue las instrucciones de esa sección. En la mayoría de los casos, el plugin que aparece en la traza de pila es el causante del problema. + +Puedes desactivar todos los plugins cambiando el nombre del directorio plugins por otro, como plugins-disabled, o archivando y eliminando el directorio plugins. + +Después, intenta iniciar el servidor. + +Si el problema se resuelve al quitar los plugins, sabrás que lo causaba uno de ellos. + +### Búsqueda binaria +Si has determinado que un plugin causa problemas, pero no consigues identificar cuál, prueba con una búsqueda binaria. + +1. Divide los plugins en dos grupos. Los grupos pueden tener tamaños distintos, pero lo ideal es que la diferencia sea mínima. Asegúrate de agrupar juntos los plugins que dependen entre sí. +2. Desactiva uno de los grupos. Para hacerlo, puedes cambiar la extensión de sus archivos de .jar a otra, como .jar-disabled, o moverlos fuera del directorio plugins a otro directorio. +3. Inicia el servidor y comprueba si el problema persiste. Si se resuelve, el plugin causante está entre los desactivados. Si no se resuelve, está entre los que siguen activos. +4. Vuelve a empezar con el grupo de plugins sospechoso. +Repite estos pasos con el grupo que contiene el plugin causante. + +:::caution[Dependencias de plugins de bibliotecas] + +Algunos plugins que instalas no son plugins típicos, sino bibliotecas. Se instalan como plugins, pero suelen ofrecer pocas funciones visibles para el usuario y otros plugins dependen de ellas. Si desactivas una biblioteca, los plugins que dependen de ella no funcionarán correctamente. Algunos ejemplos comunes son ProtocolLib, los proveedores de Vault y los plugins de permisos. + +::: + +### Comprobar las actualizaciones de plugins +Es posible que el problema ya esté corregido en la versión estable o compilación más recientes del plugin. + +Visita la página oficial de descarga del plugin y comprueba si usas la compilación o la versión estable más recientes. Si no es así, actualízalo a la versión más reciente e intenta iniciar el servidor otra vez para ver si se resolvió el problema. + +### Actualizar los plugins de bibliotecas +Muchos plugins usan bibliotecas como ProtocolLib, que debes descargar y colocar en el directorio plugins. + +Si no las actualizas a la versión o compilación más recientes, podrías tener problemas con los plugins que dependen de ellas. + +Algunas bibliotecas indican a sus usuarios que utilicen la compilación de desarrollo más reciente para admitir la última versión de Minecraft. Revisa atentamente los requisitos de tus plugins. + +### Consultar la documentación +Una configuración incorrecta del plugin o del servidor también puede causar problemas. Muchos plugins tienen su propia documentación sobre cómo configurarlos correctamente. Léela con atención y comprueba si hay algún problema con la configuración del plugin. + +Si el problema está relacionado con un plugin y aún no sabes cómo resolverlo, puedes intentar contactar con su autor. Muchos plugins ofrecen algún medio para hacerlo, como el rastreador de incidencias de GitHub, un servidor de asistencia en Discord, Gitter, IRC, etc. + +A continuación, enumeramos otros problemas que pueden surgir al ejecutar un servidor. + +## El servidor no se inicia +Si ocurre esto, revisa siempre el archivo `latest.log` de la carpeta `logs`; puede que allí aparezca el problema. Si no se generan registros, comprueba el script de inicio tal como se describe a continuación: + +### Comprobar el script de inicio +La forma recomendada de iniciar un servidor es mediante un script de inicio, que puedes generar [aquí](/es/misc/tools/start-script-gen). ¡No hagas doble clic en el archivo .jar! +Si usas Windows y el terminal desaparece poco después de iniciarlo, asegúrate de que haya una línea al final del archivo que contenga únicamente `pause`. +Si aparece un error parecido a `Error: Unable to access jarfile server.jar`, asegúrate de que el nombre del archivo .jar en el script de inicio coincida con el nombre del archivo que descargaste. Ten en cuenta que Windows oculta las extensiones de forma predeterminada, así que quizá tengas que volver a activarlas en las opciones de carpeta y búsqueda del explorador de archivos para ver el nombre correcto, incluida la extensión. + +### No se pudo enlazar el puerto +Esto puede ocurrir en dos casos: +1. Ya hay un servidor en ejecución. Busca procesos de Java en el administrador de tareas. +2. `server-ip` está configurado incorrectamente en `server.properties`. Esta opción no es un marcador de posición para tu IP externa: controla a qué interfaces de red se enlazará el servidor. En la mayoría de los casos, debe dejarse vacía. + +### Se intentó cargar un chunk guardado con una versión más reciente +{/* spellchecker:off */} +``` +java.lang.RuntimeException: Server attempted to load chunk saved with newer version of minecraft! 3955 > 3465 +[18:23:38 WARN]: at net.minecraft.world.level.chunk.storage.ChunkRegionLoader.loadChunk(ChunkRegionLoader.java:149) +[18:23:38 WARN]: at io.papermc.paper.chunk.system.scheduling.ChunkLoadTask$ChunkDataLoadTask.runOffMain(ChunkLoadTask.java:338) +[18:23:38 WARN]: at io.papermc.paper.chunk.system.scheduling.GenericDataLoadTask$ProcessOffMainTask.run(GenericDataLoadTask.java:307) +[18:23:38 WARN]: at ca.spottedleaf.concurrentutil.executor.standard.PrioritisedThreadedTaskQueue$PrioritisedTask.executeInternal(PrioritisedThreadedTaskQueue.java:351) +[18:23:38 WARN]: at ca.spottedleaf.concurrentutil.executor.standard.PrioritisedThreadedTaskQueue.executeTask(PrioritisedThreadedTaskQueue.java:118) +[18:23:38 WARN]: at ca.spottedleaf.concurrentutil.executor.standard.PrioritisedThreadPool$PrioritisedThread.pollTasks(PrioritisedThreadPool.java:274) +[18:23:38 WARN]: at ca.spottedleaf.concurrentutil.executor.standard.PrioritisedQueueExecutorThread.run(PrioritisedQueueExecutorThread.java:50) +``` +{/* spellchecker:on */} + +Ese error significa que tu mundo se creó o abrió con una versión del servidor más reciente que la que estás ejecutando. No se admite volver a una versión anterior del mundo, así que asegúrate de usar la última versión compatible de Paper. Al cargar el mundo con una versión más reciente, se actualiza automáticamente aunque todavía no hayas entrado al servidor. + +:::danger[Forzar al servidor a intentar cargar un mundo más reciente] + +El servidor se iniciará si usas el indicador `-DPaper.ignoreWorldDataVersion=true`. Sin embargo, **no se recomienda en absoluto, no se admite y puede dañar tu mundo de forma permanente**. Si vas a intentarlo, haz una copia de seguridad. + +::: + +### Carga circular de plugins + +``` +[15:01:04] [Server thread/ERROR]: [SimpleProviderStorage] Circular plugin loading detected! +[15:01:04] [Server thread/ERROR]: [SimpleProviderStorage] Circular load order: +[15:01:04] [Server thread/ERROR]: [SimpleProviderStorage] Plugin1 -> Plugin2 -> Plugin3 -> Plugin4 -> Plugin1 +[15:01:04] [Server thread/ERROR]: [SimpleProviderStorage] Please report this to the plugin authors of the first plugin of each loop or join the PaperMC Discord server for further help. +[15:01:04] [Server thread/ERROR]: [SimpleProviderStorage] If you would like to still load these plugins, acknowledging that there may be unexpected plugin loading issues, run the server with -Dpaper.useLegacyPluginLoading=true +``` + +Esto significa que la configuración de tus plugins hace que quieran iniciarse antes (o después) unos de otros, algo imposible: uno debe iniciarse primero. Por lo general, los plugins tienen motivos para querer iniciarse antes que otros; cuando se produce este conflicto, en vez de elegir un orden al azar y arriesgarse a causar problemas, el servidor te avisa y se cierra. +A menudo hay un plugin problemático. Lo mejor es comunicar el problema a sus autores; también puede solucionarse eliminándolo. Como último recurso, puedes usar el indicador de inicio `-Dpaper.useLegacyPluginLoading=true`, pero podría causar problemas difíciles de depurar. + +### Versión de Java obsoleta + +``` +Exception in thread "ServerMain" java.lang.UnsupportedClassVersionError: org/bukkit/craftbukkit/Main has been compiled by a more recent version of the Java Runtime (class file version 65.0), this version of the Java Runtime only recognizes class file versions up to 61.0 + at java.base/java.lang.ClassLoader.defineClass1(Native Method) + at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1017) + at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:150) + at java.base/java.net.URLClassLoader.defineClass(URLClassLoader.java:524) + at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:427) + at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:421) + at java.base/java.security.AccessController.doPrivileged(AccessController.java:712) + at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:420) + at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:592) + at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:525) + at java.base/java.lang.Class.forName0(Native Method) + at java.base/java.lang.Class.forName(Class.java:467) + at io.papermc.paperclip.Paperclip.lambda$main$0(Paperclip.java:38) + at java.base/java.lang.Thread.run(Thread.java:842) +``` + +Tu versión de Java está obsoleta; consulta [nuestra guía para actualizarla](/es/misc/java-install). Para evitar tener que hacer otros ajustes, desinstala la versión actual de Java, si la hay. +Si ya tienes instalada la versión correcta, es posible que el sistema operativo no la esté detectando. Asegúrate de cerrar y volver a abrir el terminal después de instalarla y de que Java esté en la variable de entorno `PATH`. + +## El servidor falla o se cierra inesperadamente + +:::caution[¡Actualiza!] + +Mantén siempre el servidor actualizado (y crea una copia de seguridad antes de actualizar). Se sabe que en versiones antiguas hay fallos que los jugadores pueden provocar en cualquier momento. + +::: + +### Cierre normal inesperado +Si el servidor se cierra con normalidad, como si hubieras escrito `/stop` o pulsado el botón para detenerlo en el panel, habilita `debug` en `server.properties`. La próxima vez que se cierre, obtendrás una traza de pila que te ayudará a depurarlo. + +### Volcado del watchdog («DO NOT REPORT THIS TO PAPER») +``` +[02:04:00] [Paper Watchdog Thread/ERROR]: --- DO NOT REPORT THIS TO PAPER - THIS IS NOT A BUG OR A CRASH - 1.21.3-66-afb5b13 (MC: 1.21.3) --- +[02:04:00] [Paper Watchdog Thread/ERROR]: The server has not responded for 10 seconds! Creating thread dump +[02:04:00] [Paper Watchdog Thread/ERROR]: ------------------------------ +[02:04:00] [Paper Watchdog Thread/ERROR]: Server thread dump (Look for plugins here before reporting to Paper!): +[02:04:00] [Paper Watchdog Thread/ERROR]: ------------------------------ +[02:04:00] [Paper Watchdog Thread/ERROR]: Current Thread: Server thread +[02:04:00] [Paper Watchdog Thread/ERROR]: PID: 129 | Suspended: false | Native: true | State: RUNNABLE +[02:04:00] [Paper Watchdog Thread/ERROR]: Stack: +[02:04:00] [Paper Watchdog Thread/ERROR]: java.base@21.0.5/sun.nio.ch.UnixFileDispatcherImpl.write0(Native Method) +[02:04:00] [Paper Watchdog Thread/ERROR]: java.base@21.0.5/sun.nio.ch.UnixFileDispatcherImpl.write(UnixFileDispatcherImpl.java:65) +[02:04:00] [Paper Watchdog Thread/ERROR]: java.base@21.0.5/sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:137) +[02:04:00] [Paper Watchdog Thread/ERROR]: java.base@21.0.5/sun.nio.ch.IOUtil.write(IOUtil.java:102) +[02:04:00] [Paper Watchdog Thread/ERROR]: java.base@21.0.5/sun.nio.ch.IOUtil.write(IOUtil.java:72) +[02:04:00] [Paper Watchdog Thread/ERROR]: java.base@21.0.5/sun.nio.ch.FileChannelImpl.write(FileChannelImpl.java:300) +[02:04:00] [Paper Watchdog Thread/ERROR]: java.base@21.0.5/sun.nio.ch.ChannelOutputStream.writeFully(ChannelOutputStream.java:68) +[02:04:00] [Paper Watchdog Thread/ERROR]: java.base@21.0.5/sun.nio.ch.ChannelOutputStream.write(ChannelOutputStream.java:105) +[02:04:00] [Paper Watchdog Thread/ERROR]: java.base@21.0.5/java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:125) +[02:04:00] [Paper Watchdog Thread/ERROR]: java.base@21.0.5/java.io.BufferedOutputStream.implFlush(BufferedOutputStream.java:252) +[02:04:00] [Paper Watchdog Thread/ERROR]: java.base@21.0.5/java.io.BufferedOutputStream.flush(BufferedOutputStream.java:240) +[02:04:00] [Paper Watchdog Thread/ERROR]: java.base@21.0.5/java.io.FilterOutputStream.close(FilterOutputStream.java:184) +``` + +Ese mensaje aparece cuando el servidor tarda mucho (más de 10 segundos) en completar el tick actual. No es un error ni un fallo: solo te advierte de un retraso grave que podría acabar provocando un fallo. +Como regla general, revisa las primeras líneas de la traza de pila, que muestran dónde se bloqueó el hilo principal cuando se generó el mensaje. A menudo, ahí encontrarás la causa principal. +Sin embargo, a veces el problema no es evidente ni aparece en la traza. Si es posible, analiza un [informe de spark](#informe-de-spark) para obtener más detalles. Si no sabes cómo proceder, visita el [Discord de Paper](https://discord.gg/papermc) para pedir ayuda. + +### Fallo sin registros +Si tienes acceso a un shell de Linux, ejecuta `dmesg -T | grep -i killed`. Esto debería indicar cómo se cerró el proceso del servidor. +Una causa común (aunque no la única) de que se cierre por OOM es que el panel del servidor tenga un límite de memoria demasiado cercano a `-Xmx`. Reduce `-Xmx` (como medida inicial, entre 1 y 2 GB) o aumenta/desactiva los límites de memoria del panel. +Si usas un proveedor de alojamiento que solo ofrece un panel, probablemente no tengas las herramientas necesarias para investigar el problema. En ese caso, abre un ticket con el proveedor. + +## Problemas de rendimiento y jugabilidad +Por desgracia, Paper no puede reproducir el comportamiento de Vanilla al 100 %, aunque ese es el objetivo (salvo en lo que respecta a los exploits). Si sigues teniendo un error que no se puede reproducir en el modo **multijugador** de Vanilla, aplica una [configuración similar a Vanilla](/es/paper/vanilla) y comprueba si ya hay una incidencia abierta en nuestro GitHub. Si no la hay, puedes crear una. + +### Comportamiento extraño de entidades, granjas, redstone o aparición +Si copiaste valores de una configuración ya preparada o de una guía de optimización, este es un buen momento para revertirlos. Si quieres, guarda una copia de las configuraciones actuales y elimina los originales para que se vuelvan a generar con los valores predeterminados. + +Si sigues teniendo estos problemas con la configuración predeterminada, prueba nuestras [configuraciones similares a Vanilla](/es/paper/vanilla), pero ten en cuenta que afectarán al rendimiento. + +Ten en cuenta también que el modo de un jugador no se comporta igual que el multijugador, tanto en la aparición de criaturas como en ciertos comportamientos de entidades. Por ejemplo, las criaturas desaparecen si están a más de 128 bloques de un jugador; esto se nota más en multijugador, especialmente si construyes granjas en las que los monstruos viajan a otra dimensión mediante un portal del Nether. Si hay jugadores en la dimensión de destino y todos están muy lejos del portal, la criatura desaparecerá al instante: ese es el comportamiento previsto de Vanilla. + +### Los métodos de duplicación no funcionan +Paper incluye algunos [ajustes no compatibles](/es/paper/reference/global-configuration#unsupported_settings) que permiten ciertas duplicaciones. Sin embargo, algunas no se pueden volver a habilitar porque afectarían a otros aspectos del servidor. Paper tampoco volverá a incorporar métodos de duplicación que ya no existan en el juego. + +## Problemas de rendimiento +### Informe de spark +Paper incluye el perfilador [spark](https://spark.lucko.me/) para diagnosticar la causa raíz de los problemas de rendimiento. +Por ejemplo, puedes generar un informe durante 300 segundos ejecutando `/spark profiler start --timeout 300`. +Si quieres diagnosticar picos de retraso que duren más de, por ejemplo, 100 ms, ejecuta `/spark profiler start --only-ticks-over 100 --timeout 300`. + +Consulta la [documentación de spark](https://spark.lucko.me/docs) para obtener una guía más detallada sobre cómo usarlo y leer informes. Si todavía no sabes cuál es la causa del problema, puedes enviarnos el enlace mediante el [Discord de Paper](https://discord.gg/papermc). + +### Uso elevado de RAM +El uso elevado de memoria es normal, a menos que se produzcan fallos por falta de memoria o tiempos de recolección de basura (GC) excesivos. + +Los programas Java almacenan objetos en memoria, en un área llamada heap. El heap crece con el tiempo; puedes definir su tamaño inicial con `-Xms` y el máximo con `-Xmx`. + +Es normal que el proceso de Java use la RAM que se le asigna y, a veces, un poco más de `-Xmx`. Esta cifra no disminuirá con el tiempo, ya que en servidores el recolector de basura (GC) rara vez devuelve RAM al sistema operativo. Esto no es un problema; de hecho, es beneficioso: al disponer de más memoria heap, el GC tendrá que dedicar menos tiempo de procesamiento a liberar memoria no utilizada. Esto no es una fuga de memoria y no provocará fallos por falta de memoria, que suelen deberse a no dejar suficiente RAM para el sistema operativo o a límites de memoria mal configurados en un contenedor. + +Hay varias métricas de memoria que se pueden medir. Por ejemplo, imagina un servidor en un contenedor de 16 GB que se ejecuta con `-Xms1G -Xmx14G`. En este caso: +* **Límite de memoria del contenedor:** 16 GB +* **Tamaño máximo del heap:** 14 GB +* **Tamaño actual del heap:** empieza en 1 GB y crece rápidamente. En cualquier momento tendrá entre 1 y 14 GB +* **Uso actual del heap:** será inferior al tamaño indicado arriba y, en condiciones normales, aumentará y disminuirá siguiendo un patrón de dientes de sierra + +Ten en cuenta que cada herramienta puede elegir distintas métricas para mostrar, así que el indicador de uso del panel quizá no coincida a simple vista con lo que muestra un plugin. + +### Uso bajo de CPU +Paper puede usar varios núcleos, pero eso no significa necesariamente que varios de ellos vayan a estar cerca del 100 % de uso. Una parte importante de la carga del servidor proviene del bucle de ticks, que usa un solo hilo. Por tanto, a partir de cierto punto, disponer de más núcleos no mejorará el rendimiento. Conviene elegir una CPU con un alto rendimiento de un solo hilo y asignar suficientes hilos al servidor (al menos 4). En servidores con muchos núcleos, esto puede traducirse en un uso bajo de CPU respecto al total de núcleos. + +Sin embargo, si tu servidor (sobre todo si es grande) insiste en usar un solo núcleo, comprueba el ajuste de asignación de CPU del panel. En algunos paneles, un número como `4` no significa que se usarán 4 núcleos, sino que se usará el núcleo con ID 4. diff --git a/src/content/docs/es/paper/admin/how-to/index.mdx b/src/content/docs/es/paper/admin/how-to/index.mdx new file mode 100644 index 000000000..3e89fd8aa --- /dev/null +++ b/src/content/docs/es/paper/admin/how-to/index.mdx @@ -0,0 +1,10 @@ +--- +title: Guías prácticas +tableOfContents: false +--- + +import PageCards from "/src/components/PageCards.astro"; + +Guías prácticas para configurar funciones concretas de Paper y administrar el servidor. + + diff --git a/src/content/docs/es/paper/admin/how-to/profiling.md b/src/content/docs/es/paper/admin/how-to/profiling.md new file mode 100644 index 000000000..e98e1c43e --- /dev/null +++ b/src/content/docs/es/paper/admin/how-to/profiling.md @@ -0,0 +1,53 @@ +--- +title: Análisis de rendimiento +description: Cómo analizar el rendimiento de tu servidor Paper. +slug: es/paper/profiling +--- + +El análisis de rendimiento permite diagnosticar problemas de rendimiento del servidor. +Un perfilador mide ciertas características de un servidor en ejecución: por ejemplo, con qué frecuencia se llama a un método +y cuánto tiempo consume en un solo tick, cuánto dura y con qué frecuencia se ejecuta el recolector de basura, entre otros datos. + +:::caution + +_Para que el análisis sea eficaz, el problema que intentas diagnosticar debe estar ocurriendo en ese momento._ + +::: + +Si necesitas ayuda para analizar un problema de rendimiento, comparte un informe de spark en el +[servidor de Discord de PaperMC](https://discord.gg/PaperMC) (#paper-help). + +## spark + +Desde la versión 1.21, Paper incluye el perfilador [spark](https://spark.lucko.me/), que es la forma recomendada +de analizar el rendimiento de Paper. + +Para empezar a analizar el rendimiento del servidor, ejecuta este comando: +``` +/spark profiler start --timeout 600 +``` + +Después de 10 minutos, se mostrará una URL al informe del perfilador. Puedes analizarlo por tu cuenta o compartirlo +con el desarrollador de un plugin o en los canales de asistencia de Paper. + +Esto es solo una pequeña parte de lo que puede hacer spark. Si quieres conocer sus distintas funciones +o aprender a analizar informes por tu cuenta, consulta la documentación de spark [aquí](https://spark.lucko.me/docs/). + +:::tip + +Si quieres usar una versión de spark más reciente que la incluida, coloca el JAR independiente del plugin spark +en el directorio `plugins` y establece en `true` la propiedad del sistema +[`paper.preferSparkPlugin`](/es/paper/reference/system-properties#paperprefersparkplugin). + +Si quieres usar [marcadores de posición](https://spark.lucko.me/docs/misc/Placeholders) de PlaceholderAPI +con la versión de spark incluida, debes instalar la [expansión de spark](https://api.extendedclip.com/expansions/spark/) +desde eCloud de PAPI (`/papi ecloud download spark` y `/papi reload`). + +::: + +## Timings + +Paper también incluye el perfilador [Timings v2](https://timings.aikar.co/), pero lleva varios años sin mantenimiento +y sus informes son difíciles de interpretar para principiantes. Se ha dejado obsoleto en favor de +spark y está desactivado de forma predeterminada desde la versión 1.21. Consulta [este debate](https://github.com/PaperMC/Paper/discussions/10565) +para obtener más información. diff --git a/src/content/docs/es/paper/admin/how-to/update.md b/src/content/docs/es/paper/admin/how-to/update.md new file mode 100644 index 000000000..bf9e4aa0f --- /dev/null +++ b/src/content/docs/es/paper/admin/how-to/update.md @@ -0,0 +1,84 @@ +--- +title: Actualizar +description: Paper incorpora nuevas funciones y correcciones todos los días; esta guía explica el proceso de actualización. +slug: es/paper/updating +--- + +Actualizar Paper es una parte importante de la administración de cualquier servidor. Como todos los días se incorporan nuevas funciones y correcciones, +recomendamos actualizar al menos una vez por semana para proteger el servidor frente a los errores más recientes. +Instalar actualizaciones es muy sencillo, pero es importante saber hacerlo correctamente. + +:::caution[No sustituyas archivos JAR mientras el servidor esté en ejecución] + +A menos que sepas exactamente qué haces y por qué, nunca es buena idea sustituir archivos JAR mientras el servidor está en ejecución, +ya sean plugins o el propio Paper. + +::: + +## Paso 1. Crear una copia de seguridad + +:::tip + +Si usas un servicio de alojamiento compartido, puede que el proveedor incluya una función para crear copias de seguridad. Consulta su +documentación antes de continuar. + +::: + +Este es el paso más importante y, aun así, el que más se suele omitir. Aunque es poco probable que +actualizar Paper por sí solo cause problemas que requieran restaurar una copia de seguridad, ¡los fallos de plugins +u otros accidentes sí podrían hacerlo! Aprovecha la actualización para crear una copia de seguridad. Contar con copias +de seguridad funcionales es esencial para cualquier servidor, grande o pequeño. Los elementos principales que debes respaldar son: + +- Las carpetas de los mundos +- Los archivos de configuración del servidor +- Los archivos de configuración y los JAR de los plugins + +Procura tener copias de seguridad de distintos momentos y guardarlas en un lugar seguro. Una opción habitual +es mantener copias rotativas, de modo que siempre conserves una cantidad determinada de copias correspondientes a un período concreto. + +## Paso 2. Actualizar plugins + +Al igual que es importante actualizar Paper, también lo es mantener los plugins al día. Nunca sabes en qué pueden estar trabajando sus autores: +correcciones de errores o nuevas funciones. + +Una función poco conocida de los servidores Paper es la carpeta `update`. Así se usa: + +1. Crea una carpeta llamada `update` dentro de la carpeta `plugins`. +2. Descarga uno por uno los plugins que quieras actualizar y colócalos en la carpeta `update`. +3. Reinicia el servidor. No elimines ni modifiques los plugins que estén fuera de la carpeta `update`. + +De este modo, puedes actualizar todos tus plugins a la vez sin mantener el servidor apagado ni sustituir sus JAR mientras está en ejecución. +No es necesario reiniciar el servidor antes de actualizar Paper. Esta función te permite actualizar Paper y los plugins +al mismo tiempo, sin necesidad de períodos de inactividad adicionales. + +## Paso 3. Actualizar Paper + +:::tip + +Si usas un servicio de alojamiento compartido, puede que el proveedor incluya una función de actualización. Consulta su +documentación antes de continuar. + +::: + +Actualizar Paper es muy sencillo. + +1. Descarga un JAR nuevo desde [nuestra página de descargas](https://papermc.io/downloads). +2. Detén el servidor. No se recomienda sustituir el JAR de Paper mientras el servidor está en ejecución, ya que puede causar problemas. +3. Cambia el nombre del archivo descargado para que coincida con el indicado en el [comando de inicio](/es/paper/getting-started#ejecutar-el-servidor). +4. Sustituye el antiguo JAR de Paper por el nuevo archivo renombrado. +5. Inicia el servidor. Revisa el registro de inicio para asegurarte de que todo salga bien. Si hay conflictos o problemas + con plugins, aparecerán aquí. + +Para reducir al mínimo el tiempo de inactividad durante las actualizaciones, algunos administradores, en vez de sustituir el JAR del servidor, +suben uno nuevo y configuran el script de inicio para usarlo en el próximo reinicio. Ambas son estrategias de actualización válidas. + +:::caution[Actualizaciones automáticas] + +Aunque instalar actualizaciones automáticamente puede resultar práctico (y el [servicio de descargas](/es/misc/downloads-service) de Paper te lo +permite fácilmente), Paper no lo recomienda debido a la posibilidad de conflictos entre plugins +u otros problemas que quizá desconozcas. Supervisa siempre el proceso de actualización y revisa con atención +el registro del servidor después. + +Si decides instalar actualizaciones automáticamente, ¡asegúrate de contar con una estrategia de copias de seguridad que funcione! + +::: diff --git a/src/content/docs/es/paper/admin/how-to/vanilla.mdx b/src/content/docs/es/paper/admin/how-to/vanilla.mdx new file mode 100644 index 000000000..64da70d5b --- /dev/null +++ b/src/content/docs/es/paper/admin/how-to/vanilla.mdx @@ -0,0 +1,49 @@ +--- +title: Una experiencia similar a Vanilla +description: Esta página enumera todos los cambios que producen una experiencia distinta de Vanilla. +slug: es/paper/vanilla +--- + +import ConfigNode from "/src/components/ConfigNode.astro"; +import { filterVanilla } from "/src/utils/config"; +import { parse } from "yaml"; + +import ServerPropertiesYML from "/src/config/paper/server-properties.yml?raw"; +import PaperWorldDefaultsYML from "/src/config/paper/paper-world-defaults.yml?raw"; +import PaperGlobalYML from "/src/config/paper/paper-global.yml?raw"; +import SpigotYML from "/src/config/paper/spigot.yml?raw"; + +Debido a la forma en que se implementa la API de Bukkit en Paper, puede haber diferencias entre la experiencia de juego de Vanilla y Paper. +Estas diferencias pueden aumentar al corregir errores presentes en Minecraft Vanilla. +Aunque muchas personas quizá no las noten, hay situaciones en las que resultan problemáticas. +Por ejemplo, los jugadores técnicos pueden tener dificultades para que sus mecanismos funcionen como deberían. +Esta página ofrece un punto de partida para quienes quieren acercarse lo máximo posible a Vanilla. + +:::note + +Esta página se inspira en la [recopilación de Earthcomputer](https://gist.github.com/Earthcomputer/2296da33b8cc91dba81b48103c0e1fe3) sobre cambios que rompen la compatibilidad con Vanilla. + +::: + +:::caution + +Esta guía solo te ayudará a acercarte lo máximo posible a Vanilla. +Por desgracia, actualmente no es posible obtener una experiencia 100 % Vanilla en Paper. + +::: +## server.properties + + +## paper-world-defaults.yml + + +## paper-global.yml + + +## spigot.yml + + +## Otras consideraciones + +* `settings.timeout-time` en `spigot.yml` refleja el ajuste del watchdog en el archivo `server.properties`. Ten en cuenta que el ajuste de `spigot.yml` se expresa en segundos, mientras que el valor predeterminado se expresa en milisegundos. +* `watchdog` en `paper-global.yml` controla el aviso anticipado del watchdog. Aunque solo es un aviso, quizá quieras desactivarlo porque puede resultar molesto. diff --git a/src/content/docs/es/paper/admin/index.mdx b/src/content/docs/es/paper/admin/index.mdx new file mode 100644 index 000000000..49c70dd57 --- /dev/null +++ b/src/content/docs/es/paper/admin/index.mdx @@ -0,0 +1,25 @@ +--- +title: Administración +tableOfContents: false +--- + +import PageCards from "/src/components/PageCards.astro"; + +¡Te damos la bienvenida a la guía de administración de Paper! Aquí encontrarás información y tutoriales +sobre la administración de un servidor Paper. + +#### Primeros pasos + + + +#### Guías prácticas + + + +#### Referencia + + + +#### Varios + + diff --git a/src/content/docs/es/paper/admin/misc/faq.md b/src/content/docs/es/paper/admin/misc/faq.md new file mode 100644 index 000000000..9d5e13770 --- /dev/null +++ b/src/content/docs/es/paper/admin/misc/faq.md @@ -0,0 +1,13 @@ +--- +title: Preguntas frecuentes +description: ¡Respondemos a las preguntas más frecuentes de nuestra comunidad! +slug: es/paper/faq +--- + +## Se detectó una versión de Java no compatible. ¿Qué debo hacer? {#unsupported-java-detected-what-do-i-do} + +Las versiones de Java no compatibles, de acceso anticipado o internas suelen carecer de funciones, tener problemas conocidos o estar directamente rotas. +Por ello, no podemos ofrecer asistencia para servidores que utilicen esas versiones. +Deberías instalar una versión compatible de Java, tal como se explica [aquí](/es/misc/java-install). + +Si aun así quieres continuar, sabiendo que lo haces bajo tu propia responsabilidad y que NO recibirás asistencia, puedes desactivar la comprobación mediante una propiedad del sistema, tal como se explica [aquí](/es/paper/reference/system-properties#paperignorejavaversion). diff --git a/src/content/docs/es/paper/admin/misc/index.mdx b/src/content/docs/es/paper/admin/misc/index.mdx new file mode 100644 index 000000000..991efb5bc --- /dev/null +++ b/src/content/docs/es/paper/admin/misc/index.mdx @@ -0,0 +1,10 @@ +--- +title: Varios +tableOfContents: false +--- + +import PageCards from "/src/components/PageCards.astro"; + +Documentación diversa relacionada con Paper. + + diff --git a/src/content/docs/es/paper/admin/misc/paper-bug-fixes.md b/src/content/docs/es/paper/admin/misc/paper-bug-fixes.md new file mode 100644 index 000000000..ef0f116fd --- /dev/null +++ b/src/content/docs/es/paper/admin/misc/paper-bug-fixes.md @@ -0,0 +1,73 @@ +--- +title: Correcciones de errores +description: Explicación de los errores de Vanilla que corregimos en Paper. +slug: es/paper/misc/paper-bug-fixes +--- + +Paper corrige muchos problemas técnicos y de jugabilidad de Minecraft. Entre las correcciones más conocidas están las de duplicación de TNT y rotura de bedrock. + +## Errores de Vanilla + +Paper corrige muchos errores de Vanilla que Mojang no pretendía. Aplicamos estos parches para corregir comportamientos o evitar abusos e +inestabilidad en el servidor. Algunas correcciones se pueden configurar, ya que entendemos que ciertos servidores quizá quieran conservar el +comportamiento de Vanilla. Encontrarás estas opciones en la [configuración global](/es/paper/reference/global-configuration) +y en la [configuración por mundo](/es/paper/reference/world-configuration). + +### ¿Qué se considera un comportamiento previsto y qué es un error? + +Cuando alguien nos informa de un problema, consultamos el sistema de seguimiento de problemas de Mojang. Si ya se informó allí, comprobamos si: + +1) Se confirmó que es un error +2) Tiene una prioridad asignada + +Si cumple estos dos criterios, aceptaremos cambios para corregirlo, ya que Mojang puede tardar mucho en hacerlo +(a veces, años). Si Mojang rechaza un problema, normalmente no lo «corregimos», pues se considera un comportamiento previsto. + +## Errores de duplicación + +Como la duplicación de TNT se considera una forma de minería automatizada y no una duplicación de recursos, ofrecemos una opción para +restaurarla. Por desgracia, esto también vuelve a habilitar la duplicación de alfombras y raíles. Normalmente no ofreceríamos una opción de configuración para ello, +pero se trata del mismo error, así que no tenemos alternativa. La opción de configuración es la siguiente: + +```yaml title="config/paper-global.yml" +unsupported-settings: + allow-piston-duplication: true +``` + +También puedes restaurar la posibilidad de duplicar bloques afectados por la gravedad, como la arena, mediante portales del End. No se +recomienda, ya que puede causar problemas en el servidor, pero ofrecemos una opción de configuración para restablecer esta función: +```yaml title="config/paper-global.yml" +unsupported-settings: + allow-unsafe-end-portal-teleportation: true +``` + +Si quieres volver a habilitar los exploits de duplicación con ganchos de cuerda, puedes hacerlo activando la siguiente opción: +```yaml title="config/paper-global.yml" +unsupported-settings: + skip-tripwire-hook-placement-validation: true +``` + +:::caution +Activar esta opción no garantiza que funcionen todos los diseños de duplicadores de ganchos de cuerda. +Los diseños que dependen de una actualización de puerta en el mismo tick podrían seguir fallando debido al manejo de la física de bloques de Paper. Consulta +[la explicación del mantenedor](https://github.com/PaperMC/Paper/issues/12114#issuecomment-2660579220) +para obtener más contexto. La [implementación original](https://github.com/PaperMC/Paper/pull/12091) +se probó con [este diseño de duplicador](https://www.youtube.com/watch?v=sRYuZn4r9RY). +::: + +## Rotura de bloques + +También corregimos la posibilidad de romper bedrock y los marcos de portal del End. Ofrecemos una opción de configuración para restaurar esta +función, aunque no se recomienda: +```yaml title="config/paper-global.yml" +unsupported-settings: + allow-permanent-block-break-exploits: true +``` + +## Nota final + +No te ofreceremos asistencia si tienes problemas mientras estas opciones estén activadas, ya que pueden causar efectos secundarios imprevistos. +Tampoco se garantiza que estas opciones sigan admitiéndose en el futuro: su comportamiento puede cambiar o pueden eliminarse en cualquier momento. + +Para conocer los motivos históricos por los que no ofrecemos opciones de configuración para muchos errores de duplicación, consulta: +[#3724](https://github.com/PaperMC/Paper/issues/3724) diff --git a/src/content/docs/es/paper/admin/misc/update-checker.md b/src/content/docs/es/paper/admin/misc/update-checker.md new file mode 100644 index 000000000..259e910a8 --- /dev/null +++ b/src/content/docs/es/paper/admin/misc/update-checker.md @@ -0,0 +1,36 @@ +--- +title: Comprobador de actualizaciones +description: Documentación del comprobador automático de actualizaciones integrado en Paper. +slug: es/paper/misc/update-checker +--- + +Desde la versión 1.21.11, Paper incluye un comprobador de actualizaciones que avisa a los administradores del servidor al iniciarlo si hay una nueva versión de Paper disponible. + +## Cómo funciona + +Al iniciarse, Paper compara su versión actual con la última versión disponible en el canal estable de los servidores de PaperMC. +Si encuentra una versión más reciente, imprimirá un aviso en la consola y en los registros del servidor. + +También puedes buscar actualizaciones manualmente en cualquier momento ejecutando el comando `version` en la consola del servidor (o dentro del juego si tienes el permiso `bukkit.command.version`). + +## Qué información se envía + +El comprobador de actualizaciones envía la siguiente información a los servidores de PaperMC: +- La versión actual de Paper +- La dirección IP de cliente de tu servidor (como ocurre con cualquier solicitud http) + +Actualmente, PaperMC no almacena ni analiza esta información, aunque las solicitudes pasan por CloudFlare. + +## Configuración +Puedes desactivar el comprobador de actualizaciones en el archivo de configuración `paper-global.yml`. La sección correspondiente es la siguiente: + +```yaml title="config/paper-global.yml" +update-checker: + enabled: false +``` + +También puedes desactivarlo añadiendo el siguiente argumento de JVM al iniciar el servidor: + +```bash +-Dpaper.disableStartupVersionCheck +``` diff --git a/src/content/docs/es/paper/admin/reference/cli-arguments.md b/src/content/docs/es/paper/admin/reference/cli-arguments.md new file mode 100644 index 000000000..77ef40ca4 --- /dev/null +++ b/src/content/docs/es/paper/admin/reference/cli-arguments.md @@ -0,0 +1,129 @@ +--- +title: Argumentos de CLI +slug: es/paper/reference/cli-arguments +description: Referencia de todos los argumentos de CLI que reconoce Paper. +version: 1.21.11 +tableOfContents: false +--- + +Paper ofrece argumentos de CLI que puedes configurar para controlar ciertos comportamientos. Al iniciar el servidor, los argumentos de CLI siempre se añaden directamente +**después** del nombre del archivo del servidor. Por ejemplo: +```bash +java -jar server.jar --nogui +``` + +`--nogui` es un argumento de CLI (más específicamente, como no tiene un valor, es un **indicador**). +Esta página sirve como referencia de todos los argumentos que ofrece Paper. + +Algunas de estas opciones corresponden directamente a ajustes que puedes modificar en el archivo `server.properties`. +Los argumentos de CLI siempre **anulan** los valores definidos en `server.properties`. + +##### `-?, --help` +Imprime un mensaje de ayuda con todos los argumentos de CLI que puedes proporcionar. El servidor no se iniciará si usas este indicador. + +##### `-C, --commands-settings ` +Ruta al archivo de ajustes de comandos. El valor predeterminado es `commands.yml`. + +##### `-P, --plugins ` +Directorio en el que se buscan los JAR de plugins. El valor predeterminado es `plugins`. + +##### `-S, --spigot-settings ` +Ruta al archivo de configuración de Spigot. El valor predeterminado es `spigot.yml`. + +##### `-W, --universe, --world-container, --world-dir ` +Carpeta en la que se colocan las demás carpetas de mundos. El valor predeterminado es `.` (esta carpeta). + +##### `--add-extra-plugin-dir, --add-plugin-dir ` +Directorio adicional en el que buscar archivos de plugins. Se puede especificar varias veces para añadir más de un +directorio de plugins. + +##### `--add-extra-plugin-jar, --add-plugin ` +Archivo JAR de plugin adicional que se cargará. Se puede especificar varias veces para cargar varios JAR de plugins. + +##### `-b, --bukkit-settings ` +Ruta al archivo de configuración de Bukkit. El valor predeterminado es `bukkit.yml`. + +##### `-c, --config ` +Ruta al archivo de propiedades del servidor Minecraft. El valor predeterminado es `server.properties`. + +##### `--demo` +Indica si se debe cargar el servidor en modo de demostración. En este modo siempre se genera el mismo mundo y se muestran recordatorios y mensajes de ayuda adicionales. + +##### `--bonusChest` +Indica si se debe crear un cofre de bonificación al crear el mundo por primera vez. + +##### `--eraseCache` +Indica si se debe forzar el borrado de la caché durante las actualizaciones del mundo. Esto elimina datos como los mapas de altura y de iluminación, +lo que puede resultar útil si quieres forzar su recálculo. + +##### `--forceUpgrade` +Indica si se debe forzar una actualización completa del mundo al iniciar el servidor. + +:::danger[Advertencia] + +Este ajuste casi nunca debería usarse. El sistema de actualización de Paper es lo bastante rápido como para realizar +las actualizaciones gradualmente mientras juegas. + +::: + +##### `-h, --host, --server-ip ` +Host en el que se escuchará. + +##### `--initSettings` +Indica si se deben crear únicamente los archivos de configuración y cerrar el servidor antes de crear mundos. Es útil +si primero quieres establecer algunos valores de configuración que podrían influir en la creación del mundo. + +##### `--jfrProfile` +Indica si se debe habilitar el perfilado de JFR (Java Flight Recorder). + +##### `--noconsole` +Desactiva la consola. + +##### `--nogui` +Desactiva la interfaz gráfica. + +##### `--nojline` +Desactiva JLine y emula la consola de Vanilla. + +##### `-o, --online-mode ` +Indica si se debe usar la autenticación en línea. + +##### `-p, --port, --server-port ` +Puerto en el que se escuchará. + +##### `--paper, --paper-settings ` +Ruta al archivo de ajustes heredado de Paper. El valor predeterminado es `paper.yml`. + +:::danger[Advertencia] + +Esta opción solo se usa para migrar el archivo de configuración heredado al nuevo formato +y no debe usarse en servidores nuevos. + +::: + +##### `--paper-dir, --paper-settings-directory ` +Ruta al directorio de ajustes de Paper. El valor predeterminado es `config`. + +##### `--pidFile ` +Ruta al archivo PID. + +##### `--recreateRegionFiles` +Indica si se deben recrear los archivos de región durante las actualizaciones del mundo. + +##### `-s, --max-players, --size ` +Número máximo de jugadores. + +##### `--safeMode` +Carga los mundos únicamente con el paquete de datos de Vanilla habilitado. + +##### `--server-name ` +Nombre del servidor. El valor predeterminado es `Unknown Server`. + +##### `--serverId ` +Establece el identificador del servidor, que se usa en los archivos de fallo. + +##### `-v, --version` +Imprime la versión de CraftBukkit. Esta opción impide que se inicie el servidor. + +##### `-w, --level-name, --world ` +Establece el nombre del mundo. diff --git a/src/content/docs/es/paper/admin/reference/commands.md b/src/content/docs/es/paper/admin/reference/commands.md new file mode 100644 index 000000000..bcbc3a2aa --- /dev/null +++ b/src/content/docs/es/paper/admin/reference/commands.md @@ -0,0 +1,216 @@ +--- +title: Comandos +slug: es/paper/reference/commands +description: Documentación sobre todos los comandos que añade Paper. +version: 1.21.8 +--- + +Esta página explica todos los comandos que añade Paper. + +## Comandos de Bukkit + +Estos comandos se encuentran en el espacio de nombres `bukkit:`. + +### version (aliases: ver, about) + +El comando version muestra información sobre la versión del servidor. El resultado puede parecerse a esto: + +![Resultado del comando version](../../../../paper/admin/reference/assets/version-command-output.png) + +También puedes usar este comando para mostrar información de versión de plugins concretos. + +![Resultado del comando version para un plugin](../../../../paper/admin/reference/assets/plugin-version-command-output.png) + +### plugins (alias: pl) + +El comando plugins muestra una lista de todos los plugins cargados. Paper distingue dos tipos de +plugins: **plugins de Paper** y **plugins de Bukkit**. Por lo general, esta diferencia solo es relevante para quienes desarrollan plugins +([guía de paper-plugin.yml](/es/paper/dev/getting-started/paper-plugins)). Los plugins aparecen en **verde** +si no se produjeron problemas al habilitarlos y se puede asumir que funcionan. +Los plugins en **rojo** no se pudieron cargar o se desactivaron. Si ocurre esto, consulta los registros de inicio para obtener más información. + +Además, los plugins de Bukkit pueden cargarse **con la compatibilidad heredada** habilitada. Estos +aparecen con una **estrella amarilla** delante del nombre. Normalmente significa que el plugin se creó para una +versión muy antigua del juego o que su autor olvidó especificar una versión objetivo de Minecraft. + +Puedes hacer clic en el nombre de un plugin para mostrar su información de versión. Esta acción equivale +a ejecutar `/version `. + +![Resultado del comando plugins](../../../../paper/admin/reference/assets/plugins-command-output.png) + +### help (alias: ?) + +El comando help muestra descripciones de todos los comandos registrados. Sirve +como referencia rápida tanto para los comandos integrados como para los que añaden los plugins. + +### reload (alias: spigot reload) + +:::danger[Obsolescencia] + +El comando reload está obsoleto y se eliminará. Si quieres actualizar los plugins, reinicia el servidor, +ya que se sabe que reload causa problemas con ellos. + +Si quieres volver a cargar las configuraciones de Paper, puedes usar [/paper reload](#reload). + +::: + +## Análisis del rendimiento + +Aunque los comandos `/mspt` y `/tps` funcionan correctamente, el comando `/spark` los ha sustituido, +así que deberías usar `/spark` en su lugar. + +### spark + +El único comando que deberías usar para obtener información de rendimiento es `/spark`. +Los subcomandos de spark están documentados [en la wiki dedicada a spark](https://spark.lucko.me/docs/Command-Usage). + +### tps + +El comando tps permite consultar los TPS (ticks por segundo, es decir, cuántas veces se ejecuta el bucle del juego +por segundo; cuanto mayor sea el valor, mejor. El objetivo es 20.0) del último minuto y de los últimos 5 y 15 minutos. + +### mspt + +El comando mspt permite consultar el MSPT medio, mínimo y máximo (milisegundos por tick, es decir, cuánto tarda +un tick; cuanto menor sea el valor, mejor. El MSPT debe ser inferior a 50 para alcanzar 20 TPS) del servidor durante los últimos 5, 10 y 60 segundos. + +### timings + +:::danger[Obsolescencia] + +El comando timings está obsoleto y se eliminará. Deberías usar el [comando spark](#spark) en su lugar. + +Puedes consultar más información aquí: https://github.com/PaperMC/Paper/discussions/10565. + +::: + +## restart + +El comando `/restart` forma parte del mecanismo de reinicio de Spigot, que reinicia el servidor cuando este falla +o cuando se ejecuta el comando manualmente. + +:::note + +Para obtener ayuda para configurar el script de reinicio, consulta +[este gist de Prof_Bloodstone](https://gist.github.com/Prof-Bloodstone/6367eb4016eaf9d1646a88772cdbbac5). + +::: + +## paper +Esta sección está dedicada a los subcomandos del comando `/paper` del juego. + +### chunkinfo +El comando `/paper chunkinfo []` muestra información sobre los chunks cargados de un mundo. +Puedes indicar el mundo con el argumento `[]`. Si lo estableces en `*` o lo omites, +se mostrará información de todos los mundos. + +El resultado distingue varios tipos de chunks cargados. A continuación se ofrece un resumen de cada tipo. +Encontrarás documentación más completa en la [wiki de Minecraft](https://minecraft.wiki/w/Chunk). + +- `Total` Como su nombre indica, este número representa **todos los chunks** cargados actualmente. +- `Inactive` También conocidos como «inaccesibles», son chunks que no reciben ticks, pero en los que se genera el chunk. +- `Full` Normalmente llamados **chunks de borde**. No se ejecutan ticks, pero las entidades y los bloques están cargados y accesibles. +- `Block Ticking` Todos los aspectos del juego funcionan como se espera, excepto que las entidades no aparecen de forma natural ni reciben ticks, aunque siguen siendo accesibles. También se llaman **chunks perezosos**. +- `Entity Ticking` El chunk recibe todos los ticks. + +### debug +El comando `/paper debug ` vuelca en un archivo información sobre todos los chunks cargados actualmente. El contenido +de este archivo normalmente no es relevante para la mayoría de los administradores de servidores y está destinado a los desarrolladores. + +### dumpitem +Puedes usar el comando `/paper dumpitem [all]` para obtener la representación de componentes de datos del +objeto que tienes en la mano. Si ejecutas `/paper dumpitem`, obtendrás los datos del objeto, que puedes usar para representarlo en +comandos que acepten un argumento de objeto. `/paper dumpitem all` muestra la **representación completa de los componentes de datos**, +incluidos los componentes predeterminados que no es necesario declarar explícitamente. + +### dumplisteners +El comando `/paper dumplisteners tofile|` está dirigido principalmente a los desarrolladores que intentan averiguar por qué +sus controladores de eventos no funcionan como se espera. `/paper dumplisteners tofile` escribe en un archivo todos los +controladores de eventos registrados actualmente, mientras que `/paper dumplisteners ` muestra únicamente los controladores +registrados para el evento especificado. + +### dumpplugins +El comando `/paper dumpplugins` está destinado a los desarrolladores que intentan resolver problemas con las dependencias o +el orden de carga de otros plugins. También se puede usar para depurar proveedores de bootstrapper, el orden general de carga +y los cargadores de clases de los plugins. + +### entity +El comando `/paper entity list [] []` muestra todas las entidades que reciben ticks actualmente. + +El argumento `[]` filtra los tipos de entidad mostrados y funciona de forma similar a una **expresión regular**: +- Puedes usar `*` para mostrar **todas** las entidades; es el valor predeterminado de este argumento. +- Puedes mostrar entidades concretas proporcionando `minecraft:` como argumento. En este caso, el espacio de nombres es muy importante. +- Para mostrar varias entidades, puedes usar `*` como comodín codicioso. Por ejemplo, para mostrar todas las entidades + cuyos nombres empiezan por **e**, puedes usar `minecraft:e*`. +- También puedes usar `?` como comodín de un solo carácter. Por ejemplo, para mostrar `pig` y `piglin`, pero **no** + `piglin_brute`, puedes proporcionar `minecraft:pig???` como filtro. + +El argumento `[]` indica el mundo cuyas entidades quieres consultar. De forma predeterminada, se usa el mundo actual +del jugador o el Overworld si se ejecuta desde la consola. + +El resultado será parecido a este: + +``` +Total Ticking: -78, Total Non-Ticking: 92 + 10 (3) : minecraft:pig + 1 (0) : minecraft:piglin +* El primer número corresponde a las entidades que procesan ticks; el segundo, a las que no. +``` + +El comentario final ya explica claramente qué representan los números. + +### fixlight +El comando `/paper fixlight` inicia un recálculo completo del mapa de iluminación de todos los chunks +cargados actualmente. Puede servir para corregir problemas de iluminación que suelen aparecer con plugins como WorldEdit. + +### heap +`/paper heap` es un comando de depuración para desarrolladores que vuelca el heap actual de JVM en un archivo `.hprof`. Este archivo se puede analizar +para detectar cuánta memoria usan determinados objetos. El archivo de salida puede ser bastante grande, así que se recomienda disponer de algo de espacio libre +en el disco antes de ejecutar el comando (por lo general, el archivo suele ser más pequeño +que la memoria usada actualmente. Puedes comprobar el consumo de memoria con el comando `/spark healthreport`). + +### holderinfo +El comando `/paper holderinfo []` muestra el número de chunks de distintos tipos que se mantienen actualmente en memoria. + +Puedes usar el argumento `[]` para indicar el mundo cuyos datos de chunks quieres consultar. Déjalo vacío +para usar `*` de forma predeterminada y mostrar la información de todos los chunks. + +En general, los tipos significan lo siguiente: +- `Total` Número total de contenedores de chunks en memoria. +- `Unloadable` Número de chunks que se pueden descargar sin riesgo. +- `Null` Chunks que recibieron la señal de descarga, pero cuyos bloqueos de planificación siguen activos. +- `ReadOnly` Número de contenedores de chunks que se pueden leer, pero no modificar. +- `Proto` Chunk «prototipo»: un chunk completamente funcional cargado en memoria, pero que no está colocado actualmente en el mundo. +- `Full` Número de chunks colocados actualmente en el mundo. + +### mobcaps +No debe confundirse con el subcomando [playermobcaps](#playermobcaps): el comando `/paper mobcaps []` muestra +los límites de criaturas **globales** para todos los jugadores de un mundo. El argumento `[]` usa el Overworld de forma predeterminada, +pero puedes indicar otros mundos para consultar sus límites de criaturas. El comando también muestra cuántos +chunks permiten la aparición de criaturas. + +### playermobcaps +El comando `/paper playermobcaps []` muestra los límites locales de criaturas de un jugador concreto. Si existe, +el argumento `[]` usa de forma predeterminada al jugador que ejecutó el comando. + +### reload +El comando `/paper reload` no es compatible y permite volver a cargar la configuración de Paper durante la ejecución. Si aparece algún problema +después de usarlo, asegúrate de reproducirlo en un servidor recién iniciado antes de pedir ayuda o +informar del problema. Ten en cuenta que este comando **no** vuelve a cargar configuraciones ajenas a Paper, como `spigot.yml`. + +### syncloadinfo +El comando `/paper syncloadinfo [clear]` requiere que se establezca explícitamente el indicador de JVM `-Dpaper.debug-sync-loads=true` +antes de ejecutarlo. Históricamente se usaba para depurar durante el desarrollo de Paper, pero +el mecanismo que lo sustenta no se utiliza actualmente. Por tanto, el archivo generado **siempre** tendrá +este aspecto: + +```json +{ + "worlds": [] +} +``` + +Salvo para comprobar si se permite ejecutar el comando, el indicador de JVM no se usa. + +### version +El comando `/paper version` es un alias del comando estándar `/version`. diff --git a/src/content/docs/es/paper/admin/reference/configuration/bukkit-commands-configuration.mdx b/src/content/docs/es/paper/admin/reference/configuration/bukkit-commands-configuration.mdx new file mode 100644 index 000000000..9da47a703 --- /dev/null +++ b/src/content/docs/es/paper/admin/reference/configuration/bukkit-commands-configuration.mdx @@ -0,0 +1,28 @@ +--- +title: commands.yml +description: Explicación del archivo commands.yml de Bukkit. +slug: es/paper/reference/bukkit-commands-configuration +tableOfContents: false +--- + +import ConfigNode from "/src/components/ConfigNode.astro"; +import CommandsYML from "/src/config/paper/commands.yml?raw"; +import { parse } from "yaml"; + +:::note + +El YAML siguiente muestra la estructura y los valores predeterminados del archivo heredado `commands.yml`. + +Haz clic en un nodo hoja para ver la descripción de ese ajuste. + +::: + +:::caution + +Los alias definidos en este archivo heredado no admiten funciones modernas, como: +- Tab completion +- Permissions + +::: + + diff --git a/src/content/docs/es/paper/admin/reference/configuration/bukkit-configuration.mdx b/src/content/docs/es/paper/admin/reference/configuration/bukkit-configuration.mdx new file mode 100644 index 000000000..7b5e95003 --- /dev/null +++ b/src/content/docs/es/paper/admin/reference/configuration/bukkit-configuration.mdx @@ -0,0 +1,20 @@ +--- +title: bukkit.yml +description: Explicación del archivo de configuración de Bukkit. +slug: es/paper/reference/bukkit-configuration +tableOfContents: false +--- + +import ConfigNode from "/src/components/ConfigNode.astro"; +import BukkitYML from "/src/config/paper/bukkit.yml?raw"; +import { parse } from "yaml"; + +:::note + +El YAML siguiente muestra la estructura y los valores predeterminados de `bukkit.yml`. + +Haz clic en un nodo hoja para ver la descripción de ese ajuste. + +::: + + diff --git a/src/content/docs/es/paper/admin/reference/configuration/bukkit-help-configuration.mdx b/src/content/docs/es/paper/admin/reference/configuration/bukkit-help-configuration.mdx new file mode 100644 index 000000000..7b75c78cb --- /dev/null +++ b/src/content/docs/es/paper/admin/reference/configuration/bukkit-help-configuration.mdx @@ -0,0 +1,20 @@ +--- +title: help.yml +description: Explicación del archivo help.yml de Bukkit. +slug: es/paper/reference/bukkit-help-configuration +tableOfContents: false +--- + +import ConfigNode from "/src/components/ConfigNode.astro"; +import HelpYML from "/src/config/paper/help.yml?raw"; +import { parse } from "yaml"; + +:::note + +El YAML siguiente muestra la estructura de `help.yml`. + +Haz clic en un nodo hoja para ver la descripción de ese ajuste. + +::: + + diff --git a/src/content/docs/es/paper/admin/reference/configuration/bukkit-permissions-configuration.mdx b/src/content/docs/es/paper/admin/reference/configuration/bukkit-permissions-configuration.mdx new file mode 100644 index 000000000..5344271f7 --- /dev/null +++ b/src/content/docs/es/paper/admin/reference/configuration/bukkit-permissions-configuration.mdx @@ -0,0 +1,28 @@ +--- +title: permissions.yml +description: Explicación del archivo permissions.yml de Bukkit. +slug: es/paper/reference/bukkit-permissions-configuration +tableOfContents: false +--- + +import ConfigNode from "/src/components/ConfigNode.astro"; +import PermissionsYML from "/src/config/paper/permissions.yml?raw"; +import { parse } from "yaml"; + +:::note + +El YAML siguiente muestra la estructura de `permissions.yml`. + +Haz clic en un nodo hoja para ver la descripción de ese ajuste. + +::: + +:::caution + +Esto NO sustituye a un plugin de permisos. + +Este archivo define metadatos sobre los propios permisos, como una descripción y un valor predeterminado. + +::: + + diff --git a/src/content/docs/es/paper/admin/reference/configuration/global-configuration.mdx b/src/content/docs/es/paper/admin/reference/configuration/global-configuration.mdx new file mode 100644 index 000000000..b6bc1ef1e --- /dev/null +++ b/src/content/docs/es/paper/admin/reference/configuration/global-configuration.mdx @@ -0,0 +1,20 @@ +--- +title: Configuración global +description: Explicación del archivo de configuración global de Paper. +slug: es/paper/reference/global-configuration +tableOfContents: false +--- + +import ConfigNode from "/src/components/ConfigNode.astro"; +import PaperGlobalYML from "/src/config/paper/paper-global.yml?raw"; +import { parse } from "yaml"; + +:::note + +El YAML siguiente muestra la estructura y los valores predeterminados de la configuración global (`config/paper-global.yml`). + +Haz clic en un nodo hoja para ver la descripción de ese ajuste. + +::: + + diff --git a/src/content/docs/es/paper/admin/reference/configuration/index.mdx b/src/content/docs/es/paper/admin/reference/configuration/index.mdx new file mode 100644 index 000000000..eee0c4794 --- /dev/null +++ b/src/content/docs/es/paper/admin/reference/configuration/index.mdx @@ -0,0 +1,135 @@ +--- +title: Configuración +description: Descripción general de los archivos de configuración de Paper. +slug: es/paper/reference/configuration +--- + +import { FileTree } from "@astrojs/starlight/components"; + +:::note + +Muchos de nuestros archivos cuentan con documentación completa. En esos casos, incluyen un enlace a su página. +Si no es así, ofrecen una breve explicación de su contenido. + +::: + + + - logs/ todos los registros del servidor + - latest.log el registro más reciente + - \-\.log.gz registros antiguos comprimidos con gzip + - config/ + - [paper-global.yml](/es/paper/reference/global-configuration) + - [paper-world-defaults.yml](/es/paper/reference/world-configuration) + - plugins/ aquí puedes colocar los JAR de tus plugins + - .paper-remapped/ se usa para almacenar JAR de plugins con los paquetes reubicados; obtén más información [aquí](https://forums.papermc.io/threads/important-dev-psa-future-removal-of-cb-package-relocation.1106/) + - bStats/ + - config.yml almacena la configuración de las métricas del plugin bStats + - spark/ carpeta del plugin para el perfilador spark incluido + - [config.json](https://spark.lucko.me/docs/Configuration) archivo principal de configuración de spark + - world/dimensions/\/\/ + - [paper-world.yml](#valores-por-mundo) almacena los [valores de configuración](/es/paper/reference/world-configuration) que se aplican únicamente al mundo con la clave `namespace:key` + - [banned-ips.json](/es/paper/reference/vanilla-data-files#banned-ipsjson) almacena las direcciones IP bloqueadas en el servidor + - [banned-players.json](/es/paper/reference/vanilla-data-files#banned-playersjson) almacena los jugadores bloqueados en el servidor + - [bukkit.yml](/es/paper/reference/bukkit-configuration) + - [commands.yml](/es/paper/reference/bukkit-commands-configuration) + - [eula.txt](/es/paper/reference/vanilla-data-files#eulatxt) almacena el estado de aceptación del EULA + - [help.yml](/es/paper/reference/bukkit-help-configuration) almacena la configuración del comando `/help` + - [ops.json](/es/paper/reference/vanilla-data-files#opsjson) almacena información sobre los jugadores con estado de operador + - [permissions.yml](/es/paper/reference/bukkit-permissions-configuration) almacena definiciones de permisos adicionales + - [server.properties](/es/paper/reference/server-properties) + - [spigot.yml](/es/paper/reference/spigot-configuration) + - usercache.json almacena en caché datos de jugadores obtenidos de la API de Mojang, como las texturas de sus cabezas + - [whitelist.json](/es/paper/reference/vanilla-data-files#whitelistjson) almacena información de los jugadores incluidos en la lista de permitidos + + +## Configuración por mundo + +Una de las funciones más potentes y, a la vez, menos comprendidas de la configuración de Paper es definir +opciones por mundo. Aunque no es posible anular todas las opciones de configuración por mundo, +sí se puede anular todo lo almacenado en `paper-world-defaults.yml`. + +### Valores predeterminados + +De forma predeterminada, Paper no define anulaciones por mundo y almacena todos los valores predeterminados en +`config/paper-world-defaults.yml`. Todo lo que aparece en este archivo se puede anular por mundo, pero no se hace +por defecto. Si cambias algo en `paper-world-defaults.yml`, el valor cambiará en todos los mundos en los que no +lo hayas anulado manualmente. + +### Valores por mundo + +Para establecer un valor en un mundo concreto, edita `paper-world.yml` dentro de la carpeta del mundo. Por ejemplo, si +quisieras habilitar `lootables.auto-replenish` en un mundo con la clave `custom:resource`, editarías +`paper-world.yml` en la carpeta `world/dimensions/custom/resource` de esta manera: + +```yaml title=world/dimensions/custom/resource/paper-world.yml {3-4} +_version: 28 + +lootables: + auto-replenish: true +``` + +De forma predeterminada, los archivos de configuración `paper-world.yml` solo contienen `_version`. Para +anular el valor predeterminado de una opción, debes añadirla manualmente copiándola de +`paper-world-defaults.yml`. + +### Herencia + +Toda la configuración que no se defina explícitamente para un mundo se hereda de `paper-world-defaults.yml`. +Esto significa que no hace falta repetir valores en `paper-world-defaults.yml` y en cada archivo +`paper-world.yml`. **No es necesario ni recomendable** copiar todo el archivo +`paper-world-default.yml` en cada archivo `paper-world.yml` que quieras modificar. Copia únicamente el +valor exacto que quieres cambiar. + +Veamos un ejemplo más complejo y práctico: establecer distintos valores de `spawn-limits` y `auto-replenish` +en dos mundos. + +```yaml title="paper-world-defaults.yml" +lootables: + auto-replenish: true +entities: + spawning: + spawn-limits: + ambient: 70 + axolotls: 10 + creature: 15 + monster: 5 + underground_water_creature: 5 + water_ambient: 5 + water_creature: 20 +``` + +```yaml title="world/dimensions/minecraft/the_nether/paper-world.yml" +entities: + spawning: + spawn-limits: + monster: 90 +``` + +```yaml title="world/dimensions/custom/resource/paper-world.yml" +lootables: + auto-replenish: false +entities: + spawning: + spawn-limits: + axolotls: 8 + creature: 15 + monster: 2 +``` + +Este ejemplo ilustra el concepto de herencia. Esta es la configuración efectiva que se aplicará a cada mundo de `world/dimensions`: + +| Clave de configuración | minecraft/overworld | minecraft/the_nether | minecraft/the_end | custom/resource | +|-------------------------------------------------------------|---------------------|----------------------|-------------------|-----------------| +| `lootables.auto-replenish` | `true` | `true` | `true` | `false` | +| `entities.spawning.spawn-limits.ambient` | `15` | `15` | `15` | `15` | +| `entities.spawning.spawn-limits.axolotls` | `5` | `5` | `5` | `8` | +| `entities.spawning.spawn-limits.creature` | `10` | `10` | `10` | `15` | +| `entities.spawning.spawn-limits.monster` | `70` | `90` | `70` | `2` | +| `entities.spawning.spawn-limits.underground_water_creature` | `5` | `5` | `5` | `5` | +| `entities.spawning.spawn-limits.water_ambient` | `20` | `20` | `20` | `20` | +| `entities.spawning.spawn-limits.water_creature` | `5` | `5` | `5` | `5` | + +Observa que nunca se modificó `world/dimensions/minecraft/the_end/paper-world.yml`. Por eso, hereda todas las +opciones de configuración de `config/paper-world-defaults.yml`. Además, `auto-replenish` solo se desactivó en +`world/dimensions/custom/resource/paper-world.yml` porque en `config/paper-world-defaults.yml` +`auto-replenish` está establecido en `true`. diff --git a/src/content/docs/es/paper/admin/reference/configuration/server-properties.mdx b/src/content/docs/es/paper/admin/reference/configuration/server-properties.mdx new file mode 100644 index 000000000..352be77e8 --- /dev/null +++ b/src/content/docs/es/paper/admin/reference/configuration/server-properties.mdx @@ -0,0 +1,20 @@ +--- +title: server.properties +description: Explicación del archivo server.properties de Minecraft. +slug: es/paper/reference/server-properties +tableOfContents: false +--- + +import ConfigNode from "/src/components/ConfigNode.astro"; +import ServerPropertiesYML from "/src/config/paper/server-properties.yml?raw"; +import { parse } from "yaml"; + +:::note + +Esta página muestra los ajustes y los valores predeterminados del archivo `server.properties`. + +Haz clic en una propiedad para obtener más información. + +::: + + diff --git a/src/content/docs/es/paper/admin/reference/configuration/spigot-configuration.mdx b/src/content/docs/es/paper/admin/reference/configuration/spigot-configuration.mdx new file mode 100644 index 000000000..2bff9326a --- /dev/null +++ b/src/content/docs/es/paper/admin/reference/configuration/spigot-configuration.mdx @@ -0,0 +1,26 @@ +--- +title: spigot.yml +description: Explicación del archivo de configuración de Spigot. +slug: es/paper/reference/spigot-configuration +tableOfContents: false +--- + +import ConfigNode from "/src/components/ConfigNode.astro"; +import SpigotYML from "/src/config/paper/spigot.yml?raw"; +import { parse } from "yaml"; + +:::note + +El YAML siguiente muestra la estructura y los valores predeterminados de `spigot.yml`. + +Haz clic en un nodo hoja para ver la descripción de ese ajuste. + +::: + +:::note + +Para anular una opción por mundo, crea una clave nueva en `world-settings` con el nombre del nivel (el nombre de la carpeta). + +::: + + diff --git a/src/content/docs/es/paper/admin/reference/configuration/vanilla-data-files.mdx b/src/content/docs/es/paper/admin/reference/configuration/vanilla-data-files.mdx new file mode 100644 index 000000000..4b40b9c07 --- /dev/null +++ b/src/content/docs/es/paper/admin/reference/configuration/vanilla-data-files.mdx @@ -0,0 +1,90 @@ +--- +title: Vanilla data files +description: Explicación de los archivos de datos de Minecraft. +slug: es/paper/reference/vanilla-data-files +--- + +import ConfigNode from "/src/components/ConfigNode.astro"; +import { parse } from "yaml"; +import EulaYML from "/src/config/paper/eula.yml?raw"; +import BannedIpsYML from "/src/config/paper/banned-ips-single.yml?raw"; +import BannedPlayersYML from "/src/config/paper/banned-players-single.yml?raw"; +import OpsYML from "/src/config/paper/ops-single.yml?raw"; +import WhitelistYML from "/src/config/paper/whitelist-single.yml?raw"; + +## `eula.txt` + +`eula.txt` es un archivo de configuración sencillo que te permite aceptar el [EULA](https://aka.ms/MinecraftEULA), +un requisito para ejecutar el servidor de Minecraft. + + + +## `banned-ips.json` + +`banned-ips.json` es un archivo JSON que almacena las direcciones IP que no pueden conectarse al servidor. + +:::caution + +Este es un archivo de datos que usa el servidor, no un archivo de configuración. + +No recomendamos editar este archivo directamente; se incluye solo como referencia. + +En su lugar, usa los comandos `/ban-ip`, `/pardon-ip` y `/banlist ips` para administrar banned-ips.json. + +::: + + + + +## `banned-players.json` + +`banned-players.json` es un archivo JSON que almacena los jugadores que no pueden conectarse al servidor. + +:::caution + +Este es un archivo de datos que usa el servidor, no un archivo de configuración. + +No recomendamos editar este archivo directamente; se incluye solo como referencia. + +En su lugar, usa los comandos `/ban`, `/pardon` y `/banlist players` para administrar banned-players.json. + +::: + + + +## `ops.json` + +`ops.json` es un archivo JSON que almacena información sobre el estado de operador de los jugadores. + +En Vanilla, se usa como sistema rudimentario de permisos y permite que ciertos jugadores eviten el límite de jugadores. + +:::caution + +Este es un archivo de datos que usa el servidor, no un archivo de configuración. + +No recomendamos editar este archivo directamente; se incluye solo como referencia. + +En su lugar, usa los comandos `/op` y `/deop` para administrar ops.json. + +::: + + + +## `whitelist.json` + +`whitelist.json` es un archivo JSON que almacena los jugadores que pueden conectarse al servidor. + +Se usa junto con la opción [`white-list`](/es/paper/reference/server-properties#white_list) de `server.properties`. + + +:::caution + +Este es un archivo de datos que usa el servidor, no un archivo de configuración. + +No recomendamos editar este archivo directamente; se incluye solo como referencia. + +En su lugar, usa el comando `/whitelist` para administrar whitelist.json. + +::: + + diff --git a/src/content/docs/es/paper/admin/reference/configuration/world-configuration.mdx b/src/content/docs/es/paper/admin/reference/configuration/world-configuration.mdx new file mode 100644 index 000000000..9e40e1624 --- /dev/null +++ b/src/content/docs/es/paper/admin/reference/configuration/world-configuration.mdx @@ -0,0 +1,21 @@ +--- +title: Configuración por mundo +slug: es/paper/reference/world-configuration +description: Explicación del archivo de configuración de mundos de Paper. +tableOfContents: false +--- + +import ConfigNode from "/src/components/ConfigNode.astro"; +import PaperWorldDefaultsYML from "/src/config/paper/paper-world-defaults.yml?raw"; +import { parse } from "yaml"; + +:::note + +El YAML siguiente muestra la estructura y los valores predeterminados de la configuración por mundo (`config/paper-world-defaults.yml` y +`world/dimensions///paper-world.yml`). + +Haz clic en un nodo hoja para ver la descripción de ese ajuste. + +::: + + diff --git a/src/content/docs/es/paper/admin/reference/index.mdx b/src/content/docs/es/paper/admin/reference/index.mdx new file mode 100644 index 000000000..d2092f12c --- /dev/null +++ b/src/content/docs/es/paper/admin/reference/index.mdx @@ -0,0 +1,10 @@ +--- +title: Referencia +tableOfContents: false +--- + +import PageCards from "/src/components/PageCards.astro"; + +Referencia de las opciones de configuración, las propiedades del sistema y otras funciones de Paper. + + diff --git a/src/content/docs/es/paper/admin/reference/paper-plugins.md b/src/content/docs/es/paper/admin/reference/paper-plugins.md new file mode 100644 index 000000000..df05c9343 --- /dev/null +++ b/src/content/docs/es/paper/admin/reference/paper-plugins.md @@ -0,0 +1,45 @@ +--- +title: Plugins de Paper +description: Guía sobre los aspectos básicos y avanzados de los plugins de Paper. +slug: es/paper/reference/paper-plugins +--- + +Esta página explica los nuevos conceptos y las posibles confusiones que pueden surgir con los plugins de Paper. + +:::note + +Los desarrolladores pueden obtener más información sobre los plugins de Paper [aquí](/es/paper/dev/getting-started/paper-plugins). + +::: + +## ¿Qué son? + +Los plugins de Paper son plugins que carga el nuevo framework de carga de plugins de Paper. Los desarrolladores los usan para +aprovechar sistemas modernos que ofrece Mojang, como los paquetes de datos. + +![Lista de plugins](../../../../paper/admin/reference/assets/plugin-list.png) + +## ¿En qué se diferencian? + +Cuando están habilitados, los plugins de Paper son **idénticos** a los de Bukkit. Esto permite que los plugins se comuniquen entre sí y sean totalmente compatibles; es decir, tanto +los plugins de Bukkit como los de Paper pueden depender unos de otros sin problemas. + +Los plugins de Paper solo se pueden cargar con el cargador de plugins de Paper y pueden usar API nuevas que no están disponibles para los plugins de Bukkit. + +### ¿Cómo añado plugins de Paper? + +Los plugins de Paper se añaden igual que los de Bukkit, así que puedes seguir [esta guía](/es/paper/adding-plugins). + +### Carga cíclica de plugins + +Con la introducción de los plugins de Paper, Paper incorpora un nuevo cargador que corrige algunos problemas peculiares. +Sin embargo, como consecuencia, ya no se admite la [carga cíclica](/es/paper/dev/getting-started/paper-plugins#cyclic-plugin-loading) entre plugins. + +Si Paper detecta un ciclo, el servidor se cerrará y mostrará un error. + +:::danger[Heredado] + +Si tu servidor **requiere** esta carga circular, puedes habilitarla añadiendo el indicador de inicio [`-Dpaper.useLegacyPluginLoading=true`](/es/paper/reference/system-properties#paperuselegacypluginloading). +Ten en cuenta que puede dejar de admitirse en el futuro. + +::: diff --git a/src/content/docs/es/paper/admin/reference/system-properties.md b/src/content/docs/es/paper/admin/reference/system-properties.md new file mode 100644 index 000000000..3dcd93c55 --- /dev/null +++ b/src/content/docs/es/paper/admin/reference/system-properties.md @@ -0,0 +1,344 @@ +--- +title: Propiedades del sistema +description: Documentación de las propiedades del sistema y las variables de entorno que Paper puede comprobar. +slug: es/paper/reference/system-properties +--- + +Puedes definir estas propiedades del sistema y variables de entorno al iniciar el servidor para configurar +distintos ajustes. + +:::danger[Advertencia] + +Los indicadores de JVM pueden alterar su funcionamiento, y lo mismo ocurre con el servidor Paper. +Si no sabes qué hace un indicador, se recomienda **no usarlo**. + +::: + +## Cómo funcionan + +Las propiedades del sistema se establecen al iniciar el servidor. Por ejemplo, si usas un archivo `.bat` o `.sh` para iniciarlo, +puedes añadir las propiedades del sistema a ese archivo. Por ejemplo: + +```bash +java -Dcom.mojang.eula.agree=true -jar paper.jar +``` + +:::note + +Algunas propiedades del sistema de Paper incluyen un carácter `.` en el nombre. Si usas PowerShell, tendrás que +escribirlas entre comillas. +Por ejemplo: `"-Dcom.mojang.eula.agree=true"` + +::: + +En este ejemplo, `-D` establece una propiedad del sistema: `com.mojang.eula.agree` tiene el valor +`true`. En los demás casos, basta con añadirlas al comando de inicio. + +:::note + +Si una propiedad del sistema aparece como `unset`, puedes habilitarla estableciéndola en `true`. + +::: + +Las [variables de entorno](https://en.wikipedia.org/wiki/Environment_variable) son otra forma de pasar valores a Paper. +Se pueden definir de distintas maneras, según el sistema operativo y cómo inicies Paper. + +En la mayoría de los casos, no tendrás que usarlas, salvo que ejecutes Paper en un contenedor (Docker) o similar. + +## Lista de propiedades del sistema + +#### paper.playerconnection.keepalive + +- **default**: `30` +- **description**: Controla cuánto tiempo esperará la conexión del jugador antes de cerrarse si no recibe señales keepalive, + en segundos. + +#### timings.bypassMax + +:::danger[Obsolescencia] + +Timings está obsoleto. Por este motivo, este indicador no tiene ningún efecto. + +::: + +- **default**: `unset` +- **description**: Permite eludir el límite máximo de datos que se envían a la API de Timings de Aikar. Activar esta opción no + permite superar el límite a menos que la API esté configurada para permitirlo. + +#### LetMeReload + +- **default**: `unset` +- **description**: Desactiva el mensaje de confirmación de recarga al usar el comando `/reload`. + +#### paper.disableChannelLimit + +- **default**: `unset` +- **description**: Desactiva el límite de canales de plugins del servidor. De este modo, se elimina el límite de 128 canales de plugins + por jugador. + +#### net.kyori.adventure.text.warnWhenLegacyFormattingDetected + +- **default**: `false` +- **description**: Activa o desactiva el aviso cuando se detecta formato heredado en un componente de chat. + +#### Paper.DisableClassPrioritization + +- **default**: `unset` +- **description**: Desactiva el sistema de priorización de clases. Suele ser útil cuando falla la reubicación o el sombreado + de clases. + +#### Paper.disableFlushConsolidate + +- **default**: `unset` +- **description**: Desactiva el sistema de consolidación de vaciado de Netty. + +#### Paper.debugDynamicMissingKeys + +- **default**: `unset` +- **description**: Habilita el registro de depuración para las claves faltantes en objetos NBT. + +#### disable.watchdog + +- **default**: `unset` +- **description**: Desactiva el sistema de avisos del watchdog. + +#### paper.explicit-flush + +- **default**: `unset` +- **description**: Habilita el vaciado explícito del canal de red. + +#### Paper.enable-sync-chunk-writes + +- **default**: `unset` +- **description**: Sincroniza las escrituras en cada llamada de escritura. Esto afecta al rendimiento, especialmente en discos duros. + +#### paper.debug-sync-loads + +- **default**: `unset` +- **description**: Habilita el registro de depuración para la carga síncrona de chunks. + +#### Paper.ignoreWorldDataVersion + +- **default**: `unset` +- **description**: Ignora la versión de los datos del mundo al cargarlo. No se recomienda y es probable que cause + problemas. + +#### Paper.bypassHostCheck + +- **default**: `unset` +- **description**: Omite la comprobación de coincidencia del patrón del host del cliente al conectarse al servidor. + +#### paper.maxCustomChannelName + +- **default**: `32767` +- **description**: Establece el tamaño máximo del nombre de un canal de plugin. + +#### Paper.maxSignLength + +- **default**: `80` +- **description**: Establece la longitud máxima de línea de los carteles. + +#### Paper.minPrecachedDatafixVersion + +- **default**: `Versión del mundo de Minecraft + 1` +- **description**: Si esperas convertir muchos chunks, quizá te convenga establecerlo para que solo + convierta a partir de cierto punto. + +#### Paper.WorkerThreadCount + +- **default**: la mitad de los núcleos físicos disponibles (**no lógicos**) o `1` si hay 3 núcleos o menos +- **description**: Establece el número de hilos de trabajo que se usarán para cargar chunks. + Consulta [esta página](/es/paper/reference/global-configuration#chunk_system_worker_threads) para obtener más información. + +#### Paper.MaxViewDistance + +- **default**: `32` +- **description**: Anula la distancia de visión máxima del servidor. No establece la distancia de visión actual, + sino que modifica su límite. + +#### Paper.excessiveTELimit + +- **default**: `750` +- **description**: Divide las entidades de bloque en varios paquetes si su número supera este valor. + +#### io.papermc.paper.suppress.sout.nags + +- **default**: `unset` +- **description**: Suprime el aviso sobre el uso de `System.out`/`System.err` en un plugin. +- + +#### io.papermc.paper.sout.nags.timeout + +- **default**: `5000` +- **description**: Tiempo en milisegundos entre avisos sobre el uso de `System.out`/`System.err` en un plugin. + Un valor igual o inferior a 0 desactiva por completo los avisos basados en tiempo. + +#### io.papermc.paper.sout.nags.interval + +- **default**: `200` +- **description**: Número de usos repetidos de `System.out`/`System.err` que se esperan antes de volver a mostrar el aviso. Se restablece si + el tiempo de espera se agota primero. Un valor igual o inferior a 0 desactiva por completo los avisos basados en mensajes. + +#### Paper.skipServerPropertiesComments + +- **default**: `unset` +- **description**: Omite los comentarios del archivo `server.properties`. + +#### paper.alwaysPrintWarningState + +- **default**: `unset` +- **description**: Siempre muestra el estado de advertencia del nivel correspondiente. + +#### Paper.parseYamlCommentsByDefault + +- **default**: `true` +- **description**: Determina si los comentarios de los archivos YAML se analizan de forma predeterminada. + +#### paperclip.patchonly + +- **default**: `false` +- **description**: Si el servidor se inicia mediante la utilidad de parches Paperclip (la distribución predeterminada de la página de descargas), + determina si solo se debe aplicar el parche al servidor Vanilla y descargar bibliotecas, sin iniciar el + servidor. + +#### Paper.IgnoreJavaVersion + +- **default**: `false` +- **description**: Permite omitir la comprobación de la versión de Java. + Consulta [esta página](/es/paper/faq#unsupported-java-detected-what-do-i-do) para obtener más información. + +#### paper.disableStartupVersionCheck + +- **default**: `unset` +- **description**: Si se establece, desactiva la búsqueda automática de actualizaciones al iniciar. Consulta [esta página](/es/paper/misc/update-checker) para + obtener más información. + +#### paper.useLegacyPluginLoading + +- **default**: `false` +- **description**: Permite la carga cíclica de plugins. Consulta [esta página](/es/paper/reference/paper-plugins#cyclic-plugin-loading) para + obtener más información. + +#### paper.disableOldApiSupport + +- **default**: `false` +- **description**: Desactiva las medidas de compatibilidad de plugins que, de otro modo, pueden provocar un retraso considerable al cargar + clases (también conocido como reescritura «Commodore» de plugins). Por lo general, esto requiere que todos tus plugins se compilen + con una versión reciente de la API. + +#### paper.preferSparkPlugin + +- **default**: `false` +- **description**: Determina si se debe desactivar el perfilador spark incluido para dar prioridad a un plugin independiente. Si no se encuentra el plugin + spark, se cargará la versión incluida, independientemente de este ajuste, a menos que se + [desactive explícitamente](/es/paper/reference/global-configuration#spark_enabled). + +#### paper.disableWorldSymlinkValidation + +- **default**: `false` +- **description**: Desactiva el recorrido de carpetas y la validación de enlaces simbólicos al cargar un mundo. Mejora considerablemente la velocidad de carga + de mundos enormes (>1 TB). Esto no desactiva la verificación de enlaces simbólicos de los paquetes de datos. + +#### paper.disableMigrationDelay + +:::caution + +No se recomienda usar este indicador en servidores de producción. Asegúrate siempre de hacer una copia de seguridad de los datos importantes +y de saber lo que estás haciendo. + +::: + +- **default**: `unset` +- **description**: Desactiva la espera de 30 segundos antes de iniciar la migración de un mundo. + +#### minecraft.api.session.host + +- **default**: `https://sessionserver.mojang.com` +- **description**: Permite especificar una URL personalizada para el servidor de sesiones, por ejemplo, para usar una caché. [ + `minecraft.api.services.host`](#minecraftapiserviceshost) y [ + `minecraft.api.profiles.host`](#minecraftapiprofileshost) también deben estar definidas para que surta efecto. + +#### minecraft.api.services.host + +- **default**: `https://api.minecraftservices.com` +- **description**: Permite especificar una URL personalizada para la API de servicios, por ejemplo, para usar una caché. [ + `minecraft.api.session.host`](#minecraftapisessionhost) y [ + `minecraft.api.profiles.host`](#minecraftapiprofileshost) también deben estar definidas para que surta efecto. + +#### minecraft.api.profiles.host + +- **default**: `https://api.mojang.com` +- **description**: Permite especificar una URL personalizada para la API de perfiles, por ejemplo, para usar una caché. [ + `minecraft.api.session.host`](#minecraftapisessionhost) y [ + `minecraft.api.services.host`](#minecraftapiserviceshost) también deben estar definidas para que surta efecto. + +#### com.mojang.eula.agree + +- **default**: `false` +- **description**: Al establecer esta opción en true, indicas que has aceptado + el [EULA de Mojang](https://aka.ms/MinecraftEULA) y se omiten las comprobaciones de `eula.txt`. + +#### org.bukkit.plugin.java.LibraryLoader.centralURL + +- **default**: `https://maven-central.storage-download.googleapis.com/maven2` +- **description**: Establece la URL del repositorio central predeterminado, desde el que se resuelven las dependencias de los plugins declaradas mediante el campo [ + `libraries`](/es/paper/dev/plugin-yml#libraries) de plugin.yml. Esta URL queda anulada por la variable de entorno [ + `PAPER_DEFAULT_CENTRAL_REPOSITORY`](#paper_default_central_repository), si está establecida. + +:::caution + +Si quieres configurarlo con Maven Central, usa un mirror, ya que usar Maven Central directamente como CDN infringe las +condiciones del servicio de Maven Central y podrías alcanzar los límites de solicitudes. + +De forma predeterminada, se usa el mirror de Maven Central de Google para Norteamérica. También puedes usar los mirrors específicos de cada región +que aparecen [aquí](https://storage-download.googleapis.com/maven-central/index.html). + +::: + +#### paper.debugEntitiesWithInvalidIds + +- **default**: `false` +- **description**: Habilita el registro del NBT completo de una entidad cuando se intenta cargar una entidad cuyo ID falta o no es válido. + (Cada vez que se registra «Skipping Entity with id» en la consola). + +#### paper.maxChatCommandInputSize + +- **default**: `256` +- **description**: Longitud máxima de un comando de chat. Un cliente Vanilla no puede enviar más de 256 caracteres. + +#### management.tls.keystore.password + +- **default**: `unset` +- **description**: Anula el valor establecido para `management-server-tls-keystore-password` en `server.properties`. + +## Lista de variables de entorno + +#### PAPER_VELOCITY_SECRET + +- **default**: `unset` +- **description**: Anula la opción de configuración global [ + `proxies.velocity.secret`](/es/paper/reference/global-configuration#proxies_velocity_secret). + +#### PAPER_DEFAULT_CENTRAL_REPOSITORY + +- **default**: `https://maven-central.storage-download.googleapis.com/maven2` +- **description**: Establece la URL del repositorio central predeterminado, desde el que se resuelven las dependencias de los plugins declaradas mediante el campo [ + `libraries`](/es/paper/dev/plugin-yml#libraries) de plugin.yml. Esta variable anula la propiedad del sistema [ + `org.bukkit.plugin.java.LibraryLoader.centralURL`](#orgbukkitpluginjavalibraryloadercentralurl), si + está establecida. + +#### MINECRAFT_MANAGEMENT_TLS_KEYSTORE_PASSWORD + +- **default**: `unset` +- **description**: Anula el valor establecido para `management-server-tls-keystore-password` en `server.properties`. Tiene + prioridad sobre la propiedad del sistema `management.tls.keystore.password`. + +:::caution + +Si quieres configurarlo con Maven Central, usa un mirror, ya que usar Maven Central directamente como CDN infringe las +condiciones del servicio de Maven Central y podrías alcanzar los límites de solicitudes. + +De forma predeterminada, se usa el mirror de Maven Central de Google para Norteamérica. También puedes usar los mirrors específicos de cada región +que aparecen [aquí](https://storage-download.googleapis.com/maven-central/index.html). + +::: diff --git a/src/content/docs/es/paper/admin/reference/vanilla-command-permissions.md b/src/content/docs/es/paper/admin/reference/vanilla-command-permissions.md new file mode 100644 index 000000000..2e61b5857 --- /dev/null +++ b/src/content/docs/es/paper/admin/reference/vanilla-command-permissions.md @@ -0,0 +1,177 @@ +--- +title: Permisos +description: Todos los permisos disponibles en la instalación predeterminada de Paper. +slug: es/paper/reference/permissions +--- + +Esta página enumera todos los permisos incluidos en el servidor Paper predeterminado. + +## Permisos de comandos de Vanilla + +Esta es una lista de los permisos para comandos de Vanilla. + +| Comando | Alias | Nodo de permiso | ¿Los jugadores tienen permiso de forma predeterminada? | +|--------------------------------------------------------------------------------|-------------------------------------------------------|----------------------------------------|-----------------------------------------------------------| +| [advancement](https://minecraft.wiki/w/Commands/advancement) | | minecraft.command.advancement | No | +| [attribute](https://minecraft.wiki/w/Commands/attribute) | | minecraft.command.attribute | No | +| [ban](https://minecraft.wiki/w/Commands/ban) | | minecraft.command.ban | No | +| [ban-ip](https://minecraft.wiki/w/Commands/ban-ip) | | minecraft.command.ban-ip | No | +| [banlist](https://minecraft.wiki/w/Commands/banlist) | | minecraft.command.banlist | No | +| [bossbar](https://minecraft.wiki/w/Commands/bossbar) | | minecraft.command.bossbar | No | +| [chase](https://minecraft.wiki/w/Commands/chase) | | minecraft.command.chase | Sí | +| [clear](https://minecraft.wiki/w/Commands/clear) | | minecraft.command.clear | No | +| [clone](https://minecraft.wiki/w/Commands/clone) | | minecraft.command.clone | No | +| [compute](https://minecraft.wiki/w/Commands/compute) | | minecraft.command.compute | No | +| [damage](https://minecraft.wiki/w/Commands/damage) | | minecraft.command.damage | No | +| [data](https://minecraft.wiki/w/Commands/data) | | minecraft.command.data | No | +| [datapack](https://minecraft.wiki/w/Commands/datapack) | | minecraft.command.datapack | No | +| [debug](https://minecraft.wiki/w/Commands/debug) | | minecraft.command.debug | No | +| [debugconfig](https://minecraft.wiki/w/Commands/debugconfig) | | minecraft.command.debugconfig | No | +| [debugmobspawning](https://minecraft.wiki/w/Commands/debugmobspawning) | | minecraft.command.debugmobspawning | No | +| [debugpath](https://minecraft.wiki/w/Commands/debugpath) | | minecraft.command.debugpath | No | +| [defaultgamemode](https://minecraft.wiki/w/Commands/defaultgamemode) | | minecraft.command.defaultgamemode | No | +| [deop](https://minecraft.wiki/w/Commands/deop) | | minecraft.command.deop | No | +| [dialog](https://minecraft.wiki/w/Commands/dialog) | | minecraft.command.dialog | No | +| [difficulty](https://minecraft.wiki/w/Commands/difficulty) | | minecraft.command.difficulty | No | +| [effect](https://minecraft.wiki/w/Commands/effect) | | minecraft.command.effect | No | +| [enchant](https://minecraft.wiki/w/Commands/enchant) | | minecraft.command.enchant | No | +| [execute](https://minecraft.wiki/w/Commands/execute) | | minecraft.command.execute | No | +| [fetchprofile](https://minecraft.wiki/w/Commands/fetchprofile) | | minecraft.command.fetchprofile | No | +| [fill](https://minecraft.wiki/w/Commands/fill) | | minecraft.command.fill | No | +| [fillbiome](https://minecraft.wiki/w/Commands/fillbiome) | | minecraft.command.fillbiome | No | +| [forceload](https://minecraft.wiki/w/Commands/forceload) | | minecraft.command.forceload | No | +| [function](https://minecraft.wiki/w/Commands/function) | | minecraft.command.function | No | +| [gamemode](https://minecraft.wiki/w/Commands/gamemode) | | minecraft.command.gamemode | No | +| [gamerule](https://minecraft.wiki/w/Commands/gamerule) | | minecraft.command.gamerule | No | +| [give](https://minecraft.wiki/w/Commands/give) | | minecraft.command.give | No | +| [help](https://minecraft.wiki/w/Commands/help) | | minecraft.command.help | Sí | +| [item](https://minecraft.wiki/w/Commands/item) | | minecraft.command.item | No | +| [jfr](https://minecraft.wiki/w/Commands/jfr) | | minecraft.command.jfr | No | +| [kick](https://minecraft.wiki/w/Commands/kick) | | minecraft.command.kick | No | +| [kill](https://minecraft.wiki/w/Commands/kill) | | minecraft.command.kill | No | +| [list](https://minecraft.wiki/w/Commands/list) | | minecraft.command.list | Sí | +| [locate](https://minecraft.wiki/w/Commands/locate) | | minecraft.command.locate | No | +| [loot](https://minecraft.wiki/w/Commands/loot) | | minecraft.command.loot | No | +| [me](https://minecraft.wiki/w/Commands/me) | | minecraft.command.me | Sí | +| [msg](https://minecraft.wiki/w/Commands/msg) | /w, /tell | minecraft.command.msg | Sí | +| [op](https://minecraft.wiki/w/Commands/op) | | minecraft.command.op | No | +| [pardon](https://minecraft.wiki/w/Commands/pardon) | | minecraft.command.pardon | No | +| [pardon-ip](https://minecraft.wiki/w/Commands/pardon-ip) | | minecraft.command.pardon-ip | No | +| [particle](https://minecraft.wiki/w/Commands/particle) | | minecraft.command.particle | No | +| [perf](https://minecraft.wiki/w/Commands/perf) | | minecraft.command.perf | No | +| [place](https://minecraft.wiki/w/Commands/place) | | minecraft.command.place | No | +| [playsound](https://minecraft.wiki/w/Commands/playsound) | | minecraft.command.playsound | No | +| [posteffect](https://minecraft.wiki/w/Commands/posteffect) | | minecraft.command.posteffect | No | +| [publish](https://minecraft.wiki/w/Commands/publish) | | minecraft.command.publish | No | +| [raid](https://minecraft.wiki/w/Commands/raid) | | minecraft.command.raid | No | +| [random](https://minecraft.wiki/w/Commands/random) | | minecraft.command.random | Sí, sin argumento de secuencia; No, con argumento de secuencia. | +| [recipe](https://minecraft.wiki/w/Commands/recipe) | | minecraft.command.recipe | No | +| [reload](https://minecraft.wiki/w/Commands/reload) | | minecraft.command.reload | No | +| [return](https://minecraft.wiki/w/Commands/return) | | minecraft.command.return | No | +| [ride](https://minecraft.wiki/w/Commands/ride) | | minecraft.command.ride | No | +| [rotate](https://minecraft.wiki/w/Commands/rotate) | | minecraft.command.rotate | No | +| [save-all](https://minecraft.wiki/w/Commands/save-all) | | minecraft.command.save-all | No | +| [save-off](https://minecraft.wiki/w/Commands/save-off) | | minecraft.command.save-off | No | +| [save-on](https://minecraft.wiki/w/Commands/save-on) | | minecraft.command.save-on | No | +| [say](https://minecraft.wiki/w/Commands/say) | | minecraft.command.say | No | +| [schedule](https://minecraft.wiki/w/Commands/schedule) | | minecraft.command.schedule | No | +| [scoreboard](https://minecraft.wiki/w/Commands/scoreboard) | | minecraft.command.scoreboard | No | +| [seed](https://minecraft.wiki/w/Commands/seed) | | minecraft.command.seed | No | +| [setblock](https://minecraft.wiki/w/Commands/setblock) | | minecraft.command.setblock | No | +| [serverpack](https://minecraft.wiki/w/Commands/serverpack) | | minecraft.command.serverpack | No | +| [setidletimeout](https://minecraft.wiki/w/Commands/setidletimeout) | | minecraft.command.setidletimeout | No | +| [setworldspawn](https://minecraft.wiki/w/Commands/setworldspawn) | | minecraft.command.setworldspawn | No | +| [spawnpoint](https://minecraft.wiki/w/Commands/spawnpoint) | | minecraft.command.spawnpoint | No | +| [spawn_armor_trims](https://minecraft.wiki/w/Commands/spawn_armor_trims) | | minecraft.command.spawn_armor_trims | No | +| [spectate](https://minecraft.wiki/w/Commands/spectate) | | minecraft.command.spectate | No | +| [spreadplayers](https://minecraft.wiki/w/Commands/spreadplayers) | | minecraft.command.spreadplayers | No | +| [stop](https://minecraft.wiki/w/Commands/stop) | | minecraft.command.stop | No | +| [stopsound](https://minecraft.wiki/w/Commands/stopsound) | | minecraft.command.stopsound | No | +| [summon](https://minecraft.wiki/w/Commands/summon) | | minecraft.command.summon | No | +| [tag](https://minecraft.wiki/w/Commands/tag) | | minecraft.command.tag | No | +| [team](https://minecraft.wiki/w/Commands/team) | | minecraft.command.team | No | +| [teammsg](https://minecraft.wiki/w/Commands/teammsg) | /tm | minecraft.command.teammsg | Sí | +| [teleport](https://minecraft.wiki/w/Commands/teleport) | /tp | minecraft.command.teleport | No | +| [tellraw](https://minecraft.wiki/w/Commands/tellraw) | | minecraft.command.tellraw | No | +| [test](https://minecraft.wiki/w/Commands/test) | | minecraft.command.test | No | +| [tick](https://minecraft.wiki/w/Commands/tick) | | minecraft.command.tick | No | +| [time](https://minecraft.wiki/w/Commands/time) | | minecraft.command.time | No | +| [title](https://minecraft.wiki/w/Commands/title) | | minecraft.command.title | No | +| [transfer](https://minecraft.wiki/w/Commands/transfer) | | minecraft.command.transfer | No | +| [trigger](https://minecraft.wiki/w/Commands/trigger) | | minecraft.command.trigger | Sí | +| [version](https://minecraft.wiki/w/Commands/version) | | minecraft.command.version | No | +| [warden_spawn_tracker](https://minecraft.wiki/w/Commands/warden_spawn_tracker) | | minecraft.command.warden_spawn_tracker | No | +| [waypoint](https://minecraft.wiki/w/Commands/waypoint) | | minecraft.command.waypoint | No | +| [weather](https://minecraft.wiki/w/Commands/weather) | | minecraft.command.weather | No | +| [whitelist](https://minecraft.wiki/w/Commands/whitelist) | | minecraft.command.whitelist | No | +| [worldborder](https://minecraft.wiki/w/Commands/worldborder) | | minecraft.command.worldborder | No | +| [xp](https://minecraft.wiki/w/Commands/xp) | /experience | minecraft.command.xp | No | + +## Permisos de comandos de Bukkit + +Esta es una lista de los permisos para comandos de Bukkit. + +| Comando | Alias | Nodo de permiso | ¿Los jugadores tienen permiso de forma predeterminada? | +|---------|--------------|------------------------|-------------------------------------| +| help | /? | bukkit.command.help | Sí | +| plugins | /pl | bukkit.command.plugins | Sí | +| reload | /rl | bukkit.command.reload | No | +| restart | | bukkit.command.restart | No | +| timings | | bukkit.command.timings | No | +| version | /ver, /about | bukkit.command.version | Sí | + +## Permisos de comandos de Paper + +Esta es una lista de los permisos para comandos de Paper. + +| Comando | Alias | Nodo de permiso | ¿Los jugadores tienen permiso de forma predeterminada? | +|---------|---------|----------------------|-------------------------------------| +| paper | | bukkit.command.paper | No | + +## Permisos de Vanilla + +Esta es una lista de todos los permisos adicionales de Vanilla. + +| Nodo de permiso | Descripción | ¿Los jugadores tienen permiso de forma predeterminada? | +|-----------------------------------|-----------------------------------------------------------------------------------------------------------------------|-------------------------------------| +| minecraft | Permite al usuario usar todas las utilidades y los comandos de Vanilla. | No | +| minecraft.admin.command\_feedback | Recibir difusiones de comandos cuando sendCommandFeedback sea true. | No | +| minecraft.nbt.place | Permite al usuario colocar bloques restringidos con NBT en el modo creativo. | No | +| minecraft.nbt.copy | Permite al usuario copiar NBT en el modo creativo. | Sí | +| minecraft.debugstick | Permite al usuario usar la debug stick en el modo creativo. | No | +| minecraft.debugstick.always | Permite al usuario usar la debug stick en todos los modos de juego. | No | +| minecraft.commandblock | Permite al usuario usar bloques de comandos. | No | +| minecraft.command.selector | Permite al usuario usar [selectores de objetivo](https://minecraft.wiki/w/Target_selectors) en los argumentos de comandos. | No | + +## Permisos de Bukkit + +Esta es una lista de todos los permisos adicionales de Bukkit. + +| Nodo de permiso | Descripción | ¿Los jugadores tienen permiso de forma predeterminada? | +|------------------------|------------------------------------------------------|-------------------------------------| +| bukkit.broadcast | Permite al usuario recibir todos los mensajes de difusión | No | +| bukkit.broadcast.admin | Permite al usuario recibir difusiones administrativas | No | +| bukkit.broadcast.user | Permite al usuario recibir difusiones para usuarios | Sí | + +## Permisos de Paper + +Esta es una lista de todos los permisos adicionales de Paper. + +| Nodo de permiso | Descripción | ¿Los jugadores tienen permiso de forma predeterminada? | +|----------------------------------------|------------------------------------------------------------------|-------------------------------------| +| bukkit.command.paper.chunkinfo | Permite al usuario ejecutar el subcomando chunkinfo | No | +| bukkit.command.paper.debug | Permite al usuario ejecutar el subcomando debug | No | +| bukkit.command.paper.dumpitem | Permite al usuario ejecutar el subcomando dumpitem | No | +| bukkit.command.paper.dumplisteners | Permite al usuario ejecutar el subcomando dumplisteners | No | +| bukkit.command.paper.dumpplugins | Permite al usuario ejecutar el subcomando dumpplugins | No | +| bukkit.command.paper.entity | Permite al usuario ejecutar el subcomando entity | No | +| bukkit.command.paper.fixlight | Permite al usuario ejecutar el subcomando fixlight | No | +| bukkit.command.paper.heap | Permite al usuario ejecutar el subcomando heap | No | +| bukkit.command.paper.holderinfo | Permite al usuario ejecutar el subcomando holderinfo | No | +| bukkit.command.paper.mobcaps | Permite al usuario ejecutar el subcomando mobcaps | No | +| bukkit.command.paper.playermobcaps | Permite al usuario ejecutar el subcomando playermobcaps | No | +| bukkit.command.paper.reload | Permite al usuario ejecutar el subcomando reload | No | +| bukkit.command.paper.syncloadinfo | Permite al usuario ejecutar el subcomando syncloadinfo | No | +| bukkit.command.paper.version | Permite al usuario ejecutar el subcomando version | No | +| paper.antixray.bypass | Permite al usuario eludir anti-xray si use-permission está habilitado | No | +| paper.bypass-visibility.tab-completion | Permite al usuario ver jugadores ocultos al completar comandos con el tabulador | No | diff --git a/src/content/docs/es/paper/contributing/events.md b/src/content/docs/es/paper/contributing/events.md new file mode 100644 index 000000000..127e5d975 --- /dev/null +++ b/src/content/docs/es/paper/contributing/events.md @@ -0,0 +1,45 @@ +--- +title: Eventos +description: Guía para añadir eventos nuevos a Paper. +slug: es/paper/contributing/events +--- + +Los eventos de la API de Paper deben cumplir varios requisitos. + +:::note + +Ten en cuenta que quizá no todos los eventos existentes sigan estas +pautas, pero todos los eventos nuevos o modificados deben cumplirlas. + +::: + +Todos los eventos nuevos deben ubicarse en el paquete (o en un subpaquete de) `io.papermc.paper.event`. + +### Constructores + +Todos los constructores nuevos deben llevar la anotación +[`@ApiStatus.Internal`](https://javadoc.io/doc/org.jetbrains/annotations/latest/org/jetbrains/annotations/ApiStatus.Internal.html) +para indicar que no se consideran parte de la API y que pueden cambiar en cualquier momento sin previo aviso. + +Los constructores que se sustituyan, si no se eliminan, deben marcarse con +[`@Deprecated`](jd:java:java.lang.Deprecated) y [`@DoNotUse`](jd:paper:io.papermc.paper.annotation.DoNotUse). + +### Mutabilidad +Algunos tipos de la API son «mutables», lo que puede provocar comportamientos inesperados en los eventos. Por eso, los tipos mutables como +[](jd:paper:org.bukkit.Location) y [](jd:paper:org.bukkit.util.Vector) +deben clonarse al devolverse desde un «getter» de un evento. + +### `HandlerList` +Para poder escuchar una clase de evento o cualquiera de sus subclases, debe haber un campo [`HandlerList`](jd:paper:org.bukkit.event.HandlerList) +con una instancia y un método estático para obtenerlo. +Consulta la documentación de [](jd:paper:org.bukkit.event.Event) para obtener más detalles. +Este campo debe ser estático, final y llamarse `HANDLER_LIST`. + +También puedes evitar añadir un `HandlerList` a cada evento y colocarlo solo en un evento «padre común». Así, un plugin podrá escuchar el +evento padre para capturar los eventos secundarios y también escuchar cada evento secundario por separado. + +### Varios + +* En la mayoría de los casos, los parámetros nuevos o los valores devueltos por métodos de tipo [](jd:paper:org.bukkit.inventory.ItemStack) +no deben llevar [`@Nullable`](https://javadoc.io/doc/org.jspecify/jspecify/latest/org/jspecify/annotations/Nullable.html); +en su lugar, deben aceptar un ItemStack vacío. diff --git a/src/content/docs/es/paper/contributing/index.mdx b/src/content/docs/es/paper/contributing/index.mdx new file mode 100644 index 000000000..d5f6062b5 --- /dev/null +++ b/src/content/docs/es/paper/contributing/index.mdx @@ -0,0 +1,11 @@ +--- +title: Contribuir +tableOfContents: false +--- + +import PageCards from "/src/components/PageCards.astro"; + +¡Te damos la bienvenida a la guía para contribuir a Paper! Aquí encontrarás información y tutoriales para desarrolladores +que quieran colaborar con el proyecto Paper. + + diff --git a/src/content/docs/es/paper/dev/api/command-api/arguments/adventure.mdx b/src/content/docs/es/paper/dev/api/command-api/arguments/adventure.mdx new file mode 100644 index 000000000..4e3bef740 --- /dev/null +++ b/src/content/docs/es/paper/dev/api/command-api/arguments/adventure.mdx @@ -0,0 +1,137 @@ +--- +title: Aventura +description: Documentación para todos los argumentos que devuelven objetos de la API de Adventure. +slug: es/paper/dev/command-api/arguments/adventure +--- + +import ComponentMp4 from "../../../../../../paper/dev/api/command-api/arguments/assets/vanilla-arguments/component.mp4?url"; +import KeyMp4 from "../../../../../../paper/dev/api/command-api/arguments/assets/vanilla-arguments/key.mp4?url"; +import NamedColorMp4 from "../../../../../../paper/dev/api/command-api/arguments/assets/vanilla-arguments/namedcolor.mp4?url"; +import StyleMp4 from "../../../../../../paper/dev/api/command-api/arguments/assets/vanilla-arguments/style.mp4?url"; +import SignedMessageMp4 from "../../../../../../paper/dev/api/command-api/arguments/assets/vanilla-arguments/signedmessage.mp4?url"; + +import Video from "/src/components/Video.astro"; + +Estos argumentos devuelven una clase del paquete `net.kyori`. Técnicamente no son nativos de Minecraft o Bukkit, pero como Paper incluye la biblioteca Adventure, se usan ampliamente en el ecosistema de Paper. + +## Argumento del componente +:::note +Este argumento es muy técnico. Siguiendo el mismo formato que el comando `/tellraw ` para su segundo argumento, espera la representación JSON de un componente de texto, lo que lo hace inapropiado para la entrada general del usuario. +::: +El resultado se devuelve como un componente de Aventura con el que trabajar. + +### Ejemplo de uso +```java +Commands.argument("input", ArgumentTypes.component()) + .executes(context -> { + final Component input = context.getArgument("input", Component.class); + + context.getSource().getSender().sendRichMessage( "Tu mensaje: ", + Placeholder.component("input", input) + ); + return Command.SINGLE_SUCCESS; + }) +``` +### Vista previa del juego +
Velocity. Para más información, consulta el anuncio. +--- + +import ConfigNode from "/src/components/ConfigNode.astro"; +import WaterfallConfigYML from "/src/config/waterfall/waterfall-config.yml?raw"; +import { parse } from "yaml"; + +Esta página detalla las distintas opciones de configuración de Waterfall. Puedes encontrarlas en +waterfall.yml. + +Si necesitas información sobre las opciones de config.yml de BungeeCord, consulta las páginas de documentación +correspondientes. + +:::note + +El YAML siguiente muestra la estructura y los valores predeterminados de la configuración global. + +Haz clic en una hoja del árbol para ver la descripción de esa opción. + +::: + + diff --git a/src/content/docs/es/waterfall/getting-started.md b/src/content/docs/es/waterfall/getting-started.md new file mode 100644 index 000000000..996891cfb --- /dev/null +++ b/src/content/docs/es/waterfall/getting-started.md @@ -0,0 +1,62 @@ +--- +title: Primeros pasos +description: Cómo empezar a ejecutar Waterfall. +slug: es/waterfall/getting-started +banner: + destructive: true + content: Te recomendamos migrar a Velocity. Para más información, consulta el anuncio. +--- + +## ¿Qué es Waterfall? + +Waterfall es una bifurcación de BungeeCord, un proxy que se usa principalmente para trasladar jugadores entre varios +servidores de Minecraft. + +Waterfall se centra en tres áreas principales: + +- Estabilidad: Waterfall busca ser estable. Lo lograremos haciendo que el código base se pueda probar + y desalentando las prácticas que causan retrasos en el proxy. +- Funciones: Waterfall busca incluir más funciones que BungeeCord original. +- Escalabilidad: Waterfall debería poder gestionar muchos jugadores simultáneos si cuenta con una + CPU razonablemente moderna, memoria suficiente y una buena conexión de red. + +## Requisitos + +Waterfall requiere **Java 8** o una versión posterior. El equipo de Paper recomienda usar Java 11 o +superior. Por lo general, se recomiendan las versiones LTS de Java, aunque también podrían funcionar versiones más recientes. + +## Migrar desde BungeeCord + +Waterfall reemplaza directamente a BungeeCord, por lo que no necesitas cambiar la +configuración. + +## Obtener un JAR del proxy + +Paper ofrece JAR ejecutables del proxy directamente desde nuestra [página de descargas](https://papermc.io/downloads/waterfall). + +Haz clic en el número de compilación para descargar un archivo. + +## Ejecutar el proxy + +Para ejecutar el proxy, simplemente inícialo como cualquier otra aplicación Java. + +Abre una terminal, ve a la ubicación donde guardaste el archivo y ejecuta + +```bash +java -Xms512M -Xmx512M -jar waterfall-###.jar +``` + +Las opciones recomendadas por Aikar para Waterfall son las siguientes: + +```bash +java -Xms512M -Xmx512M -XX:+UseG1GC -XX:G1HeapRegionSize=4M -XX:+UnlockExperimentalVMOptions -XX:+ParallelRefProcEnabled -XX:+AlwaysPreTouch -jar waterfall-###.jar +``` + +Puedes cambiar la cantidad de memoria modificando los valores de las opciones `-Xms` y `-Xmx`. + +Para configurar el proxy, consulta la página de [configuración](/es/waterfall/configuration). + +## Actualizar el proxy + +Para actualizar el proxy, primero detenlo de forma segura ejecutando el comando `end`. Después, reemplaza el JAR +antiguo del proxy por uno nuevo e inicia el proxy. Eso es todo. diff --git a/src/content/docs/es/waterfall/index.mdx b/src/content/docs/es/waterfall/index.mdx new file mode 100644 index 000000000..62e3856f5 --- /dev/null +++ b/src/content/docs/es/waterfall/index.mdx @@ -0,0 +1,13 @@ +--- +title: Documentación de Waterfall +tableOfContents: false +banner: + destructive: true + content: Te recomendamos migrar a Velocity. Para más información, consulta el anuncio. +--- + +import PageCards from "/src/components/PageCards.astro"; + +Waterfall es una bifurcación de BungeeCord que busca mejorar el rendimiento y la estabilidad. + + diff --git a/src/pages/es/adventure/version-history/adventure-platform-mod.astro b/src/pages/es/adventure/version-history/adventure-platform-mod.astro new file mode 100644 index 000000000..59bf026ba --- /dev/null +++ b/src/pages/es/adventure/version-history/adventure-platform-mod.astro @@ -0,0 +1,5 @@ +--- +import Releases from "/src/components/changelog/Releases.astro"; +--- + + diff --git a/src/pages/es/adventure/version-history/adventure-platform.astro b/src/pages/es/adventure/version-history/adventure-platform.astro new file mode 100644 index 000000000..24c6f98a0 --- /dev/null +++ b/src/pages/es/adventure/version-history/adventure-platform.astro @@ -0,0 +1,5 @@ +--- +import Releases from "/src/components/changelog/Releases.astro"; +--- + + diff --git a/src/pages/es/adventure/version-history/adventure.astro b/src/pages/es/adventure/version-history/adventure.astro new file mode 100644 index 000000000..9f1d8209b --- /dev/null +++ b/src/pages/es/adventure/version-history/adventure.astro @@ -0,0 +1,5 @@ +--- +import Releases from "/src/components/changelog/Releases.astro"; +--- + +