Skip to content

Maps and content

Map format

A map is a Tiled document plus a layout of our own. The Tiled document draws the map: tiles, layers, collisions and text. The layout holds what people interact with: areas and their behaviours, placed entities, room settings and metadata. Authors draw in Tiled, upload a package, and place or change the rest with the editor in the game.

This page describes version 1. The files in schema/ are its machine-readable half:

FileContents
schema/manifest.schema.jsonJSON Schema of the package manifest
schema/tiled.schema.jsonJSON Schema of a Tiled document with the conventions below
schema/layout.schema.jsonJSON Schema of the layout document and the property vocabulary
schema/problem.schema.jsonJSON Schema of the error document the upload returns
schema/tiled-types.jsonthe custom types to import into Tiled

go test ./schema checks that the reference maps and the examples on this page are valid, that each rule in the error tables rejects a broken document, and that the custom types match the vocabulary.

Packages

A package is a zip archive that holds one map:

manifest.json      required
plaza.tmj          the Tiled document, at the root
layout.json        an optional layout document, at the root
tiles.png          tileset images, sounds, documents and other assets, in any folder
sounds/chime.wav

Manifest

{ "version": 1, "map": "plaza.tmj", "layout": "layout.json" }
FieldMeaning
versionpackage format version, 1
mapfile name of the Tiled document at the root, ending in .tmj
layoutfile name of the layout document at the root, ending in .json; optional

Files

KindExtensions
Tiled document.tmj
JSON.json
Images.png, .jpg, .jpeg, .webp, .gif, .svg
Sounds.mp3, .ogg, .wav
Documents.pdf
Scripts.js, .mjs

Paths use letters, digits, spaces and ._()+-, with / between folders. The upload skips files and folders whose name starts with a dot, the __MACOSX folder, and Tiled's .tiled-project and .tiled-session files. Every other file needs one of the extensions above. Tiled's XML formats and its external tileset and template files are refused with a hint: save the map as JSON, embed the tilesets and detach the templates.

Limits

WhatLimit
Upload100 MiB
Unpacked256 MiB and 1,000 files
One file32 MiB; 4 MiB for the layout, 64 KiB for the manifest
Path255 bytes, 8 folders deep
Map512 × 512 tiles
Tileset image4,096 pixels a side
Layout1,000 areas, 5,000 entities, 16 properties per area or entity, 50 collections

The upload measures the bytes it unpacks, not the sizes the archive claims. Tenant quotas apply on top.

Upload

Admins of a tenant upload a package with POST /api/v1/maps to create a map, or with PUT /api/v1/maps/{map}/package to replace its package, as the multipart field package; so does an API key of the tenant with the scope maps:write (Partner API), sent as the bearer token to one of the tenant's hosts, which suits a build pipeline: no person's session expires under it. Each upload goes to the audit log as map.created or map.replaced, with the admin or the key as its actor. An Idempotency-Key header makes a repeated upload answer what the first one did, for a day. Authors push a folder or a zip archive from the command line:

vws maps push --url https://acme.example.com --token "$TOKEN" ./plaza
vws maps push --url https://acme.example.com --key "$KEY" --map <map id> ./plaza

--token is an access token of an admin of the site's tenant, and --key an API key with maps:write; without either, the command takes VWS_API_KEY, else VWS_ACCESS_TOKEN. The upload:

  • The Tiled document is validated and its areas are imported into the layout, as Areas drawn in Tiled describes.
  • A new map without a layout document gets a layout made of the imported areas, with metadata from the Tiled map properties.
  • A package with a layout document replaces the stored layout. Areas in it whose id starts with tiled- are replaced by the import, so a downloaded package uploads again unchanged.
  • A replacement without a layout document keeps the stored layout: areas made in the game stay, imported areas are replaced, and the Tiled map properties name, description, copyright and thumbnail overwrite the metadata fields they set.
  • The package's files replace the map's files, and rooms using the map reload it: each sends its members a notice of kind NOTICE_KIND_REFRESH_REQUIRED.

An error rejects the whole package; warnings come back with the result. Both use the error document.

