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.
| Kind | Examples | Role |
|---|---|---|
| Scripting Xtras | FileIO, NetLingo, Multiuser, XML Parser | New Lingo APIs via new(xtra "...") or global handlers. |
| Media/Asset Xtras | TextXtra, Flash Asset, QT/AVI agents, Sound Control | New member types and their rendering/decoding. |
| Transition Xtras | third-party wipes | Extra transition channel effects. |
| Tool Xtras | authoring-only helpers | No runtime presence. |
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 dumpDistribution rules (why titles break)
- A projector loads Xtras from its
Xtrasfolder (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:
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 = 0Method 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):
| Method | Purpose |
|---|---|
ConnectToNetServer | Open a client connection (host, port, user, password, movieID). |
WaitForNetConnection | Listen for a peer connection (peer-to-peer mode). |
BreakConnection | Disconnect. |
SendNetMessage | Send a message (subject, recipient, content). |
GetNetMessage | Pop the next received message (propList with sender/subject/content). |
CheckNetMessages | Poll: number of pending messages. |
GetNumberWaitingNetMessages | Same information, explicit form. |
SetNetMessageHandler | Register a Lingo callback for incoming messages/events. |
GetNetOutgoingBytes | Unsent buffer size (flow control). |
SetNetBufferLimits | Tune buffer limits. |
GetPeerConnectionList | Connected peers (host mode). |
GetNetAddressCookie | Opaque address token for the connection. |
GetNetErrorString | Human-readable error for a MUS error code. |
Usage shape in shipped games:
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
endProtocol 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:
- Registry, not special cases: one plugin registry mapping Xtra name -> implementation | stub | unsupported-diagnostic.
- Method-level decisions: implement, stub with deterministic values, or reject each method based on what decompiled game code actually reaches; never blanket-return success.
- Instance semantics:
new(xtra "X")returns distinct instances with per-instance state (FileIO handles, connection objects). - Callbacks re-enter Lingo correctly:
SetNetMessageHandler-style callbacks must dispatch through the normal single-threaded model between frame events, never mid-handler. interface()support: returning a plausible method listing keeps introspection-driven code alive.- Diagnose loudly: log every unsupported Xtra call with arguments; those logs are the roadmap for what to implement next.