public static bool Shutdown() { SaveSystem.ShuttingDown = true; TerminalBackend.InvokeCommand("sos.save"); AppearanceManager.Exit(); return(true); }
/// <summary> /// Starts the storyline with the specified Storyline ID. /// </summary> /// <param name="stid">The storyline ID to start.</param> public static void Start(string stid) { if (SaveSystem.CurrentSave.StoriesExperienced == null) { SaveSystem.CurrentSave.StoriesExperienced = new List <string>(); } foreach (var type in ReflectMan.Types) { foreach (var mth in type.GetMethods(BindingFlags.Public | BindingFlags.Static)) { foreach (var attrib in Array.FindAll(mth.GetCustomAttributes(false), a => a is StoryAttribute || a is MissionAttribute)) { var story = attrib as StoryAttribute; if (story.StoryID == stid) { new Thread(() => { Context = new Engine.StoryContext { Id = stid, Method = mth, AutoComplete = true, }; SaveSystem.CurrentSave.PickupPoint = Context.Id; Context.OnComplete += () => { if (story is MissionAttribute) { var mission = story as MissionAttribute; ConsoleEx.ForegroundColor = ConsoleColor.Yellow; ConsoleEx.Bold = true; Console.WriteLine(" - mission complete - "); ConsoleEx.Bold = false; ConsoleEx.ForegroundColor = ConsoleColor.White; Console.WriteLine($"{mission.Name} successfully finished. You have earned {mission.CodepointAward} Codepoints for your efforts."); SaveSystem.CurrentSave.Codepoints += mission.CodepointAward; TerminalBackend.PrintPrompt(); TerminalBackend.PrefixEnabled = true; } StoryComplete?.Invoke(stid); SaveSystem.CurrentSave.PickupPoint = null; }; mth.Invoke(null, null); if (Context.AutoComplete) { Context.MarkComplete(); } }).Start(); return; } } } } #if DEBUG throw new ArgumentException("Story ID not found: " + stid + " - Talk to Michael. NOW."); #else Debug.Print("No such story: " + stid); #endif }
/// <summary> /// Static constructor for <see cref="TerminalBackend"/>. /// </summary> static TerminalBackend() { ServerMessageReceived onMessageReceived = (msg) => { if (msg.Name == "trm_invokecommand") { string text3 = ""; string text4 = msg.Contents; if (TerminalBackend.PrefixEnabled) { text3 = text4.Remove(0, $"{SaveSystem.CurrentUser.Username}@{SaveSystem.CurrentSave.SystemName}:~$ ".Length); } IsForwardingConsoleWrites = true; if (TerminalBackend.InStory == false) { TerminalBackend.InvokeCommand(text3, true); } if (TerminalBackend.PrefixEnabled) { Console.Write($"{SaveSystem.CurrentUser.Username}@{SaveSystem.CurrentSave.SystemName}:~$ "); } IsForwardingConsoleWrites = false; } else if (msg.Name == "pleasewrite") { Console.Write(msg.Contents); } else if (msg.Name == "handshake_from") { 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; if (SaveSystem.CurrentUser.Username == uName && SaveSystem.CurrentSave.Password == pass && CurrentSave.SystemName == sys) { ForwardGUID = guid; ServerManager.SendMessage("trm_handshake_accept", $@"{{ guid: ""{ServerManager.thisGuid}"", target: ""{guid}"" }}"); IsForwardingConsoleWrites = true; InvokeCommand("sos.status"); Console.Write($"{SaveSystem.CurrentUser.Username}@{SaveSystem.CurrentSave.SystemName}:~$ "); IsForwardingConsoleWrites = false; } } }; ServerManager.MessageReceived += onMessageReceived; }
public static void PushObjective(string name, string desc, Func <bool> completeFunc, Action onComplete) { if (CurrentObjectives == null) { CurrentObjectives = new List <Objective>(); } var currentObjective = new Objective(name, desc, completeFunc, onComplete); CurrentObjectives.Add(currentObjective); var t = new Thread(() => { var obj = currentObjective; while (!obj.IsComplete) { Thread.Sleep(5000); } Thread.Sleep(500); CurrentObjectives.Remove(obj); obj.Complete(); }); t.IsBackground = true; t.Start(); Console.WriteLine(); ConsoleEx.ForegroundColor = ConsoleColor.Red; ConsoleEx.Bold = true; Console.WriteLine("NEW OBJECTIVE:"); Console.WriteLine(); ConsoleEx.ForegroundColor = ConsoleColor.White; ConsoleEx.Bold = false; Console.WriteLine("A new objective has been added to your system."); ConsoleEx.Bold = true; Console.WriteLine(name); ConsoleEx.Bold = false; Console.WriteLine(); Console.WriteLine(desc); Console.WriteLine(); Console.WriteLine("Run 'status' at any time to view your current objectives."); TerminalBackend.PrintPrompt(); }
/// <summary> /// Buy an upgrade, deducting the specified amount of Codepoints. /// </summary> /// <param name="id">The upgrade ID to buy</param> /// <param name="cost">The amount of Codepoints to deduct</param> /// <returns>True if the upgrade was installed successfully, false if the user didn't have enough Codepoints or the upgrade wasn' found.</returns> public static bool Buy(string id, ulong cost) { if (SaveSystem.CurrentSave.Codepoints >= cost) { SaveSystem.CurrentSave.Upgrades[id] = true; TerminalBackend.InvokeCommand("sos.save"); SaveSystem.TransferCodepointsToVoid(cost); Installed?.Invoke(); Desktop.ResetPanelButtons(); Desktop.PopulateAppLauncher(); return(true); } else { if (!Silent) { Console.WriteLine($"{{SHIFTORIUM_NOTENOUGHCP}}: {cost} > {SaveSystem.CurrentSave.Codepoints}"); } return(false); } }
/// <summary> /// Start the entire ShiftOS engine. /// </summary> /// <param name="useDefaultUI">Whether ShiftOS should initiate it's Windows Forms front-end.</param> public static void Begin(bool useDefaultUI = true) { AppDomain.CurrentDomain.UnhandledException += (o, a) => { CrashHandler.Start((Exception)a.ExceptionObject); }; if (!System.IO.File.Exists(Paths.SaveFile)) { var root = new ShiftOS.Objects.ShiftFS.Directory(); root.Name = "System"; root.permissions = UserPermissions.Guest; System.IO.File.WriteAllText(Paths.SaveFile, JsonConvert.SerializeObject(root)); } if (Utils.Mounts.Count == 0) { Utils.Mount(System.IO.File.ReadAllText(Paths.SaveFile)); } Paths.Init(); Localization.SetupTHETRUEDefaultLocals(); SkinEngine.Init(); Random rnd = new Random(); int loadingJoke1 = rnd.Next(10); int loadingJoke2 = rnd.Next(11); TerminalBackend.OpenTerminal(); TerminalBackend.InStory = true; var thread = new Thread(new ThreadStart(() => { //Do not uncomment until I sort out the copyright stuff... - Michael //AudioManager.Init(); var defaultConf = new EngineConfig(); if (System.IO.File.Exists("engineconfig.json")) { defaultConf = JsonConvert.DeserializeObject <EngineConfig>(System.IO.File.ReadAllText("engineconfig.json")); } else { System.IO.File.WriteAllText("engineconfig.json", JsonConvert.SerializeObject(defaultConf, Formatting.Indented)); } Thread.Sleep(350); Console.WriteLine("{MISC_KERNELVERSION}"); Thread.Sleep(50); Console.WriteLine("Copyright (c) 2018 DevX. Licensed under MIT."); Console.WriteLine(""); Console.WriteLine("THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR"); Console.WriteLine("IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,"); Console.WriteLine("FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE"); Console.WriteLine("AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER"); Console.WriteLine("LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,"); Console.WriteLine("OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE"); Console.WriteLine("SOFTWARE."); Console.WriteLine(""); Thread.Sleep(250); Console.WriteLine("{MISC_KERNELBOOTED}"); Console.WriteLine("{MISC_SHIFTFSDRV}"); Thread.Sleep(350); Console.WriteLine("{MISC_SHIFTFSBLOCKSREAD}"); Console.WriteLine("{LOADINGMSG1_" + loadingJoke1 + "}"); Thread.Sleep(500); Console.WriteLine("{MISC_LOADINGCONFIG}"); Thread.Sleep(30); Console.WriteLine("{MISC_BUILDINGCMDS}"); TerminalBackend.PopulateTerminalCommands(); if (IsSandbox == false) { Console.WriteLine("{MISC_CONNECTINGTONETWORK}"); Ready.Reset(); if (PreDigitalSocietyConnection != null) { PreDigitalSocietyConnection?.Invoke(); Ready.WaitOne(); } ServerManager.GUIDReceived += (str) => { //Connection successful! Stop waiting! Console.WriteLine("{MISC_CONNECTIONSUCCESSFUL}"); Thread.Sleep(100); Console.WriteLine("{LOADINGMSG2_" + loadingJoke2 + "}"); Thread.Sleep(500); }; try { if (ServerManager.ServerOnline) { ServerManager.Initiate(UserConfig.Get().DigitalSocietyAddress, UserConfig.Get().DigitalSocietyPort); // This halts the client until the connection is successful. ServerManager.guidReceiveARE.WaitOne(); Console.WriteLine("{MISC_DHCPHANDSHAKEFINISHED}"); } else { Console.WriteLine("{MISC_NONETWORK}"); Console.WriteLine("{LOADINGMSG2_" + loadingJoke2 + "}"); } FinishBootstrap(); } catch (Exception ex) { // "No errors, this never gets called." Console.WriteLine("[inetd] SEVERE: " + ex.Message); string dest = "Startup Exception " + DateTime.Now.ToString().Replace("/", "-").Replace(":", "-") + ".txt"; System.IO.File.WriteAllText(dest, ex.ToString()); Console.WriteLine("[inetd] Full exception details have been saved to: " + dest); Thread.Sleep(3000); System.Diagnostics.Process.GetCurrentProcess().Kill(); } //Nothing happens past this point - but the client IS connected! It shouldn't be stuck in that while loop above. } else { Console.WriteLine("{MISC_SANDBOXMODE}"); CurrentSave = new Save { IsSandbox = true, Username = "******", Password = "******", SystemName = "shiftos", Users = new List <ClientSave> { new ClientSave { Username = "******", Password = "", Permissions = 0 } }, Class = 0, ID = new Guid(), Upgrades = new Dictionary <string, bool>(), CurrentLegions = null, IsMUDAdmin = false, IsPatreon = false, Language = "english", LastMonthPaid = 0, MajorVersion = 1, MinorVersion = 0, MusicEnabled = false, MusicVolume = 100, MyShop = "", PasswordHashed = false, PickupPoint = "", RawReputation = 0.0f, Revision = 0, ShiftnetSubscription = 0, SoundEnabled = true, StoriesExperienced = null, StoryPosition = 0, UniteAuthToken = "", }; CurrentUser = CurrentSave.Users.First(); Localization.SetupTHETRUEDefaultLocals(); Shiftorium.Init(); TerminalBackend.InStory = false; TerminalBackend.PrefixEnabled = true; Desktop.InvokeOnWorkerThread(new Action(() => { ShiftOS.Engine.Scripting.LuaInterpreter.RunSft(Paths.GetPath("kernel.sft")); })); Desktop.InvokeOnWorkerThread(new Action(() => Desktop.PopulateAppLauncher())); GameReady?.Invoke(); } })); thread.IsBackground = true; thread.Start(); }
/// <summary> /// Restarts the game. /// </summary> public static void Restart() { TerminalBackend.InvokeCommand("sos.shutdown"); System.Windows.Forms.Application.Restart(); }
public static void StartDevXLies() { int chatProgress = 0; //bool LoopStuck = false; string textToWrite = ""; const int TYPE_SPEED_MS = 45; bool done = false; bool write = true; while (done == false) { write = true; switch (chatProgress) { case 0: textToWrite = "User joined: @" + SaveSystem.CurrentSave.Username; break; case 1: textToWrite = $"Hello, {SaveSystem.CurrentSave.Username}."; break; case 2: //If C:\ShiftOS doesn't exist the player won't notice this is here. if (Directory.Exists(Paths.GetPath("classic"))) { textToWrite = "I see you've participated in my previous ShiftOS experiment. Welcome back, Shifter. I assume you know lots about ShiftOS, but there are some updates I have to tell you."; } else { write = false; } break; case 3: //DevX hates ShiftOS-Next secretly. if (Directory.Exists(Paths.GetPath("classic") + "-Next")) { textToWrite = "Hmmmm.... looking at my sentience records, I see you've participated in ShiftOS-Next. This is gonna be difficult."; } else { write = false; } break; case 4: textToWrite = "There's a lot that has changed within ShiftOS."; break; case 5: textToWrite = "First off, I want to tell you a bit about myself in case you don't already know."; break; case 6: textToWrite = "My name is DevX. I am the architect of ShiftOS. I have chosen you to take part in helping me out with it."; break; case 7: textToWrite = "You see, in my past attempts it has all been about an evolving operating system and seeing how the users work with it..."; break; case 8: textToWrite = "Almost one hundred percent of the time, people have found out it was an experiment and they could simply return to their regular system with a specific upgrade."; break; case 9: textToWrite = "But now, I want to try something different - something unique."; break; case 10: textToWrite = "ShiftOS is the same as it has been in my previous attempts, but now, your goal is to gain as much wealth and power as possible."; break; case 11: textToWrite = "Right now you are inside my segregation LAN. Only you and me exist within this domain. You are free from other users unless I create them."; break; case 12: textToWrite = "Since you have proved your sentience, I have a task for you outside the segregation LAN."; break; case 13: textToWrite = "But first... you need to be taught a few things."; break; case 14: textToWrite = "First off, when I bring you into my multi-user domain, you'll first want to establish as much wealth as possible."; break; case 15: textToWrite = "Wealth comes in the form of Codepoints - a currency used among users of the multi-user domain."; break; case 16: textToWrite = @"You can get Codepoints by doing the following: - Stealing them from other users - Extracting them from inactive/unverified sentiences - Using specific scripts/programs within ShiftOS - Creating paid scripts/applications within ShiftOS"; break; case 17: textToWrite = "You can use Codepoints to buy upgrades using the 'shiftorium.buy' command, or you can use them to pay other users, or scripts."; break; case 18: textToWrite = "Within the multi-user domain you are free to do whatever you want. Larcany, theft, deceiving, lies, and distribution of malware is permitted under my watch."; break; case 19: textToWrite = "Do whatever you have to to get Codepoints."; break; case 20: textToWrite = "Then use them to make yourself stronger by buying upgrades at the shiftorium."; break; case 21: textToWrite = "If you want to get a bit devious within the multi-user domain, look around for scripts that will expose user account information."; break; case 22: textToWrite = "Or just spread a virus around the mud."; break; case 23: textToWrite = "Or you can be the 'good' guy and stop these attacks and gain the trust of other users."; break; case 24: textToWrite = "It's up to you. Just, don't mess with my system. You won't want me coming to you after that. I'm watching."; break; case 25: textToWrite = "User left chat: @" + SaveSystem.CurrentSave.Username; done = true; SaveSystem.CurrentSave.StoryPosition++; TerminalBackend.InvokeCommand("sos.save"); break; } if (write == true) { Console.WriteLine(); Console.Write("DevX: "); foreach (char c in textToWrite) { Console.Beep(750, TYPE_SPEED_MS); if (c == '\n') { } else if (c == '\r') { Console.WriteLine(); } else { Console.Write(c); } } Thread.Sleep(1000); } chatProgress += 1; } }
/// <summary> /// Start the entire ShiftOS engine. /// </summary> /// <param name="useDefaultUI">Whether ShiftOS should initiate it's Windows Forms front-end.</param> public static void Begin(bool useDefaultUI = true) { if (!System.IO.File.Exists(Paths.SaveFile)) { var root = new ShiftOS.Objects.ShiftFS.Directory(); root.Name = "System"; root.permissions = Permissions.All; System.IO.File.WriteAllText(Paths.SaveFile, JsonConvert.SerializeObject(root)); } if (Utils.Mounts.Count == 0) { Utils.Mount(System.IO.File.ReadAllText(Paths.SaveFile)); } Paths.Init(); Localization.SetupTHETRUEDefaultLocals(); SkinEngine.Init(); TerminalBackend.OpenTerminal(); TerminalBackend.InStory = true; var thread = new Thread(new ThreadStart(() => { //Do not uncomment until I sort out the copyright stuff... - Michael //AudioManager.Init(); var defaultConf = new EngineConfig(); if (System.IO.File.Exists("engineconfig.json")) { defaultConf = JsonConvert.DeserializeObject <EngineConfig>(System.IO.File.ReadAllText("engineconfig.json")); } else { System.IO.File.WriteAllText("engineconfig.json", JsonConvert.SerializeObject(defaultConf, Formatting.Indented)); } Thread.Sleep(350); Console.WriteLine("Initiating kernel..."); Thread.Sleep(250); Console.WriteLine("Reading filesystem..."); Thread.Sleep(100); Console.WriteLine("Reading configuration..."); Console.WriteLine("{CONNECTING_TO_MUD}"); if (defaultConf.ConnectToMud == true) { try { bool guidReceived = false; ServerManager.GUIDReceived += (str) => { guidReceived = true; Console.WriteLine("{CONNECTION_SUCCESSFUL}"); }; ServerManager.Initiate("secondary4162.cloudapp.net", 13370); while (guidReceived == false) { } } catch (Exception ex) { Console.WriteLine("{ERROR}: " + ex.Message); Thread.Sleep(3000); ServerManager.StartLANServer(); } } else { ServerManager.StartLANServer(); } ServerManager.MessageReceived += (msg) => { if (msg.Name == "mud_savefile") { CurrentSave = JsonConvert.DeserializeObject <Save>(msg.Contents); } else if (msg.Name == "mud_login_denied") { oobe.PromptForLogin(); } }; ReadSave(); while (CurrentSave == null) { } Shiftorium.Init(); while (CurrentSave.StoryPosition < 5) { } Thread.Sleep(75); if (Shiftorium.UpgradeInstalled("desktop")) { Console.Write("{START_DESKTOP}"); Thread.Sleep(50); Console.WriteLine(" ...{DONE}."); } Story.Start(); Thread.Sleep(50); Console.WriteLine("{SYSTEM_INITIATED}"); TerminalBackend.InStory = false; Shiftorium.LogOrphanedUpgrades = true; Desktop.InvokeOnWorkerThread(new Action(() => Desktop.PopulateAppLauncher())); GameReady?.Invoke(); })); thread.IsBackground = true; thread.Start(); }
public static Exception HandledException = null; // this value determines if we can try to set the game back on track or we cant do anything about it public static void Start(Exception e) { if (SaveSystem.CurrentSave != null) { TerminalBackend.InvokeCommand("sos.save"); // SAVE BEFORE CRASHING } ServerManager.Disconnect(); while (Application.OpenForms.Count > 0) { Application.OpenForms[0].Close(); } //Set our global exception variable, and show the exception dialog. HandledException = e; System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly(); System.IO.FileInfo fileInfo = new System.IO.FileInfo(assembly.Location); DateTime lastModified = fileInfo.LastWriteTime; // put all this in a text document string rtbcrash_Text = $@" === {AssemblyName} has crashed. === Game: {AssemblyName} Description: {AssemblyDescription} Basic Information For User: --------------------------------- When: {DateTime.Now.ToString()} Why: {HandledException.Message} What: {HandledException.GetType().Name} We, at the ShiftOS Development Team, apologise for your game crash, we will take this bug report seriously - and it has been emailed to the development team of ShiftOS, thank you for enjoying our game! Advanced Information (for experts and developers): ---------------------------------------------------- Host system information: --------------------------------- Operating system: {Environment.OSVersion.Platform.ToString()} Version: {Environment.OSVersion.VersionString} Is 64-bit: {Environment.Is64BitOperatingSystem} ShiftOS exec path: {Application.ExecutablePath} Advanced Host Information: --------------------------------- CPU Name: {GetHardwareInfo.GetProcessorName()} Physical RAM Installed: {GetHardwareInfo.GetRAMAmount()} GPU Name: {GetHardwareInfo.GetGPUName()} ShiftOS basic information: --------------------------------- ShiftOS Version: {Assembly.GetExecutingAssembly().GetName().Version} ShiftOS Date: {lastModified.ToString()} ShiftOS environment information: --------------------------------- Is Save loaded: {(SaveSystem.CurrentSave != null)} Paths loaded in system: {JsonConvert.SerializeObject(Paths.GetAll())} Crash: {HandledException.GetType().Name} -------------------------------------------- Exception message: {HandledException.Message} HResult (this is technical): {HandledException.HResult} Has inner exception: {(HandledException.InnerException != null)} Stack trace: {HandledException.StackTrace}"; if (HandledException.InnerException != null) { var i = HandledException.InnerException; rtbcrash_Text += $@" Inner: {i.GetType().Name} -------------------------------------------- Exception message: {i.Message} HResult (this is technical): {i.HResult} Stack trace: {i.StackTrace}"; } File.WriteAllText("crash.txt", rtbcrash_Text); // make that text document and put above super long string in it var result = MessageBox.Show(caption: "ShiftOS - Fatal error", text: "ShiftOS has encountered a fatal error and has been shut down. Info about the error has been saved to a file called crash.txt in the same folder as the active executable. Would you like to try and recover the game session?", buttons: MessageBoxButtons.YesNo); if (result == DialogResult.Yes) { Application.Restart(); // tries to restart if user clicks yes, who wouldve guessed } }
/// <summary> /// Initiate a new Digital Society connection. /// </summary> /// <param name="mud_address">The IP address or hostname of the target server</param> /// <param name="port">The target port.</param> public static void Initiate(string mud_address, int port) { client = new NetObjectClient(); client.OnDisconnected += (o, a) => { if (!UserDisconnect) { Desktop.PushNotification("digital_society_connection", "Disconnected from Digital Society.", "The ShiftOS kernel has been disconnected from the Digital Society. We are attempting to re-connect you."); TerminalBackend.PrefixEnabled = true; ConsoleEx.ForegroundColor = ConsoleColor.Red; ConsoleEx.Bold = true; Console.Write($@"Disconnected from MUD: "); ConsoleEx.Bold = false; ConsoleEx.Italic = true; ConsoleEx.ForegroundColor = ConsoleColor.DarkYellow; Console.WriteLine("You have been disconnected from the multi-user domain for an unknown reason. Your save data is preserved within the kernel and you will be reconnected shortly."); TerminalBackend.PrefixEnabled = true; TerminalBackend.PrintPrompt(); Initiate(mud_address, port); } }; client.OnReceived += (o, a) => { if (PingTimer.IsRunning) { DigitalSocietyPing = PingTimer.ElapsedMilliseconds; PingTimer.Reset(); } var msg = a.Data.Object as ServerMessage; if (msg.Name == "Welcome") { thisGuid = new Guid(msg.Contents); GUIDReceived?.Invoke(msg.Contents); guidReceiveARE.Set(); TerminalBackend.PrefixEnabled = true; TerminalBackend.PrintPrompt(); } else if (msg.Name == "allusers") { foreach (var acc in JsonConvert.DeserializeObject <string[]>(msg.Contents)) { Console.WriteLine(acc); } TerminalBackend.PrintPrompt(); } else if (msg.Name == "update_your_cp") { var args = JsonConvert.DeserializeObject <Dictionary <string, object> >(msg.Contents); if (args["username"] as string == SaveSystem.CurrentUser.Username) { SaveSystem.CurrentSave.Codepoints += (ulong)args["amount"]; Desktop.InvokeOnWorkerThread(new Action(() => { Infobox.Show($"MUD Control Centre", $"Someone bought an item in your shop, and they have paid {args["amount"]}, and as such, you have been granted these Codepoints."); })); SaveSystem.SaveGame(); } } else if (msg.Name == "broadcast") { Console.WriteLine(msg.Contents); } else if (msg.Name == "forward") { MessageReceived?.Invoke(JsonConvert.DeserializeObject <ServerMessage>(msg.Contents)); } else if (msg.Name == "Error") { var ex = JsonConvert.DeserializeObject <Exception>(msg.Contents); TerminalBackend.PrefixEnabled = true; ConsoleEx.ForegroundColor = ConsoleColor.Red; ConsoleEx.Bold = true; Console.Write($@"{{MUD_ERROR}}: "); ConsoleEx.Bold = false; ConsoleEx.Italic = true; ConsoleEx.ForegroundColor = ConsoleColor.DarkYellow; Console.WriteLine(ex.Message); TerminalBackend.PrefixEnabled = true; TerminalBackend.PrintPrompt(); } else { MessageReceived?.Invoke(msg); } }; try { client.Connect(mud_address, port); } catch (SocketException ex) { System.Diagnostics.Debug.Print(ex.ToString()); Initiate(mud_address, port); } }