DDirectorWikiDirector & Lingo Encyclopedia

Xtras

The Xtra plugin system - types, distribution, FileIO, NetLingo, the Multiuser Xtra with its full method list, and how to shim Xtras in an emulator.

What Xtras are

Xtras are native plugin modules (successors to Director 4's XObjects) that extend the player. Windows Xtras are .x32 DLLs implementing the MOA (Macromedia Open Architecture) COM-like interface; Mac equivalents shipped as resource-fork/PEF libraries.

KindExamplesRole
Scripting XtrasFileIO, NetLingo, Multiuser, XML ParserNew Lingo APIs via new(xtra "...") or global handlers.
Media/Asset XtrasTextXtra, Flash Asset, QT/AVI agents, Sound ControlNew member types and their rendering/decoding.
Transition Xtrasthird-party wipesExtra transition channel effects.
Tool Xtrasauthoring-only helpersNo runtime presence.
lingo
fileObj = new(xtra "fileio")
put the moviexTraList / _movie.xtraList     -- movie's declared Xtras
put _player.xtraList                        -- everything loaded
showXlib                                    -- legacy listing
openXlib "some.x32" / closeXlib             -- explicit XObject/Xtra loading (legacy)
put interface(xtra "fileio")                -- self-describing method dump

Distribution rules (why titles break)

  • A projector loads Xtras from its Xtras folder (or embedded copies); Shockwave used a shared system folder with signed auto-download.
  • Director auto-detects Xtras needed by sprites/members, but not those used only from Lingo; authors had to add them manually, and forgetting was a classic shipping bug.
  • Missing Xtra behavior: member types render as placeholders; new(xtra ...) returns VOID; scripting calls throw errors. Preservation runtimes should reproduce a detectable failure, not a silent success.

FileIO

The standard file Xtra, on every install since D5:

lingo
f = new(xtra "fileio")
f.openFile("data.txt", 1)          -- 1 read, 2 write, 0 read/write
txt = f.readFile()                  -- whole file as string
f.closeFile()

f.createFile("save.txt")
f.openFile("save.txt", 2)
f.writeString("score=100" & RETURN)
f.closeFile()
f = 0

Method surface: openFile, closeFile, createFile, delete, readFile, readLine, readWord, readChar, readToken, writeString, writeChar, writeReturn, getLength, getPosition, setPosition, fileName, displayOpen, displaySave, status, error, getOSDirectory, setNewLineConversion, plus getNthFileNameInFolder() (a global, not a FileIO method). Shockwave sandboxing blocked arbitrary FileIO; projector titles use it freely for saves and configs. Emulator note: text mode converts line endings per setNewLineConversion; classic saves are CR-delimited.

NetLingo

The network operation surface (getNetText, postNetText, preloadNetThing, downloadNetThing, gotoNetMovie, gotoNetPage, netDone, netError, netTextResult, netAbort, netStatus, browser cache controls). Full semantics in Memory and streaming. In Shockwave the browser supplied the transport; in projectors, NetLingo/NetManage Xtras did.

The Multiuser Xtra

Macromedia's client for the Shockwave Multiuser Server (MUS protocol) and peer connections; the backbone of early multiplayer Shockwave games (and the origin of Habbo's FUSE protocol lineage: Habbo shipped a customized Multiusr.x32).

Method surface (recovered from the Xtra's own handler template string; identical in the stock MX-era Xtra and the Habbo-shipped one):

MethodPurpose
ConnectToNetServerOpen a client connection (host, port, user, password, movieID).
WaitForNetConnectionListen for a peer connection (peer-to-peer mode).
BreakConnectionDisconnect.
SendNetMessageSend a message (subject, recipient, content).
GetNetMessagePop the next received message (propList with sender/subject/content).
CheckNetMessagesPoll: number of pending messages.
GetNumberWaitingNetMessagesSame information, explicit form.
SetNetMessageHandlerRegister a Lingo callback for incoming messages/events.
GetNetOutgoingBytesUnsent buffer size (flow control).
SetNetBufferLimitsTune buffer limits.
GetPeerConnectionListConnected peers (host mode).
GetNetAddressCookieOpaque address token for the connection.
GetNetErrorStringHuman-readable error for a MUS error code.

Usage shape in shipped games:

lingo
gConn = new(xtra "Multiuser")
err = gConn.ConnectToNetServer("localhost", 9125, "user", "pass", "moviename")
gConn.SetNetMessageHandler(#onNetMessage, me)

on onNetMessage me
  repeat while gConn.CheckNetMessages() > 0
    msg = gConn.GetNetMessage()
    handlePacket me, msg[#content]
  end repeat
end

Protocol notes for preservationists: the stock MUS protocol frames typed messages with subjects and recipient lists; Habbo's fork replaced the payload with its own text protocol (delimiter-based packets, see Strings and chunks) while keeping the Xtra's connection API. Names like BINDATA/GETBINDATA seen in game traffic are protocol payload subjects, not Xtra methods: shim the transport, parse payloads in Lingo-land, exactly as the original did.

Habbo-era Xtra ecosystem (case study)

A late Habbo client references: Multiuser (network), FileIO (local prefs/logs), NetLingo (HTTP), plus custom native Xtras (BobbaXtra, SteamXtra, Curl) added by post-Macromedia maintainers. The preservation lesson generalizes: expect any long-lived title to accrete custom Xtras, and inventory them by grepping decompiled sources for xtra( and new(xtra.

Shimming Xtras in an emulator

Rules that keep shims honest:

  1. Registry, not special cases: one plugin registry mapping Xtra name -> implementation | stub | unsupported-diagnostic.
  2. Method-level decisions: implement, stub with deterministic values, or reject each method based on what decompiled game code actually reaches; never blanket-return success.
  3. Instance semantics: new(xtra "X") returns distinct instances with per-instance state (FileIO handles, connection objects).
  4. Callbacks re-enter Lingo correctly: SetNetMessageHandler-style callbacks must dispatch through the normal single-threaded model between frame events, never mid-handler.
  5. interface() support: returning a plausible method listing keeps introspection-driven code alive.
  6. Diagnose loudly: log every unsupported Xtra call with arguments; those logs are the roadmap for what to implement next.