예제 #1
0
        /// <summary>
        /// Initializes a new instance of a <see cref="TerminalEmulator"/> using the specified font to display text.
        /// </summary>
        public TerminalEmulator()
        {
            var options = new TerminalOptions();

            options.LFlag = PtyConstants.ICANON | PtyConstants.ECHO;
            options.C_cc[PtyConstants.VERASE] = (byte)'\b';
            options.C_cc[PtyConstants.VEOL]   = (byte)'\r';
            options.C_cc[PtyConstants.VEOL2]  = (byte)'\n';

            PseudoTerminal.CreatePair(out _master, out _slave, options);

            _stdout           = new StreamWriter(_master);
            _stdin            = new StreamReader(_master);
            _stdout.AutoFlush = true;


            HasFocusedChanged += (o, a) =>
            {
                if (IsFocused)
                {
                    _cursorOn   = true;
                    _cursorAnim = 0;
                    Invalidate(true);
                }
            };
        }
예제 #2
0
 private async void OnTerminalOptionsChanged(object sender, TerminalOptions e)
 {
     await _applicationView.RunOnDispatcherThread(() =>
     {
         BackgroundOpacity = e.BackgroundOpacity;
     });
 }
예제 #3
0
 private async void OnTerminalOptionsChanged(object sender, TerminalOptions e)
 {
     await _dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
     {
         BackgroundOpacity = e.BackgroundOpacity;
     });
 }
예제 #4
0
        public static async Task Main(string[] Arguments)
        {
            Splash();

            Stage = Environment.GetEnvironmentVariable("SecureDNS_Enviroment") ?? "Production";

            ApplicationData = Stage == "Production" ? Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "Texnomic", "SecureDNS - Terminal Edition") : Environment.CurrentDirectory;

            Directory.CreateDirectory(ApplicationData);

            if (!File.Exists(Path.Combine(ApplicationData, AppSettingsFile)))
            {
                await File.WriteAllBytesAsync(Path.Combine(ApplicationData, AppSettingsFile), ReadResource(AppSettingsFile));

                await File.WriteAllBytesAsync(Path.Combine(ApplicationData, "AppSettings.Production.json"), ReadResource("AppSettings.Production.json"));

                await File.WriteAllBytesAsync(Path.Combine(ApplicationData, "AppSettings.Development.json"), ReadResource("AppSettings.Development.json"));
            }

            Configurations = new ConfigurationBuilder()
                             .SetBasePath(ApplicationData)
                             .AddJsonFile(AppSettingsFile, false, true)
                             .AddJsonFile($"AppSettings.{Stage}.json", true, true)
                             .AddUserSecrets <Program>(true, true)
                             .AddEnvironmentVariables()
                             .Build();


            Options = Configurations.GetSection("Terminal Options").Get <TerminalOptions>();

            BuildHost();

            await HostBuilder.RunConsoleAsync();
        }
예제 #5
0
        public override OutputBuilder Render(TerminalOptions terminalOptions)
        {
            var topics = HelpManager.Instance.GetHelpTopics().Where(topic => topic.Aliases.Count > 0);

            var output = new OutputBuilder();

            if (!topics.Any())
            {
                output.AppendLine("There are no help topics written yet.");
                return(output);
            }

            // Format the first column to the number of characters to fit the longest topic, then have the description to the right of that.
            var lineFormat = "{0," + -1 * HelpManager.Instance.MaxPrimaryAliasLength + "} {1}";

            output.AppendLine("Available help topics:");
            output.AppendSeparator(color: "yellow");
            foreach (var topic in topics)
            {
                var primaryAlias = topic.Aliases.FirstOrDefault();
                output.AppendLine(string.Format(lineFormat, primaryAlias, "TODO: Topic Short Description Support Here"));
            }
            output.AppendSeparator(color: "yellow");

            output.AppendLine();
            output.AppendLine("<%yellow%>NOTE:<%n%> You can also use the \"<%green%>commands<%n%>\" command to list out commands, and you can get help for a specific command with \"<%green%>help <command name><%n%>\".");
            return(output);
        }
예제 #6
0
        protected void Dispose(bool disposing)
        {
            if (_debug > 0)
            {
                Console.WriteLine("TelnetSSH-Dispose-End");
            }

            if (!this.disposed)
            {
                if (disposing)
                {
                    _isRunning = false;
                    this.close();
                    if (_Console != null)
                    {
                        _Console = null;
                    }
                    if (_terminalOptions != null)
                    {
                        _terminalOptions = null;
                    }
                    if (_terminalSettings != null)
                    {
                        _terminalSettings = null;
                    }
                }

                //free unmanaged objects
                //AdditionalCleanup();

                this.disposed = true;
            }
        }
