diff options
Diffstat (limited to 'ShiftOS_TheReturn/SaveSystem.cs')
| -rw-r--r-- | ShiftOS_TheReturn/SaveSystem.cs | 453 |
1 files changed, 368 insertions, 85 deletions
diff --git a/ShiftOS_TheReturn/SaveSystem.cs b/ShiftOS_TheReturn/SaveSystem.cs index 9ae18a9..55f5cd5 100644 --- a/ShiftOS_TheReturn/SaveSystem.cs +++ b/ShiftOS_TheReturn/SaveSystem.cs @@ -39,6 +39,7 @@ using static System.Net.Mime.MediaTypeNames; namespace ShiftOS.Engine { + [Obsolete("Use the servers.conf file instead.")] public class EngineConfig { public bool ConnectToMud = true; @@ -46,10 +47,34 @@ namespace ShiftOS.Engine public int MudDefaultPort = 13370; } + /// <summary> + /// Management class for the ShiftOS save system. + /// </summary> public static class SaveSystem { + /// <summary> + /// Boolean representing whether the system is shutting down. + /// </summary> public static bool ShuttingDown = false; + /// <summary> + /// Gets or sets the current logged in client-side user. + /// </summary> + public static ClientSave CurrentUser { get; set; } + + /// <summary> + /// Boolean representing whether the save system is ready to be used. + /// </summary> + public static bool Ready = false; + + /// <summary> + /// Occurs before the save system connects to the ShiftOS Digital Society. + /// </summary> + public static event Action PreDigitalSocietyConnection; + + /// <summary> + /// Gets or sets the current server-side save file. + /// </summary> public static Save CurrentSave { get; set; } /// <summary> @@ -67,11 +92,10 @@ namespace ShiftOS.Engine { var root = new ShiftOS.Objects.ShiftFS.Directory(); root.Name = "System"; - root.permissions = Permissions.All; + root.permissions = UserPermissions.Guest; System.IO.File.WriteAllText(Paths.SaveFile, JsonConvert.SerializeObject(root)); } - if (Utils.Mounts.Count == 0) Utils.Mount(System.IO.File.ReadAllText(Paths.SaveFile)); Paths.Init(); @@ -96,128 +120,377 @@ namespace ShiftOS.Engine } Thread.Sleep(350); - Console.WriteLine("Initiating kernel..."); + Console.WriteLine("ShiftKernel v0.4.2"); + Console.WriteLine("(MIT) DevX 2017, Very Little Rights Reserved"); + Console.WriteLine(""); + Console.WriteLine("THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR"); + Console.WriteLine("IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,"); + Console.WriteLine("FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE"); + Console.WriteLine("AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER"); + Console.WriteLine("LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,"); + Console.WriteLine("OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE"); + Console.WriteLine("SOFTWARE."); + Console.WriteLine(""); Thread.Sleep(250); - Console.WriteLine("Reading filesystem..."); + Console.WriteLine("[init] Kernel boot complete."); + Console.WriteLine("[sfs] Loading SFS driver v3"); Thread.Sleep(100); - Console.WriteLine("Reading configuration..."); + Console.WriteLine("[sfs] 4096 blocks read."); + Console.WriteLine("[simpl-conf] Reading configuration files (global-3.conf)"); + Console.WriteLine("[termdb] Building command database from filesystem..."); + TerminalBackend.PopulateTerminalCommands(); + Console.WriteLine("[inetd] Connecting to network..."); - Console.WriteLine("{CONNECTING_TO_MUD}"); + Ready = false; - if (defaultConf.ConnectToMud == true) + if (PreDigitalSocietyConnection != null) { - bool guidReceived = false; - ServerManager.GUIDReceived += (str) => + PreDigitalSocietyConnection?.Invoke(); + + while (!Ready) { + Thread.Sleep(10); + } + } + + + + bool guidReceived = false; + ServerManager.GUIDReceived += (str) => + { + //Connection successful! Stop waiting! guidReceived = true; - Console.WriteLine("{CONNECTION_SUCCESSFUL}"); - }; + Console.WriteLine("[inetd] Connection successful."); + }; - try - { - - ServerManager.Initiate("secondary4162.cloudapp.net", 13370); - while(guidReceived == false) - { + try + { - } - } - catch (Exception ex) + ServerManager.Initiate(UserConfig.Get().DigitalSocietyAddress, UserConfig.Get().DigitalSocietyPort); + //This haults the client until the connection is successful. + while (ServerManager.thisGuid == new Guid()) { - Console.WriteLine("{ERROR}: " + ex.Message); - Thread.Sleep(3000); - ServerManager.StartLANServer(); - while (guidReceived == false) - { - - } + Thread.Sleep(10); } + Console.WriteLine("[inetd] DHCP GUID recieved, finished setup"); + FinishBootstrap(); } - else + catch (Exception ex) { - ServerManager.StartLANServer(); + //No errors, this never gets called. + Console.WriteLine("[inetd] SEVERE: " + ex.Message); + Thread.Sleep(3000); + Console.WriteLine("[sys] SEVERE: Cannot connect to server. Shutting down in 5..."); + Thread.Sleep(1000); + Console.WriteLine("[sys] 4..."); + Thread.Sleep(1000); + Console.WriteLine("[sys] 3..."); + Thread.Sleep(1000); + Console.WriteLine("[sys] 2..."); + Thread.Sleep(1000); + Console.WriteLine("[sys] 1..."); + Thread.Sleep(1000); + Console.WriteLine("[sys] Bye bye."); + System.Diagnostics.Process.GetCurrentProcess().Kill(); } - ServerManager.MessageReceived += (msg) => - { - if(msg.Name == "mud_savefile") - { - CurrentSave = JsonConvert.DeserializeObject<Save>(msg.Contents); - } - else if(msg.Name == "mud_login_denied") - { - oobe.PromptForLogin(); - } - }; + //Nothing happens past this point - but the client IS connected! It shouldn't be stuck in that while loop above. - ReadSave(); - while(CurrentSave == null) - { + })); + thread.IsBackground = true; + thread.Start(); + } + /// <summary> + /// Finish bootstrapping the engine. + /// </summary> + private static void FinishBootstrap() + { + KernelWatchdog.Log("mud_handshake", "handshake successful: kernel watchdog access code is \"" + ServerManager.thisGuid.ToString() + "\""); + + ServerMessageReceived savehandshake = null; + + savehandshake = (msg) => + { + if (msg.Name == "mud_savefile") + { + CurrentSave = JsonConvert.DeserializeObject<Save>(msg.Contents); + ServerManager.MessageReceived -= savehandshake; + } + else if (msg.Name == "mud_login_denied") + { + oobe.PromptForLogin(); + ServerManager.MessageReceived -= savehandshake; } + }; + ServerManager.MessageReceived += savehandshake; - Shiftorium.Init(); - while (CurrentSave.StoryPosition < 1) + ReadSave(); + + while (CurrentSave == null) + { + Thread.Sleep(10); + } + + Localization.SetupTHETRUEDefaultLocals(); + + Shiftorium.Init(); + + while (CurrentSave.StoryPosition < 1) + { + Thread.Sleep(10); + } + + Thread.Sleep(75); + + Thread.Sleep(50); + Console.WriteLine("[usr-man] Accepting logins on local tty 1."); + + Sysname: + bool waitingForNewSysName = false; + bool gobacktosysname = false; + + if (string.IsNullOrWhiteSpace(CurrentSave.SystemName)) + { + Infobox.PromptText("Enter a system name", "Your system does not have a name. All systems within the digital society must have a name. Please enter one.", (name) => { + if (string.IsNullOrWhiteSpace(name)) + Infobox.Show("Invalid name", "Please enter a valid name.", () => + { + gobacktosysname = true; + waitingForNewSysName = false; + }); + else if (name.Length < 5) + Infobox.Show("Value too small.", "Your system name must have at least 5 characters in it.", () => + { + gobacktosysname = true; + waitingForNewSysName = false; + }); + else + { + CurrentSave.SystemName = name; + if (!string.IsNullOrWhiteSpace(CurrentSave.UniteAuthToken)) + { + var unite = new Unite.UniteClient("http://getshiftos.ml", CurrentSave.UniteAuthToken); + unite.SetSysName(name); + } + SaveSystem.SaveGame(); + gobacktosysname = false; + waitingForNewSysName = false; + } + }); - } - Thread.Sleep(75); + } + + while (waitingForNewSysName) + { + Thread.Sleep(10); + } - Thread.Sleep(50); - Console.WriteLine("{SYSTEM_INITIATED}"); + if (gobacktosysname) + { + goto Sysname; + } - TerminalBackend.InStory = false; - TerminalBackend.PrefixEnabled = true; - Shiftorium.LogOrphanedUpgrades = true; - Desktop.InvokeOnWorkerThread(new Action(() => + if (CurrentSave.Users == null) + CurrentSave.Users = new List<ClientSave>(); + + Console.WriteLine($@" + `-:/++++::.` + .+ydNMMMMMNNMMMMMNhs/. + /yNMMmy+:-` `````.-/ohNMMms- + `oNMMh/.`:oydmNMMMMNmhs+- .+dMMm+` Welcome to ShiftOS. + `oMMmo``+dMMMMMMMMMMMMMMMMMNh/`.sNMN+ + :NMN+ -yMMMMMMMNdhyssyyhdmNMMMMNs``sMMd. SYSTEM STATUS: + oMMd.`sMMMMMMd+. `/MMMMN+ -mMN: ---------------------- + oMMh .mMMMMMM/ `-::::-.` :MMMMMMh`.mMM: + :MMd .NMMMMMMs .dMMMMMMMMMNddMMMMMMMd`.NMN. Codepoints: {SaveSystem.CurrentSave.Codepoints} + mMM. dMMMMMMMo -mMMMMMMMMMMMMMMMMMMMMs /MMy Upgrades: {SaveSystem.CurrentSave.CountUpgrades()} installed + :MMh :MMMMMMMMm` .+shmMMMMMMMMMMMMMMMN` NMN` {Shiftorium.GetAvailable().Count()} available + oMM+ sMMMMMMMMMN+` `-/smMMMMMMMMMMM: hMM: Filesystems: {Utils.Mounts.Count} filesystems mounted in memory. + sMM+ sMMMMMMMMMMMMds/-` .sMMMMMMMMM/ yMM/ + +MMs +MMMMMMMMMMMMMMMMMmhs:` +MMMMMMMM- dMM- System name: {CurrentSave.SystemName.ToUpper()} + .MMm `NMMMMMMMMMMMMMMMMMMMMMo `NMMMMMMd .MMN Users: {Users.Count()} found. + hMM+ +MMMMMMmsdNMMMMMMMMMMN/ -MMMMMMN- yMM+ + `NMN- oMMMMMd `-/+osso+- .mMMMMMN: +MMd + -NMN: /NMMMm` :yMMMMMMm- oMMd` + -mMMs``sMMMMNdhso++///+oydNMMMMMMNo .hMMh` + `yMMm/ .omMMMMMMMMMMMMMMMMMMMMd+``oNMNo + -hMMNo. -ohNMMMMMMMMMMMMmy+. -yNMNy` + .sNMMms/. `-/+++++/:-` ./yNMMmo` + :sdMMMNdyso+++ooshdNMMMdo- + `:+yhmNNMMMMNNdhs+- + ```` "); + + if (CurrentSave.Users.Count == 0) + { + CurrentSave.Users.Add(new ClientSave { - ShiftOS.Engine.Scripting.LuaInterpreter.RunSft(Paths.GetPath("kernel.sft")); - })); - Desktop.InvokeOnWorkerThread(new Action(() => Desktop.PopulateAppLauncher())); - if (CurrentSave.StoryPosition == 1) + Username = "root", + Password = "", + Permissions = UserPermissions.Root + }); + Console.WriteLine("[usr-man] WARN: No users found. Creating new user with username \"root\", with no password."); + } + TerminalBackend.InStory = false; + + TerminalBackend.PrefixEnabled = false; + + if (LoginManager.ShouldUseGUILogin) + { + Action<ClientSave> Completed = null; + Completed += (user) => { - Desktop.InvokeOnWorkerThread(new Action(() => - { - TutorialManager.StartTutorial(); - - })); - while(TutorialManager.IsInTutorial == true) { } - GameReady?.Invoke(); + CurrentUser = user; + LoginManager.LoginComplete -= Completed; + }; + LoginManager.LoginComplete += Completed; + Desktop.InvokeOnWorkerThread(() => + { + LoginManager.PromptForLogin(); + }); + while (CurrentUser == null) + { + Thread.Sleep(10); } - else + } + else + { + + Login: + string username = ""; + int progress = 0; + bool goback = false; + TextSentEventHandler ev = null; + ev = (text) => { - GameReady?.Invoke(); + if (progress == 0) + { + string loginstr = CurrentSave.SystemName + " login: "; + string getuser = text.Remove(0, loginstr.Length); + if (!string.IsNullOrWhiteSpace(getuser)) + { + if (CurrentSave.Users.FirstOrDefault(x => x.Username == getuser) == null) + { + Console.WriteLine(); + Console.WriteLine("User not found."); + goback = true; + progress++; + TerminalBackend.TextSent -= ev; + return; + } + username = getuser; + progress++; + } + else + { + Console.WriteLine(); + Console.WriteLine("Username not provided."); + TerminalBackend.TextSent -= ev; + goback = true; + progress++; + } + } + else if (progress == 1) + { + string passwordstr = "password: "; + string getpass = text.Remove(0, passwordstr.Length); + var user = CurrentSave.Users.FirstOrDefault(x => x.Username == username); + if (user.Password == getpass) + { + Console.WriteLine(); + Console.WriteLine("Welcome to ShiftOS."); + CurrentUser = user; + progress++; + } + else + { + Console.WriteLine(); + Console.WriteLine("Access denied."); + goback = true; + progress++; + } + TerminalBackend.TextSent -= ev; + } + }; + TerminalBackend.TextSent += ev; + Console.WriteLine(); + Console.Write(CurrentSave.SystemName + " login: "); + ConsoleEx.Flush(); + while (progress == 0) + { + Thread.Sleep(10); } + if (goback) + goto Login; + Console.WriteLine(); + Console.Write("password: "); + ConsoleEx.Flush(); + while (progress == 1) + Thread.Sleep(10); + if (goback) + goto Login; + } + TerminalBackend.PrefixEnabled = true; + Shiftorium.LogOrphanedUpgrades = true; + Desktop.InvokeOnWorkerThread(new Action(() => + { + ShiftOS.Engine.Scripting.LuaInterpreter.RunSft(Paths.GetPath("kernel.sft")); })); - thread.IsBackground = true; - thread.Start(); + + + Desktop.InvokeOnWorkerThread(new Action(() => Desktop.PopulateAppLauncher())); + GameReady?.Invoke(); } + /// <summary> + /// Delegate type for events with no caller objects or event arguments. You can use the () => {...} (C#) lambda expression with this delegate + /// </summary> public delegate void EmptyEventHandler(); + /// <summary> + /// Gets a list of all client-side users. + /// </summary> public static List<ClientSave> Users { - get; - private set; + get + { + return CurrentSave.Users; + } } + /// <summary> + /// Occurs when the engine is loaded and the game can take over. + /// </summary> public static event EmptyEventHandler GameReady; - public static void TransferCodepointsToVoid(int amount) + /// <summary> + /// Deducts a set amount of Codepoints from the save file... and sends them to a place where they'll never be seen again. + /// </summary> + /// <param name="amount">The amount of Codepoints to deduct.</param> + public static void TransferCodepointsToVoid(long amount) { + if (amount < 0) + throw new ArgumentOutOfRangeException("We see what you did there. Trying to pull Codepoints from the void? That won't work."); CurrentSave.Codepoints -= amount; NotificationDaemon.AddNotification(NotificationType.CodepointsSent, amount); } + /// <summary> + /// Restarts the game. + /// </summary> public static void Restart() { TerminalBackend.InvokeCommand("sos.shutdown"); System.Windows.Forms.Application.Restart(); } + /// <summary> + /// Requests the save file from the server. If authentication fails, this will cause the user to be prompted for their website login and a new save will be created if none is associated with the login. + /// </summary> public static void ReadSave() { //Migrate old saves. @@ -249,12 +522,9 @@ namespace ShiftOS.Engine { if (Utils.FileExists(Paths.GetPath("user.dat"))) { - var userdat = JsonConvert.DeserializeObject<ClientSave>(Utils.ReadAllText(Paths.GetPath("user.dat"))); + string token = Utils.ReadAllText(Paths.GetPath("user.dat")); - ServerManager.SendMessage("mud_login", $@"{{ - username: ""{userdat.Username}"", - password: ""{userdat.Password}"" -}}"); + ServerManager.SendMessage("mud_token_login", token); } else { @@ -264,6 +534,9 @@ namespace ShiftOS.Engine } + /// <summary> + /// Creates a new save, starting the Out Of Box Experience (OOBE). + /// </summary> public static void NewSave() { AppearanceManager.Invoke(new Action(() => @@ -276,6 +549,9 @@ namespace ShiftOS.Engine })); } + /// <summary> + /// Saves the game to the server, updating website stats if possible. + /// </summary> public static void SaveGame() { if(!Shiftorium.Silent) @@ -284,14 +560,7 @@ namespace ShiftOS.Engine 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}"" -}}"); - + Utils.WriteAllText(Paths.GetPath("user.dat"), CurrentSave.UniteAuthToken); ServerManager.SendMessage("mud_save", JsonConvert.SerializeObject(CurrentSave, Formatting.Indented)); } if (!Shiftorium.Silent) @@ -299,15 +568,29 @@ namespace ShiftOS.Engine System.IO.File.WriteAllText(Paths.SaveFile, Utils.ExportMount(0)); } - public static void TransferCodepointsFrom(string who, int amount) + /// <summary> + /// Transfers codepoints from an arbitrary character to the save file. + /// </summary> + /// <param name="who">The character name</param> + /// <param name="amount">The amount of Codepoints.</param> + public static void TransferCodepointsFrom(string who, long amount) { + if (amount < 0) + throw new ArgumentOutOfRangeException("We see what you did there... You can't just give a fake character Codepoints like that. It's better if you transfer them to the void."); NotificationDaemon.AddNotification(NotificationType.CodepointsReceived, amount); CurrentSave.Codepoints += amount; } } + /// <summary> + /// Delegate for handling Terminal text input. + /// </summary> + /// <param name="text">The text inputted by the user (including prompt text).</param> public delegate void TextSentEventHandler(string text); + /// <summary> + /// Denotes that this Terminal command or namespace is for developers. + /// </summary> public class DeveloperAttribute : Attribute { |