GET /api/v1/maps lists the tenant's maps, newest first, for its admins; every map the API answers, from the listing, GET /api/v1/maps/{map} or an upload, names the rooms that use it with their paths, so that the administration shows what a replacement reloads.

Storage

A map's files live in object storage under tenants/<tenant id>/maps/<map id>/<version>/, where the version is the first 16 hexadecimal digits of a SHA-256 over the package's paths and contents. A folder therefore never changes, and GET /api/v1/maps/{map}/files/<version>/<path> serves its files as cacheable for a year. The room snapshot's tiled_url names the current version's Tiled document, whose relative paths resolve inside the same folder. A replacement keeps the previous version for the clients still loading it and deletes older ones. Every stored file has a file_object row of kind map_asset, deleted with the file. GET /api/v1/maps/{map}/layout serves the layout with an ETag that changes with the map.

layout.unknown-prefab and layout.unknown-collection check a layout against the tenant's entity catalogue.

Tiled documents

Tiled is a third-party editor with an open JSON format. The format accepts what Tiled 1.9 and later save, with these conventions.

Map

  • Orthogonal and finite, with tiles of 32 × 32 pixels, at most 512 × 512 tiles.
  • Tile layers saved as CSV, which Tiled writes as a JSON array; base64 and compression are refused.
  • Tilesets embedded in the map, each based on one image. Tiles larger than the grid sit on the bottom-left corner of their cell, as in Tiled.
  • No object templates: detach template instances before saving.

Layers

  • Group layers flatten into group/child names, and children inherit the group's opacity, visibility and offset. Names should be unique after flattening, because scripts address layers by name.
  • Exactly one top-level object layer is named avatars, and it stays empty. Layers before it draw under avatars, layers after it draw over them.
  • Hidden layers load but neither draw nor collide; scripts can show them.
  • Image layers are not drawn.

Collisions

A cell blocks avatars when a visible tile layer has a tile in it whose tileset tile sets the property collides to true, or when the tile layer itself sets collides to true. A collision layer that nobody sees is a visible tile layer with collides and an opacity of 0. The layout's entities block the cells their prefabs' collision grids cover (Entities). Players never collide with each other.

Objects

ObjectMeaning
Rectangle of class areaan area, see below
Textdrawn with its font, size, colour, wrapping and alignment; a string property font-family replaces the font with a CSS font list
Tile objectdrawn in its layer
Anything elseignored

Tiled 1.10 and later save an object's class as type, Tiled 1.9 as class; both work.

Areas drawn in Tiled

An area is a rectangle of class area, not rotated. Its name is the area's name. Each behaviour is a custom property whose type is the behaviour's class from the vocabulary:

{
  "id": 8,
  "name": "meeting-room",
  "type": "area",
  "x": 96,
  "y": 96,
  "width": 160,
  "height": 128,
  "rotation": 0,
  "visible": true,
  "properties": [
    { "name": "capacity", "type": "class", "propertytype": "capacity", "value": { "max": 6 } },
    { "name": "meeting", "type": "class", "propertytype": "meeting", "value": { "name": "plaza-meeting", "hostTags": "staff, facilities" } }
  ]
}
  • The class members are the behaviour's fields, with the same names and defaults.
  • The property's name becomes the behaviour's id, so it follows the id rules.
  • A list of tags is text, with the tags separated by commas.
  • A colour may be #RRGGBB or Tiled's #AARRGGBB; the alpha is dropped.
  • A module area's settings are JSON text, such as {"title": "Welcome"}; empty text sets none.
  • Tiled does not save a member that equals its default. A required field therefore has no useful default in Tiled, and leaving it unset is an error.

Import schema/tiled-types.json with Tiled's Custom Types Editor to get the class area and every behaviour class with its members and defaults.

The upload copies each area into the layout with the id tiled- followed by the object id, its coordinates rounded to whole pixels. The area above becomes:

{
  "id": "tiled-8",
  "name": "meeting-room",
  "x": 96,
  "y": 96,
  "width": 160,
  "height": 128,
  "properties": [
    { "id": "capacity", "type": "capacity", "data": { "max": 6 } },
    { "id": "meeting", "type": "meeting", "data": { "name": "plaza-meeting", "hostTags": ["staff", "facilities"] } }
  ]
}