예제 #7
0
        public TerminalViewModel(ISettingsService settingsService, ITrayProcessCommunicationService trayProcessCommunicationService, IDialogService dialogService,
                                 IKeyboardCommandService keyboardCommandService, ApplicationSettings applicationSettings, ShellProfile shellProfile,
                                 IApplicationView applicationView, IClipboardService clipboardService, string terminalState = null)
        {
            MessengerInstance.Register <ApplicationSettingsChangedMessage>(this, OnApplicationSettingsChanged);
            MessengerInstance.Register <CurrentThemeChangedMessage>(this, OnCurrentThemeChanged);
            MessengerInstance.Register <TerminalOptionsChangedMessage>(this, OnTerminalOptionsChanged);
            MessengerInstance.Register <KeyBindingsChangedMessage>(this, OnKeyBindingsChanged);

            SettingsService = settingsService;

            _terminalOptions = SettingsService.GetTerminalOptions();

            TrayProcessCommunicationService = trayProcessCommunicationService;

            DialogService           = dialogService;
            _keyboardCommandService = keyboardCommandService;
            ApplicationSettings     = applicationSettings;
            ApplicationView         = applicationView;
            ClipboardService        = clipboardService;

            ShellProfile  = shellProfile;
            TerminalTheme = shellProfile.TerminalThemeId == Guid.Empty ? SettingsService.GetCurrentTheme() : SettingsService.GetTheme(shellProfile.TerminalThemeId);

            TabThemes               = new ObservableCollection <TabThemeViewModel>(SettingsService.GetTabThemes().Select(theme => new TabThemeViewModel(theme, this)));
            CloseCommand            = new AsyncCommand(TryCloseAsync, CanExecuteCommand);
            CloseLeftTabsCommand    = new RelayCommand(CloseLeftTabs, CanExecuteCommand);
            CloseRightTabsCommand   = new RelayCommand(CloseRightTabs, CanExecuteCommand);
            CloseOtherTabsCommand   = new RelayCommand(CloseOtherTabs, CanExecuteCommand);
            FindNextCommand         = new RelayCommand(FindNext, CanExecuteCommand);
            FindPreviousCommand     = new RelayCommand(FindPrevious, CanExecuteCommand);
            CloseSearchPanelCommand = new RelayCommand(CloseSearchPanel, CanExecuteCommand);
            EditTitleCommand        = new AsyncCommand(EditTitleAsync, CanExecuteCommand);
            DuplicateTabCommand     = new RelayCommand(DuplicateTab, CanExecuteCommand);
            CopyCommand             = new AsyncCommand(Copy, () => HasSelection);
            PasteCommand            = new AsyncCommand(Paste);
            CopyLinkCommand         = new AsyncCommand(() => CopyTextAsync(HoveredUri), () => !string.IsNullOrWhiteSpace(HoveredUri));
            ShowSearchPanelCommand  = new RelayCommand(() => ShowSearchPanel = true, () => !ShowSearchPanel);

            if (!string.IsNullOrEmpty(terminalState))
            {
                Restore(terminalState);
            }
            else
            {
                var defaultTabTheme = TabThemes.FirstOrDefault(t => t.Theme.Id == ShellProfile.TabThemeId);
                defaultTabTheme.IsSelected = true;
            }

            Terminal = new Terminal(TrayProcessCommunicationService, _terminalId);
            Terminal.KeyboardCommandReceived += Terminal_KeyboardCommandReceived;
            Terminal.OutputReceived          += Terminal_OutputReceived;
            Terminal.SizeChanged             += Terminal_SizeChanged;
            Terminal.TitleChanged            += Terminal_TitleChanged;
            Terminal.Exited += Terminal_Exited;
            Terminal.Closed += Terminal_Closed;

            ContextMenu    = BuidContextMenu();
            TabContextMenu = BuildTabContextMenu();
        }
