Saltar al contenido principal

API de scripts

Los scripts son archivos Rhai (.rhai) que editan el proyecto actual — generar terreno, pintar layers, colocar objetos — con un formulario de parámetros opcional que se muestra en el panel Scripts.

Estructura de un script​

Un script puede definir cuatro funciones; solo apply es obligatoria.

// Título y descripción mostrados en el panel Scripts (opcional).
fn meta() {
#{
name: "Mi script",
description: "Lo que hace este script.",
undo: true, // guarda el historial de deshacer (true por defecto; false es más rápido)
iterative: false, // si es true, el panel muestra un número de iteraciones (ver más abajo)
}
}

// Formulario de entrada (opcional). Ver «Parámetros».
fn params() {
[
#{ id: "radius", label: "Radio", type: "int", min: 1, max: 64, value: 8 },
]
}

// Puertos de salida (opcional). Ver «Salidas».
fn outputs() {
[
#{ id: "cells", label: "Celdas", type: "map2d" },
]
}

// Obligatoria. `map` es la API de edición, `p` contiene los valores del formulario
// por id (más `p.iteration`, el índice de pasada desde 0 en modo iterativo).
fn apply(map, p) {
let r = p.radius;
}

Scripts iterativos​

Con iterative: true en meta(), el panel Scripts muestra un número de iteraciones (1..100000) y apply se ejecuta ese número de veces. p.iteration es el índice de la pasada actual, empezando en 0. Entre pasadas, cada salida map2d se devuelve a la entrada map2d con el mismo id, así un script puede conservar un estado de una iteración a la siguiente.

Parámetros​

Cada entrada de params() es un object map. El valor inicial va en value (default es una palabra reservada en Rhai).

typeClaves adicionalesp[id] en apply
intmin, max, valueentero
floatmin, max, valuedecimal
boolvaluebooleano
textvaluecadena
choiceoptions: [...], valuela cadena de la opción elegida
layerlayer_typeun mapa #{ kind, index, name }
colorvalue ("#rrggbb" o [r, g, b])un mapa #{ r, g, b } (0–255)
map2d—un mapa 2D de luminancia de solo lectura (ver abajo)

Para int y float, si se omiten min/max se muestra un campo numérico libre en lugar de un control deslizante.

layer_type es "material", "cover", "biome", "object", "resource", "feature", "combined", "annotation" o "any". Pasa p[id].index a las funciones de edición de abajo (todos los tipos salvo materiales y biomas empiezan en 1).

Una entrada map2d se alimenta a través del nodo Script del editor de nodos (conecta cualquier campo escalar a su puerto); al ejecutarse desde el panel Scripts, contiene en su lugar las restricciones de la herramienta (1 donde la celda las cumple, 0 en el resto).

Un valor map2d ofrece:

FunciónDescripción
m.width(), m.height()dimensiones (width() == 0 significa que no se ha proporcionado ningún mapa)
m.get(x, z)valor de la celda (0.0 fuera de los límites)
m.set(x, z, v)define el valor (float o int)
m.neighbor_count(threshold)nuevo map2d donde cada celda contiene cuántos de sus 8 vecinos tienen un valor >= threshold
m.neighbor_count_equal(value)nuevo map2d que cuenta los 8 vecinos cuyo valor es igual a value
m.neighbor_count_equal(value, wrap)igual, con wrap = true para bordes toroidales (las celdas del borde dan la vuelta)
new_map2d(w, h)función libre que crea un mapa lleno de ceros

Salidas​

outputs() declara puertos de salida (misma forma de object map que params(), con type "map2d", "color" o "material"). Se escriben en apply:

FunciónDescripción
map.set_output(id, map2d)escribe una salida map2d
map.set_output_color(id, r, g, b)escribe una salida de color (0–255)
map.set_output_material(id, index)escribe una salida de índice de material

Las salidas alimentan los puertos de salida del nodo Script en el editor de nodos y controlan el bucle de retroalimentación entre iteraciones (ver «Scripts iterativos»).