Imported areas belong to the Tiled document: the editor in the game shows them but cannot change them, and the next upload replaces them.

Map, tileset and tile properties

OnPropertyTypeMeaning
Mapnamestringthe metadata name
Mapdescriptionstringthe metadata description
Mapcopyrightstringcredits shown with the room's information
Mapthumbnailfile or stringpath of an image in the package
Mapscriptstringthe map's scripts, one per line: scripts of the package, named relative to the Tiled document, or https URLs, at most 8 (Scripting API)
Mapany nameclass variablea room variable, see below
Tilesetcopyrightstringcredits for the tileset
Tilecollidesboolthe tile blocks avatars
Tilenamestringa name scripts can place the tile by (Scripting API)
Tile layercollidesboolevery tile of the layer blocks avatars

The upload warns about every other property and ignores it.

Variables

A map property of class variable declares a room variable. The property's name is the variable's name: letters, digits and _.-, starting with a letter or _.

FieldDefaultMeaning
defaultnullthe initial value, as JSON text
persistfalsethe value is kept in the database; otherwise it lasts until the room empties
readTagsemptytags that may read the variable; empty lets everyone read it
writeTagsemptytags that may change the variable; empty lets everyone change it

Scripts can only set declared variables. The tags are those of a player's membership of the room's world; the realtime protocol describes how variables are read, written and kept.

Layout documents

{
  "version": 1,
  "areas": [
    {
      "id": "6f1d2c1e-5a43-4c0e-9d7a-3b8e2f4a9c10",
      "name": "kiosk",
      "x": 704,
      "y": 544,
      "width": 64,
      "height": 64,
      "properties": [
        { "id": "kiosk-website", "type": "website", "data": { "url": "https://example.com/kiosk", "trigger": "action" } },
        { "id": "kiosk-hint", "type": "tooltip", "data": { "text": "Press space for the kiosk" } }
      ]
    }
  ],
  "entities": [
    {
      "id": "3d0c3a43-91a4-4f0b-8a51-2f3a6c1b9e70",
      "prefab": { "collection": "lounge", "id": "0f8e7d6c-5b4a-4c3d-8e2f-1a0b9c8d7e6f" },
      "x": 512,
      "y": 320,
      "properties": [
        { "id": "radio-music", "type": "audio", "data": { "url": "sounds/lounge.mp3", "loop": true, "radius": 160, "shared": true } }
      ]
    }
  ],
  "collections": ["lounge"],
  "settings": { "broadcast": { "enabled": true, "title": "Town hall", "tags": ["staff"] } },
  "metadata": { "name": "Plaza", "thumbnail": "thumbnail.png", "tags": ["reference"] }
}
FieldMeaning
version1
areasareas with their behaviours
entitiesplaced entities
collectionsids of the entity collections the editor offers for this map; empty offers every collection of the tenant
settingsroom settings
metadatahow the map presents itself

Every field but version is optional. Coordinates are whole map pixels from the top-left corner.

Ids

Areas, entities and properties have ids of 1 to 64 letters, digits and _.-, starting with a letter or a digit. Area and entity ids are unique in the layout, and property ids within their area or entity. The editor creates UUIDs; hand-written layouts may use readable ids. Ids that start with tiled- belong to areas imported from Tiled.

Areas

FieldMeaning
idsee Ids
nameup to 100 characters; entry points use it, and players see it when they enter
x, y, width, heightthe rectangle, inside the map
propertiesbehaviours from the vocabulary

Entities

FieldMeaning
id, nameas for areas
prefabcollection and id of the prefab, as the entity catalogue names them
x, ythe top-left corner; the image, the size, the collision cells and the sorting against avatars come from the prefab (Entities)
propertieswebsite, file, audio, meeting and description behaviours, which act when a player activates the entity

A player reaches an entity standing within 48 pixels of its image, and activates it there with the action key or a click on it, whatever the triggers of its behaviours. Its websites and files open as an area's do and close once the player walks out of reach, and its meeting holds the player until then. Its sounds fade to silence over their radius as the player walks away and stop beyond it; without a radius, a sound plays at full volume until the player walks out of reach. A shared sound plays for everyone in the room whom its radius reaches, or for everyone without a radius. An entity that an access area hides from a player does not act for it.

