Ir al contenido
Wiki Hartico

Sintaxis

El documento es una lista de pilas. Cada pila es una baldosa, y dentro van sus wireds de abajo arriba, en el mismo orden en el que están apilados en la sala.

// Sala 4021 · 3/1/2025, 10:15:32
// Esta vista es la sala completa: los wireds como bloques y el resto
// de furnis de suelo como `furni`. Los de pared no aparecen.
// Quitar un bloque o una línea `furni` = recogerlo al inventario
// (los marcados `// temporal` no vuelven: se eliminan).
// Cambiar su pila = moverlo. Cambiar `z` = cambiar su altura (absoluta, en centésimas).

stack (3, 1) {
    trigger.says #48211 {
        text = "abre"
        only_owner = true
        match_type = any
    }
    effect.teleport_to #48212 {
        furni_source = triggering
        user_source = signal
        furnis = [ #48360, #48361 ]
        delay = 5
    }
    condition.has_furni_on #48213 {
        matching = all
        furnis = [ #48301, #48302 ]
        furni_source = triggering
    }
}

stack (4, 1) {
    trigger.periodically #48220 {
        time = 5
    }
    effect.show_message #48221 {
        user_source = signal
        message = "[b]Bienvenido[/b]"
        visibility = whole_room
        notification_style = blue
        delay = 9
    }
}

Así se ve un volcado, simplificado: en una sala real cada furni de suelo tiene su línea furni y las listas lo nombran por su etiqueta.

Pilas

stack (x, y) { …wireds… }