Nodo Script​

En el editor de nodos, el nodo Script expone directamente en el grafo las entradas de un script: las entradas int, float, color, map2d y layer de material se convierten en puertos de entrada con nombre (con un control integrado mientras no están conectadas); los demás tipos se editan dentro del nodo. El nodo nunca se evalúa en la vista previa en directo ni con Aplicar al mapa: el script solo se ejecuta con el botón del propio nodo.

La API map​

Las coordenadas son x (oeste→este) y z (norte→sur), con origen en 0,0. Las coordenadas fuera de los límites se ignoran.

Dimensiones y límites​

FunciónDevuelve
map.width()anchura del mapa en celdas
map.height()altura del mapa en celdas
map.water_level()nivel global del agua
map.min_height()altura mínima permitida
map.max_height()altura máxima permitida

Alturas​

Las alturas son f64 (precisión inferior al bloque), limitadas a [min_height, max_height].

FunciónDescripción
map.get_height(x, z)altura de la celda
map.set_height(x, z, h)define la altura
map.add_height(x, z, dh)suma dh a la altura
map.slope(x, z)pendiente local en grados

Material de superficie​

Índice desde 0 en la paleta de materiales.

FunciónDescripción
map.get_surface(x, z)índice del material
map.set_surface(x, z, mat)define el índice del material
map.set_surface_mask(mask, mat_on)pinta toda la superficie desde un map2d: celda >= 0.5 → mat_on, si no 0
map.set_surface_mask(mask, mat_on, mat_off)igual, con un material mat_off explícito para las celdas < 0.5
map.set_surface_mask(mask, mat_on, x0, z0, x1, z1)pinta solo el rectángulo [x0..=x1, z0..=z1]

Una sola llamada a set_surface_mask bloquea el mapa entero una única vez, mucho más rápido que un bucle de set_surface celda por celda.

Selección​

Expone la selección activa de la herramienta para que un script pueda limitar su trabajo a la región seleccionada sin cambiar el tamaño del mapa.

FunciónDevuelve
map.has_selection()true si hay una selección «solo» no vacía activa
map.selection_bounds()rectángulo envolvente [x0, z0, x1, z1] (inclusivo); todo el mapa si no hay una selección utilizable

Combina selection_bounds() con la forma rectangular de set_surface_mask para procesar solo el área activa.

Bioma​

Índice desde 0 en la lista de biomas.

FunciónDescripción
map.get_biome(x, z)índice del bioma
map.set_biome(x, z, id)define el índice del bioma

Cubiertas​

Empiezan en 1, apilables, alfa 0..=255 (255 por defecto).

FunciónDescripción
map.add_cover(x, z, id)añade una cubierta (alfa 255)
map.add_cover(x, z, id, alpha)añade una cubierta con alfa
map.remove_cover(x, z, id)quita una cubierta

Layers de objetos​

Empiezan en 1, apilables; mismas firmas que las cubiertas.

FunciónDescripción
map.add_object(x, z, id)añade un objeto (alfa 255)
map.add_object(x, z, id, alpha)añade un objeto con alfa
map.remove_object(x, z, id)quita un objeto

Layers de recursos​

Empiezan en 1, apilables; mismas firmas que las cubiertas.

FunciónDescripción
map.add_resource(x, z, id)añade un recurso (alfa 255)
map.add_resource(x, z, id, alpha)añade un recurso con alfa
map.remove_resource(x, z, id)quita un recurso

Layers de features​

Empiezan en 1, apilables; mismas firmas que las cubiertas.

FunciónDescripción
map.add_feature(x, z, id)añade una feature (alfa 255)
map.add_feature(x, z, id, alpha)añade una feature con alfa
map.remove_feature(x, z, id)quita una feature

Layers combinados​

Empiezan en 1, apilables; mismas firmas que las cubiertas.