Properties

A property is { "id": ..., "type": ..., "data": { ... } }, where type names a behaviour of the vocabulary and data holds its fields. Fields left out take their defaults.

Settings

FieldDefaultMeaning
broadcast.enabledfalsepeople allowed to broadcast get the broadcast control, and everyone the broadcast reaches sees and hears them while they broadcast
broadcast.titleemptythe broadcast's name, up to 100 characters
broadcast.scoperoomroom reaches this room, world every room of the world
broadcast.tagsemptytags allowed to broadcast, besides editors
broadcast.audienceVideofalsespeakers see the listeners' cameras
broadcast.notificationSoundnonean asset played when a broadcast starts, instead of the built-in sound
broadcast.notificationstrueplay that sound
recording.tagsemptytags allowed to record the spaces of the room, besides editors, where the room offers the recording feature
recording.soundstruea chime for everyone in a recorded space when its recording starts and stops
access.editTagsemptytags allowed to edit areas and entities anywhere in the map, besides editors

Metadata

FieldDefaultMeaning
nameemptydisplay name, up to 100 characters
descriptionemptyup to 2,000 characters
copyrightemptycredits, up to 2,000 characters
thumbnailnonean asset shown in room lists
tagsemptytags for search and room lists

Assets

An asset field takes a path in the package or an absolute http or https URL. Paths are served from the map's files. website.url and embed.url take URLs only, because a page served from a package would run on the product's own origin.

Vocabulary

TypeOnBehaviour
startareasa spawn point and an entry point
exitareasswitches rooms
websiteareas, entitiesopens a web page in a panel or a tab
embedareasshows a web page on the map
fileareas, entitiesopens a document or an image
audioareas, entitiesplays a sound
meetingareas, entitiesjoins a meeting
speakerareasbroadcasts to a stage's listeners
listenerareasfollows a stage's broadcast
silentareaskeeps players out of proximity bubbles
focusareasfits the camera to the area
highlightareasdarkens everything outside the area
tooltipareasshows a text above the player
descriptionareas, entitiesdescribes it in the map explorer
chatareasa chat for the people inside
accessareaslimits who may enter and edit
lockareaslets players lock the area
capacityareaslimits how many players fit
deskareasa desk a member can own
moduleareasa kind of area that a module adds

An area or entity holds any number of website, file and audio properties and at most one of each other type. start and exit exclude each other, and so do meeting, speaker and listener.

Triggers decide when a behaviour acts: enter when the player enters the area, action when the player presses the action key after a prompt, and icon by adding the panel collapsed, as an icon. A user setting turns enter into action for websites and files. On entities, behaviours act when the player activates the entity, whatever the trigger.

start

FieldDefaultMeaning
defaultfalsea join without an entry point starts here

exit

FieldDefaultMeaning
roomthis rooma room slug of the same world, or /world/room for another world of the tenant
startthe default startthe name of a start area in that room

An exit needs room, start or both.

website

FieldDefaultMeaning
urlrequiredhttp or https URL of the page
triggerenterenter, action or icon
actionMessageemptythe prompt for the action trigger, up to 200 characters
newTabfalseopen a browser tab instead of a panel
width50width of the panel, percent of the screen
closabletruethe player may close the panel
allowApifalsethe page may use the scripting API (Scripting API)
policyfullscreen; autoplay; clipboard-write; encrypted-media; picture-in-picturethe iframe's allow attribute
hideUrlfalsethe panel hides the page's address

The panel closes when the player leaves the area.

embed

Shows the page inside the area's rectangle on the map, whether anyone stands there or not.

FieldDefaultMeaning
urlrequiredhttp or https URL of the page
allowApifalsethe page may use the scripting API (Scripting API)
policyas for websitethe iframe's allow attribute

file

FieldDefaultMeaning
urlrequiredthe asset to show, such as a PDF or an image
namerequiredthe file's display name, up to 200 characters
trigger, actionMessage, newTab, width, closableas for website

