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… }| Parte | Obligatoria | Qué es |
|---|---|---|
familia | sí | trigger, effect, condition, selector, extra o variable |
nombre | sí | El nombre del wired dentro de su familia (says, teleport_to…) |
etiqueta | no | Cómo referenciar este wired desde otro bloque, sin usar su #id — ver Etiquetas |
#id | no | El 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).
| Parte | Obligatoria | Qué es |
|---|---|---|
etiqueta | sí | Cómo referenciar este furni desde otro campo — ver Etiquetas |
"classname" | sí | El nombre interno del furni, entre comillas |
#id | no | El id del furni en la sala. Sin él, es un furni nuevo que se compra y se coloca — ver Furnis normales |
z = N | no (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 = N | no (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):
| Wired | Conjunto A | Conjunto B |
|---|---|---|
effect.send_signal, effect.neg_send_signal | antennas | secondary_furnis |
effect.change_var | furnis | secondary_furnis |
effect.furni_to_furni | furnis | secondary_furnis |
effect.modify_highscore | furnis | secondary_furnis |
effect.place_furni, effect.move_furni_as_group | furnis | secondary_furnis |
effect.init_transaction | furnis | secondary_furnis |
condition.var_val_match | furnis | secondary_furnis |
condition.stuff_is, condition.not_stuff_is | furnis | secondary_furnis |
condition.chest_has_item_type | furnis | secondary_furnis |
extra.mov_physics | furnis | secondary_furnis |
extra.custom_contract, extra.scan_chest_furni_by_type | furnis | secondary_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#idlibremente. - 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
classnamesaneado 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
nombredel wired seguido de_N, empezando siempre en_1—periodically_1,periodically_2…
Un wired que ningún otro bloque referencia sale sin etiqueta.
| Mensaje | Cuá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 = valorSe 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_varycondition.neg_has_varmiran a un furni si no escribesscope, así que con una variable de usuario tienes que ponerscope = 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
| Tipo | Se escribe | Ejemplo |
|---|---|---|
bool | true / false | only_owner = true |
int | un entero, con - delante si es negativo; también en hexadecimal (0x1F) o binario (0b101) | delay = 5, literal_value = -3, literal_value = 0x1F |
enum | el nombre del valor, sin comillas | furni_source = triggering |
string | entre comillas dobles | text = "abre" |
raw_string | igual que string, pero su contenido tiene formato interno | raw = "a\tb\tc" |
ids | lista de referencias a furni | furnis = [ #48360, #48361 ] |
variable | el nombre de la variable, entre comillas | variable = "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 enumeradoLos 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 ambiguosin 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
| Escape | Es |
|---|---|
\" | comilla doble |
\\ | barra invertida |
\n | salto de línea |
\t | tabulador |
\r | retorno 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.