예제 #8
0
        /// <summary>Builds the prompt string for this player.</summary>
        /// <returns>The formatted prompt for this player.</returns>
        public override OutputBuilder BuildPrompt(TerminalOptions terminalOptions)
        {
            return(new OutputBuilder(5).Append("WRM> "));

            /* TODO: Allow for player-customized prompts...
             * // Returns a string with the %tokens% replaced with appropriate values
             * string prompt = Prompt;
             *
             * if (prompt != null && prompt.Contains("%"))  // Quick check, we can skip parsing if we have no chance of tokens
             * {
             *  // TODO: This routine needs optimization
             *  // Find all PlayerPromptables and replace their tokens with values if they exist in the supplied prompt string
             *  foreach (MethodInfo m in GetType().GetMethods())
             *  {
             *      object[] promptAttrs = m.GetCustomAttributes(typeof(PlayerPromptableAttribute), false);
             *      if (promptAttrs.Length > 0 &&
             *          prompt.IndexOf(((PlayerPromptableAttribute)promptAttrs[0]).Token) >= 0)
             *      {
             *          var promptAttr = (PlayerPromptableAttribute)promptAttrs[0];
             *          prompt = prompt.Replace(promptAttr.Token, (string)m.Invoke(this, new object[] { }));
             *      }
             *  }
             * }
             *
             * return prompt;
             */
        }
예제 #9
0
        public override OutputBuilder Render(TerminalOptions terminalOptions, HelpTopic helpTopic)
        {
            var output = new OutputBuilder();

            // TODO: What was this !element doing? Does it still work? Test with zMUD or something and re-read MXP specs?
            if (terminalOptions.UseMXP)
            {
                output.AppendLine($"{AnsiSequences.MxpSecureLine}<!element see '<send href=\"help &cref;\">' att='cref' open>");
            }

            output.AppendSeparator(color: "yellow", design: '=');
            output.AppendLine($"HELP TOPIC: {helpTopic.Aliases.First()}");
            output.AppendSeparator(color: "yellow");

            if (terminalOptions.UseMXP)
            {
                var lines = helpTopic.Contents.Split(new string[] { AnsiSequences.NewLine }, StringSplitOptions.None);
                foreach (var line in lines)
                {
                    output.AppendLine($"{AnsiSequences.MxpOpenLine}{line}<%n%>");
                }
            }
            else
            {
                output.AppendLine($"{helpTopic.Contents}");
            }

            output.AppendSeparator(color: "yellow", design: '=');
            return(output);
        }
예제 #10
0
        public override OutputBuilder Render(TerminalOptions terminalOptions, Thing viewer, Thing viewedThing)
        {
            var senses = viewer.FindBehavior <SensesBehavior>();

            return(new OutputBuilder().AppendLine(senses.CanPerceiveThing(viewedThing) ?
                                                  $"You examine <%cyan%><%b%>{viewedThing.Name}<%n%>:<%nl%>{viewedThing.Description}" :
                                                  "You cannot perceive that thing."));
        }
예제 #11
0
        public string CreateTerminal(TerminalOptions options)
        {
            var terminal = new Terminal(options);

            terminal.ConnectionClosed += OnTerminalConnectionClosed;
            _terminals.Add(terminal.Id, terminal);
            return(terminal.WebSocketUrl);
        }
예제 #12
0
 public TelnetSSHLogin()
 {
     _instance         = this;
     _isRunning        = true;
     _Console          = new ConsoleMain();
     _terminalOptions  = new TerminalOptions("");
     _terminalSettings = new TerminalSettings();
     _timeout          = _Console.ProtocolOptions.SocketConnectTimeout / 1000;
 }
예제 #13
0
 public TerminalSession(ITerminalConnection connection, ITerminalSettings terminalSettings, TerminalOptions terminalOptions)
 {
     _terminalSettings = terminalSettings;
     _terminalOptions  = terminalOptions;
     //VT100Žw’è‚Å‚àxtermƒV[ƒPƒ“ƒX‚ð‘—‚Á‚Ä‚­‚éƒAƒvƒŠƒP[ƒVƒ‡ƒ“‚ªŒã‚ð‚½‚½‚È‚¢‚Ì‚Å
     _terminal  = AbstractTerminal.Create(new TerminalInitializeInfo(this, connection.Destination));
     _output    = new TerminalTransmission(_terminal, _terminalSettings, connection);
     _keepAlive = new KeepAlive(this);
 }