audio

FieldDefaultMeaning
urlrequiredthe asset to play
volume1from 0 to 1
loopfalseplay again at the end
triggerenterenter or action
actionMessageemptythe prompt for the action trigger
radius0on entities, pixels over which the sound fades to silence; 0 keeps it at full volume
sharedfalseon entities, everyone within radius hears a sound one player starts

In an area, the sound stops when the player leaves.

meeting

FieldDefaultMeaning
nameemptyareas of the room with the same name share one meeting; empty gives the area its own
triggerenterenter or action
actionMessageemptythe prompt for the action trigger
audioMutedfalsejoin with the microphone off
videoMutedfalsejoin with the camera off
chattruethe meeting has a chat
raiseHandtrueplayers can raise a hand
hostTagsemptytags whose players host the meeting: they can mute and remove people
providernonean outside meeting tool that holds the meeting instead of the platform: zoom, teams, meet or other
linkemptythe meeting's https address in that tool, up to 2000 characters; required with a provider, empty without one

With a provider, the meeting takes place in the outside tool. The room starts no meeting of its own there, its players stay out of bubbles as in any meeting, and the action key opens link in a new browser tab, whatever the trigger, since browsers open a tab only on a gesture of the player's. A player who opened it shows as in a meeting while it stands in the area. A zoom link's host is zoom.us, zoomgov.com or one of their subdomains, a teams link's teams.microsoft.com or teams.live.com, and a meet link's meet.google.com, written in lower case as browsers write them; other takes any https address.

A meeting scheduled in a meeting area with an outside link (Identity) takes the area over the same way from 15 minutes before its start until its end, and the platform's meeting returns afterwards. The room tells its players the link as the meeting property's link state, checks every minute which scheduled meetings run, and learns at once of a meeting in an outside tool scheduled or cancelled.

speaker

FieldDefaultMeaning
stagerequiredthe broadcast's name, up to 100 characters
chatfalsethe broadcast has a chat
showAudiencefalsespeakers see who listens

listener

FieldDefaultMeaning
stagerequiredthe broadcast to follow
chatfalselisteners can use the broadcast's chat
canSpeakfalselisteners can talk to the speakers
raiseHandtruelisteners can raise a hand
waitingUrlnonean asset shown while no speaker is live

Speaker and listener areas with the same stage form one broadcast: the players in a speaker area broadcast to those in its listener areas, who see and hear them while one speaks and the waitingUrl while nobody does. Players in either area stay out of bubbles; their status shows as broadcasting or listening.

silent

Players inside show as silent and never join proximity bubbles. It has no fields.

focus

FieldDefaultMeaning
margin0space kept around the area, as a fraction of its size

highlight

FieldDefaultMeaning
opacity0.6opacity of the darkness outside the area
edgeWidth10width of the soft edge, in pixels
duration250fade-in time, in milliseconds
color#000000colour of the darkness

tooltip

FieldDefaultMeaning
textrequiredup to 500 characters
duration5000milliseconds; 0 keeps the text until the player leaves the area

description

FieldDefaultMeaning
textrequiredup to 2,000 characters
searchablefalsethe map explorer's search finds it

chat

FieldDefaultMeaning
channelrequiredthe chat's name. Players inside share the chat, which keeps its history while anyone is there; when the area empties, the chat is soft-deleted
openfalseopen the chat panel on entering

access

FieldDefaultMeaning
enterTagsemptytags that may enter; empty lets everyone enter
editTagsemptytags that may place, move and remove the entities wholly inside, as large as their prefabs; empty leaves it to editors

lock

FieldDefaultMeaning
tagsemptytags that may lock and unlock the area; empty lets everyone inside do it

capacity

FieldDefaultMeaning
maxrequiredplayers who fit, from 1 to 10,000

desk

FieldDefaultMeaning
claimselfself lets a member claim a free desk; with assigned, editors assign it
claimTagsemptytags that may claim the desk; empty lets every member claim it

module

An area kind of a module the tenant added (Extensions). A player who enters the area opens the module's page for it in the side panel, where the room turns the module on; elsewhere the area does nothing.

