The Shaper

The Shaper is the world editor built into the client. It is not a separate program: it is a set of extra panels and menus that appear inside the same window, working on the world you are standing in. Everything you change is live — you are editing the world you are looking at.

Every label below is the one you will actually see on screen.

1. Turning it on

The Shaper only exists if the client was started with it enabled. The switch is in worlds.ini or override.ini:

DisableShaper=0

A missing key counts as off. In the modified client it is already set. Once the client is running:

Options → Shaper On/Off

That switches the window between one tile (just the world) and four, and enables the orthographic camera under Options → View. The orthographic view is the one to use for lining things up — no perspective means what looks aligned is aligned.

2. The four panels, one by one

The Shaper open inside the client, showing its panels
The Shaper, open. The world you are standing in, its contents as a tree, the properties of whatever is selected, and the libraries you drag pieces out of — all inside the same window as the game.
the world the ordinary 3D view click an object to select it the tree every object, nested rooms → objects → parts properties what the selection is made of Edit… Add… Delete Help libraries ready-made pieces, in tabs drag one out to build drag Options → Shaper On/Off switches between one tile and these four.
The Shaper's four panels. Drag a piece out of libraries and drop it on the 3D view or on the tree — where you drop it decides where it lands.

The world (top left)

The ordinary 3D view, still live. You walk through it the way you always do, and clicking an object selects it. This is also a drop target: dragging a piece from the libraries onto it places that piece where the cursor is pointing.

How the drop position is worked out: the client casts a ray from the camera through the point under your cursor, finds whatever object that ray hits, and adds the new object to that object's room, at the point where the ray landed. So dropping onto a floor puts the object on the floor; dropping into empty sky finds nothing and the drop fails.

The tree (top right)

The world's contents as a hierarchy: rooms, the objects in them, and the objects inside those. Selecting a node here selects that object everywhere else.

This is the panel to use when an object is hidden inside another one, or is somewhere you cannot see. It is also a drop target, and dropping onto the tree is more precise than dropping onto the view: the object is added to the node you dropped it on, with no ray casting and no guessing.

Properties (bottom left)

What the selected object is made of. A list of properties, a toolbar along the top, and four buttons along the bottom.

ButtonDoes
Edit...Change the selected property. This is where you type a texture URL, a name, a colour.
Add...Add an entry to a property that holds a list. Only meaningful on list properties.
DeleteRemove the selected entry, or set the property to nothing if it is allowed to be empty.
HelpThe client's own help text for that property. Genuinely useful — it is documentation nobody wrote down anywhere else.

Edit → Sortable Attributes opens a separate panel for ordering an object's attributes.

Libraries (bottom right)

Ready-made pieces, in tabs. The tabs across the top are separate libraries. Libraries → Icons On/Off (Ctrl+I) switches between pictures and names — names are faster to scan once you know what things are called.

Libraries are read-only by default. Libraries → New Library and New Library Entry both refuse unless the client was started with AllowChangeLibrary=1 in worlds.ini. Without it you get "You must set AllowChangeLibrary=1 to modify libraries". The library files themselves live in the libraries directory beside the client.

3. The toolbar widgets, one by one

Along the top of the properties panel. These are not buttons you click. You press one and drag, and the selected object follows the drag. While you drag, the widget reports the object's new position back to you, which is how you get exact values without typing them.

WidgetDoesUse it for
Horizontal translateMoves the object on the ground planeLaying out a room. The one you use most.
Vertical translateMoves the object up and downGetting something off the floor, or hanging it.
PitchTilts forwards and backRamps, leaning objects.
RollTilts side to sideSame, on the other axis.
YawTurns on the spotFacing a wall the right way. Second most used.
ScaleResizesMaking one library piece into three different sizes of the same thing.
Cut / Copy / Paste / Save / UndoThe same as the Edit and File menu entriesConvenience, nothing new.

Snapping

Edit → Snap Tool Settings opens a small panel with X Snap Value, Y Snap Value, Z Snap Value and a Use Snap Tool checkbox. With snapping on, every movement is rounded to the nearest multiple of those values.

Shaper.useSnapTool=1
Shaper.snapX=100
Shaper.snapY=100
Shaper.snapZ=1

Remembered in worlds.ini. The defaults are 100, 100 and 1 — a coarse grid horizontally and a fine one vertically, which suits laying out floors and walls: you want walls to land on the same grid, and you want fine control over height.

Turn snapping on before you place anything. Straightening a room by hand afterwards is miserable, and a room built off-grid is obvious to everyone who walks into it.

4. Starting a world

File → New          (Ctrl+N)

The client loads home:NewWorld.world as a template, clones it, marks the clone as changed, and teleports you into it. You are now standing inside a new, unsaved world.

File → Open...      (Ctrl+O)

Opens a world from disk. The dialog offers *.world (saved worlds) and *.class (compiled world classes).

