diff --git a/internal/connections/clientsettings.go b/internal/connections/clientsettings.go index 90fc39c4..2ec54307 100644 --- a/internal/connections/clientsettings.go +++ b/internal/connections/clientsettings.go @@ -3,11 +3,12 @@ package connections type ClientSettings struct { Display DisplaySettings Discord DiscordSettings - Client ClientType + Client ClientType // Client data provided by `Core.Hello` GMCP command // Enabled GMCP Modules - GMCPModules map[string]int + GMCPModules map[string]int // Enabled GMCP Modules (if any) // Is MSP enabled? - MSPEnabled bool + MSPEnabled bool // Do they accept sound in their client? + SendTelnetGoAhead bool // Defaults false, should we send a IAC GA after prompts? } type DisplaySettings struct { diff --git a/internal/events/eventtypes.go b/internal/events/eventtypes.go index dd1a9ad1..1837101b 100644 --- a/internal/events/eventtypes.go +++ b/internal/events/eventtypes.go @@ -58,7 +58,7 @@ type Message struct { func (m Message) Type() string { return `Message` } -// Messages that are intended to reach all users on the system +// Special commands that only the webclient is equipped to handle type WebClientCommand struct { ConnectionId uint64 Text string @@ -66,7 +66,7 @@ type WebClientCommand struct { func (b WebClientCommand) Type() string { return `WebClientCommand` } -// Messages that are intended to reach all users on the system +// GMCP Commands from clients to server type GMCPIn struct { ConnectionId uint64 Command string @@ -75,7 +75,7 @@ type GMCPIn struct { func (b GMCPIn) Type() string { return `GMCP` } -// Messages that are intended to reach all users on the system +// GMCP Commands from server to client type GMCPOut struct { ConnectionId uint64 UserId int @@ -91,7 +91,7 @@ type System struct { func (s System) Type() string { return `System` } -// Messages that are intended to reach all users on the system +// Payloads describing sound/music to play type MSP struct { UserId int SoundType string // SOUND or MUSIC diff --git a/internal/inputhandlers/term_iac.go b/internal/inputhandlers/term_iac.go index 127c5c9e..b8c4f559 100644 --- a/internal/inputhandlers/term_iac.go +++ b/internal/inputhandlers/term_iac.go @@ -187,6 +187,16 @@ func TelnetIACHandler(clientInput *connections.ClientInput, sharedState map[stri continue } + if ok, _ := term.Matches(iacCmd, term.TelnetDontSuppressGoAhead); ok { + slog.Info("Received", "type", "IAC (TelnetDontSuppressGoAhead)") + + cs := connections.GetClientSettings(clientInput.ConnectionId) + cs.SendTelnetGoAhead = true + connections.OverwriteClientSettings(clientInput.ConnectionId, cs) + + continue + } + // Is it a screen size report? if ok, payload := term.Matches(iacCmd, term.TelnetScreenSizeResponse); ok { diff --git a/internal/term/term.go b/internal/term/term.go index 1148dc64..18933fc3 100644 --- a/internal/term/term.go +++ b/internal/term/term.go @@ -48,8 +48,9 @@ var ( // // GENERAL SETUP // - // // Suppress Go Ahead - TelnetSuppressGoAhead = TerminalCommand{[]byte{TELNET_IAC, TELNET_WILL, TELNET_OPT_SUP_GO_AHD}, []byte{}} + // // Do/Don't Suppress Go Ahead + TelnetSuppressGoAhead = TerminalCommand{[]byte{TELNET_IAC, TELNET_WILL, TELNET_OPT_SUP_GO_AHD}, []byte{}} + TelnetDontSuppressGoAhead = TerminalCommand{[]byte{TELNET_IAC, TELNET_DONT, TELNET_OPT_SUP_GO_AHD}, []byte{}} // // Echo On TelnetEchoOn = TerminalCommand{[]byte{TELNET_IAC, TELNET_WILL, TELNET_OPT_ECHO}, []byte{}} // // Echo Off @@ -76,6 +77,8 @@ var ( TelnetAcceptedChangeCharset = TerminalCommand{[]byte{TELNET_IAC, TELNET_SB, 2}, []byte{TELNET_IAC, TELNET_SE}} // Client rejectected change TelnetRejectedChangeCharset = TerminalCommand{[]byte{TELNET_IAC, TELNET_SB, 3, TELNET_IAC, TELNET_SE}, []byte{}} + // Go Ahead + TelnetGoAhead = TerminalCommand{[]byte{TELNET_IAC, TELNET_GA}, []byte{}} /////////////////////////// // ANSI COMMANDS diff --git a/internal/users/userrecord.go b/internal/users/userrecord.go index c5edae8c..21b7149d 100644 --- a/internal/users/userrecord.go +++ b/internal/users/userrecord.go @@ -290,36 +290,34 @@ func (u *UserRecord) GetConnectTime() time.Time { return u.connectionTime } -func (u *UserRecord) GetCommandPrompt(fullRedraw bool, forcePromptType ...string) string { +func (u *UserRecord) GetCommandPrompt(fullRedraw bool) string { promptOut := `` - if len(forcePromptType) == 0 || forcePromptType[0] != `mprompt` { - if u.activePrompt != nil { + if u.activePrompt != nil { - if activeQuestion := u.activePrompt.GetNextQuestion(); activeQuestion != nil { - promptOut = activeQuestion.String() - } + if activeQuestion := u.activePrompt.GetNextQuestion(); activeQuestion != nil { + promptOut = activeQuestion.String() } } + goAhead := `` + if connections.GetClientSettings(u.ConnectionId()).SendTelnetGoAhead { + goAhead = term.TelnetGoAhead.String() + } + if len(promptOut) == 0 { var customPrompt any = nil var inCombat bool = u.Character.Aggro != nil - if len(forcePromptType) > 0 { - customPrompt = u.GetConfigOption(forcePromptType[0] + `-compiled`) - } else { - - if inCombat { - customPrompt = u.GetConfigOption(`fprompt-compiled`) - } + if inCombat { + customPrompt = u.GetConfigOption(`fprompt-compiled`) + } - // No other custom prompts? try the default setting - if customPrompt == nil { - customPrompt = u.GetConfigOption(`prompt-compiled`) - } + // No other custom prompts? try the default setting + if customPrompt == nil { + customPrompt = u.GetConfigOption(`prompt-compiled`) } var ok bool @@ -339,10 +337,10 @@ func (u *UserRecord) GetCommandPrompt(fullRedraw bool, forcePromptType ...string if len(suggested) > 0 { suggested = `` + suggested + `` } - return term.AnsiMoveCursorColumn.String() + term.AnsiEraseLine.String() + promptOut + unsent + suggested + return term.AnsiMoveCursorColumn.String() + term.AnsiEraseLine.String() + promptOut + unsent + suggested + goAhead } - return promptOut + return promptOut + goAhead } func (u *UserRecord) ProcessPromptString(promptStr string) string { diff --git a/main.go b/main.go index 92313d35..062e9e20 100644 --- a/main.go +++ b/main.go @@ -297,6 +297,11 @@ func handleTelnetConnection(connDetails *connections.ConnectionDetails, wg *sync connDetails.ConnectionId(), ) + connections.SendTo( + term.TelnetSuppressGoAhead.BytesWithPayload(nil), + connDetails.ConnectionId(), + ) + clientSetupCommands := "" + //term.AnsiAltModeStart.String() + // alternative mode (No scrollback) //term.AnsiCursorHide.String() + // Hide Cursor (Because we will manually echo back) //term.AnsiCharSetUTF8.String() + // UTF8 mode