예제 #14
0
 public override OutputBuilder Render(TerminalOptions terminalOptions, Thing player)
 {
     // WheelMUD Core does not have any knowledge of game-specific stats and so on (if even applicable), so
     // by default, the prompt always prints quite simply. Games should generally export their own prompt
     // renderer with a higher priority, and do something smarter here. The Core PlayerBehavior has a Prompt
     // property which can be used to store player-customized prompt templates, and your Prompt renderer can
     // (for example) transform their custom prompt template into their final prompt output.
     return(new OutputBuilder(2).Append("> "));
 }
예제 #15
0
        private async Task <TerminalSize> CreateXtermView(TerminalOptions options, TerminalColors theme, IEnumerable <KeyBinding> keyBindings)
        {
            var serializedOptions     = JsonConvert.SerializeObject(options);
            var serializedTheme       = JsonConvert.SerializeObject(theme);
            var serializedKeyBindings = JsonConvert.SerializeObject(keyBindings);
            var size = await ExecuteScriptAsync($"createTerminal('{serializedOptions}', '{serializedTheme}', '{serializedKeyBindings}')").ConfigureAwait(true);

            return(JsonConvert.DeserializeObject <TerminalSize>(size));
        }
예제 #16
0
        public Task ChangeOptionsAsync(TerminalOptions options)
        {
            if (_terminalClosed)
            {
                return(Task.CompletedTask);
            }

            return(_optionsChanged.InvokeAsync(options));
        }
예제 #17
0
        private Task <TerminalSize> CreateXtermViewAsync(TerminalOptions options, TerminalColors theme, IEnumerable <KeyBinding> keyBindings)
        {
            var serializedOptions     = JsonConvert.SerializeObject(options);
            var serializedTheme       = JsonConvert.SerializeObject(theme);
            var serializedKeyBindings = JsonConvert.SerializeObject(keyBindings);

            return(ExecuteScriptAsync(
                       $"createTerminal('{serializedOptions}', '{serializedTheme}', '{serializedKeyBindings}')")
                   .ContinueWith(t => JsonConvert.DeserializeObject <TerminalSize>(t.Result)));
        }
        public override OutputBuilder Render(TerminalOptions terminalOptions, IEnumerable <Command> commands, string categoryName)
        {
            var output = new OutputBuilder().AppendLine($"<%yellow%>{categoryName} commands<%n%>:");

            foreach (var command in commands)
            {
                // NEED AN ALTERNATE NON-MXP VERSION, AND NEED SECURE LINE API TO BE THE ONLY WAY TO SEND SECURE LINES - Name to make very clear it cannot contain user-generated content? "AppendTrustedSecureLine" with extra comments?
                output.AppendLine($"{AnsiSequences.MxpSecureLine}<send \"help {command.Name}\">{command.Name.PadRight(15)}</send> {command.Description}");
            }
            return(output);
        }
예제 #19
0
            /// <inheritdoc/>
            public ServerResponseType HandleMessage(Backend backend, ServerMessageType message, string session, BinaryReader datareader, BinaryWriter datawriter)
            {
                PseudoTerminal _master = null;
                PseudoTerminal _slave  = null;

                var options = new TerminalOptions();

                options.LFlag = PtyConstants.ICANON;
                options.C_cc[PtyConstants.VERASE] = (byte)'\b';
                options.C_cc[PtyConstants.VEOL]   = (byte)'\r';
                options.C_cc[PtyConstants.VEOL2]  = (byte)'\n';

                PseudoTerminal.CreatePair(out _master, out _slave, options);



                int slaveRemoteId = _remoteStreams.Create(_slave, session);


                var stdout = new StreamWriter(new BroadcastingStream(backend, session));

                stdout.AutoFlush = true;
                var stdin = new StreamReader(_master);

                string commandname = datareader.ReadString();
                int    argCount    = datareader.ReadInt32();

                string[] argv = new string[argCount];
                for (int i = 0; i < argCount; i++)
                {
                    argv[i] = datareader.ReadString();
                }

                var trmmgr = backend.GetBackendComponent <TerminalManager>();

                Task.Run(() =>
                {
                    try
                    {
                        trmmgr.RunCommand(backend, commandname, argv, session, stdin, stdout);
                    }
                    catch (TerminationRequestException)
                    {
                        Logger.Log("Terminated command.");
                    }
                    finally
                    {
                        stdout.Write((char)0x02);
                    }
                });
                datawriter.Write(slaveRemoteId);

                return(ServerResponseType.REQ_SUCCESS);
            }
