aboutsummaryrefslogtreecommitdiff
path: root/ShiftOS_TheReturn
diff options
context:
space:
mode:
authorMichael VanOverbeek <[email protected]>2017-04-07 17:02:38 +0000
committerMichael VanOverbeek <[email protected]>2017-04-07 17:02:38 +0000
commit3d48f3101aa25050e6b219fc1111293273a59fa4 (patch)
tree40bf8d722245d02d87b0914a38e2b09673e093c0 /ShiftOS_TheReturn
parentedf4aef6adf8a2a45c347f70804fc5ac93070576 (diff)
parent3789b48df00e89fa6dcd7e27bb6885ba880504f6 (diff)
downloadshiftos_thereturn-3d48f3101aa25050e6b219fc1111293273a59fa4.tar.gz
shiftos_thereturn-3d48f3101aa25050e6b219fc1111293273a59fa4.tar.bz2
shiftos_thereturn-3d48f3101aa25050e6b219fc1111293273a59fa4.zip
Merge branch 'master' of https://github.com/shiftos-game/ShiftOS
Diffstat (limited to 'ShiftOS_TheReturn')
-rw-r--r--ShiftOS_TheReturn/AudioManager.cs126
-rw-r--r--ShiftOS_TheReturn/Commands.cs819
-rw-r--r--ShiftOS_TheReturn/Localization.cs219
-rw-r--r--ShiftOS_TheReturn/Resources/strings_de.txt38
-rw-r--r--ShiftOS_TheReturn/Resources/strings_en.txt4
-rw-r--r--ShiftOS_TheReturn/SaveSystem.cs332
-rw-r--r--ShiftOS_TheReturn/ServerManager.cs248
-rw-r--r--ShiftOS_TheReturn/Shiftorium.cs332
-rw-r--r--ShiftOS_TheReturn/TerminalTextWriter.cs131
9 files changed, 2238 insertions, 11 deletions
diff --git a/ShiftOS_TheReturn/AudioManager.cs b/ShiftOS_TheReturn/AudioManager.cs
new file mode 100644
index 0000000..7466eeb
--- /dev/null
+++ b/ShiftOS_TheReturn/AudioManager.cs
@@ -0,0 +1,126 @@
+/*
+ * 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.
+ */
+
+#define NOSOUND
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using NAudio;
+using NAudio.Wave;
+
+namespace ShiftOS.Engine
+{
+ public static class AudioManager
+ {
+ private static WaveOut _out = null;
+ private static AudioFileReader _reader = null;
+ private static IAudioProvider _provider = null;
+ private static bool _running = true;
+
+ public static void Init(IAudioProvider _p)
+ {
+#if !NOSOUND
+ _provider = _p;
+ AppearanceManager.OnExit += () =>
+ {
+ _running = false;
+ _out?.Stop();
+ _reader?.Dispose();
+ _out?.Dispose();
+ System.IO.File.Delete("temp.mp3");
+ };
+ var t = new Thread(() =>
+ {
+ SaveSystem.GameReady += () =>
+ {
+ while(_out == null)
+ {
+
+ }
+ _out.Volume = _provider.Volume;
+ };
+ Random rnd = new Random();
+ while(_running == true)
+ {
+ int track = rnd.Next(0, _provider.Count);
+ byte[] mp3 = _provider.GetTrack(track);
+ System.IO.File.WriteAllBytes("temp.mp3", mp3);
+ _reader = new AudioFileReader("temp.mp3");
+ _out = new WaveOut();
+ _out.Init(_reader);
+ _out.Volume = _provider.Volume;
+
+ _out.Play();
+ while(_out.PlaybackState == PlaybackState.Playing)
+ {
+ Thread.Sleep(5000); //even when the player isn't playing, this will give a good delay between songs.
+ }
+ _reader.Dispose();
+ _out.Dispose();
+ }
+ });
+ t.IsBackground = true;
+ t.Start();
+#endif
+ }
+
+ public static void SetVolume(float volume)
+ {
+ _provider.Volume = volume; //persist between songs
+ _out.Volume = volume;
+ }
+
+ internal static void Kill()
+ {
+ _running = false;
+ _out.Stop();
+ _out.Dispose();
+ _reader.Dispose();
+ }
+ }
+
+ public interface IAudioProvider
+ {
+ /// <summary>
+ /// Gets a byte[] array corresponding to an MP3 track given an index.
+ /// </summary>
+ /// <param name="index">A track index to use when finding the right track.</param>
+ /// <returns>The MP3 byte[] array.</returns>
+ byte[] GetTrack(int index);
+
+ /// <summary>
+ /// Gets the 1-based count of all available tracks.
+ /// </summary>
+ int Count { get; }
+
+ /// <summary>
+ /// Gets or sets the track player's volume.
+ /// </summary>
+ float Volume { get; set; }
+ }
+}
diff --git a/ShiftOS_TheReturn/Commands.cs b/ShiftOS_TheReturn/Commands.cs
new file mode 100644
index 0000000..3cd1640
--- /dev/null
+++ b/ShiftOS_TheReturn/Commands.cs
@@ -0,0 +1,819 @@
+/*
+ * 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.
+ */
+
+#define DEVEL
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using ShiftOS.Engine.Properties;
+using System.IO;
+using Newtonsoft.Json;
+using System.IO.Compression;
+
+using ShiftOS.Objects;
+using Discoursistency.Base.Models.Authentication;
+using ShiftOS.Engine.Scripting;
+using ShiftOS.Objects.ShiftFS;
+
+namespace ShiftOS.Engine
+{
+ [Namespace("infobox", hide = true)]
+ [RequiresUpgrade("desktop;wm_free_placement")]
+ public static class InfoboxDebugCommands
+ {
+
+ [RequiresArgument("title")]
+ [RequiresArgument("msg")]
+ [Command("show")]
+ public static bool ShowInfo(Dictionary<string, object> args)
+ {
+ Desktop.InvokeOnWorkerThread(new Action(() =>
+ {
+ Infobox.Show(args["title"].ToString(), args["msg"].ToString());
+ }));
+ return true;
+ }
+
+ [RequiresArgument("title")]
+ [RequiresArgument("msg")]
+ [Command("yesno")]
+ public static bool ShowYesNo(Dictionary<string, object> args)
+ {
+ bool forwarding = TerminalBackend.IsForwardingConsoleWrites;
+ var fGuid = TerminalBackend.ForwardGUID;
+ Action<bool> callback = (result) =>
+ {
+ TerminalBackend.IsForwardingConsoleWrites = forwarding;
+ TerminalBackend.ForwardGUID = (forwarding == true) ? fGuid : null;
+ string resultFriendly = (result == true) ? "yes" : "no";
+ Console.WriteLine($"{SaveSystem.CurrentSave.Username} says {resultFriendly}.");
+ TerminalBackend.IsForwardingConsoleWrites = false;
+ };
+ Desktop.InvokeOnWorkerThread(new Action(() =>
+ {
+ Infobox.PromptYesNo(args["title"].ToString(), args["msg"].ToString(), callback);
+
+ }));
+ return true;
+ }
+
+ [RequiresArgument("title")]
+ [RequiresArgument("msg")]
+ [Command("text")]
+ public static bool ShowText(Dictionary<string, object> args)
+ {
+ bool forwarding = TerminalBackend.IsForwardingConsoleWrites;
+ var fGuid = TerminalBackend.ForwardGUID;
+ Action<string> callback = (result) =>
+ {
+ TerminalBackend.IsForwardingConsoleWrites = forwarding;
+ TerminalBackend.ForwardGUID = (forwarding == true) ? fGuid : null;
+ Console.WriteLine($"{SaveSystem.CurrentSave.Username} says \"{result}\".");
+ TerminalBackend.IsForwardingConsoleWrites = false;
+ };
+ Desktop.InvokeOnWorkerThread(new Action(() =>
+ {
+ Infobox.PromptText(args["title"].ToString(), args["msg"].ToString(), callback);
+ }));
+ return true;
+ }
+
+ }
+
+ [Namespace("audio")]
+ public static class AudioCommands
+ {
+ [Command("setvol", description = "Set the volume of the system audio to anywhere between 0 and 100.")]
+ [RequiresArgument("value")]
+ [RequiresUpgrade("audio_volume")]
+ public static bool SetVolume(Dictionary<string,object> args)
+ {
+ int val = Convert.ToInt32(args["value"].ToString());
+ float volume = (val / 100F);
+ AudioManager.SetVolume(volume);
+ return true;
+ }
+ [RequiresUpgrade("audio_volume")]
+ [Command("mute", description = "Sets the volume of the system audio to 0")]
+ public static bool MuteAudio()
+ {
+ AudioManager.SetVolume(0);
+ return true;
+ }
+ }
+
+ [RequiresUpgrade("mud_fundamentals")]
+ [Namespace("mud")]
+ public static class MUDCommands
+ {
+ [MultiplayerOnly]
+ [Command("status")]
+ public static bool Status()
+ {
+ ServerManager.PrintDiagnostics();
+ return true;
+ }
+
+ [Command("connect")]
+ public static bool Connect(Dictionary<string, object> args)
+ {
+ try
+ {
+ string ip = (args.ContainsKey("addr") == true) ? args["addr"] as string : "michaeltheshifter.me";
+ int port = (args.ContainsKey("port") == true) ? Convert.ToInt32(args["port"] as string) : 13370;
+ try
+ {
+ ServerManager.Initiate(ip, port);
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine("{ERROR}: " + ex.Message);
+ }
+
+ TerminalBackend.PrefixEnabled = false;
+ return true;
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine("Error running script:" + ex);
+ return false;
+ }
+ }
+
+ [Command("reconnect")]
+ [RequiresUpgrade("hacker101_deadaccts")]
+ public static bool Reconnect()
+ {
+ Console.WriteLine("--reconnecting to multi-user domain...");
+ KernelWatchdog.MudConnected = true;
+ Console.WriteLine("--done.");
+ return true;
+ }
+
+ [MultiplayerOnly]
+ [Command("disconnect")]
+ [RequiresUpgrade("hacker101_deadaccts")]
+ public static bool Disconnect()
+ {
+ Console.WriteLine("--connection to multi-user domain severed...");
+ KernelWatchdog.MudConnected = false;
+ return true;
+ }
+
+ [MultiplayerOnly]
+ [Command("sendmsg")]
+ [KernelMode]
+ [RequiresUpgrade("hacker101_deadaccts")]
+ [RequiresArgument("header")]
+ [RequiresArgument("body")]
+ public static bool SendMessage(Dictionary<string, object> args)
+ {
+ ServerManager.SendMessage(args["header"].ToString(), args["body"].ToString());
+ return true;
+ }
+ }
+
+ [TutorialLock]
+ [Namespace("trm")]
+ public static class TerminalCommands
+ {
+ [Command("clear")]
+ public static bool Clear()
+ {
+ AppearanceManager.ConsoleOut.Clear();
+ return true;
+ }
+
+ [Command("echo")]
+ [RequiresArgument("text")]
+ public static bool Echo(Dictionary<string, object> args)
+ {
+ Console.WriteLine(args["text"]);
+ return true;
+ }
+ }
+
+#if DEVEL
+ internal class Rock : Exception
+ {
+ internal Rock() : base("Someone threw a rock at the window, and the Terminal shattered.")
+ {
+
+ }
+ }
+
+ [MultiplayerOnly]
+ [Namespace("dev")]
+ public static class ShiftOSDevCommands
+ {
+ [Command("rock", description = "A little surprise for unstable builds...")]
+ public static bool ThrowASandwichingRock()
+ {
+ Infobox.Show("He who lives in a glass house shouldn't throw stones...", new Rock().Message);
+ return false;
+ }
+
+
+ [Command("unbuy")]
+ [RequiresArgument("upgrade")]
+ public static bool UnbuyUpgrade(Dictionary<string, object> args)
+ {
+ try
+ {
+ SaveSystem.CurrentSave.Upgrades[args["upgrade"] as string] = false;
+ }
+ catch
+ {
+ Console.WriteLine("Upgrade not found.");
+ }
+ return true;
+ }
+
+ [Command("getallupgrades")]
+ public static bool GetAllUpgrades()
+ {
+ Console.WriteLine(JsonConvert.SerializeObject(SaveSystem.CurrentSave.Upgrades, Formatting.Indented));
+ return true;
+ }
+
+ [Command("multarg")]
+ [RequiresArgument("id")]
+ [RequiresArgument("name")]
+ [RequiresArgument("type")]
+ public static bool MultArg(Dictionary<string, object> args)
+ {
+ Console.WriteLine("Success! "+args.ToString());
+ return true;
+ }
+
+
+ [Command("freecp")]
+ public static bool FreeCodepoints(Dictionary<string, object> args)
+ {
+ if (args.ContainsKey("amount"))
+ try
+ {
+ int codepointsToAdd = Convert.ToInt32(args["amount"].ToString());
+ SaveSystem.TransferCodepointsFrom("dev", codepointsToAdd);
+ return true;
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine("{ERROR}: " + ex.Message);
+ return true;
+ }
+
+ SaveSystem.TransferCodepointsFrom("dev", 1000);
+ return true;
+ }
+
+ [Command("unlockeverything")]
+ public static bool UnlockAllUpgrades()
+ {
+ foreach (var upg in Shiftorium.GetDefaults())
+ {
+ Shiftorium.Buy(upg.ID, 0);
+ }
+ return true;
+ }
+
+ [Command("info")]
+ public static bool DevInformation()
+ {
+ Console.WriteLine("{SHIFTOS_PLUS_MOTTO}");
+ Console.WriteLine("{SHIFTOS_VERSION_INFO}" + Assembly.GetExecutingAssembly().GetName().Version);
+ return true;
+ }
+ [Command("pullfile")]
+ public static bool PullFile(Dictionary<string, object> args)
+ {
+ if (args.ContainsKey("physical") && args.ContainsKey("virtual"))
+ {
+ string file = (string)args["physical"];
+ string dest = (string)args["virtual"];
+ if (System.IO.File.Exists(file))
+ {
+ Console.WriteLine("Pulling physical file to virtual drive...");
+ byte[] filebytes = System.IO.File.ReadAllBytes(file);
+ ShiftOS.Objects.ShiftFS.Utils.WriteAllBytes(dest, filebytes);
+ }
+ else
+ {
+ Console.WriteLine("The specified file does not exist on the physical drive.");
+ }
+ }
+ else
+ {
+ Console.WriteLine("You must supply a physical path.");
+ }
+ return true;
+ }
+ [Command("crash")]
+ public static bool CrashInstantly()
+ {
+ CrashHandler.Start(new Exception("ShiftOS was sent a command to forcefully crash."));
+ return true;
+ }
+ }
+#endif
+
+ [Namespace("sos")]
+ public static class ShiftOSCommands
+ {
+ [RemoteLock]
+ [Command("shutdown")]
+ public static bool Shutdown()
+ {
+ TerminalBackend.InvokeCommand("sos.save");
+ SaveSystem.ShuttingDown = true;
+ AppearanceManager.Exit();
+ return true;
+ }
+
+ [Command("lang", "{COMMAND_SOS_LANG_USAGE}", "{COMMAND_SOS_LANG_DESCRIPTION}")]
+ [RequiresArgument("language")]
+ public static bool SetLanguage(Dictionary<string, object> userArgs)
+ {
+ try
+ {
+ string lang = "";
+
+ if (userArgs.ContainsKey("language"))
+ lang = (string)userArgs["language"];
+ else
+ throw new Exception("You must specify a valid 'language' value.");
+
+ if (Localization.GetAllLanguages().Contains(lang))
+ {
+ SaveSystem.CurrentSave.Language = lang;
+ SaveSystem.SaveGame();
+ Console.WriteLine("{LANGUAGE_CHANGED}");
+ return true;
+ }
+
+ throw new Exception($"Couldn't find language with ID: {lang}");
+ }
+ catch
+ {
+ return false;
+ }
+ }
+
+ [Command("help", "{COMMAND_HELP_USAGE}", "{COMMAND_HELP_DESCRIPTION}")]
+ public static bool Help()
+ {
+ foreach (var exec in System.IO.Directory.GetFiles(Environment.CurrentDirectory))
+ {
+ if (exec.EndsWith(".exe") || exec.EndsWith(".dll"))
+ {
+ try
+ {
+ var asm = Assembly.LoadFile(exec);
+
+ var types = asm.GetTypes();
+
+ foreach (var type in types)
+ {
+ if (Shiftorium.UpgradeAttributesUnlocked(type))
+ {
+ foreach (var a in type.GetCustomAttributes(false))
+ {
+ if (a is Namespace)
+ {
+ var ns = a as Namespace;
+
+ if (!ns.hide)
+ {
+ string descp = "{NAMESPACE_" + ns.name.ToUpper() + "_DESCRIPTION}";
+ if (descp == Localization.Parse(descp))
+ descp = "";
+ else
+ descp = Shiftorium.UpgradeInstalled("help_description") ? Localization.Parse("{SEPERATOR}" + descp) : "";
+
+ Console.WriteLine($"{{NAMESPACE}}{ns.name}" + descp);
+
+ foreach (var method in type.GetMethods(BindingFlags.Public | BindingFlags.Static))
+ {
+ if (Shiftorium.UpgradeAttributesUnlocked(method))
+ {
+ foreach (var ma in method.GetCustomAttributes(false))
+ {
+ if (ma is Command)
+ {
+ var cmd = ma as Command;
+
+ if (!cmd.hide)
+ {
+ string descriptionparse = "{COMMAND_" + ns.name.ToUpper() + "_" + cmd.name.ToUpper() + "_DESCRIPTION}";
+ string usageparse = "{COMMAND_" + ns.name.ToUpper() + "_" + cmd.name.ToUpper() + "_USAGE}";
+ if (descriptionparse == Localization.Parse(descriptionparse))
+ descriptionparse = "";
+ else
+ descriptionparse = Shiftorium.UpgradeInstalled("help_description") ? Localization.Parse("{SEPERATOR}" + descriptionparse) : "";
+
+ if (usageparse == Localization.Parse(usageparse))
+ usageparse = "";
+ else
+ usageparse = Shiftorium.UpgradeInstalled("help_usage") ? Localization.Parse("{SEPERATOR}" + usageparse, new Dictionary<string, string>() {
+ {"%ns", ns.name},
+ {"%cmd", cmd.name}
+ }) : "";
+
+ Console.WriteLine($"{{COMMAND}}{ns.name}.{cmd.name}" + usageparse + descriptionparse);
+ }
+ }
+ }
+ }
+
+ }
+ }
+
+ }
+ }
+ }
+ }
+
+ }
+ catch { }
+ }
+ }
+
+ return true;
+ }
+
+ [MultiplayerOnly]
+ [Command("save")]
+ public static bool Save()
+ {
+ SaveSystem.SaveGame();
+ return true;
+ }
+
+ [MultiplayerOnly]
+ [Command("status")]
+ public static bool Status()
+ {
+ Console.WriteLine($@"ShiftOS version {Assembly.GetExecutingAssembly().GetName().Version.ToString()}
+
+Codepoints: {SaveSystem.CurrentSave.Codepoints}
+Upgrades: {SaveSystem.CurrentSave.CountUpgrades()} installed,
+ {Shiftorium.GetAvailable().Length} available");
+ return true;
+ }
+ }
+
+ [MultiplayerOnly]
+ [Namespace("shiftorium")]
+ public static class ShiftoriumCommands
+ {
+ [Command("buy")]
+ [RequiresArgument("upgrade")]
+ public static bool BuyUpgrade(Dictionary<string, object> userArgs)
+ {
+ try
+ {
+ string upgrade = "";
+
+ if (userArgs.ContainsKey("upgrade"))
+ upgrade = (string)userArgs["upgrade"];
+ else
+ throw new Exception("You must specify a valid 'upgrade' value.");
+
+ foreach (var upg in Shiftorium.GetAvailable())
+ {
+ if (upg.ID == upgrade)
+ {
+ Shiftorium.Buy(upgrade, upg.Cost);
+ return true;
+ }
+ }
+
+ throw new Exception($"Couldn't find upgrade with ID: {upgrade}");
+ }
+ catch
+ {
+ return false;
+ }
+ }
+
+ [RequiresUpgrade("shiftorium_bulk_buy")]
+ [Command("bulkbuy")]
+ [RequiresArgument("upgrades")]
+ public static bool BuyBulk(Dictionary<string, object> args)
+ {
+ if (args.ContainsKey("upgrades"))
+ {
+ string[] upgrade_list = (args["upgrades"] as string).Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries);
+ foreach (var upg in upgrade_list)
+ {
+ var dict = new Dictionary<string, object>();
+ dict.Add("upgrade", upg);
+ BuyUpgrade(dict);
+ }
+ }
+ else
+ {
+ throw new Exception("Please specify a list of upgrades in the 'upgrades' argument. Each upgrade is separated by a comma.");
+ }
+ return true;
+ }
+
+
+ [Command("info")]
+ public static bool ViewInfo(Dictionary<string, object> userArgs)
+ {
+ try
+ {
+ string upgrade = "";
+
+ if (userArgs.ContainsKey("upgrade"))
+ upgrade = (string)userArgs["upgrade"];
+ else
+ throw new Exception("You must specify a valid 'upgrade' value.");
+
+ foreach (var upg in Shiftorium.GetDefaults())
+ {
+ if (upg.ID == upgrade)
+ {
+ Console.WriteLine($@"Information for {upgrade}:
+
+{upg.Category}: {upg.Name} - {upg.Cost} Codepoints
+------------------------------------------------------
+
+{upg.Description}
+
+To buy this upgrade, run:
+shiftorium.buy{{upgrade:""{upg.ID}""}}");
+ return true;
+ }
+ }
+
+ throw new Exception($"Couldn't find upgrade with ID: {upgrade}");
+ }
+ catch
+ {
+ return false;
+ }
+ }
+
+ [Command("categories")]
+ public static bool ListCategories()
+ {
+ foreach(var cat in Shiftorium.GetCategories())
+ {
+ Console.WriteLine($"{cat} - {Shiftorium.GetAvailable().Where(x=>x.Category==cat).Count()} upgrades");
+ }
+ return true;
+ }
+
+ [Command("list")]
+ public static bool ListAll(Dictionary<string, object> args)
+ {
+ try
+ {
+ bool showOnlyInCategory = false;
+
+ string cat = "Other";
+
+ if (args.ContainsKey("cat"))
+ {
+ showOnlyInCategory = true;
+ cat = args["cat"].ToString();
+ }
+
+ Dictionary<string, int> upgrades = new Dictionary<string, int>();
+ int maxLength = 5;
+
+ IEnumerable<ShiftoriumUpgrade> upglist = Shiftorium.GetAvailable();
+ if (showOnlyInCategory)
+ {
+ if (Shiftorium.IsCategoryEmptied(cat))
+ {
+ ConsoleEx.Bold = true;
+ ConsoleEx.ForegroundColor = ConsoleColor.Red;
+ Console.WriteLine("Shiftorium Query Error");
+ Console.WriteLine();
+ ConsoleEx.Bold = false;
+ ConsoleEx.ForegroundColor = ConsoleColor.Gray;
+ Console.WriteLine("Either there are no upgrades in the category \"" + cat + "\" or the category was not found.");
+ return true;
+ }
+ upglist = Shiftorium.GetAvailable().Where(x => x.Category == cat);
+ }
+
+
+ if(upglist.Count() == 0)
+ {
+ ConsoleEx.Bold = true;
+ ConsoleEx.ForegroundColor = ConsoleColor.Red;
+ Console.WriteLine("No upgrades available!");
+ Console.WriteLine();
+ ConsoleEx.Bold = false;
+ ConsoleEx.ForegroundColor = ConsoleColor.Gray;
+ Console.WriteLine("You have installed all available upgrades for your system. Please check back later for more.");
+ return true;
+
+ }
+ foreach (var upg in upglist)
+ {
+ if (upg.ID.Length > maxLength)
+ {
+ maxLength = upg.ID.Length;
+ }
+
+ upgrades.Add(upg.ID, upg.Cost);
+ }
+
+ Console.WriteLine("ID".PadRight((maxLength + 5) - 2) + "Cost (Codepoints)");
+
+ foreach (var upg in upgrades)
+ {
+ Console.WriteLine(upg.Key.PadRight((maxLength + 5) - upg.Key.Length) + " " + upg.Value.ToString());
+ }
+ return true;
+ }
+ catch (Exception e)
+ {
+ CrashHandler.Start(e);
+ return false;
+ }
+ }
+ }
+
+ [Namespace("win")]
+ public static class WindowCommands
+ {
+
+
+
+ [RemoteLock]
+ [Command("list")]
+ public static bool List()
+ {
+ Console.WriteLine("Window ID\tName");
+ foreach (var app in AppearanceManager.OpenForms)
+ {
+ //Windows are displayed the order in which they were opened.
+ Console.WriteLine($"{AppearanceManager.OpenForms.IndexOf(app)}\t{app.Text}");
+ }
+ return true;
+ }
+
+ [RemoteLock]
+ [Command("open")]
+ public static bool Open(Dictionary<string, object> args)
+ {
+ try
+ {
+ if (args.ContainsKey("app"))
+ {
+ var app = args["app"] as string;
+ //ANNND now we start reflecting...
+ foreach (var asmExec in System.IO.Directory.GetFiles(Environment.CurrentDirectory))
+ {
+ if (asmExec.EndsWith(".exe") || asmExec.EndsWith(".dll"))
+ {
+ var asm = Assembly.LoadFile(asmExec);
+ try
+ {
+ foreach (var type in asm.GetTypes())
+ {
+ if (type.BaseType == typeof(UserControl))
+ {
+ foreach (var attr in type.GetCustomAttributes(false))
+ {
+ if (attr is WinOpenAttribute)
+ {
+ if (app == (attr as WinOpenAttribute).ID)
+ {
+ if (SaveSystem.CurrentSave.Upgrades.ContainsKey(app))
+ {
+ if (Shiftorium.UpgradeInstalled(app))
+ {
+ IShiftOSWindow frm = Activator.CreateInstance(type) as IShiftOSWindow;
+ AppearanceManager.SetupWindow(frm);
+ return true;
+ }
+ else
+ {
+ throw new Exception($"{app} was not found on your system! Try looking in the shiftorium...");
+ }
+ }
+ else
+ {
+ IShiftOSWindow frm = Activator.CreateInstance(type) as IShiftOSWindow;
+ AppearanceManager.SetupWindow(frm);
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ catch { }
+
+ }
+ }
+
+ }
+ else
+ {
+ foreach (var asmExec in System.IO.Directory.GetFiles(Environment.CurrentDirectory))
+ {
+ if (asmExec.EndsWith(".exe") || asmExec.EndsWith(".dll"))
+ {
+ try
+ {
+ var asm = Assembly.LoadFile(asmExec);
+
+ foreach (var type in asm.GetTypes())
+ {
+ if (type.GetInterfaces().Contains(typeof(IShiftOSWindow)))
+ {
+ foreach (var attr in type.GetCustomAttributes(false))
+ {
+ if (attr is WinOpenAttribute)
+ {
+ if (Shiftorium.UpgradeAttributesUnlocked(type))
+ {
+ Console.WriteLine("win.open{app:\"" + (attr as WinOpenAttribute).ID + "\"}");
+ }
+ }
+ }
+ }
+ }
+ }
+ catch { }
+ }
+ }
+
+
+ return true;
+ }
+ Console.WriteLine("Couldn't find the specified app on your system.");
+ return true;
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine("Error running script:" + ex);
+ return false;
+ }
+ }
+
+ [RemoteLock]
+ [Command("close", usage = "{win:integer32}", description ="Closes the specified window.")]
+ [RequiresArgument("win")]
+ [RequiresUpgrade("close_command")]
+ public static bool CloseWindow(Dictionary<string, object> args)
+ {
+ int winNum = -1;
+ if (args.ContainsKey("win"))
+ winNum = Convert.ToInt32(args["win"].ToString());
+ string err = null;
+
+ if (winNum < 0 || winNum >= AppearanceManager.OpenForms.Count)
+ err = "The window number must be between 0 and " + (AppearanceManager.OpenForms.Count - 1).ToString() + ".";
+
+ if (string.IsNullOrEmpty(err))
+ {
+ Console.WriteLine($"Closing {AppearanceManager.OpenForms[winNum].Text}...");
+ AppearanceManager.Close(AppearanceManager.OpenForms[winNum].ParentWindow);
+ }
+ else
+ {
+ Console.WriteLine(err);
+ }
+
+ return true;
+ }
+
+ }
+}
diff --git a/ShiftOS_TheReturn/Localization.cs b/ShiftOS_TheReturn/Localization.cs
new file mode 100644
index 0000000..c1a6bd6
--- /dev/null
+++ b/ShiftOS_TheReturn/Localization.cs
@@ -0,0 +1,219 @@
+/*
+ * 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 Newtonsoft.Json;
+using ShiftOS.Objects.ShiftFS;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ShiftOS.Engine
+{
+ public interface ILanguageProvider
+ {
+ List<string> GetJSONTranscripts();
+ void WriteDefaultTranscript();
+ void WriteTranscript();
+ string GetCurrentTranscript();
+ string[] GetAllLanguages();
+ }
+
+ public static class Localization
+ {
+ private static ILanguageProvider _provider = null;
+ private static string _languageid = null;
+
+ public static string[] GetAllLanguages()
+ {
+ if(_provider == null)
+ {
+ return JsonConvert.DeserializeObject<string[]>(Properties.Resources.languages);
+ }
+ else
+ {
+ return _provider.GetAllLanguages();
+ }
+ }
+
+ public static void SetupTHETRUEDefaultLocals()
+ {
+ if (_provider == null)
+ {
+ var lines = Properties.Resources.strings_en;
+ var path = "english.local";
+ Utils.WriteAllText(Paths.GetPath(path), lines);
+ }
+ else if (SaveSystem.CurrentSave == null)
+ {
+ var lines = Properties.Resources.strings_en;
+ var path = "english.local";
+ Utils.WriteAllText(Paths.GetPath(path), lines);
+ }
+ else
+ {
+ _provider.WriteTranscript();
+ }
+ }
+
+ public static void SetupDefaultLocals(string lines, string path)
+ {
+ Utils.WriteAllText(Paths.GetPath(path), lines);
+
+ }
+
+
+ /// <summary>
+ /// Takes in a string and parses localization blocks into text blocks in the current language.
+ /// </summary>
+ /// <example>"{CODEPOINTS}: 0" will come out as "Codepoints: 0" if the current language is english.</example>
+ /// <param name="original">The string to parse</param>
+ /// <returns>The parsed string.</returns>
+ ///
+ public static string Parse(string original)
+ {
+ return Parse(original, new Dictionary<string, string>());
+ }
+
+
+ public static string Parse(string original, Dictionary<string, string> replace)
+ {
+ Dictionary<string, string> localizationStrings = new Dictionary<string, string>();
+
+
+
+ try
+ {
+ localizationStrings = JsonConvert.DeserializeObject<Dictionary<string, string>>(_provider.GetCurrentTranscript());
+ }
+ catch
+ {
+ localizationStrings = JsonConvert.DeserializeObject<Dictionary<string, string>>(Utils.ReadAllText(Paths.GetPath("english.local")));
+ }
+
+ foreach (var kv in localizationStrings)
+ {
+ original = original.Replace(kv.Key, kv.Value);
+ }
+
+ List<string> orphaned = new List<string>();
+ if (Utils.FileExists("0:/dev_orphaned_lang.txt"))
+ {
+ orphaned = JsonConvert.DeserializeObject<List<string>>(Utils.ReadAllText("0:/dev_orphaned_lang.txt"));
+ }
+
+
+ int start_index = 0;
+ int length = 0;
+ bool indexing = false;
+
+ foreach (var c in original)
+ {
+ if (c == '{')
+ {
+ start_index = original.IndexOf(c);
+ indexing = true;
+ }
+
+ if (indexing == true)
+ {
+ length++;
+ if (c == '}')
+ {
+ indexing = false;
+ string o = original.Substring(start_index, length);
+ if (!orphaned.Contains(o))
+ {
+ orphaned.Add(o);
+ }
+ start_index = 0;
+ length = 0;
+ }
+ }
+ }
+
+ if (orphaned.Count > 0)
+ {
+ Utils.WriteAllText("0:/dev_orphaned_lang.txt", JsonConvert.SerializeObject(orphaned, Formatting.Indented));
+ }
+
+ //string original2 = Parse(original);
+
+ string usernameReplace = "";
+ string domainReplace = "";
+
+ if (SaveSystem.CurrentSave != null)
+ {
+ usernameReplace = SaveSystem.CurrentSave.Username;
+ domainReplace = SaveSystem.CurrentSave.SystemName;
+ }
+
+ string namespaceReplace = "";
+ string commandReplace = "";
+
+ if (TerminalBackend.latestCommmand != "" && TerminalBackend.latestCommmand.IndexOf('.') > -1)
+ {
+ namespaceReplace = TerminalBackend.latestCommmand.Split('.')[0];
+ commandReplace = TerminalBackend.latestCommmand.Split('.')[1];
+ }
+
+ Dictionary<string, string> defaultReplace = new Dictionary<string, string>() {
+ {"%username", usernameReplace},
+ {"%domain", domainReplace},
+ {"%ns", namespaceReplace},
+ {"%cmd", commandReplace},
+ {"%cp", SaveSystem.CurrentSave?.Codepoints.ToString() },
+ };
+
+ foreach (KeyValuePair<string, string> replacement in replace)
+ {
+ original = original.Replace(replacement.Key, Parse(replacement.Value));
+ }
+
+ foreach (KeyValuePair<string, string> replacement in defaultReplace)
+ {
+ original = original.Replace(replacement.Key, replacement.Value);
+ }
+
+ return original;
+ }
+
+ public static void RegisterProvider(ILanguageProvider p)
+ {
+ _provider = p;
+ }
+
+ public static void SetLanguageID(string id)
+ {
+ _languageid = id;
+ }
+
+ public static string GetLanguageID()
+ {
+ return _languageid;
+ }
+ }
+}
diff --git a/ShiftOS_TheReturn/Resources/strings_de.txt b/ShiftOS_TheReturn/Resources/strings_de.txt
index 10535c8..06ef9d7 100644
--- a/ShiftOS_TheReturn/Resources/strings_de.txt
+++ b/ShiftOS_TheReturn/Resources/strings_de.txt
@@ -36,7 +36,7 @@ Wenn eine Systemdatei von dem Virenscanner erkannt wird, wird sie ersetzt.",
"{TERMINAL}":"Terminal",
"{PONG}":"Pong",
"{CODEPOINTS}":"Codepoints",
- "{CODEPOINTS_VALUE}":"%cp "
+ "{CODEPOINTS_VALUE}":"%cp ",
"{SHIFTORIUM}":"Shiftorium",
"{HACK}":"Hack",
"{SHIFTER}":"Shifter",
@@ -151,15 +151,17 @@ Wenn eine Systemdatei von dem Virenscanner erkannt wird, wird sie ersetzt.",
"{ERROR_COMMAND_WRONG}": "Check your syntax and try again",
"{LOGIN_EXP}": "Login as the admin of the multi user domain.",
- "{USAGE}": "Usage: ",
+ "{USAGE}": "Verwendung: ",
"{NAMESPACE_SOS_DESCRIPTION}":"The ShiftOS Namespace",
"{COMMAND_HELP_USAGE}":"%ns.%cmd{[topic:]}",
- "{COMMAND_HELP_DESCRIPTION}":"Lists all commands",
+ "{COMMAND_HELP_DESCRIPTION}":"Listet alle Befehle auf",
"{COMMAND_SOS_SHUTDOWN_USAGE}":"%ns.%cmd",
"{COMMAND_SOS_SHUTDOWN_DESCRIPTION}":"Saves and shuts down ShiftOS",
"{COMMAND_SOS_STATUS_USAGE}":"%ns.%cmd",
"{COMMAND_SOS_STATUS_DESCRIPTION}":"Displays how many codepoints you have",
+ "{COMMAND_SOS_LANG_USAGE}":"%ns.%cmd{[language:\"english\"]}",
+ "{COMMAND_SOS_LANG_DESCRIPTION}":"Sprache �ndern.",
"{COMMAND_DEV_CRASH_USAGE}":"%ns.%cmd",
"{COMMAND_DEV_CRASH_DESCRIPTION}":"Shuts down ShiftOS forcefully",
"{COMMAND_DEV_UNLOCKEVERYTHING_USAGE}":"%ns.%cmd",
@@ -177,7 +179,7 @@ Wenn eine Systemdatei von dem Virenscanner erkannt wird, wird sie ersetzt.",
"{COMMAND_DEV_MULTARG_USAGE}":"%ns.%cmd{id:,name:,type:}",
"{COMMAND_DEV_MULTARG_DESCRIPTION}":"A command which requiers multiple arguments",
- "{ERR_COMMAND_NOT_FOUND}":"Command not found.",
+ "{ERR_COMMAND_NOT_FOUND}":"Befehl nicht gefunden.",
"{MUD_ERROR}":"MUD error",
"{PROLOGUE_NO_USER_DETECTED}":"No user detected. Please enter a username.",
@@ -200,26 +202,44 @@ Wenn eine Systemdatei von dem Virenscanner erkannt wird, wird sie ersetzt.",
"{SENTIENCE_POSSIBLEHUMAN}":"Sentience: Possible human - user can perform actions based on a choice.",
"{SENTIENCE_POSSIBLEHUMANPLUS}":"Sentience: Possible human+ - user can infer, and can pass arguments.",
"{SENTIENCE_HUMAN}":"Sentience: Human. Thanks for your patience.",
- "{SENTIENCE_INVALIDPASSWORD}":"The password you entered is invalid.",
+ "{SENTIENCE_INVALIDPASSWORD}":"Das eingegebene Passwort ist ung�ltig.",
"{ARGS_PASSWORD}":"password",
"{SHIFTOS_PLUS_MOTTO}":"ShiftOS, Shift it YOUR way.",
"{SHIFTOS_VERSION_INFO}":"ShiftOS Version: ",
- "{USER_NAME}":"Username",
+ "{USER_NAME}":"Benutzername",
"{DISCOURSE_INTEGRATION}":"Discourse Integration",
"{SYSTEM_NAME}":"System Name",
"{USER_INFO}":"User Information",
"{SELECT_LANG}":"Select language",
"{WELCOME_TO_SHIFTOS}":"Welcome to ShiftOS Alpha!",
- "{CREATE}":"Create",
- "{INSTALL}":"Install",
+ "{CREATE}":"Erstellen",
+ "{INSTALL}":"Installieren",
"{ALIAS}":"Alias:",
"{OBSOLETE_SYS_SHUTDOWN}":"sys.shutdown is obsolete",
"{PY_EXCEPTION}":"There was an error running python code.",
- "{LUA_ERROR}":"There was an error running lua code."
+ "{LUA_ERROR}":"There was an error running lua code.",
+ "{LANGUAGE_CHANGED}":"Die Sprache wurde ge�ndert. Bitte �ndern Sie ShiftOS neu, damit �nderungen voll wirksam werden.",
"{TERMINAL_NAME}":"Terminal",
"{ARTPAD_NAME}":"Artpad",
"{PONG_NAME}":"Pong",
+ "{WAV_PLAYER_NAME}":"WAV Player",
+ "{SHIFTORIUM_NAME}":"Shiftorium",
+ "{TEXTPAD_NAME}":"TextPad",
+ "{VIRUS_SCANNER_NAME}":"Virus Scanner",
+ "{SKIN_LOADER_NAME}":"Skin Loader",
+ "{SHIFTER_NAME}":"Shifter",
+ "{NAME_CHANGER_NAME}":"Name Changer",
+ "{MUD_PASSWORD_CRACKER_NAME}":"Multi-User Domain Password Cracker v1.0",
+ "{MUD_CONTROL_CENTRE_NAME}":"MUD Control Centre",
+ "{MUD_AUTHENTICATOR_NAME}":"Multi-User Domain Admin Panel",
+ "{GRAPHIC_PICKER_NAME}":"Graphic Picker",
+ "{FILE_SKIMMER_NAME}":"File Skimmer",
+ "{FILE_DIALOG_NAME}":"File Dialog",
+ "{DIALOG_NAME}":"Dialog",
+ "{COLOR_PICKER_NAME}":"Color Picker",
+ "{CHAT_NAME}":"Chat",
+ "{GERMAN_SECRET}":"guten tag polen ist anschluss",
} \ No newline at end of file
diff --git a/ShiftOS_TheReturn/Resources/strings_en.txt b/ShiftOS_TheReturn/Resources/strings_en.txt
index c42edab..68719c0 100644
--- a/ShiftOS_TheReturn/Resources/strings_en.txt
+++ b/ShiftOS_TheReturn/Resources/strings_en.txt
@@ -32,7 +32,7 @@ If a system file is deleted by the virus scanner, it will be replaced.",
"{TERMINAL}":"Terminal",
"{PONG}":"Pong",
"{CODEPOINTS}":"Codepoints",
- "{CODEPOINTS_VALUE}":"%cp "
+ "{CODEPOINTS_VALUE}":"%cp ",
"{SHIFTORIUM}":"Shiftorium",
"{HACK}":"Hack",
"{SHIFTER}":"Shifter",
@@ -215,7 +215,7 @@ If a system file is deleted by the virus scanner, it will be replaced.",
"{ALIAS}":"Alias:",
"{OBSOLETE_SYS_SHUTDOWN}":"sys.shutdown is obsolete",
"{PY_EXCEPTION}":"There was an error running python code.",
- "{LUA_ERROR}":"There was an error running lua code."
+ "{LUA_ERROR}":"There was an error running lua code.",
"{TERMINAL_NAME}":"Terminal",
"{ARTPAD_NAME}":"Artpad",
diff --git a/ShiftOS_TheReturn/SaveSystem.cs b/ShiftOS_TheReturn/SaveSystem.cs
new file mode 100644
index 0000000..9ff3111
--- /dev/null
+++ b/ShiftOS_TheReturn/SaveSystem.cs
@@ -0,0 +1,332 @@
+/*
+ * 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.
+ */
+
+//#define ONLINEMODE
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using System.IO;
+using Newtonsoft.Json;
+using ShiftOS.Objects;
+using ShiftOS.Objects.ShiftFS;
+using oobe = ShiftOS.Engine.OutOfBoxExperience;
+using static System.Net.Mime.MediaTypeNames;
+
+namespace ShiftOS.Engine
+{
+ public class EngineConfig
+ {
+ public bool ConnectToMud = true;
+ public string MudDefaultIP = "dome.rol.im";
+ public int MudDefaultPort = 13370;
+ }
+
+ public static class SaveSystem
+ {
+ public static bool ShuttingDown = false;
+
+ public static Save CurrentSave { get; set; }
+
+ /// <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 = 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)
+ {
+ bool guidReceived = false;
+ ServerManager.GUIDReceived += (str) =>
+ {
+ //Connection successful! Stop waiting!
+ guidReceived = true;
+ Console.WriteLine("Connection successful.");
+ };
+
+ try
+ {
+
+ ServerManager.Initiate("secondary4162.cloudapp.net", 13370);
+ //This haults the client until the connection is successful.
+ while (ServerManager.thisGuid == new Guid())
+ {
+
+ }
+ Console.WriteLine("GUID received - bootstrapping complete.");
+ FinishBootstrap();
+ }
+ catch (Exception ex)
+ {
+ //No errors, this never gets called.
+ Console.WriteLine("{ERROR}: " + ex.Message);
+ Thread.Sleep(3000);
+ ServerManager.StartLANServer();
+ while (ServerManager.thisGuid == new Guid())
+ {
+
+ }
+ Console.WriteLine("GUID received - bootstrapping complete.");
+ FinishBootstrap();
+ }
+ }
+ else
+ {
+ ServerManager.StartLANServer();
+ }
+
+ //Nothing happens past this point - but the client IS connected! It shouldn't be stuck in that while loop above.
+
+
+ }));
+ thread.IsBackground = true;
+ thread.Start();
+ }
+
+ public static void FinishBootstrap()
+ {
+ KernelWatchdog.Log("mud_handshake", "handshake successful: kernel watchdog access code is \"" + ServerManager.thisGuid.ToString() + "\"");
+
+ 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)
+ {
+
+ }
+
+ Localization.SetupTHETRUEDefaultLocals();
+
+ Shiftorium.Init();
+
+ while (CurrentSave.StoryPosition < 1)
+ {
+
+ }
+
+ Thread.Sleep(75);
+
+ Thread.Sleep(50);
+ Console.WriteLine("{SYSTEM_INITIATED}");
+
+ TerminalBackend.InStory = false;
+ TerminalBackend.PrefixEnabled = true;
+ Shiftorium.LogOrphanedUpgrades = true;
+ Desktop.InvokeOnWorkerThread(new Action(() =>
+ {
+ ShiftOS.Engine.Scripting.LuaInterpreter.RunSft(Paths.GetPath("kernel.sft"));
+ }));
+ Desktop.InvokeOnWorkerThread(new Action(() => Desktop.PopulateAppLauncher()));
+ if (CurrentSave.StoryPosition == 1)
+ {
+ Desktop.InvokeOnWorkerThread(new Action(() =>
+ {
+ TutorialManager.StartTutorial();
+
+ }));
+ while (TutorialManager.IsInTutorial == true) { }
+ GameReady?.Invoke();
+ }
+ else
+ {
+ GameReady?.Invoke();
+ }
+ }
+
+ public delegate void EmptyEventHandler();
+
+ public static List<ClientSave> Users
+ {
+ get;
+ private set;
+ }
+
+ public static event EmptyEventHandler GameReady;
+
+ public static void TransferCodepointsToVoid(int amount)
+ {
+ CurrentSave.Codepoints -= amount;
+ NotificationDaemon.AddNotification(NotificationType.CodepointsSent, amount);
+ }
+
+ public static void Restart()
+ {
+ TerminalBackend.InvokeCommand("sos.shutdown");
+ System.Windows.Forms.Application.Restart();
+ }
+
+ public static void ReadSave()
+ {
+ //Migrate old saves.
+ if(System.IO.Directory.Exists("C:\\ShiftOS2"))
+ {
+ Console.WriteLine("Old save detected. Migrating filesystem to MFS...");
+ foreach (string file in System.IO.Directory.EnumerateDirectories("C:\\ShiftOS2")
+.Select(d => new DirectoryInfo(d).FullName))
+ {
+ if(!Utils.DirectoryExists(file.Replace("C:\\ShiftOS2\\", "0:/").Replace("\\", "/")))
+ Utils.CreateDirectory(file.Replace("C:\\ShiftOS2\\", "0:/").Replace("\\", "/"));
+ }
+ foreach (string file in System.IO.Directory.EnumerateFiles("C:\\ShiftOS2"))
+ {
+
+ string rfile = Path.GetFileName(file);
+ Utils.WriteAllBytes(file.Replace("C:\\ShiftOS2\\", "0:/").Replace("\\", "/"), System.IO.File.ReadAllBytes(file));
+ Console.WriteLine("Exported file " + file);
+ }
+
+ }
+
+
+ if (Utils.FileExists(Paths.SaveFileInner))
+ {
+ oobe.ShowSaveTransfer(JsonConvert.DeserializeObject<Save>(Utils.ReadAllText(Paths.SaveFileInner)));
+ }
+ else
+ {
+ if (Utils.FileExists(Paths.GetPath("user.dat")))
+ {
+ var userdat = JsonConvert.DeserializeObject<ClientSave>(Utils.ReadAllText(Paths.GetPath("user.dat")));
+
+ ServerManager.SendMessage("mud_login", $@"{{
+ username: ""{userdat.Username}"",
+ password: ""{userdat.Password}""
+}}");
+ }
+ else
+ {
+ NewSave();
+ }
+ }
+
+ }
+
+ public static void NewSave()
+ {
+ AppearanceManager.Invoke(new Action(() =>
+ {
+ CurrentSave = new Save();
+ CurrentSave.Codepoints = 0;
+ CurrentSave.Upgrades = new Dictionary<string, bool>();
+ Shiftorium.Init();
+ oobe.Start(CurrentSave);
+ }));
+ }
+
+ public static void SaveGame()
+ {
+ if(!Shiftorium.Silent)
+ Console.WriteLine("");
+ if(!Shiftorium.Silent)
+ Console.Write("{SE_SAVING}... ");
+ if (SaveSystem.CurrentSave != null)
+ {
+ string username = CurrentSave.Username;
+ string password = CurrentSave.Password;
+
+ Utils.WriteAllText(Paths.GetPath("user.dat"), $@"{{
+ username: ""{username}"",
+ password: ""{password}""
+}}");
+
+ ServerManager.SendMessage("mud_save", JsonConvert.SerializeObject(CurrentSave, Formatting.Indented));
+ }
+ if (!Shiftorium.Silent)
+ Console.WriteLine(" ...{DONE}.");
+ System.IO.File.WriteAllText(Paths.SaveFile, Utils.ExportMount(0));
+ }
+
+ public static void TransferCodepointsFrom(string who, long amount)
+ {
+ NotificationDaemon.AddNotification(NotificationType.CodepointsReceived, amount);
+ CurrentSave.Codepoints += amount;
+ }
+ }
+
+ public delegate void TextSentEventHandler(string text);
+
+ public class DeveloperAttribute : Attribute
+ {
+
+ }
+}
diff --git a/ShiftOS_TheReturn/ServerManager.cs b/ShiftOS_TheReturn/ServerManager.cs
new file mode 100644
index 0000000..4fce247
--- /dev/null
+++ b/ShiftOS_TheReturn/ServerManager.cs
@@ -0,0 +1,248 @@
+/*
+ * 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;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using ShiftOS.Objects;
+using NetSockets;
+using System.Windows.Forms;
+using System.Threading;
+using ShiftOS;
+using static ShiftOS.Engine.SaveSystem;
+using Newtonsoft.Json;
+
+namespace ShiftOS.Engine
+{
+ public static class ServerManager
+ {
+ public static void PrintDiagnostics()
+ {
+ Console.WriteLine($@"{{CLIENT_DIAGNOSTICS}}
+
+{{GUID}}: {thisGuid}
+{{CLIENT_DATA}}:
+
+{JsonConvert.SerializeObject(client, Formatting.Indented)}");
+ }
+
+ public static Guid thisGuid { get; private set; }
+ private static NetObjectClient client { get; set; }
+ private static bool UserDisconnect = false;
+
+ public static void Disconnect()
+ {
+ UserDisconnect = true;
+ if (client != null)
+ {
+ client.Disconnect();
+ }
+ Disconnected?.Invoke();
+
+ }
+
+ public static event EmptyEventHandler Disconnected;
+
+ public static void InitiateMUDHack()
+ {
+ MessageReceived += ServerManager_MessageReceived;
+ SendMessage("mudhack_init", "");
+ }
+
+ public static event Action<string> ServerPasswordGenerated;
+ public static event EmptyEventHandler ServerAccessGranted;
+ public static event EmptyEventHandler ServerAccessDenied;
+ public static event Action<string> GUIDReceived;
+ public static event Action<List<OnlineUser>> UsersReceived;
+
+ private static void ServerManager_MessageReceived(ServerMessage msg)
+ {
+ switch(msg.Name)
+ {
+ case "mudhack_users":
+ UsersReceived?.Invoke(JsonConvert.DeserializeObject<List<OnlineUser>>(msg.Contents));
+ break;
+ case "mudhack_init":
+ ServerPasswordGenerated?.Invoke(msg.Contents);
+ break;
+ case "mudhack_denied":
+ ServerAccessDenied?.Invoke();
+ break;
+ case "mudhack_granted":
+ ServerAccessGranted?.Invoke();
+ break;
+ case "getguid_fromserver":
+ if(SaveSystem.CurrentSave.Username == msg.Contents)
+ {
+ client.Send(new NetObject("yes_i_am", new ServerMessage
+ {
+ Name = "getguid_reply",
+ GUID = msg.GUID,
+ Contents = thisGuid.ToString(),
+ }));
+ }
+ break;
+ case "getguid_reply":
+ GUIDReceived?.Invoke(msg.Contents);
+ break;
+ }
+ }
+
+ public static void Detach_ServerManager_MessageReceived()
+ {
+ MessageReceived -= new ServerMessageReceived(ServerManager_MessageReceived);
+ }
+
+ public static void Initiate(string mud_address, int port)
+ {
+ client = new NetObjectClient();
+ client.OnDisconnected += (o, a) =>
+ {
+ if (!UserDisconnect)
+ {
+ 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) =>
+ {
+ var msg = a.Data.Object as ServerMessage;
+ if (msg.Name == "Welcome")
+ {
+ thisGuid = new Guid(msg.Contents);
+ GUIDReceived?.Invoke(msg.Contents);
+ 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.CurrentSave.Username)
+ {
+ SaveSystem.CurrentSave.Codepoints += (long)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 == "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);
+ }
+ };
+
+ client.Connect(mud_address, port);
+
+ }
+
+ public static void SendMessage(string name, string contents)
+ {
+ var sMsg = new ServerMessage
+ {
+ Name = name,
+ Contents = contents,
+ GUID = thisGuid.ToString(),
+ };
+
+ client.Send(new NetObject("msg", sMsg));
+
+ }
+
+ private static bool singleplayer = false;
+ public static bool IsSingleplayer { get { return singleplayer; } }
+
+ public static void StartLANServer()
+ {
+ singleplayer = true;
+ ShiftOS.Server.Program.ServerStarted += (address) =>
+ {
+ Console.WriteLine($"Connecting to {address}...");
+ Initiate(address, 13370);
+ };
+ Disconnected += () =>
+ {
+ ShiftOS.Server.Program.Stop();
+ };
+ ShiftOS.Server.Program.Main(new[] { "" });
+
+
+ }
+
+
+ public static event ServerMessageReceived MessageReceived;
+
+ }
+
+ public delegate void ServerMessageReceived(ServerMessage msg);
+
+ public class MultiplayerOnlyAttribute : Attribute
+ {
+ /// <summary>
+ /// Marks this application as a multiplayer-only application.
+ /// </summary>
+ public MultiplayerOnlyAttribute()
+ {
+
+ }
+ }
+}
diff --git a/ShiftOS_TheReturn/Shiftorium.cs b/ShiftOS_TheReturn/Shiftorium.cs
new file mode 100644
index 0000000..43ea13a
--- /dev/null
+++ b/ShiftOS_TheReturn/Shiftorium.cs
@@ -0,0 +1,332 @@
+/*
+ * 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 Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+using static ShiftOS.Engine.SaveSystem;
+using System.Diagnostics;
+
+namespace ShiftOS.Engine
+{
+ public static class Shiftorium
+ {
+ /// <summary>
+ /// Whether or not shiftorium output should be written to the console.
+ /// </summary>
+ public static bool Silent = false;
+
+ /// <summary>
+ /// Gets all Shiftorium categories.
+ /// </summary>
+ /// <param name="onlyAvailable">Should we look in the "available" upgrade list (i.e, what the user can buy right now), or the full upgrade list?</param>
+ /// <returns>All Shiftorium categories from the list, in a <see cref="System.String[]"/>. </returns>
+ public static string[] GetCategories(bool onlyAvailable = true)
+ {
+ List<string> cats = new List<string>();
+ IEnumerable < ShiftoriumUpgrade > upgrades = GetDefaults();
+ if (onlyAvailable)
+ upgrades = new List<ShiftoriumUpgrade>(GetAvailable());
+
+ foreach(var upg in upgrades)
+ {
+ if (!cats.Contains(upg.Category))
+ cats.Add(upg.Category);
+ }
+
+ return cats.ToArray();
+ }
+
+ public static void InvokeUpgradeInstalled()
+ {
+ Installed?.Invoke();
+ }
+
+ public static string GetCategory(string id)
+ {
+ var upg = GetDefaults().FirstOrDefault(x => x.ID == id);
+ if (upg == null)
+ return "Other";
+ return (upg.Category == null) ? "Other" : upg.Category;
+ }
+
+ public static IEnumerable<ShiftoriumUpgrade> GetAllInCategory(string cat)
+ {
+ return GetDefaults().Where(x => x.Category == cat);
+ }
+
+ public static bool IsCategoryEmptied(string cat)
+ {
+ return GetDefaults().Where(x => x.Category == cat).FirstOrDefault(x => x.Installed == false) == null;
+ }
+
+ public static bool Buy(string id, int 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;
+ }
+ }
+
+ public static bool UpgradeAttributesUnlocked(Type type)
+ {
+ foreach(var attr in type.GetCustomAttributes(true))
+ {
+ if(attr is RequiresUpgradeAttribute)
+ {
+ var rAttr = attr as RequiresUpgradeAttribute;
+ return rAttr.Installed;
+ }
+ }
+
+ return true;
+ }
+
+ public static bool UpgradeAttributesUnlocked(MethodInfo type)
+ {
+ foreach (var attr in type.GetCustomAttributes(true))
+ {
+ if (attr is RequiresUpgradeAttribute)
+ {
+ var rAttr = attr as RequiresUpgradeAttribute;
+ return rAttr.Installed;
+ }
+ }
+
+ return true;
+ }
+
+ public static bool UpgradeAttributesUnlocked(PropertyInfo type)
+ {
+ foreach (var attr in type.GetCustomAttributes(true))
+ {
+ if (attr is RequiresUpgradeAttribute)
+ {
+ var rAttr = attr as RequiresUpgradeAttribute;
+ return rAttr.Installed;
+ }
+ }
+
+ return true;
+ }
+
+ public static bool UpgradeAttributesUnlocked(FieldInfo type)
+ {
+ foreach (var attr in type.GetCustomAttributes(true))
+ {
+ if (attr is RequiresUpgradeAttribute)
+ {
+ var rAttr = attr as RequiresUpgradeAttribute;
+ return rAttr.Installed;
+ }
+ }
+
+ return true;
+ }
+
+ public static bool IsInitiated { get; private set; }
+
+ public static void Init()
+ {
+ if (IsInitiated == false)
+ {
+ IsInitiated = true;
+ //Let the crash handler deal with this one...
+ var dict = GetDefaults();
+ foreach (var itm in dict)
+ {
+ if (!SaveSystem.CurrentSave.Upgrades.ContainsKey(itm.ID))
+ {
+ try
+ {
+ SaveSystem.CurrentSave.Upgrades.Add(itm.ID, false);
+ }
+ catch
+ {
+
+ }
+ }
+ }
+ }
+
+ }
+
+ public static int GetCPValue(string id)
+ {
+ foreach(var upg in GetDefaults())
+ {
+ if (upg.ID == id)
+ return upg.Cost;
+ }
+ return 0;
+ }
+
+ public static ShiftoriumUpgrade[] GetAvailable()
+ {
+ List<ShiftoriumUpgrade> available = new List<ShiftoriumUpgrade>();
+ foreach(var defaultupg in GetDefaults())
+ {
+ if (!UpgradeInstalled(defaultupg.ID) && DependenciesInstalled(defaultupg))
+ available.Add(defaultupg);
+ }
+ return available.ToArray();
+ }
+
+ public static bool DependenciesInstalled(ShiftoriumUpgrade upg)
+ {
+ if (string.IsNullOrEmpty(upg.Dependencies))
+ {
+ return true;//root upgrade, no parents
+ }
+ else if (upg.Dependencies.Contains(";"))
+ {
+ string[] dependencies = upg.Dependencies.Split(';');
+ foreach(var dependency in dependencies)
+ {
+ if (!UpgradeInstalled(dependency))
+ return false;
+ }
+ return true;
+ }
+ else
+ {
+ return UpgradeInstalled(upg.Dependencies);
+ }
+ }
+
+ public static event EmptyEventHandler Installed;
+
+ public static bool UpgradeInstalled(string id)
+ {
+ if (SaveSystem.CurrentSave != null)
+ {
+ if (!IsInitiated)
+ Init();
+ }
+ try
+ {
+ if (SaveSystem.CurrentSave == null)
+ return false;
+
+ if (SaveSystem.CurrentSave.StoriesExperienced == null)
+ SaveSystem.CurrentSave.StoriesExperienced = new List<string>();
+
+ bool upgInstalled = false;
+ if(SaveSystem.CurrentSave.Upgrades.ContainsKey(id))
+ upgInstalled = SaveSystem.CurrentSave.Upgrades[id];
+
+ if(upgInstalled == false)
+ return SaveSystem.CurrentSave.StoriesExperienced.Contains(id);
+ return true;
+ }
+ catch
+ {
+ Console.WriteLine("Upgrade " + id + "DNE.");
+ Console.WriteLine();
+ return false;
+ }
+
+ }
+
+ //LEAVE THIS AS FALSE. The game will set it when the save is loaded.
+ public static bool LogOrphanedUpgrades = false;
+
+ private static IShiftoriumProvider _provider = null;
+
+ public static void RegisterProvider(IShiftoriumProvider p)
+ {
+ _provider = p;
+ }
+
+ //Bless the newer NEWER engine.
+ public static List<ShiftoriumUpgrade> GetDefaults()
+ {
+ try
+ {
+ return _provider.GetDefaults();
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine("Couldn't get the upgrade definition list from the provider.");
+ Console.WriteLine("This might be able to help:");
+ Console.WriteLine(ex);
+ return JsonConvert.DeserializeObject<List<ShiftoriumUpgrade>>(Properties.Resources.Shiftorium);
+ }
+ }
+ }
+
+ public interface IShiftoriumProvider
+ {
+ List<ShiftoriumUpgrade> GetDefaults();
+ }
+
+ public class ShiftoriumUpgradeLookupException : Exception
+ {
+ public ShiftoriumUpgradeLookupException(string id) : base("A shiftorium upgrade of ID \"" + id + "\" was not found in the system.")
+ {
+ ID = id;
+
+ Debug.WriteLine("UpgradeNotFound: " + id);
+
+ }
+
+ public string ID { get; private set; }
+ }
+
+
+
+ public class ShiftoriumUpgrade
+ {
+ public string Name { get; set; }
+ public string Description { get; set; }
+ public int Cost { get; set; }
+ public string ID { get { return (this.Id != null ? this.Id : (Name.ToLower().Replace(" ", "_"))); } }
+ public string Id { get; set; }
+ public string Category { get; set; }
+ public bool Installed
+ {
+ get
+ {
+ return Shiftorium.UpgradeInstalled(ID);
+ }
+ }
+ public string Dependencies { get; set; }
+ }
+}
diff --git a/ShiftOS_TheReturn/TerminalTextWriter.cs b/ShiftOS_TheReturn/TerminalTextWriter.cs
new file mode 100644
index 0000000..55e27cf
--- /dev/null
+++ b/ShiftOS_TheReturn/TerminalTextWriter.cs
@@ -0,0 +1,131 @@
+/*
+ * 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;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.IO;
+using System.Windows.Forms;
+
+namespace ShiftOS.Engine
+{
+ public class TerminalTextWriter : TextWriter
+ {
+ [System.Runtime.InteropServices.DllImport("user32.dll")]
+ public static extern bool LockWindowUpdate(IntPtr hWndLock);
+
+
+ public override Encoding Encoding
+ {
+ get
+ {
+ return Encoding.Unicode;
+ }
+ }
+
+ public ITerminalWidget UnderlyingControl
+ {
+ get
+ {
+ return AppearanceManager.ConsoleOut;
+ }
+ }
+
+ public void select()
+ {
+ Desktop.InvokeOnWorkerThread(new Action(() =>
+ {
+ UnderlyingControl?.SelectBottom();
+
+ }));
+ }
+
+ public override void Write(char value)
+ {
+ if (TerminalBackend.IsForwardingConsoleWrites)
+ {
+ ServerManager.SendMessage("write", $@"{{
+ guid: ""{TerminalBackend.ForwardGUID}"",
+ text: ""{value}""
+}}");
+ }
+ else
+ {
+ Desktop.InvokeOnWorkerThread(new Action(() =>
+ {
+ UnderlyingControl?.Write(value.ToString());
+ select();
+ }));
+ }
+ }
+
+ public override void WriteLine(string value)
+ {
+ if (TerminalBackend.IsForwardingConsoleWrites)
+ {
+ ServerManager.SendMessage("write", $@"{{
+ guid: ""{TerminalBackend.ForwardGUID}"",
+ text: ""{value + Environment.NewLine}""
+}}");
+ }
+ else
+ {
+
+ Desktop.InvokeOnWorkerThread(new Action(() =>
+ {
+ UnderlyingControl?.WriteLine(value);
+ select();
+ }));
+ }
+ }
+
+ public void SetLastText()
+ {
+ }
+
+ public override void Write(string value)
+ {
+ if (TerminalBackend.IsForwardingConsoleWrites)
+ {
+ ServerManager.SendMessage("write", $@"{{
+ guid: ""{TerminalBackend.ForwardGUID}"",
+ text: ""{value}""
+}}");
+ }
+ else
+ {
+
+ Desktop.InvokeOnWorkerThread(new Action(() =>
+ {
+ UnderlyingControl?.Write(value.ToString());
+ select();
+ }));
+ }
+ }
+
+
+ }
+}