FunciónDescripción
map.add_combined(x, z, id)añade un layer combinado (alfa 255)
map.add_combined(x, z, id, alpha)añade un layer combinado con alfa
map.remove_combined(x, z, id)quita un layer combinado

Anotaciones​

Empiezan en 1, un color por celda (id = índice entre los 16 colores fijos de anotación).

FunciónDescripción
map.add_annotation(x, z, id)pinta el color de anotación (sustituye al existente)
map.remove_annotation(x, z)borra la anotación de la celda
map.set_annotation_mask(mask, on)pinta desde un map2d: celda >= 0.5 → on, si no se borra
map.set_annotation_mask(mask, on, off)igual, con un color off explícito para las celdas < 0.5 (0 borra)
map.set_annotation_mask(mask, on, off, x0, z0, x1, z1)igual, limitado al rectángulo [x0..=x1, z0..=z1]
map.set_annotation_ids(states, x0, z0)estampa ids de anotación por celda: cada celda de states pinta el id round(value) (0 borra) en (x0+lx, z0+lz)

Agua por celda​

FunciónDescripción
map.get_water(x, z)nivel local del agua (o el nivel global si no hay)
map.set_water(x, z, level)define el nivel local del agua
map.clear_water(x, z)quita el agua local

Búsqueda por nombre​

Devuelven el índice de una entrada de la paleta, o -1 si no se encuentra. Los índices de cubiertas y objetos empiezan en 1, igual que en add_*/remove_*.

FunciónDevuelve
map.material_index(name)índice de material desde 0
map.cover_index(name)índice de cubierta desde 1
map.biome_index(name)índice de bioma desde 0
map.object_index(name)índice de objeto desde 1
map.resource_index(name)índice de recurso desde 1
map.feature_index(name)índice de feature desde 1
map.combined_index(name)índice de layer combinado desde 1
map.annotation_index(name)índice de color de anotación desde 1

Tamaño de las paletas​

map.material_count(), map.cover_count(), map.biome_count(), map.object_count(), map.resource_count(), map.feature_count(), map.combined_count(), map.annotation_count().

Material más cercano​

map.nearest_material(r, g, b) devuelve el índice de paleta del material más cercano (distancia CIELAB) al color sRGB indicado, o -1 si la paleta está vacía. Como en el nodo «Bloque más cercano», el color de un material es la media ponderada de los colores de textura de sus bloques (o el color de vista previa si no se puede resolver ninguna textura).

map.nearest_block_material(r, g, b) busca en cambio entre todos los bloques vanilla de cubo completo (como el nodo Bloque más cercano), reutiliza o crea la entrada de paleta correspondiente y devuelve su índice (-1 si la tabla de colores de bloques no está disponible o la paleta está llena).

Progreso y cancelación​

FunciónDescripción
map.report_progress(current, total, message)actualiza la barra de progreso
map.is_cancelled()true si el usuario ha cancelado

print(...) y debug(...) escriben en el registro de la aplicación.

Ejemplo​

Elevar un cono de terreno y pintar su superficie, con una entrada de radio:

fn meta() {
#{ name: "Elevar un cono", description: "Eleva un cono y pinta piedra." }
}

fn params() {
[
#{ id: "radius", label: "Radio", type: "int", min: 1, max: 128, value: 32 },
#{ id: "peak", label: "Altura de la cima", type: "float", min: 0.0, max: 256.0, value: 64.0 },
]
}

fn apply(map, p) {
let r = p.radius;
let cx = map.width() / 2;
let cz = map.height() / 2;
let stone = map.material_index("minecraft:stone");

for dz in -r..=r {
if map.is_cancelled() { return; }
map.report_progress(dz + r, 2 * r, "Elevando el terreno...");
for dx in -r..=r {
let dist = ((dx * dx + dz * dz) as float).sqrt();
if dist <= r {
map.add_height(cx + dx, cz + dz, p.peak * (1.0 - dist / r));
if stone >= 0 { map.set_surface(cx + dx, cz + dz, stone); }
}
}
}
}