예제 #20
0
        public override OutputBuilder Render(TerminalOptions terminalOptions, Thing player)
        {
            // Pretty basic placeholder. Most game systems will probably want to define their own stats systems
            // and races and attributes and so on, and provide a more traditional "score" breakdown of the
            // current character state as pertains to the actual game system.
            var livingBehavior = player.FindBehavior <LivingBehavior>();
            var output         = new OutputBuilder();

            output.AppendLine($"{player.Name}. You are {livingBehavior.Consciousness}");
            return(output);
        }
예제 #21
0
        public string Post()
        {
            var cols    = int.Parse(this.Request.GetQueryNameValuePairs().SingleOrDefault(q => q.Key == "cols").Value);
            var rows    = int.Parse(this.Request.GetQueryNameValuePairs().SingleOrDefault(q => q.Key == "rows").Value);
            var options = new TerminalOptions
            {
                Columns = cols,
                Rows    = rows
            };

            return(_terminalsManager.CreateTerminal(options));
        }
예제 #22
0
        public TerminalViewModel(ISettingsService settingsService, ITrayProcessCommunicationService trayProcessCommunicationService, IDialogService dialogService,
                                 IKeyboardCommandService keyboardCommandService, ApplicationSettings applicationSettings, ShellProfile shellProfile,
                                 IApplicationView applicationView, IDispatcherTimer dispatcherTimer, IClipboardService clipboardService, string terminalState = null)
        {
            SettingsService = settingsService;
            SettingsService.CurrentThemeChanged        += OnCurrentThemeChanged;
            SettingsService.TerminalOptionsChanged     += OnTerminalOptionsChanged;
            SettingsService.ApplicationSettingsChanged += OnApplicationSettingsChanged;
            SettingsService.KeyBindingsChanged         += OnKeyBindingsChanged;

            _terminalOptions = SettingsService.GetTerminalOptions();

            TrayProcessCommunicationService = trayProcessCommunicationService;

            DialogService           = dialogService;
            _keyboardCommandService = keyboardCommandService;
            ApplicationSettings     = applicationSettings;
            ApplicationView         = applicationView;
            ClipboardService        = clipboardService;

            ShellProfile  = shellProfile;
            TerminalTheme = shellProfile.TerminalThemeId == Guid.Empty ? SettingsService.GetCurrentTheme() : SettingsService.GetTheme(shellProfile.TerminalThemeId);

            TabThemes = new ObservableCollection <TabTheme>(SettingsService.GetTabThemes());
            TabTheme  = TabThemes.FirstOrDefault(t => t.Id == ShellProfile.TabThemeId);

            CloseCommand            = new RelayCommand(async() => await TryClose().ConfigureAwait(false));
            CloseLeftTabsCommand    = new RelayCommand(CloseLeftTabs);
            CloseRightTabsCommand   = new RelayCommand(CloseRightTabs);
            CloseOtherTabsCommand   = new RelayCommand(CloseOtherTabs);
            FindNextCommand         = new RelayCommand(FindNext);
            FindPreviousCommand     = new RelayCommand(FindPrevious);
            CloseSearchPanelCommand = new RelayCommand(CloseSearchPanel);
            SelectTabThemeCommand   = new RelayCommand <string>(SelectTabTheme);
            EditTitleCommand        = new AsyncCommand(EditTitle);
            DuplicateTabCommand     = new RelayCommand(DuplicateTab);

            if (!String.IsNullOrEmpty(terminalState))
            {
                Restore(terminalState);
            }

            Terminal = new Terminal(TrayProcessCommunicationService, _terminalId);
            Terminal.KeyboardCommandReceived += Terminal_KeyboardCommandReceived;
            Terminal.OutputReceived          += Terminal_OutputReceived;
            Terminal.SizeChanged             += Terminal_SizeChanged;
            Terminal.TitleChanged            += Terminal_TitleChanged;
            Terminal.Exited += Terminal_Exited;
            Terminal.Closed += Terminal_Closed;

            Overlay = new OverlayViewModel(dispatcherTimer);
        }
