Connections
A connection is the byte stream between the terminal and whatever drives it. The session sends the terminal’s output (query responses, mouse reports) to the connection, and feeds the connection’s incoming bytes to the emulator. The package ships five connections and an interface for your own.
| The far end is | Use |
|---|---|
| A host that speaks telnet: a MUD, a BBS, a login service | TelnetConnection |
| A service that speaks plain lines over TCP, such as a MUD or a server of your own | TcpConnection |
| A WebSocket relay in front of a pty, a serial port, or a host | WebSocketConnection |
| A command line shared by ttyd | TtydConnection |
| A program of yours in the same process | LocalProgramConnection |
| Anything else: a pty or a serial port on the same machine | Your own ITerminalConnection |
A host that sends stray characters at connect, or never learns the window
size, expects telnet; switch from TcpConnection to TelnetConnection.
Set a connection on the session, which opens it and disposes any previous one:
session.SetConnection(new TelnetConnection("host", 23));SetConnection(null) detaches. A session needs no connection to show text;
see Writing to the terminal yourself.
Telnet
Section titled “Telnet”TelnetConnection speaks the telnet protocol over TCP: it negotiates options,
reports the window size (NAWS) when the grid resizes, and answers the terminal
type query with xterm-256color; set TerminalType before connecting to
answer with another name. Use it for a login service or a MUD that expects
telnet.
session.SetConnection(new TelnetConnection("your.mud", 4000));Raw TCP
Section titled “Raw TCP”TcpConnection is a raw byte stream, no negotiation. It suits a service that
speaks plain lines: a MUD on a plain port, or a server of your own. Bytes go
both ways as typed and as received, so a protocol with its own handshake,
such as IRC’s PING and PONG, needs a program in front of it.
session.SetConnection(new TcpConnection("your.game.server", 4000));WebSocket
Section titled “WebSocket”WebSocketConnection treats each message from the server as bytes for the
terminal, and sends each run of input as one binary message. It runs on every
platform, WebGL included, where it is the way to reach a network host.
session.SetConnection(new WebSocketConnection("wss://relay.example.com/term"));Set Subprotocols before connecting if the server expects one. A page served
over HTTPS can only open wss:// addresses, and the server decides which
pages may connect.
TtydConnection is a WebSocket connection to ttyd,
which shares a command line program over a WebSocket. It reports the grid
size when it connects and on every resize, so a full-screen program on the
far end fills the terminal. Give it the address ending in /ws:
session.SetConnection(new TtydConnection("wss://relay.example.com/ws"));Start ttyd with --writable, or it ignores input. Set AuthToken if the
server was started with a credential.
To speak another relay’s framing, derive from WebSocketConnection and
override OnConnected, HandleMessage, Send, and NotifyResize.
Connection events
Section titled “Connection events”SetConnection returns at once. The connect, the reads, and the writes happen
on background threads, and keys typed before the connect completes go out once
it does. The session marshals every event to the main thread, so you do not
handle threading yourself:
session.ConnectionOpened += () => status.text = "Connected";session.ConnectionClosed += reason => status.text = reason.IsError ? $"Failed: {reason.Message}" : "Disconnected";When the connection closes, the session also prints the reason into the terminal; turn off Print Close Reason to handle it yourself.
A program in the same process
Section titled “A program in the same process”ITerminalProgram is a terminal program hosted inside the Unity process. It
receives input bytes and resize events and writes ANSI back, the same contract
a remote host has. LocalProgramConnection adapts it to the session.
public sealed class Greeter : ITerminalProgram{ IProgramHost _host;
public void Start(IProgramHost host) { _host = host; _host.Write("\x1b[2J\x1b[HHello. Press a key.\r\n"); }
public void OnInput(byte[] data) => _host.Write(data); // echo public void OnResize(int cols, int rows) { } public void Stop() { }}
session.SetConnection(new LocalProgramConnection(new Greeter()));This is how you build an in-game shell or console, or port an existing
terminal program. Write the escape sequences the emulator understands (see
Rendering and painting for the supported set),
and read input as the bytes a terminal keyboard produces, or hand them to an
AnsiInputDecoder to get keys, text, and mouse events. A program that also
implements ITerminalTick is called every frame.
For a full-screen interface, see Interfaces, which also covers programs that draw cells directly and skip escape sequences.
IProgramHost.Exit() ends the program and closes the connection. The built-in
DemoShell is an ITerminalProgram; read it for a worked example of line
editing and command handling.
IProgramHost.Cols and Rows give the grid size, and OnResize reports each
change. Lines end with \r\n.
The demo shell
Section titled “The demo shell”DemoShell is the program Start Demo Shell runs. It also serves as a
starting console: AddCommand adds a command of your own, which help then
lists.
var shell = new DemoShell();shell.AddCommand("restart", "restart the reactor", _ => reactor.Restart());session.SetConnection(new LocalProgramConnection(shell));Its telnet command opens a TelnetConnection inside the shell, and Ctrl-]
returns to the prompt. Attach does the same with any connection, from a
command of your own:
shell.AddCommand("uplink", "open the relay", _ => shell.Attach(new WebSocketConnection(url)));RemoveCommand takes a command out of the shell and its help list, such as
exit where the shell should stay. In a WebGL player the shell has no
telnet command, since TcpConnection.IsSupported is false there. Set
BannerFont to a FIGlet font to add the figlet command.
Writing to the terminal yourself
Section titled “Writing to the terminal yourself”For output with nothing behind it, such as a boot sequence or a log a player only reads, write to the emulator:
session.Emulator.FeedText("\x1b[32mSYSTEM READY\x1b[0m\r\n");Feed takes bytes and FeedText a string, escape sequences included. Call
them on the main thread.
Your own connection
Section titled “Your own connection”Implement ITerminalConnection to bridge to anything else: a serial port or a
pty on desktop.
- Return from
Connectat once, then raiseConnectedwhen the stream opens. - Raise
DataReceivedwith incoming bytes. Any thread will do; the session moves each event to the main thread. - Raise
Closedonce, withCloseReason.Endedfor a close the far end asked for orCloseReason.Failedfor an error. - Queue the terminal’s output in
Sendand return; do the write on a thread of your own. - Pass the grid size on in
NotifyResizeif the far end wants it.
To add a protocol on top of TCP, derive from TcpConnection and override
HandleIncoming, as TelnetConnection does.
Platforms
Section titled “Platforms”TcpConnection and TelnetConnection need sockets and threads, which a WebGL
player lacks; TcpConnection.IsSupported says whether this platform has them. On WebGL, use WebSocketConnection, TtydConnection,
LocalProgramConnection, or a connection of your own.
Themes and screen types covers the look.