FieldDefaultMeaning
modulethe id of the module
typethe area kind, as the module's manifest names it
settingsemptythe values of the kind's settings, at most 64, which the module's schema describes and the editor checks

Runtime rules

Players and areas

  • A player's position is the point under the avatar's feet, in map pixels. A player is in an area when x ≤ px < x + width and y ≤ py < y + height.
  • Every area that contains the player applies its behaviours. Where several do, focus and highlight come from the smallest, and from the later one in the layout when sizes are equal; so does the meeting or stage the player talks in, of its meeting, speaker and listener areas, so that a speaker area inside a meeting room is a stage while the player stands in it.
  • Entering an area that has a name shows the name briefly.
  • Editors are members with the editor, admin or owner role. They pass every tag check of this page.

Start position

The first of these that applies places a joining player:

  1. A resumed session keeps its position.
  2. An entry point, from an exit or the URL fragment (#name), picks a start area with that name, at random when several share it; an exit without start uses the rules below from step 3.
  3. The position where the player last left this room, when it was saved less than an hour ago and can still be entered.
  4. The player's own desk.
  5. A start area with default, at random.
  6. Any start area, at random.
  7. The centre of the map.

The server saves each account's position per room in Postgres whenever the player leaves the room, and keeps it until the account or the room is deleted.

In an area, the player lands on a random walkable point at least 16 pixels from its edges, or on the middle of a side too short for that; an area without a walkable point is passed over. A blocked centre of the map gives way to the walkable cell nearest to it. Walkable means free of the Tiled document's collisions and of the cells the layout's entities block, as their prefabs' collision grids mark them (Entities); a player who returns within the hour to a point an entity now covers enters by these rules instead.

The server applies steps 2, 3, 5, 6 and 7, from the start area that Join.spawn names; resume brings step 1, and desks step 4. A join through an exit without start looks the same as any other join in protocol v1, so it starts from step 3.

Exits

Walking into an exit area switches rooms without reloading the page and places the player at the exit's start. An exit without room, or to the current room, moves the player to that start area. When the player may not enter the destination, a notice says so and the player stays. Standing in an exit area when the room loads does not count as walking into it.

Access, locks and capacity

  • An access area blocks players without one of its enterTags like a wall, and they do not see the entities whose centre it holds.
  • The people in a conversation can lock it: those inside a meeting area, the owner of a desk, and players inside a lock area with one of its tags. They lock and unlock with the action key. A locked area blocks players outside it, while players inside may stay, and the players in any area of a locked meeting walk between its areas; guests with a valid link to a scheduled meeting still enter its room (Identity).
  • A capacity area blocks players outside it while max players are inside.
  • A blocked entry flashes the area and shows a notice. The client keeps the player out like a wall; a move the room refuses all the same, from a client that had not heard of a lock yet, returns the player to where the room keeps it.

Room-wide state of a property travels in the realtime protocol's AreaState, keyed by area id, property id and key:

PropertyKeyValueSet by
lock, meeting, desklockedbooleanthe people allowed to lock, with SetAreaState
capacityoccupantsnumberthe server
deskowneruser id, or nullthe server
meetinglinkthe outside link of a scheduled meeting under way, or nullthe server

Behaviours in the client

The client applies what concerns only the player: it opens websites and files in a panel or a browser tab and closes the panel when the player leaves, plays sounds, joins meetings with the action key where they wait for it, opens the outside tools of meetings in a browser tab, shows silence, tooltips and the names of areas, fits the camera to focus areas, darkens the map round highlight areas and shows embeds over the map. Space is the action key.

Desks

A desk belongs to at most one member, who returns there after an absence of more than an hour, can walk back to it, and can lock it for a private meeting. Guests and anonymous users cannot own desks. Ownership is stored apart from the layout, so copying a map does not copy claims, and claims survive uploads as long as the area and property ids stay the same.

Errors

The upload answers an invalid package with an RFC 9457 problem whose issues list every finding: status 413 when the upload is too large, 422 otherwise. A valid package's result lists its warnings the same way.

{
  "type": "about:blank",
  "title": "Unprocessable Content",
  "status": 422,
  "detail": "The package was refused. Errors: 2, warnings: 1.",
  "issues": [
    { "severity": "error", "code": "tiled.finite", "file": "plaza.tmj", "pointer": "/infinite", "message": "Infinite maps are not supported." },
    { "severity": "error", "code": "layout.website", "file": "plaza.tmj", "pointer": "/layers/7/objects/3/properties/2/value", "message": "The website behaviour needs a url." },
    { "severity": "warning", "code": "tiled.unknown-property", "file": "plaza.tmj", "pointer": "/properties/6", "message": "The property mood is not part of the format and is ignored." }
  ]
}
FieldMeaning
severityerror rejects the package, warning does not
codeone of the codes below
filepath of the file in the package, when the issue concerns one
pointerJSON pointer to the value in that file
messagean explanation for people in the language of the request's Accept-Language, English when the server speaks none of them; programs use code

A failed schema rule has the code <document>.<rule>, where the rule is the schema's $defs entry that holds the failed keyword, or document for the top level. A rule that requires an array to contain an item is reported once, at the array. Behaviours of areas drawn in Tiled fail with the layout code of their type. The upload performs the checks marked "upload", which need more than one document or the files themselves.

Package and manifest

CodeChecked byRule
package.too-largeuploadthe upload is larger than 100 MiB; status 413
package.not-zipuploadthe upload is not a zip archive
package.unpacked-sizeuploadthe files add up to more than 256 MiB
package.too-many-filesuploadthe package holds more than 1,000 files
package.file-sizeuploada file is larger than its limit
package.pathuploada path is absolute, has an empty, . or .. segment, uses other characters than letters, digits, spaces and ._()+-, is longer than 255 bytes or deeper than 8 folders
package.duplicate-pathuploadtwo paths differ only in case
package.file-typeuploada file has an extension the format does not accept
package.contentuploada file's content does not match its extension
package.manifestuploadthere is no manifest.json at the root, or it is not JSON
package.missing-fileuploadthe manifest, the Tiled document or the layout names a file the package lacks
manifest.documentschemathe manifest is not an object with version 1 and map, or has other fields
manifest.tiled-fileschemamap is not a file name at the root ending in .tmj
manifest.layout-fileschemalayout is not a file name at the root ending in .json, or is manifest.json

Tiled document

CodeChecked byRule
tiled.jsonuploadthe Tiled document is not JSON
tiled.documentschemathe document is not an object, or has no tileset
tiled.mapschemathe document is not a Tiled map, or lacks a field every map has
tiled.orthogonalschemathe map is not orthogonal
tiled.finiteschemathe map is infinite
tiled.tile-sizeschemathe map's tiles are not 32 × 32 pixels
tiled.map-sizeschemathe map is larger than 512 × 512 tiles
tiled.avatars-layerschemathere is no top-level object layer named avatars, there are several, or it holds objects
tiled.layerschemaa layer has an unknown type or no name, or an object or group layer lacks its contents
tiled.tile-dataschemaa tile layer is not saved as CSV
tiled.objectschemaan object is not a JSON object
tiled.templateschemaan object is a template instance
tiled.area-shapeschemaan area is not an unrotated rectangle with a positive size
tiled.behaviourschemaa behaviour of an area has no object value
tiled.singletonsschemaan area has behaviours that exclude each other
tiled.propertyschemaa custom property lacks its name, type or value
tiled.typed-propertyschemaa property the format reads has the wrong type, such as a collides that is not a bool
tiled.variableschemaa variable has a malformed name or fields
tiled.tilesetschemaa tileset is not a JSON object
tiled.embedded-tilesetschemaa tileset is external instead of embedded
tiled.image-tilesetschemaa tileset is not based on one image
tiled.tagsschemaa tag list is not tags separated by commas
tiled.colorschemaa colour is not #RRGGBB or #AARRGGBB
tiled.layer-sizeuploada tile layer's size differs from the map's, or its data does not hold one tile per cell
tiled.giduploada tile refers to no tile of the map's tilesets
tiled.tileset-imageuploada tileset image is larger than 4,096 pixels a side, or its size differs from the tileset's imagewidth and imageheight
tiled.area-boundsuploadan area reaches outside the map
tiled.variable-defaultuploada variable's default is not JSON
tiled.scriptsuploadthe script property lists more than 8 scripts, or one that is neither a script of the package nor an https URL
tiled.unknown-propertyuploada warning: the format ignores a property, which may be a typo or belong to another tool
tiled.image-layeruploada warning: image layers are not drawn

Layout document

CodeChecked byRule
layout.jsonuploadthe layout document is not JSON
layout.documentschemathe document is not an object with version 1, or has other fields
layout.areaschemaan area lacks a field, has another field, or has a coordinate, size or name out of range
layout.entityschemaan entity lacks a field, has another field, or has a coordinate or name out of range
layout.prefabschemaa prefab reference lacks its collection or id
layout.propertyschemaa property lacks its id, type or data, or has an unknown type
layout.entity-propertyschemaan entity has a type of property entities do not support
layout.singletonsschemaan area or entity has properties that exclude each other
layout.startschemathe data of a start property does not match its fields
layout.exitschemathe data of an exit property does not match its fields
layout.websiteschemathe data of a website property does not match its fields
layout.embedschemathe data of an embed property does not match its fields
layout.fileschemathe data of a file property does not match its fields
layout.audioschemathe data of an audio property does not match its fields
layout.meetingschemathe data of a meeting property does not match its fields
layout.speakerschemathe data of a speaker property does not match its fields
layout.listenerschemathe data of a listener property does not match its fields
layout.silentschemaa silent property has data
layout.focusschemathe data of a focus property does not match its fields
layout.highlightschemathe data of a highlight property does not match its fields
layout.tooltipschemathe data of a tooltip property does not match its fields
layout.descriptionschemathe data of a description property does not match its fields
layout.chatschemathe data of a chat property does not match its fields
layout.accessschemathe data of an access property does not match its fields
layout.lockschemathe data of a lock property does not match its fields
layout.capacityschemathe data of a capacity property does not match its fields
layout.deskschemathe data of a desk property does not match its fields
layout.moduleschemathe data of a module property names no module id or area kind, or holds more than 64 settings
layout.settingsschemasettings has an unknown section
layout.broadcast-settingsschemasettings.broadcast has an unknown or malformed field
layout.recording-settingsschemasettings.recording has an unknown or malformed field
layout.access-settingsschemasettings.access has an unknown or malformed field
layout.metadataschemametadata has an unknown or malformed field
layout.idschemaan id breaks the id rules
layout.roomschemaan exit's room is not a room slug or /world/room
layout.http-urlschemaa URL is not an absolute http or https URL
layout.assetschemaan asset is neither a path in the package nor an http or https URL
layout.tagsschemaa tag list holds a malformed or repeated tag
layout.colorschemaa colour is not #RRGGBB
layout.duplicate-iduploadtwo areas or entities share an id, or two properties of one area or entity do
layout.area-boundsuploadan area reaches outside the map
layout.entity-boundsuploadan entity's position lies outside the map
layout.unknown-prefabuploadan entity's prefab is not in the tenant's collections
layout.unknown-collectionuploadcollections names a collection the tenant cannot use
layout.asset-typeuploadan asset path names a file of the wrong kind, such as an image for audio
layout.lonely-listeneruploada warning: a listener's stage has no speaker area
layout.insecure-urluploada warning: an http URL, which browsers block on https sites
layout.replaced-areauploada warning: the layout held imported areas that differ from the Tiled document's, and the upload replaced them

Versions

  • The manifest and the layout carry a version, which changes only with a breaking change. The Tiled conventions follow the manifest's version, and stored layouts record theirs in map.layout_version.
  • An addition keeps the version: a new behaviour, a new optional field with a default, a new setting. Servers reject fields and types they do not know, so a package that uses an addition needs a server that has it.
  • A breaking change raises the version: a field renamed or removed, or given another meaning or default. Servers then accept packages of earlier versions and migrate them on upload, migrate stored layouts in the release that brings the change, and serve only the current version.
  • Each migration is listed below with test fixtures of both versions, and schema/ keeps the schemas of every version still accepted.

There are no migrations yet.

Found a mistake? Tell us.