예제 #23
0
        public TerminalViewModel(ISettingsService settingsService, ITrayProcessCommunicationService trayProcessCommunicationService, IDialogService dialogService,
                                 IKeyboardCommandService keyboardCommandService, ApplicationSettings applicationSettings, ShellProfile shellProfile,
                                 IApplicationView applicationView, IClipboardService clipboardService, string terminalState = null)
        {
            MessengerInstance.Register <ApplicationSettingsChangedMessage>(this, OnApplicationSettingsChanged);
            MessengerInstance.Register <CurrentThemeChangedMessage>(this, OnCurrentThemeChanged);
            MessengerInstance.Register <TerminalOptionsChangedMessage>(this, OnTerminalOptionsChanged);

            SettingsService = settingsService;

            _terminalOptions = SettingsService.GetTerminalOptions();

            TrayProcessCommunicationService = trayProcessCommunicationService;

            DialogService           = dialogService;
            _keyboardCommandService = keyboardCommandService;
            ApplicationSettings     = applicationSettings;
            ApplicationView         = applicationView;
            ClipboardService        = clipboardService;

            ShellProfile  = shellProfile;
            TerminalTheme = shellProfile.TerminalThemeId == Guid.Empty ? SettingsService.GetCurrentTheme() : SettingsService.GetTheme(shellProfile.TerminalThemeId);

            TabThemes = new ObservableCollection <TabTheme>(SettingsService.GetTabThemes());
            TabTheme  = TabThemes.FirstOrDefault(t => t.Id == ShellProfile.TabThemeId);

            CloseCommand            = new AsyncCommand(CloseTab, CanExecuteCommand);
            CloseLeftTabsCommand    = new RelayCommand(CloseLeftTabs, CanExecuteCommand);
            CloseRightTabsCommand   = new RelayCommand(CloseRightTabs, CanExecuteCommand);
            CloseOtherTabsCommand   = new RelayCommand(CloseOtherTabs, CanExecuteCommand);
            FindNextCommand         = new RelayCommand(FindNext, CanExecuteCommand);
            FindPreviousCommand     = new RelayCommand(FindPrevious, CanExecuteCommand);
            CloseSearchPanelCommand = new RelayCommand(CloseSearchPanel, CanExecuteCommand);
            SelectTabThemeCommand   = new RelayCommand <string>(SelectTabTheme, CanExecuteCommand);
            EditTitleCommand        = new AsyncCommand(EditTitle, CanExecuteCommand);
            DuplicateTabCommand     = new RelayCommand(DuplicateTab, CanExecuteCommand);

            if (!String.IsNullOrEmpty(terminalState))
            {
                Restore(terminalState);
            }

            Terminal = new Terminal(TrayProcessCommunicationService, _terminalId);
            Terminal.KeyboardCommandReceived += Terminal_KeyboardCommandReceived;
            Terminal.OutputReceived          += Terminal_OutputReceived;
            Terminal.SizeChanged             += Terminal_SizeChanged;
            Terminal.TitleChanged            += Terminal_TitleChanged;
            Terminal.Exited += Terminal_Exited;
            Terminal.Closed += Terminal_Closed;
        }
예제 #24
0
        public override OutputBuilder Render(TerminalOptions terminalOptions, Thing viewer, Thing room)
        {
            var senses = viewer.FindBehavior <SensesBehavior>();
            var output = new OutputBuilder();

            if (senses.CanPerceiveThing(room))
            {
                output.AppendLine($"<%red%><%b%>{room.Name}<%n%>");
                output.AppendLine(room.Description);
            }
            else
            {
                output.AppendLine("You cannot perceive much of note about the room.");
            }

            // TODO: Perhaps group things in the room by things you can pick up, things that are alive, etc?
            //   var entities = senses.PerceiveEntities();  and also render players nicely; "(AFK)" etc?
            //   var items = senses.PerceiveItems();        and also track tick or build sense-specific strings (like hearing only while blind...)

            // Handle exits differently from other Thing types
            // TODO: Also render closable exits like doors nicely; "(closed)"?
            // TODO: For viewer that is PlayerBehavior with negotiated MXP connection, render with embedded command links for click-to-execute support?
            var outputExits = from exit in senses.PerceiveExits() select $"<%magenta%>{exit}<%n%>";

            // TODO: Color the parts of the thing names which are also legit keywords for the thing...
            // TODO: For viewer that is PlayerBehavior with negotiated MXP connection, render with embedded command links for click-to-execute support?
            var outputThings = from thing in room.Children
                               where senses.CanPerceiveThing(thing) && thing != viewer && !thing.HasBehavior <ExitBehavior>()
                               select $"  {thing.FullName}<%n%>";

            if (outputExits.Any() || outputThings.Any())
            {
                output.AppendLine("<%yellow%>Here you notice:<%n%>");
                if (outputExits.Any())
                {
                    output.AppendLine($"  Routes: {string.Join(", ", outputExits)}");
                }
                foreach (var outputThing in outputThings)
                {
                    output.AppendLine(outputThing);
                }
            }
            else
            {
                output.AppendLine("<%yellow%>You notice nothing else inside the room.<%n%>");
            }

            return(output);
        }
