2017-01-08 10:17:07 -05:00
/ *
* MIT License
*
* Copyright ( c ) 2017 Michael VanOverbeek and ShiftOS devs
*
* Permission is hereby granted , free of charge , to any person obtaining a copy
* of this software and associated documentation files ( the "Software" ) , to deal
* in the Software without restriction , including without limitation the rights
* to use , copy , modify , merge , publish , distribute , sublicense , and / or sell
* copies of the Software , and to permit persons to whom the Software is
* furnished to do so , subject to the following conditions :
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software .
*
* THE SOFTWARE IS PROVIDED "AS IS" , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
* IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
* LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING FROM ,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE .
* /
using System ;
2017-01-08 09:57:10 -05:00
using System.Collections.Generic ;
2017-05-24 16:41:49 -04:00
using System.Diagnostics ;
2017-01-08 09:57:10 -05:00
using System.Linq ;
using System.Reflection ;
using System.Text ;
using System.Text.RegularExpressions ;
using System.Threading.Tasks ;
using Newtonsoft.Json ;
using static ShiftOS . Engine . SaveSystem ;
2017-04-30 20:28:31 -04:00
namespace ShiftOS.Engine
{
2017-05-20 15:58:04 -04:00
/// <summary>
/// Backend for the ShiftOS terminal.
/// </summary>
2017-04-30 20:28:31 -04:00
public static class TerminalBackend
{
2017-05-20 15:58:04 -04:00
/// <summary>
/// Occurs when a command is processed.
/// </summary>
2017-01-18 10:01:37 -05:00
public static event Action < string , string > CommandProcessed ;
2017-05-20 15:58:04 -04:00
/// <summary>
/// Gets or sets whether the current command is elevated.
/// </summary>
2017-01-08 09:57:10 -05:00
public static bool Elevated { get ; set ; }
2017-05-20 15:58:04 -04:00
/// <summary>
/// Parses command-line arguments using the ShiftOS syntax and stores them in a <see cref="Dictionary{string, string}"/>, removing the parsed text from the original string.
/// </summary>
/// <param name="text">The text to parse.</param>
/// <returns><see cref="Dictionary{string, string}"/> containing the parsed arguments.</returns>
2017-04-30 20:28:31 -04:00
public static Dictionary < string , string > GetArgs ( ref string text )
{
2017-01-08 09:57:10 -05:00
bool shouldParse = false ;
int argStart = 0 ;
2017-04-30 20:28:31 -04:00
if ( text . Contains ( "{" ) )
{
2017-01-08 09:57:10 -05:00
shouldParse = true ;
argStart = text . IndexOf ( '{' ) ;
}
2017-04-30 20:28:31 -04:00
if ( shouldParse = = false )
{
2017-01-08 09:57:10 -05:00
string replacement = Regex . Replace ( text , @"\t|\n|\r" , "" ) ;
text = replacement + "{}" ;
shouldParse = true ;
argStart = text . IndexOf ( '{' ) ;
}
string args = text . Substring ( argStart , text . Length - argStart ) ;
text = text . Remove ( argStart , text . Length - argStart ) . Replace ( " " , "" ) ;
2017-03-12 09:29:17 -07:00
return JsonConvert . DeserializeObject < Dictionary < string , string > > ( args ) ;
2017-01-08 09:57:10 -05:00
}
2017-05-20 15:58:04 -04:00
/// <summary>
/// String representing the last command entered by the user.
/// </summary>
2017-01-08 09:57:10 -05:00
public static string LastCommand = "" ;
2017-05-26 17:06:38 -04:00
/// <summary>
/// Gets the output of the last command.
/// </summary>
public static string LastCommandBuffer { get ; private set ; }
2017-05-20 15:58:04 -04:00
/// <summary>
/// Invokes a ShiftOS terminal command.
/// </summary>
/// <param name="ns">The command's namespace.</param>
/// <param name="command">The command name.</param>
/// <param name="arguments">The command arguments.</param>
/// <param name="isRemote">Whether the command should be sent through Remote Terminal Session (RTS).</param>
2017-04-30 20:28:31 -04:00
public static void InvokeCommand ( string ns , string command , Dictionary < string , string > arguments , bool isRemote = false )
{
try
{
2017-03-12 09:29:17 -07:00
if ( string . IsNullOrWhiteSpace ( ns ) )
return ;
bool commandWasClient = RunClient ( ns , command , arguments , isRemote ) ;
2017-04-30 20:28:31 -04:00
if ( ! commandWasClient & & ! string . IsNullOrWhiteSpace ( ns ) )
{
2017-06-02 08:15:51 -04:00
Console . WriteLine ( "Error: Command not found." ) ;
2017-03-12 09:29:17 -07:00
}
CommandProcessed ? . Invoke ( ns + "." + command , JsonConvert . SerializeObject ( arguments ) ) ;
2017-04-30 20:28:31 -04:00
}
catch ( Exception ex )
{
2017-03-12 09:29:17 -07:00
Console . WriteLine ( $"Command parse error: {ex.Message}" ) ; // This shouldn't ever be called now
PrefixEnabled = true ;
}
}
2017-05-20 15:58:04 -04:00
/// <summary>
/// Transforms a <see cref="Dictionary{String, String}"/> of arguments to a <see cref="Dictionary{String, Object}"/>.
/// </summary>
/// <param name="argss">The original argument dictionary to convert.</param>
/// <returns>The converted dictionary.</returns>
2017-04-30 20:28:31 -04:00
public static string GetSentArgs ( Dictionary < string , string > argss )
{
2017-03-12 09:29:17 -07:00
Dictionary < string , object > args = new Dictionary < string , object > ( ) ;
2017-04-30 20:28:31 -04:00
foreach ( KeyValuePair < string , string > arg in argss )
{
2017-03-12 09:29:17 -07:00
args [ arg . Key ] = arg . Value ;
}
return JsonConvert . SerializeObject ( args ) ;
}
2017-05-24 16:41:49 -04:00
public class TerminalCommand
{
public override int GetHashCode ( )
{
int hash = 0 ;
foreach ( char c in ToString ( ) )
{
hash + = ( int ) c ;
}
return hash ;
}
public Command CommandInfo { get ; set ; }
public List < string > RequiredArguments { get ; set ; }
public string Dependencies { get ; set ; }
public MethodInfo CommandHandler ;
public Type CommandType ;
public override string ToString ( )
{
StringBuilder sb = new StringBuilder ( ) ;
sb . Append ( this . CommandInfo . name ) ;
if ( this . RequiredArguments . Count > 0 )
{
2017-06-16 20:36:43 -04:00
sb . Append ( " " ) ;
2017-05-24 16:41:49 -04:00
foreach ( var arg in RequiredArguments )
{
2017-06-16 20:36:43 -04:00
sb . Append ( "--" + arg ) ;
sb . Append ( " " ) ;
2017-05-24 16:41:49 -04:00
if ( RequiredArguments . IndexOf ( arg ) < RequiredArguments . Count - 1 )
sb . Append ( ',' ) ;
}
sb . Append ( "}" ) ;
}
sb . Append ( "|" ) ;
sb . Append ( CommandHandler . Name + "()" ) ;
return sb . ToString ( ) ;
}
public bool RequiresElevation { get ; set ; }
2017-06-16 21:10:13 -04:00
public virtual void Invoke ( Dictionary < string , object > args )
2017-05-24 16:41:49 -04:00
{
List < string > errors = new List < string > ( ) ;
bool requiresAuth = false ;
if ( ! KernelWatchdog . IsSafe ( this ) )
{
if ( SaveSystem . CurrentUser . Permissions = = Objects . UserPermissions . Admin )
requiresAuth = true ;
else
errors . Add ( "You can't run this command - you do not have permission." ) ;
}
if ( errors . Count > 0 )
{
foreach ( var error in errors )
{
Console . WriteLine ( "Command error: " + error ) ;
}
return ;
}
if ( requiresAuth )
{
Infobox . PromptText ( "Enter your password." , "This command requires you to have elevated permissions. Please enter your password to confirm this action." , ( pass ) = >
{
if ( pass = = SaveSystem . CurrentUser . Password )
{
var uname = SaveSystem . CurrentUser . Username ;
SaveSystem . CurrentUser = SaveSystem . CurrentSave . Users . FirstOrDefault ( x = > x . Username = = "root" ) ;
try
{
var h = CommandHandler ;
h . Invoke ( null , new [ ] { args } ) ;
}
catch
{
var h = CommandHandler ;
h . Invoke ( null , null ) ;
}
SaveSystem . CurrentUser = SaveSystem . CurrentSave . Users . FirstOrDefault ( x = > x . Username = = uname ) ;
}
else
{
Infobox . Show ( "Access denied." , "Incorrect password provided. The command will not run." ) ;
}
} , true ) ;
}
try
{
CommandHandler . Invoke ( null , new [ ] { args } ) ;
}
catch
{
CommandHandler . Invoke ( null , null ) ;
}
}
}
2017-06-16 21:10:13 -04:00
public class WinOpenCommand : TerminalCommand
{
public Type ShiftOSWindow { get ; set ; }
public override void Invoke ( Dictionary < string , object > args )
{
AppearanceManager . SetupWindow ( ( IShiftOSWindow ) Activator . CreateInstance ( ShiftOSWindow , null ) ) ;
}
}
2017-05-24 16:41:49 -04:00
public class MemoryTextWriter : System . IO . TextWriter
{
public override Encoding Encoding
{
get
{
return Encoding . Unicode ;
}
}
private StringBuilder sb = null ;
public MemoryTextWriter ( )
{
sb = new StringBuilder ( ) ;
}
public override string ToString ( )
{
return sb . ToString ( ) ;
}
public override void Write ( char value )
{
sb . Append ( value ) ;
}
public override void WriteLine ( )
{
sb . AppendLine ( ) ;
}
public override void Write ( string value )
{
sb . Append ( value ) ;
}
public override void Close ( )
{
sb . Clear ( ) ;
sb = null ;
base . Close ( ) ;
}
public override void WriteLine ( string value )
{
sb . AppendLine ( value ) ;
}
}
public static List < TerminalCommand > Commands { get ; private set ; }
public static void PopulateTerminalCommands ( )
{
Commands = new List < TerminalCommand > ( ) ;
2017-06-16 20:36:43 -04:00
foreach ( var type in ReflectMan . Types )
2017-05-24 16:41:49 -04:00
{
2017-06-16 21:10:13 -04:00
if ( type . GetInterfaces ( ) . Contains ( typeof ( IShiftOSWindow ) ) )
{
var winopenattrib = type . GetCustomAttributes ( false ) . FirstOrDefault ( x = > x is WinOpenAttribute ) as WinOpenAttribute ;
if ( winopenattrib ! = null )
{
var winc = new WinOpenCommand ( ) ;
winc . CommandType = type ;
var rupg = type . GetCustomAttributes ( ) . FirstOrDefault ( x = > x is RequiresUpgradeAttribute ) as RequiresUpgradeAttribute ;
if ( rupg ! = null )
winc . Dependencies = rupg . Upgrade ;
winc . CommandInfo = new Engine . Command ( winopenattrib . ID , "" , "Opens the \"" + winopenattrib . ID + " program." ) ;
winc . RequiredArguments = new List < string > ( ) ;
winc . RequiresElevation = false ;
winc . ShiftOSWindow = type ;
var ambiguity = Commands . FirstOrDefault ( x = > x . CommandInfo . name = = winc . CommandInfo . name ) ;
if ( ambiguity ! = null )
throw new Exception ( "Ambiguity error. The program " + winc . CommandInfo . name + " collides with another program or terminal command with the same name. Please either change the already-existing program/command, or change this one's WinOpenAttribute value to compensate." ) ;
Commands . Add ( winc ) ;
}
}
2017-06-16 20:36:43 -04:00
foreach ( var mth in type . GetMethods ( BindingFlags . Public | BindingFlags . Static ) )
2017-05-24 16:41:49 -04:00
{
2017-06-16 20:36:43 -04:00
var cmd = mth . GetCustomAttributes ( false ) . FirstOrDefault ( x = > x is Command ) ;
if ( cmd ! = null )
2017-05-24 16:41:49 -04:00
{
2017-06-16 20:36:43 -04:00
var tc = new TerminalCommand ( ) ;
tc . RequiresElevation = ! ( type . GetCustomAttributes ( false ) . FirstOrDefault ( x = > x is KernelModeAttribute ) = = null ) ;
2017-06-11 17:34:38 +10:00
2017-06-16 20:36:43 -04:00
tc . CommandInfo = cmd as Command ;
tc . RequiresElevation = tc . RequiresElevation | | ! ( mth . GetCustomAttributes ( false ) . FirstOrDefault ( x = > x is KernelModeAttribute ) = = null ) ;
tc . RequiredArguments = new List < string > ( ) ;
foreach ( var arg in mth . GetCustomAttributes ( false ) . Where ( x = > x is RequiresArgument ) )
{
var rarg = arg as RequiresArgument ;
tc . RequiredArguments . Add ( rarg . argument ) ;
2017-05-24 16:41:49 -04:00
}
2017-06-16 20:36:43 -04:00
var rupg = mth . GetCustomAttributes ( false ) . FirstOrDefault ( x = > x is RequiresUpgradeAttribute ) as RequiresUpgradeAttribute ;
if ( rupg ! = null )
tc . Dependencies = rupg . Upgrade ;
else
tc . Dependencies = "" ;
tc . CommandType = type ;
tc . CommandHandler = mth ;
var ambiguity = Commands . FirstOrDefault ( x = > x . CommandInfo . name = = tc . CommandInfo . name ) ;
if ( ambiguity ! = null )
throw new Exception ( "Command ambiguity error. You can't have two commands with the same name: " + $"{tc} == {ambiguity}" ) ;
if ( ! Commands . Contains ( tc ) )
Commands . Add ( tc ) ;
2017-05-24 16:41:49 -04:00
}
}
2017-06-16 20:36:43 -04:00
2017-05-24 16:41:49 -04:00
}
Console . WriteLine ( "[termdb] " + Commands . Count + " commands found." ) ;
}
2017-05-20 15:58:04 -04:00
/// <summary>
/// Invokes a ShiftOS terminal command.
/// </summary>
/// <param name="text">The full command text in regular ShiftOS syntax</param>
/// <param name="isRemote">Whether the command should be sent through Remote Terminal Session (RTS).</param>
2017-04-30 20:28:31 -04:00
public static void InvokeCommand ( string text , bool isRemote = false )
{
2017-05-28 07:21:16 -04:00
if ( string . IsNullOrWhiteSpace ( text ) )
return ;
2017-05-24 17:18:28 -04:00
var tw = new MemoryTextWriter ( ) ;
Console . SetOut ( tw ) ;
2017-04-30 20:28:31 -04:00
try
{
2017-01-08 09:57:10 -05:00
var args = GetArgs ( ref text ) ;
2017-01-21 21:27:25 -05:00
bool commandWasClient = RunClient ( text , args , isRemote ) ;
2017-01-08 09:57:10 -05:00
2017-04-30 20:28:31 -04:00
if ( ! commandWasClient )
{
2017-06-02 08:15:51 -04:00
Console . WriteLine ( "Error: Command not found." ) ;
2017-01-08 09:57:10 -05:00
}
2017-03-12 09:29:17 -07:00
CommandProcessed ? . Invoke ( text , GetSentArgs ( args ) ) ;
2017-04-30 20:28:31 -04:00
}
catch ( Exception ex )
{
2017-01-08 09:57:10 -05:00
Console . WriteLine ( $"Command parse error: {ex.Message}" ) ;
PrefixEnabled = true ;
}
2017-05-24 17:18:28 -04:00
string buffer = tw . ToString ( ) ;
2017-05-26 17:06:38 -04:00
LastCommandBuffer = buffer ;
2017-05-24 17:18:28 -04:00
Console . SetOut ( new TerminalTextWriter ( ) ) ;
2017-05-26 17:06:38 -04:00
if ( ! isRemote )
Console . Write ( buffer ) ;
2017-05-24 17:18:28 -04:00
2017-01-08 09:57:10 -05:00
}
2017-05-20 15:58:04 -04:00
/// <summary>
/// Gets or sets whether the user prefix is printed after a command completes.
/// </summary>
2017-01-08 09:57:10 -05:00
public static bool PrefixEnabled { get ; set ; }
2017-05-20 15:58:04 -04:00
/// <summary>
/// Gets or sets whether the user is in a story plot, and thus, the terminal input should be disabled.
/// </summary>
2017-01-08 09:57:10 -05:00
public static bool InStory { get ; set ; }
2017-05-20 15:58:04 -04:00
/// <summary>
/// Another latest command string.
/// </summary>
2017-01-08 09:57:10 -05:00
public static string latestCommmand = "" ;
2017-05-20 15:58:04 -04:00
/// <summary>
/// Occurs when the engine requests a Terminal to be open.
/// </summary>
2017-01-08 09:57:10 -05:00
public static event EmptyEventHandler TerminalRequested ;
2017-05-20 15:58:04 -04:00
/// <summary>
/// Opens a Terminal.
/// </summary>
2017-04-30 20:28:31 -04:00
internal static void OpenTerminal ( )
{
2017-01-08 09:57:10 -05:00
TerminalRequested ? . Invoke ( ) ;
}
2017-05-20 15:58:04 -04:00
/// <summary>
/// Determines if the specified command method can be ran in RTS
/// </summary>
/// <param name="mth">The method to scan</param>
/// <param name="isRemote">Is the user in an RTS session?</param>
/// <returns>Whether the command can be run.</returns>
2017-04-30 20:28:31 -04:00
public static bool CanRunRemotely ( MethodInfo mth , bool isRemote )
{
2017-01-21 21:27:25 -05:00
if ( ! isRemote )
return true ;
2017-04-30 20:28:31 -04:00
foreach ( var attr in mth . GetCustomAttributes ( false ) )
{
2017-01-21 21:27:25 -05:00
if ( attr is RemoteLockAttribute )
return false ;
}
return true ;
}
2017-05-20 15:58:04 -04:00
/// <summary>
/// Runs a command on the client-side.
/// </summary>
/// <param name="ns">The command's namespace.</param>
/// <param name="cmd">The command name.</param>
/// <param name="args">The command's arguments.</param>
/// <param name="isRemote">Whether the command should be ran through RTS.</param>
/// <returns>Whether the command ran successfully.</returns>
2017-04-30 20:28:31 -04:00
public static bool RunClient ( string ns , string cmd , Dictionary < string , string > args , bool isRemote = false )
{
2017-03-12 09:29:17 -07:00
return RunClient ( ns + "." + cmd , args , isRemote ) ;
}
2017-05-20 15:58:04 -04:00
/// <summary>
/// Runs a command on the client.
/// </summary>
/// <param name="text">The command text.</param>
/// <param name="argss">The command arguments.</param>
/// <param name="isRemote">Whether the command should be ran through RTS.</param>
/// <returns>Whether the command ran successfully.</returns>
2017-04-30 20:28:31 -04:00
public static bool RunClient ( string text , Dictionary < string , string > argss , bool isRemote = false )
{
2017-03-12 09:45:11 -07:00
Dictionary < string , object > args = new Dictionary < string , object > ( ) ;
2017-04-30 20:28:31 -04:00
foreach ( KeyValuePair < string , string > arg in argss )
{
2017-03-12 09:45:11 -07:00
args [ arg . Key ] = arg . Value ;
}
return RunClient ( text , args , isRemote ) ;
}
2017-05-20 15:58:04 -04:00
/// <summary>
/// Runs a command on the client.
/// </summary>
/// <param name="text">The command text.</param>
/// <param name="args">The command arguments.</param>
/// <param name="isRemote">Whether the command should be run in RTS.</param>
/// <returns>Whether the command ran successfully.</returns>
2017-04-30 20:28:31 -04:00
public static bool RunClient ( string text , Dictionary < string , object > args , bool isRemote = false )
{
2017-01-08 09:57:10 -05:00
latestCommmand = text ;
2017-03-12 09:45:11 -07:00
//Console.WriteLine(text + " " + "{" + string.Join(",", args.Select(kv => kv.Key + "=" + kv.Value).ToArray()) + "}" + " " + isRemote);
2017-05-24 16:41:49 -04:00
string [ ] split = text . Split ( '.' ) ;
2017-06-16 20:36:43 -04:00
var cmd = Commands . FirstOrDefault ( x = > x . CommandInfo . name = = text ) ;
2017-05-24 16:41:49 -04:00
if ( cmd = = null )
return false ;
if ( ! Shiftorium . UpgradeInstalled ( cmd . Dependencies ) )
return false ;
bool res = false ;
foreach ( var arg in cmd . RequiredArguments )
{
if ( ! args . ContainsKey ( arg ) )
2017-04-30 20:28:31 -04:00
{
2017-05-24 16:41:49 -04:00
res = true ;
Console . WriteLine ( "You are missing an argument with the key \"" + arg + "\"." ) ;
2017-04-30 20:28:31 -04:00
}
2017-01-08 09:57:10 -05:00
}
2017-05-24 16:41:49 -04:00
if ( res = = true )
return true ;
try
{
cmd . Invoke ( args ) ;
}
catch ( Exception ex )
{
Console . WriteLine ( "Command error: " + ex . Message ) ;
}
return true ;
2017-01-08 09:57:10 -05:00
}
2017-05-12 19:17:47 -04:00
2017-05-20 15:58:04 -04:00
/// <summary>
/// Prints the user prompt to the terminal.
/// </summary>
2017-03-09 16:46:34 -05:00
public static void PrintPrompt ( )
{
2017-05-28 07:21:16 -04:00
Console . WriteLine ( ) ;
2017-05-01 15:08:36 -04:00
if ( SaveSystem . CurrentSave ! = null & & CurrentUser ! = null )
2017-03-11 10:28:16 -05:00
{
2017-05-12 21:22:08 -04:00
ConsoleEx . BackgroundColor = SkinEngine . LoadedSkin . TerminalBackColorCC ;
ConsoleEx . Italic = false ;
ConsoleEx . Underline = false ;
ConsoleEx . ForegroundColor = ConsoleColor . Magenta ;
ConsoleEx . Bold = true ;
Console . Write ( SaveSystem . CurrentUser . Username ) ;
ConsoleEx . Bold = false ;
ConsoleEx . ForegroundColor = ConsoleColor . Gray ;
Console . Write ( "@" ) ;
ConsoleEx . Italic = true ;
ConsoleEx . Bold = true ;
ConsoleEx . ForegroundColor = ConsoleColor . Yellow ;
Console . Write ( SaveSystem . CurrentSave . SystemName ) ;
ConsoleEx . Italic = false ;
ConsoleEx . Bold = false ;
ConsoleEx . ForegroundColor = ConsoleColor . Gray ;
Console . Write ( ":~" ) ;
Console . ForegroundColor = ConsoleColor . White ;
ConsoleEx . Italic = true ;
if ( KernelWatchdog . InKernelMode = = true )
Console . Write ( "#" ) ;
else
Console . Write ( "$" ) ;
ConsoleEx . Italic = false ;
ConsoleEx . Bold = false ;
ConsoleEx . ForegroundColor = SkinEngine . LoadedSkin . TerminalForeColorCC ;
Console . Write ( " " ) ;
2017-05-28 07:21:16 -04:00
ConsoleEx . Flush ( ) ;
2017-03-11 10:28:16 -05:00
}
2017-03-09 16:46:34 -05:00
}
2017-05-20 15:58:04 -04:00
/// <summary>
/// Static constructor for <see cref="TerminalBackend"/>.
/// </summary>
2017-01-21 16:23:10 -05:00
static TerminalBackend ( )
{
ServerMessageReceived onMessageReceived = ( msg ) = >
{
if ( msg . Name = = "trm_invokecommand" )
{
string text3 = "" ;
string text4 = msg . Contents ;
2017-04-30 20:28:31 -04:00
if ( TerminalBackend . PrefixEnabled )
{
2017-05-28 14:44:08 -04:00
text3 = text4 . Remove ( 0 , $"{SaveSystem.CurrentUser.Username}@{SaveSystem.CurrentSave.SystemName}:~$ " . Length ) ;
2017-01-21 16:23:10 -05:00
}
IsForwardingConsoleWrites = true ;
2017-04-30 20:28:31 -04:00
if ( TerminalBackend . InStory = = false )
{
2017-01-21 21:27:25 -05:00
TerminalBackend . InvokeCommand ( text3 , true ) ;
2017-01-21 16:23:10 -05:00
}
2017-04-30 20:28:31 -04:00
if ( TerminalBackend . PrefixEnabled )
{
2017-05-28 14:44:08 -04:00
Console . Write ( $"{SaveSystem.CurrentUser.Username}@{SaveSystem.CurrentSave.SystemName}:~$ " ) ;
2017-01-21 16:23:10 -05:00
}
IsForwardingConsoleWrites = false ;
2017-04-30 20:28:31 -04:00
}
else if ( msg . Name = = "pleasewrite" )
{
2017-01-21 16:23:10 -05:00
Console . Write ( msg . Contents ) ;
2017-04-30 20:28:31 -04:00
}
else if ( msg . Name = = "handshake_from" )
{
2017-01-21 16:23:10 -05:00
var a = JsonConvert . DeserializeObject < Dictionary < string , object > > ( msg . Contents ) ;
string uName = a [ "username" ] as string ;
string pass = a [ "password" ] as string ;
string sys = a [ "sysname" ] as string ;
string guid = msg . GUID ;
2017-05-28 14:44:08 -04:00
if ( SaveSystem . CurrentUser . Username = = uName & & SaveSystem . CurrentSave . Password = = pass & & CurrentSave . SystemName = = sys )
2017-04-30 20:28:31 -04:00
{
2017-01-21 16:23:10 -05:00
ForwardGUID = guid ;
ServerManager . SendMessage ( "trm_handshake_accept" , $ @ "{{
2017-01-21 19:10:58 -05:00
guid : "" { ServerManager . thisGuid } "" ,
target : "" { guid } ""
2017-01-21 16:23:10 -05:00
} } ");
2017-01-08 09:57:10 -05:00
2017-01-21 16:23:10 -05:00
IsForwardingConsoleWrites = true ;
InvokeCommand ( "sos.status" ) ;
2017-05-28 14:44:08 -04:00
Console . Write ( $"{SaveSystem.CurrentUser.Username}@{SaveSystem.CurrentSave.SystemName}:~$ " ) ;
2017-01-21 16:23:10 -05:00
IsForwardingConsoleWrites = false ;
}
}
} ;
ServerManager . MessageReceived + = onMessageReceived ;
}
2017-05-20 15:58:04 -04:00
/// <summary>
/// Gets whether the terminal backend is forwarding console write requests through RTS to a remote client.
/// </summary>
2017-02-06 15:21:53 -05:00
public static bool IsForwardingConsoleWrites { get ; internal set ; }
2017-05-20 15:58:04 -04:00
/// <summary>
/// Gets the RTS forward GUID.
/// </summary>
2017-02-06 16:00:01 -05:00
public static string ForwardGUID { get ; internal set ; }
2017-03-12 09:29:17 -07:00
2017-05-20 15:58:04 -04:00
/// <summary>
/// Occurs when the user inputs text in a Terminal.
/// </summary>
2017-04-30 20:28:31 -04:00
public static event TextSentEventHandler TextSent ;
2017-05-20 15:58:04 -04:00
/// <summary>
/// Fakes the user inputting text to a Terminal.
/// </summary>
/// <param name="text">The text to input.</param>
2017-04-30 20:28:31 -04:00
public static void SendText ( string text )
{
TextSent ? . Invoke ( text ) ;
}
2017-01-08 09:57:10 -05:00
}
}