diff options
| author | Michael VanOverbeek <[email protected]> | 2017-04-07 17:02:38 +0000 |
|---|---|---|
| committer | Michael VanOverbeek <[email protected]> | 2017-04-07 17:02:38 +0000 |
| commit | 3d48f3101aa25050e6b219fc1111293273a59fa4 (patch) | |
| tree | 40bf8d722245d02d87b0914a38e2b09673e093c0 /ShiftOS_TheReturn | |
| parent | edf4aef6adf8a2a45c347f70804fc5ac93070576 (diff) | |
| parent | 3789b48df00e89fa6dcd7e27bb6885ba880504f6 (diff) | |
| download | shiftos_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.cs | 126 | ||||
| -rw-r--r-- | ShiftOS_TheReturn/Commands.cs | 819 | ||||
| -rw-r--r-- | ShiftOS_TheReturn/Localization.cs | 219 | ||||
| -rw-r--r-- | ShiftOS_TheReturn/Resources/strings_de.txt | 38 | ||||
| -rw-r--r-- | ShiftOS_TheReturn/Resources/strings_en.txt | 4 | ||||
| -rw-r--r-- | ShiftOS_TheReturn/SaveSystem.cs | 332 | ||||
| -rw-r--r-- | ShiftOS_TheReturn/ServerManager.cs | 248 | ||||
| -rw-r--r-- | ShiftOS_TheReturn/Shiftorium.cs | 332 | ||||
| -rw-r--r-- | ShiftOS_TheReturn/TerminalTextWriter.cs | 131 |
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(); + })); + } + } + + + } +} |