예제 #25
0
        public override OutputBuilder Render(TerminalOptions terminalOptions, Thing activePlayer)
        {
            string mudNameLine = "                                "; // TODO: Dynamic centering instead, if we want centering!
            string plural      = string.Empty;
            var    output      = new OutputBuilder();

            string plural1 = "is";

            // TODO: Should query for players who can be known about by this player (e.g. omit wiz-inviz players, if any?)
            if (PlayerManager.Instance.Players.Count > 1)
            {
                plural  = "s";
                plural1 = "are";
            }

            // TODO: A game-system specific renderer could be used to includ race/class info and so on, if desired.
            // TODO: Dividing lines could be influenced by activePlayer connection Terminal.Width.
            mudNameLine += GameConfiguration.Name;
            output.AppendLine();
            output.AppendSeparator();
            output.AppendLine(mudNameLine);
            output.AppendSeparator();
            output.AppendLine();
            output.AppendLine($"The following player{plural} {plural1} currently online:");
            foreach (PlayerBehavior player in PlayerManager.Instance.Players)
            {
                var playerName  = player.Parent.Name;
                var playerState = GetPlayerState(player);
                if (terminalOptions.UseMXP)
                {
                    // TODO: "tell {0}" is not a good menu command; possibly friend add/remove, invite to group, hailing, and so on.
                    // TODO: #107: Fix handling of MXP Secure Lines...  (This wasn't being built in a safe way, and does not render correctly now.)
                    output.AppendLine($"<%mxpsecureline%><send \"finger {playerName}|tell {playerName}\" \"|finger|tell\">{playerName}</send> - {player.Parent.FullName} {playerState}");
                }
                else
                {
                    output.AppendLine($"{playerName} - {player.Parent.FullName} {playerState}");
                }
            }

            output.AppendLine();
            output.AppendSeparator();
            output.AppendLine($"Counted {PlayerManager.Instance.Players.Count} player{plural} online.");
            output.AppendLine();
            output.AppendSeparator();
            return(output);
        }
예제 #26
0
        public override OutputBuilder Render(TerminalOptions terminalOptions, Command command)
        {
            var output = new OutputBuilder().AppendLine($"<%yellow%>{command.Name.ToUpper()}<%n%>:");

            if (!string.IsNullOrWhiteSpace(command.Description))
            {
                output.AppendLine(command.Description);
            }
            // TODO: Add command.Usage?  Rename Example to "Examples" as string[]?
            if (!string.IsNullOrWhiteSpace(command.Example))
            {
                output.AppendLine("<%yellow%>USAGE<%n%>:");
                output.AppendLine(command.Example);
            }
            // TODO: Add command.SeeAlso as string[]?
            return(output);
        }