x e y son la baldosa. La llave { va en la misma línea que la cabecera: el analizador no admite un salto de línea entre stack (3, 1) y su {.

Las coordenadas son enteros de 0 a 2147483647. Una negativa o una mayor da el error stack (x, y): las coordenadas de una casilla van de 0 a 2147483647. Una casilla que cae fuera de la sala no da error aquí: la rechaza la vista previa con la casilla (x,y) no existe en la sala (ver Cuando una fila no se puede hacer).

La posición no es solo informativa: si el bloque tiene #id y lo pones bajo una stack (x, y) distinta de la que trae de la sala, al aplicar se mueve ahí — ver Crear, borrar y mover.

Bloques de wired

familia.nombre [etiqueta] [#id] { …campos… }
ParteObligatoriaQué es
familiasítrigger, effect, condition, selector, extra o variable
nombresíEl nombre del wired dentro de su familia (says, teleport_to…)
etiquetanoCómo referenciar este wired desde otro bloque, sin usar su #id — ver Etiquetas
#idnoEl id del furni en la sala. Sin él, el bloque es un wired nuevo — ver Crear, borrar y mover
{ … }síLos campos, o vacío

familia.nombre no te lo inventas: sale del esquema del editor, y la lista completa está en la Referencia. Un familia.nombre que no exista es un error.

No hay nada más en la cabecera: detrás de familia.nombre (y del #id, si lo hay) solo puede venir {. Escribir cualquier otra cosa ahí, como una cadena entre comillas, es un error de sintaxis — ver Editar y aplicar.

Un wired sin campos que cambiar se escribe con las llaves vacías:

extra.exec_in_order #48232 {
}

Furnis normales

La vista es la sala completa: junto a los wireds (que salen como bloques), una pila también declara los furnis que no son wired (baldosas, puertas, tapices…) para poder referenciarlos desde un campo y para poder editarlos igual que con el ratón:

furni <etiqueta> "classname" [#id] [{ z = N, rot = N }]

Al volcar la sala, el editor escribe los furnis de suelo de la sala: los wireds con ventana como bloques y todo lo demás —furni normal y tablones— como línea furni. Los furnis de pared no aparecen, ni los furnis temporales. Hay tres excepciones entre los wireds. Un wired que Wired Code no sabe leer, una pieza nueva del servidor que el editor todavía no conoce, sale como un comentario en su casilla, y lo mismo «Dar Premio» si no tienes permiso de Super Wired (ver Un wired que el editor no conoce). Y un wired cuya configuración el servidor no consigue leer sale como una línea furni con su classname (ver Un wired que el servidor no puede leer).

ParteObligatoriaQué es
etiquetasíCómo referenciar este furni desde otro campo — ver Etiquetas
"classname"síEl nombre interno del furni, entre comillas
#idnoEl id del furni en la sala. Sin él, es un furni nuevo que se compra y se coloca — ver Furnis normales
z = Nno (el volcado lo escribe siempre)La altura, entera y en centésimas (250 = 2,50), de -4000 a 8000 — sí, admite negativos: hundir un furni bajo el suelo se escribe z = -50. En un furni nuevo, si no la escribes, cae donde caería si lo soltaras con el ratón: encima de lo más alto de todas las casillas que ocupa (también de un asiento o una cama), o a la altura de la baldosa mágica que tenga debajo; escribe z si necesitas otra altura. En uno existente, cambiarla cambia su altura — ver Furnis normales
rot = Nno (el volcado lo escribe siempre)La rotación como índice, contando desde 0 entre las posiciones que admite ese furni: el mismo número que enseña el infostand y que da @rotation. Un furni con dos posiciones solo acepta 0 y 1. Si no lo escribes, un furni nuevo sale con 0 y uno existente conserva la suya; cambiarlo en un furni existente lo rota — ver Furnis normales
stack (2, 1) {
    furni tile1 "dice_wired_grey" #48300 { z = 250, rot = 0 }
}

Una línea furni no es un wired: no tiene familia ni ventana propia, así que no lleva más campos que z y rot. Es la misma línea tanto si declaras un furni para referenciarlo desde otro campo como si lo estás editando (moviéndolo, subiéndolo, rotándolo o recogiéndolo) — ver Crear, borrar y mover.

Es siempre un furni de suelo: un furni de pared no se declara con una línea furni, pero sí se puede nombrar por su #id dentro de una lista, como furnis = [ #48360 ] — ver Crear, borrar y mover.

Los furnis temporales —los que crea «Colocar Furni Temporal»— no salen en el documento: no tienen línea furni y desde el texto no se recogen, ni se mueven, ni se suben, ni se giran. Una línea furni con el #id de un temporal (de un texto viejo, a veces marcada // temporal) no hace nada — ver Furnis normales.

La altura (z) no es un dato suelto: la compara condition.has_altitude, decide cómo se apilan unos furnis encima de otros y la usan los proyectiles para saber a qué altura impactan — por eso el documento la enseña y la deja cambiar.

Antenas y señales

Una antena (ver Señales y pilas remotas) puede ser cualquier furni, pero lo suyo es usar la Antena Wired Pequeña (wf_antenna2); no tiene ventana, así que se declara con una línea furni y el Recibir Señal la referencia en furnis:

stack (1, 1) {
    furni ant "wf_antenna2" #48400
}

stack (5, 1) {
    trigger.recv_signal #48410 {
        furnis = [ ant ]
    }
    effect.show_message #48411 {
        message = "ha llegado la señal"
        user_source = signal
    }
}

El Enviar Señal marca sus antenas en el campo antennas, que es una lista como furnis: admite #id y etiquetas, y la antena puede ser un furni nuevo del mismo documento (se resuelve al crearlo, como cualquier etiqueta):

stack (1, 1) {
    furni ant "wf_antenna2"
}

stack (3, 1) {
    trigger.says {
        text = "dispara"
    }
    effect.send_signal {
        antenna_source = selected
        users_to_advance = triggering
        antennas = [ ant ]
    }
}

stack (5, 1) {
    trigger.recv_signal {
        furnis = [ ant ]
    }
    effect.show_message {
        message = "ha llegado la señal"
        user_source = signal
    }
}

antenna_source = selected es lo que hace que el envío use las antenas de antennas; con triggering, selector o signal la antena sale de la pila y el campo sobra. Como antena vale cualquier furni —la señal se empareja por el furni concreto, no por su tipo—, pero lo suyo es usar wf_antenna2 (ver La antena).

Los dos conjuntos manuales

Quince wireds tienen dos listas de furnis marcadas a mano en vez de una: el conjunto A (la fuente selected / primary_selection) y el conjunto B (secondary_selection). En el DSL son dos campos de tipo lista, los dos opcionales (omitidos = vacíos):

WiredConjunto AConjunto B
effect.send_signal, effect.neg_send_signalantennassecondary_furnis
effect.change_varfurnissecondary_furnis
effect.furni_to_furnifurnissecondary_furnis
effect.modify_highscorefurnissecondary_furnis
effect.place_furni, effect.move_furni_as_groupfurnissecondary_furnis
effect.init_transactionfurnissecondary_furnis
condition.var_val_matchfurnissecondary_furnis
condition.stuff_is, condition.not_stuff_isfurnissecondary_furnis
condition.chest_has_item_typefurnissecondary_furnis
extra.mov_physicsfurnissecondary_furnis
extra.custom_contract, extra.scan_chest_furni_by_typefurnissecondary_furnis

Además de su lista normal de furnis, effect.give_var y condition.var_age_match llevan otra lista manual, reference_furnis: los furnis de los que sale la variable de referencia (con reference_scope = furni y reference_var_target = 0).

effect.furni_to_furni {
    moved_furni_source = selected            // mueve el conjunto A…
    target_furni_source = secondary_selection // …hasta el conjunto B
    furnis = [ caja1, caja2 ]
    secondary_furnis = [ destino ]
}

Etiquetas

Una etiqueta identifica un bloque —furni o wired— dentro del documento, para referenciarlo desde un campo sin usar su #id:

furnis = [ tile1, #48360 ]
  • Es un identificador ([A-Za-z_][A-Za-z0-9_]*), único en todo el documento.
  • No puede llamarse stack, furni, true, false, ni como ninguna familia (trigger, effect, condition, selector, extra, variable).
  • La lleva siempre un furni; un wired solo si algún otro bloque lo va a referenciar.
  • Dentro de una lista [ … ] de furnis se pueden mezclar etiquetas y #id libremente.
  • Es solo texto del documento, no algo que guarde el servidor: puedes renombrarla sin más. Cambia su nombre y el de todas las referencias que la usan.

Al volcar la sala, el editor genera una etiqueta para cada furni normal (todos llevan línea furni) y para cada wired que otro wired referencia:

  • Furnis: el classname saneado a identificador (_ en vez de lo que no sea letra, dígito o _; si empezara por dígito, f_ delante) y, si se repite en el documento, _2, _3… — tile_dark, tile_dark_2.
  • Wireds: el nombre del wired seguido de _N, empezando siempre en _1 — periodically_1, periodically_2…

Un wired que ningún otro bloque referencia sale sin etiqueta.

MensajeCuándo
etiqueta repetida 'x' (línea L)Dos bloques del documento (furni o wired) usan la misma etiqueta. Sale en el segundo
'furnis': etiqueta desconocida 'x'Un campo referencia una etiqueta que ningún bloque del documento declara

Ejemplo

Una baldosa declarada y un wired que la usa como fuente:

stack (2, 1) {
    furni tile1 "dice_wired_grey" #48300
}

stack (3, 1) {
    condition.has_furni_on #48213 {
        matching = all
        furnis = [ tile1 ]
        furni_source = triggering
    }
}

Campos

nombre = valor

Se separan por salto de línea o por coma. Las dos formas valen y se pueden mezclar:

trigger.says #48211 { text = "abre", only_owner = true }

Dos reglas que ahorran disgustos:

  • Un campo que no escribes vale su valor por defecto. Por eso el editor omite al volcar todo lo que esté en su defecto: lo que ves escrito es lo que está cambiado. La columna «Por defecto» de la referencia dice cuál es en cada caso. Cuidado con los ámbitos: condition.has_var y condition.neg_has_var miran a un furni si no escribes scope, así que con una variable de usuario tienes que poner scope = user; si no, al crear o cambiar el bloque el editor da un error: condition.has_var: 'puntos' es una variable de usuario y 'variable' mira furni (scope = furni): escribe scope = user o elige una variable de furni.
  • Un campo que ese wired no tiene es un error. No se ignora en silencio.

El valor por defecto es el de una caja recién colocada en el juego. Por eso un bloque nuevo sin campos se guarda igual que la caja que pondrías con el ratón; los pocos campos en los que no es así lo dicen en la referencia. Y una caja que acabas de colocar, y que nadie ha guardado todavía, sale casi siempre como un bloque vacío, { }. Si cambias uno de sus campos, los demás se guardan con los valores con los que se colocó.

Tipos de valor

TipoSe escribeEjemplo
booltrue / falseonly_owner = true
intun entero, con - delante si es negativo; también en hexadecimal (0x1F) o binario (0b101)delay = 5, literal_value = -3, literal_value = 0x1F
enumel nombre del valor, sin comillasfurni_source = triggering
stringentre comillas doblestext = "abre"
raw_stringigual que string, pero su contenido tiene formato internoraw = "a\tb\tc"
idslista de referencias a furnifurnis = [ #48360, #48361 ]
variableel nombre de la variable, entre comillasvariable = "puntos"

Un entero se puede escribir en decimal, en hexadecimal (0x1F) o en binario (0b101), cómodos para las máscaras de bits:

effect.change_var {
    variable = "banderas"
    operation = bitwise_or
    literal_value = 0b101   // 5: pone los bits 0 y 2
}

En la ventana normal (el campo valor o variable), 0x y 0b solo valen en minúscula y sin signo delante; en el texto vale también 0X1F, 0B101 y -0x10. Al recargar, el volcado los escribe siempre en decimal.

Los enteros van de -2147483648 a 2147483647, o del rango más estrecho que diga la columna «Tipo» de la referencia. Fuera de rango, el editor da un error: con literal_value = 0xFFFFFFFF sale 'literal_value': 4294967295 está fuera de rango (-2147483648..2147483647). La máscara con los 32 bits a uno es -1.

Enumerados

El nombre es lo normal, pero también se acepta el entero suelto. Sirve para los valores que la ventana ya no ofrece y que aún viven en wireds antiguos; el editor los vuelca así, con un comentario:

mode = 7 // sin nombre en el enumerado

Los nombres y sus números están en la referencia, wired a wired.

Listas

Van entre corchetes, con comas, y pueden ocupar varias líneas:

furnis = [
    #48360,
    #48361
]

Una lista vacía es []. Las de ids llevan # delante de cada número o una etiqueta. Los wireds con dos conjuntos manuales (antenas, furnis y secondary_furnis) usan dos listas de este tipo — ver Los dos conjuntos manuales.

Un #id dentro de una lista tiene que ser un furni que esté en la sala — salvo que ya estuviera así en el volcado, que entonces se respeta tal cual (un furni recogido hace tiempo no puede impedirte guardar el resto).

Las de ids también aceptan etiquetas del documento, mezcladas con #id en la misma lista: furnis = [ tile1, #48361 ] — ver Etiquetas.

Variables

Se escriben por su nombre:

effect.change_var #48230 {
    variable = "puntos"
    var_target = 2
    operation = add
    reference_variable = "puntos"
    reference_scope = user
    reference_var_target = 3
    use_reference = true
    delay = 4
}

Dos casos en los que el editor escribe la id en vez del nombre, con un comentario:

variable = "~113"  // sin resolver
variable = "~113"  // nombre ambiguo
  • sin resolver: la sala no tiene (ya) ninguna caja con esa id. Se conserva tal cual.
  • nombre ambiguo: hay dos o más variables con ese mismo nombre y el wired no dice de cuál habla (la misma caja replicada en dos furnis, por ejemplo). Escribir el nombre reapuntaría el wired a otra variable sin avisar, así que se escribe la id, que sí es única. Si escribes tú el nombre ambiguo, el editor te lo dice y te ofrece las ids entre las que elegir.

Las internas repetidas se resuelven solas por el ámbito. @position, @position.x, @position.y, @altitude y @type existen dos veces, una de furni y otra de usuario, con la misma palabra. No hace falta escribir ids: el editor mira qué portador pide el wired —el fijo del wired, como en los selectores por variable, o el que tú pongas en su campo de ámbito (scope, reference_scope…)— y se queda con la variable de ese portador:

selector.filter_furni_by_var {
    variable = "@position.y"      // selector de furnis → la @position.y de furni
    amount = 1
}

effect.change_var {
    variable = "@position.y"      // scope = user → la @position.y de usuario
    scope = user
    operation = assign
    literal_value = 3
}

Solo si ni así queda una sola candidata verás el error de nombre ambiguo. Con una interna repetida sale siempre en los cuatro campos que no tienen portador —wrapped_variable de la caja Eco y override_min_variable, override_max_variable y audience_variable de los Variable FX—: no hay ámbito que decida, así que el volcado escribe la id y, si escribes tú el nombre, el editor te da las ids entre las que elegir.

Escribir la id a mano para esquivar el error en otro campo es la forma más fácil de acertar la del portador equivocado: un selector de furnis con la variable de usuario no filtraría nada. El editor lo frena con un error al crear o cambiar el bloque: selector.filter_furni_by_var: '@position.y' es una variable de usuario y 'variable' mira furni: elige una variable de furni (escribir el nombre '@position.y' sin id la resuelve por el ámbito).

Comentarios

De // hasta el final de la línea. Se pueden poner en cualquier sitio y el editor los ignora del todo: no se guardan. Al recargar, el documento vuelve a salir del servidor y tus comentarios desaparecen.

// Pila de la puerta
stack (3, 1) {
    trigger.says #48211 { text = "abre" } // la contraseña
}

El editor sí escribe comentarios propios al volcar: la cabecera con la sala y la fecha, las notas de los campos de solo lectura y de los valores o variables que no sabe nombrar, y el aviso de un wired que no conoce o que no puedes ver (un Dar Premio sin permiso de Super Wired).

Escapes dentro de las comillas

EscapeEs
\"comilla doble
\\barra invertida
\nsalto de línea
\ttabulador
\rretorno de carro

El tabulador importa más de lo que parece: es el separador interno de varios wireds (los diálogos de bot, la ropa de bot, los premios…), así que verás cadenas como "Hola\tAdiós\tHasta luego".

Cualquier otra barra invertida se come a sí misma y deja pasar el carácter tal cual: "\x" es x, y "C:\datos" acaba siendo C:datos. No es un error, no avisa. Si quieres una barra invertida de verdad, escríbela doble: "C:\\datos".

Una cadena no puede contener un salto de línea de verdad: se escribe \n. Si te dejas la comilla de cierre, el editor lo marca como Cadena sin cerrar.

El caso típico es la tabla del Conector de texto: en su ventana escribes una pareja por línea, pero en Wired Code esas líneas van en una sola cadena, separadas por los dos caracteres \n (barra invertida y ene), nunca por un salto de línea de verdad:

extra.var_text_connector {
    table = "1=rojo\n2=naranja\n3=amarillo\n4=verde"
}

Así NO, aunque sea lo que ves en la ventana del conector — cada pareja en su propia línea dentro de las comillas da Cadena sin cerrar en cascada:

extra.var_text_connector {
    table = "1=rojo
2=naranja"
}

La tabla entera —las parejas y los \n que las separan— cabe en 1000 caracteres, que es el tope del texto de cualquier wired. Si te pasas, el editor da el error extra.var_text_connector: el texto ocupa 1043 caracteres y el servidor guarda como mucho 1000 y Aplicar queda apagado hasta que lo arregles. Las 30 líneas son un límite del cuadro de texto de la ventana: por texto solo cuentan los caracteres. Pero si después cambias esa tabla en la ventana, el cuadro la recorta a sus 30 primeras líneas y al guardar se pierde el resto.

Algunos campos de texto tienen además un tope más bajo, que dice la referencia: el de un Mensaje, por ejemplo, es string máx. 400, 8 líneas, y cada \n cuenta como un salto de línea. Si te pasas, el editor da un error ('message': texto demasiado largo (401 > 400) o 'message': demasiadas líneas (9 > 8)) y Aplicar queda apagado hasta que lo arregles.

Campos de solo lectura

Algunos wireds reciben del servidor un valor calculado que la ventana solo enseña y que no se devuelve al guardar. El editor los escribe marcados:

variable.room #48240 {
    availability = permanent
    current_value = 137 // solo lectura
}

Puedes cambiar el número: no pasará nada. Al aplicar, ese hueco no viaja.

Identificadores

Todos los nombres —familias, wireds, campos y valores de enumerado— van en inglés y en snake_case, y solo admiten letras minúsculas, dígitos y _. Es el mismo vocabulario que la referencia, y no cambia con el idioma del cliente.

En esta página