The Worlds menu lists every world currently loaded. One you have changed and not saved shows (changed) after its name. Picking one teleports you to it — this is how you move between several worlds you are working on, and how you copy an object from one into another.

5. Putting an object in

  1. Find the piece in Libraries.
  2. Press the mouse on the entry and drag. The cursor changes.
  3. Drop it on the 3D view (placed where the ray hits) or on the tree (added to the node you chose).

If the drop cannot be made, the client says so in the chat area — "Target doesn't..." — naming the file it tried. That message is in the chat area and easy to miss; if a drop seems to do nothing, look there first.

A .class or a saved object file is loaded immediately when dropped. Anything that is not a live, dynamic object has its source URL cleared as it is dropped, so the copy in your world is independent of the file it came from — change the original later and your world does not change. That is usually what you want, and occasionally a surprise.

6. Properties of things that are not objects

File → World Properties...      the world itself
File → Console Properties...    the client's own console
File → Pilot Properties...      your avatar
PanelWhat lives in it
World PropertiesThe world's own settings — its name, its server, what it is made of at the top level.
Console PropertiesThe client's settings, including the Avatar (URL) field. This is where you point at your own avatar. See the RWX guide.
Pilot PropertiesYour avatar as an object in the world — where it is, how it is oriented.

Right-clicking an object in the world offers Edit Properties..., which is the same as selecting it and looking at the properties panel.

7. Undo, cut, copy, paste

Edit → Undo     (Ctrl+Z)
Edit → Cut      (Ctrl+X)
Edit → Copy     (Ctrl+C)
Edit → Paste    (Ctrl+V)

Undo is a stack of individual changes — a property set, an addition, a paste, a deletion — each recorded as it happens.

The clipboard is shared across the whole editor, so you can copy an object in one world and paste it into another. Combined with the Worlds menu, that is the practical way to reuse something you built.

8. Saving

File → Save...      (Ctrl+S)
FormatWhat it isFor
.world The world itself. Type a name with no extension, or with .wor, and the client corrects it. Saved relative to the client's current directory. The actual thing you host.
.mft A manifest — a text listing of the world's properties rather than the world. Reading what is in a world, and comparing two versions. Save one before and after a session and diff them.

If saving fails the reason is printed in the chat area rather than thrown away. When you quit with unsaved worlds open the Shaper asks first, and it also tries to save modified worlds if the client is dying from an error.

9. Hosting what you built

A world is a file. Put the .world and everything it references on any web host that serves plain files over HTTP, and the address looks like this:

http://your.host/worlds/mine.world#Reception@1228.0,2465.0,150.0,157.0,0.0,0.0,-1.0
└────────── the file ──────────┘└─ room ─┘└─────────── where to stand ───────────┘

Both servers in this project have an HTTP server built in for exactly this. See the server guide, and docs/15-hosting-content.md for letting other people host their own.

10. Shortcuts

KeysDoes
Ctrl+NNew world
Ctrl+OOpen world
Ctrl+SSave world
Ctrl+ZUndo
Ctrl+X / Ctrl+C / Ctrl+VCut, copy, paste
Ctrl+ILibrary icons on/off

11. Driving it from a mod

Each call below corresponds to something described above, so a sequence you keep repeating becomes one menu entry.

worlds.shaper.available()          is there one at all
worlds.shaper.show(true)           show or hide the four panels
worlds.shaper.visible()
worlds.shaper.undo()  .cut()  .copy()  .paste()
worlds.shaper.save('world.world')  -- or .mft for a text manifest
worlds.shaper.properties('world' | 'console' | 'me')
worlds.shaper.snap(true)           snapping on or off
worlds.shaper.snap(100, 100, 1)    the grid it snaps to
worlds.shaper.describe()           a line about its state
worlds.menu('Build: fine grid', function()
  worlds.shaper.show(true)
  worlds.shaper.snap(10, 10, 1)
  worlds.shaper.snap(true)
  worlds.tell(worlds.shaper.describe())
end)

What is deliberately missing. There is no way to reach inside the editing panel and alter objects directly. That is where the Shaper keeps its own undo record, and a script writing behind its back would leave the editor describing a world that no longer exists. What is exposed is what the client already treats as one complete operation. See the Lua guide.

12. If it crashes

An Internal Program Error dialog saying "Assertion failed: line N in file X" comes from the native renderer, not from Java.

The cause is the renderer being asked about an object that has no live geometry. Three things do that: moving an object, inserting one before its geometry is built, and rebuilding the render device after a window resize. The modified client guards the four call sites responsible.

Resizing is the one that is only partly fixable. The renderer runs on Direct3D 9 through DXVK inside Wine, and resizing forces the device to be rebuilt — which is the path most likely to hand Java a released object. A guard can stop the client from asking; it cannot stop the device from being rebuilt. Working at a fixed window size crashes noticeably less.

If you do see the dialog, the file and line number in it are the useful part — they identify which call was not guarded. Write them down before dismissing it.

And save often. Ctrl+S.