예제 #27
0
        public override OutputBuilder Render(TerminalOptions terminalOptions, Thing player)
        {
            var stats       = player.Stats;
            var statEffects = player.Behaviors.OfType <StatEffect>();
            var output      = new OutputBuilder();

            var health       = stats["HP"];
            var healthMod    = statEffects.Where(e => e.Stat.Abbreviation == "HP").Sum(e => e.ValueMod);
            var mana         = stats["MANA"];
            var damage       = stats["DAMAGE"];
            var init         = stats["INIT"];
            var attack       = stats["ATK"];
            var defense      = stats["DEF"];
            var armorPenalty = stats["ARMORPENALTY"];
            var wieldMax     = stats["WEAPONWIELDMAX"];
            var hunt         = stats["HUNT"];
            var familiar     = stats["FAMILIAR"];
            var fate         = stats["FATE"];

            var healthLine       = $"{health.Name,-13} {health.Value,5:####0}/{health.MaxValue,-5:####0} ({healthMod})".PadRight(31);
            var manaLine         = $"{mana.Name,-12} {mana.Value,5:####0}/{mana.MaxValue,-5:####0}".PadRight(31);
            var damageLine       = $"{damage.Name,-13} {damage.Value,5:##0}/{damage.MaxValue,-5:##0}".PadRight(31);
            var initLine         = $"{init.Name,-16} {init.Value,-6}".PadRight(31);
            var attackLine       = $"{attack.Name,-15} {attack.Value,3:##0}/{attack.MaxValue,-3:##0}".PadRight(31);
            var defenseLine      = $"{defense.Name,-14} {defense.Value,3:##0}/{defense.MaxValue,-3:##0}".PadRight(31);
            var armorPenaltyLine = $"{armorPenalty.Name,-16} {armorPenalty.Value,2}".PadRight(31);
            var wieldMaxLine     = $"{wieldMax.Name,-16} {wieldMax.Value,1}/{wieldMax.MaxValue,-1}".PadRight(31);
            var huntLine         = $"{hunt.Name,-16} {hunt.Value,2}({hunt.MaxValue,2})".PadRight(31);
            var familiarLine     = $"{familiar.Name,-16} {familiar.Value,1:0}{familiar.MaxValue,-1:(0)}".PadRight(31);
            var fateLine         = $"{fate.Name,-16} {fate.Value,2}({fate.MaxValue,2})".PadRight(31);
            var nameAndTitle     = string.IsNullOrWhiteSpace(player.Title) ? player.Name : $"{player.Name}, {player.Title}";
            var pipe             = "<%green%>|<%n%>";

            output.AppendLine("<%green%>+-------------------------------------------------------------------+");
            output.AppendLine($"{pipe} {nameAndTitle,-19} Level {"?",-6}  Reputation {"?",-6}  Kudos {"?",-6} {pipe}");
            output.AppendLine("<%green%>+----------------+----------------+----------------+----------------+");
            output.AppendLine($"{pipe} {healthLine} {pipe} {manaLine} {pipe}");
            output.AppendLine($"{pipe} {damageLine} {pipe} {initLine} {pipe}");
            output.AppendLine($"{pipe} {attackLine} {pipe} {defenseLine} {pipe}");
            output.AppendLine($"{pipe} {armorPenaltyLine} {pipe} {wieldMaxLine} {pipe}");
            output.AppendLine($"{pipe} {huntLine} {pipe} {familiarLine} {pipe}");
            output.AppendLine($"{pipe} {fateLine} {pipe} {string.Empty.PadRight(31)} {pipe}");
            output.AppendLine("<%green%>+---------------------------------^---------------------------------+<%n%>");

            return(output);
        }
예제 #28
0
        public override OutputBuilder Render(TerminalOptions terminalOptions, Thing player)
        {
            var senses = player.FindBehavior <SensesBehavior>();
            var output = new OutputBuilder();

            var invThings = player.Children.Where(presentThing => senses.CanPerceiveThing(presentThing)).ToArray();

            output.AppendLine(invThings.Length > 0
                ? "<%yellow%>Searching your inventory, you find:<%n%>"
                : "<%yellow%>You found no inventory.<%n%>");

            foreach (var presentThing in invThings)
            {
                output.AppendLine($"  <%magenta%>{presentThing.FullName}<%n%>");
            }

            return(output);
        }
예제 #29
0
        public void DoesNotCrashWhenReflowingToTinyWidth()
        {
            var options = new TerminalOptions()
            {
                Cols = 10, Rows = 10
            };

            options.Scrollback = 1;
            var terminal = new Terminal(null, options);

            terminal.Feed("1234567890\r\n");
            terminal.Feed("ABCDEFGH\r\n");
            terminal.Feed("abcdefghijklmnopqrstxxx\r\n");
            terminal.Feed("\r\n");

            // if we resize to a small column width, content is pushed back up and out the top
            // of the buffer. Ensure that this does not crash
            terminal.Resize(3, 10);
        }
예제 #30
0
        public override OutputBuilder Render(TerminalOptions terminalOptions, IEnumerable <Command> commands)
        {
            // Build a list of categories for the commands available to this player.
            var output = new OutputBuilder().AppendLine("Please specify a command category:");

            foreach (CommandCategory category in Enum.GetValues(typeof(CommandCategory)))
            {
                if (category == CommandCategory.None)
                {
                    continue;
                }
                var matchingcommands = commands.Where(command => command.Category.HasFlag(category));
                if (matchingcommands.Any())
                {
                    // THIS DOESN'T WORK ANYMORE - NEED TO USE SECURE LINE API AND HAVE SEPARATE OUTPUT FOR NON-MXP CLIENTS!
                    output.AppendLine($"<%mxpsecureline%><send \"commands {category}\">{category}</send> ({matchingcommands.Count()})");
                }
            }

            return(output);
        }