예제 #1
0
        private void SaveCurrent()
        {
            var Backup = Path.ChangeExtension(FileName, ".sav.gz");

            if (!File.Exists(Backup))
            {
                if (Compression.CompressFile(FileName, Backup))
                {
                    Log.Write("{0}: Created backup file {1}", GetType().Name, Backup);
                    MessageBox.Show($"Because this is your first time overwriting this file, a backup ({Path.GetFileName(Backup)}) has been created in the same directory.", "Backup created", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
                else
                {
                    if (MessageBox.Show($"Unable to create a backup. You can try using the Save file manager to manually create one. Still continue to save the file?", "Backup failed", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2) == DialogResult.No)
                    {
                        Log.Write("{0}: Unable to create backup. User exit", GetType().Name);
                        return;
                    }
                    Log.Write("{0}: Unable to create backup. User continue", GetType().Name);
                }
            }
            try
            {
                using (var FS = File.Create(FileName))
                {
                    F.Export(FS);
                }
                HasChange = false;
            }
            catch (Exception ex)
            {
                Log.Write(new Exception("Unable to save changes", ex));
                Tools.E($"Unable to save your file. Make sure it's not currently loaded in Satisfactory or another application.\r\n{ex.Message}", "Saving changes");
            }
        }
예제 #2
0
        private void SaveCurrent()
        {
            var Backup = Path.ChangeExtension(FileName, ".bak");

            if (!File.Exists(Backup))
            {
                File.Copy(FileName, Backup);
                MessageBox.Show($"Because this is your first time overwriting this file, a backup ({Path.GetFileName(Backup)}) has been created in the same directory.", "Backup created", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            using (var FS = File.Create(FileName))
            {
                F.Export(FS);
            }
            HasChange = false;
        }
예제 #3
0
        static int Main(string[] args)
        {
            //Set "NOFORM" to better experiment
#if !NOFORM
            //Remove console handle to not block any scripts.
            Tools.FreeConsole();
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new frmMain(args.FirstOrDefault()));
            return(RET.SUCCESS);
#else
            //Allocate console or the Console.ReadKey() will crash
            Tools.AllocConsole();
            using (var FS = File.OpenRead(Path.Combine(Environment.ExpandEnvironmentVariables(SAVEDIR), "Vanilla.sav")))
            {
                using (var BR = new BinaryReader(FS))
                {
                    var F = new SaveFile(BR);
                    Console.Error.WriteLine(string.Join("\r\n", F.Entries.Select(m => m.ObjectData.Name).Distinct()));
                    //Do your tests on the file here
                    using (var FSOut = File.Create(Path.Combine(Environment.ExpandEnvironmentVariables(SAVEDIR), "Test.sav")))
                    {
                        F.Export(FSOut);
                    }
                }
            }
            return(Exit(RET.SUCCESS));
#endif
        }
예제 #4
0
        private void saveAsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (F != null)
            {
                if (NameChanged || MessageBox.Show(@"It's recommended that you change the session name to avoid confusion.
It's totally fine to not change it but different session names makes it easier to tell them apart.

Proceed WITHOUT changing it?", "Session Name Change recommended", MessageBoxButtons.YesNo, MessageBoxIcon.Information) == DialogResult.Yes)
                {
                    if (SFD.ShowDialog() == DialogResult.OK)
                    {
                        using (var FS = File.Create(SFD.FileName))
                        {
                            F.Export(FS);
                        }
                        FileName  = SFD.FileName;
                        HasChange = false;
                    }
                }
            }
        }
예제 #5
0
        private void renameToolStripMenuItem_Click(object sender, EventArgs e)
        {
            var Node = GetSelectedFile();

            if (Node != null)
            {
                FileStream FS = null;
                SaveFile   F  = null;
                try
                {
                    FS = File.OpenRead(GetName(Node));
                }
                catch (Exception ex)
                {
                    Log.Write(new Exception("Unable to rename the file", ex));
                    Tools.E($"Unable to rename the file.\r\n{ex.Message}", "File rename");
                    return;
                }
                using (FS)
                {
                    F = SaveFile.Open(FS);
                }
                if (F != null)
                {
                    using (var Ren = new frmRename(F.SessionName, Node.Text))
                    {
                        if (Ren.ShowDialog() == DialogResult.OK)
                        {
                            var NewName = Path.Combine(Path.GetDirectoryName(GetName(Node)), Ren.RenameFileName + ".sav");
                            //Show rename dialog if the file itself is renamed and the destination exists already
                            if (
                                Node.Text == Ren.RenameFileName ||
                                !File.Exists(NewName) ||
                                MessageBox.Show($"There is already a file named {Ren.RenameFileName}.sav. Overwrite this file?", "Confirm overwrite", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2) == DialogResult.Yes)
                            {
                                F.SessionName = Ren.RenameSessionName;
                                try
                                {
                                    FS = File.Create(NewName);
                                }
                                catch (Exception ex)
                                {
                                    Log.Write(new Exception("Unable to rename the file", ex));
                                    FS = null;
                                    Tools.E($"Unable to rename the file.\r\n{ex.Message}", "File rename");
                                }
                                if (FS != null)
                                {
                                    using (FS)
                                    {
                                        F.Export(FS);
                                        try
                                        {
                                            File.Delete(GetName(Node));
                                        }
                                        catch (Exception ex)
                                        {
                                            Log.Write(new Exception("Unable to delete the old copy", ex));
                                            Tools.E($"File renamed, but we are unable to delete the old copy. Please do so manually.\r\n{ex.Message}", "Unable to rename");
                                        }
                                        InitFiles();
                                    }
                                }
                            }
                        }
                    }
                }
                else
                {
                    InvalidMessage();
                }
            }
        }
예제 #6
0
        private static int HandleArguments(string[] args)
        {
            var    Ops         = new List <Modes>();
            string Filename    = null;
            string SessionName = null;

            if (args.Contains("/?"))
            {
                Help();
                return(RET.HELP);
            }
            for (var i = 0; i < args.Length; i++)
            {
                var arg = args[i];
                Log.Write("{0}: processing argument: {1}", nameof(HandleArguments), arg);
                switch (arg.ToLower())
                {
                case "/verify":
                    Ops.Add(Modes.Verify);
                    break;

                case "/list":
                    Ops.Add(Modes.List);
                    break;

                case "/pack":
                    Ops.Add(Modes.Pack);
                    break;

                case "/render":
                    Ops.Add(Modes.Render);
                    break;

                case "/info":
                    Ops.Add(Modes.Info);
                    break;

                case "/rename":
                    Ops.Add(Modes.RenameSession);
                    if (i < args.Length - 1)
                    {
                        SessionName = args[++i];
                    }
                    else
                    {
                        Log.Write("{0}: /rename requires a new session name", nameof(HandleArguments));
                        Console.WriteLine("/rename requires a new session name");
                        return(RET.ARG);
                    }
                    break;

                default:
                    if (string.IsNullOrEmpty(Filename))
                    {
                        Filename = arg;
                    }
                    else
                    {
                        Log.Write("{0}: unknown argument: {1}", nameof(HandleArguments), arg);
                        Console.WriteLine("Unknown argument: {0}", arg);
                        return(RET.ARG);
                    }
                    break;
                }
            }

            if (Ops.Count == 0 && args.Length < 2)
            {
                return(RET.UI);
            }

            Tools.AllocConsole();

            if (string.IsNullOrEmpty(Filename))
            {
                Log.Write("{0}: No file name argument supplied", nameof(HandleArguments));
                Console.WriteLine("No file name argument supplied");
                return(RET.ARG);
            }

            Ops = Ops.Distinct().ToList();

            var        Changes = false;
            var        IsGz    = false;
            SaveFile   SF      = null;
            FileStream FS      = null;

            try
            {
                FS = File.Open(Filename, FileMode.Open, FileAccess.ReadWrite, FileShare.Read);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Unable to open input file");
                Log.Write("{0}: Unable to open input file", nameof(HandleArguments));
                Log.Write(ex);
                return(RET.IO);
            }
            using (FS)
            {
                IsGz = Tools.IsGzFile(FS);
                try
                {
                    SF = SaveFile.Open(FS);
                    if (SF == null)
                    {
                        throw new InvalidDataException("The file is not a valid satisfactory save game");
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Invalid game file");
                    Log.Write("{0}: Invalid game file", nameof(HandleArguments));
                    Log.Write(ex);
                    return(RET.IO);
                }


                if (Ops.Contains(Modes.Verify))
                {
                    Log.Write("{0}: Verifying file", nameof(HandleArguments));
                    //Verify does nothing on its own
                    Check(SF.PlayTime.Ticks >= 0, "Positive play time");
                    Check(Tools.IsMatch(SF.SessionName, @"^[\w\.\- ]{1,31}$"), "Non-Problematic Session Name");
                    Check(SF.LevelType == SaveFile.DEFAULT_LEVEL_TYPE, $"Level type is '{SaveFile.DEFAULT_LEVEL_TYPE}'");
                    Check(SF.SaveDate.ToUniversalTime() < DateTime.UtcNow, "Date in past");
                    foreach (var key in "sessionName Visibility startloc".Split(' '))
                    {
                        Check(SF.Properties.ContainsKey(key), $"Header contains field '{key}'");
                    }
                    //Don't double error with the previous one
                    if (SF.Properties.ContainsKey("sessionName"))
                    {
                        Check(SF.Properties["sessionName"] == SF.SessionName, "Both session names match");
                    }
                    else
                    {
                        Console.WriteLine("[SKIP]: Both session names match");
                    }
                }

                if (Ops.Contains(Modes.List))
                {
                    Log.Write("{0}: Printing item list", nameof(HandleArguments));
                    foreach (var e in SF.Entries.GroupBy(m => m.ObjectData.Name).OrderBy(m => m.Key))
                    {
                        Console.WriteLine("{1}\t{0}", e.Key, e.Count());
                    }
                }

                if (Ops.Contains(Modes.Render))
                {
                    var ImgFile = Path.ChangeExtension(Filename, ".png");
                    Log.Write("{0}: Rendering map as original size to {1}", nameof(HandleArguments), ImgFile);
                    Console.WriteLine("Initializing image...");
                    MapRender.Init(-1, -1);
                    Console.WriteLine("Rendering file...");
                    using (var IMG = MapRender.RenderFile(SF, 8.192))
                    {
                        Console.WriteLine("Saving image...");
                        IMG.Save(ImgFile);
                    }
                }

                if (Ops.Contains(Modes.Info))
                {
                    Log.Write("{0}: Showing game info", nameof(HandleArguments));
                    Console.WriteLine("Save File Size:\t{0}", FS.Position);
                    Console.WriteLine("Build Version:\t{0}", SF.BuildVersion);
                    Console.WriteLine("Save Version:\t{0}", SF.SaveVersion);
                    Console.WriteLine("Header Version:\t{0}", SF.SaveHeaderVersion);
                    Console.WriteLine("Session Name:\t{0}", SF.SessionName);
                    Console.WriteLine("Save Date:\t{0}", SF.SaveDate);
                    Console.WriteLine("Play Time:\t{0}", SF.PlayTime);
                    foreach (var KV in SF.Properties)
                    {
                        Console.WriteLine("{0}:\t{1}", KV.Key, KV.Value);
                    }
                    Console.WriteLine("Object Count:\t{0}", SF.Entries.Count);
                    Console.WriteLine("String List:\t{0}", SF.StringList.Count);
                }

                if (Ops.Contains(Modes.RenameSession))
                {
                    Log.Write("{0}: Renaming session to {1}", nameof(HandleArguments), SessionName);
                    SF.SetSessionName(SessionName);
                    Changes = true;
                }

                if (Ops.Contains(Modes.Pack))
                {
                    string     NewFile;
                    FileStream OUT;
                    FS.Seek(0, SeekOrigin.Begin);
                    if (IsGz)
                    {
                        if (Filename.ToLower().EndsWith(".sav.gz"))
                        {
                            NewFile = Path.ChangeExtension(Filename, null);
                        }
                        else
                        {
                            NewFile = Path.ChangeExtension(Filename, ".sav");
                        }
                    }
                    else
                    {
                        NewFile = Filename + ".gz";
                    }
                    try
                    {
                        OUT = File.Create(NewFile);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("Can't create output file");
                        Log.Write("{0}: Can't create {1}", nameof(HandleArguments), NewFile);
                        Log.Write(ex);
                        return(RET.IO);
                    }
                    Log.Write("{0}: {1} file", nameof(HandleArguments), IsGz ? "Compressing" : "Decompressing");
                    using (OUT)
                    {
                        if (IsGz)
                        {
                            Compression.DecompressStream(FS, OUT);
                        }
                        else
                        {
                            Compression.CompressStream(FS, OUT);
                        }
                    }
                    Log.Write("{0}: {1} file OK", nameof(HandleArguments), IsGz ? "Compressing" : "Decompressing");
                }
                if (Changes)
                {
                    Log.Write("{0}: Writing back changes", nameof(HandleArguments));
                    FS.Seek(0, SeekOrigin.Begin);
                    SF.Export(FS);
                    FS.Flush();
                    FS.SetLength(FS.Position);
                }
            }

            return(RET.SUCCESS);
        }
예제 #7
0
        static int Main(string[] args)
        {
            //Set "NOFORM" to better experiment
#if !NOFORM
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new frmMain());
            return(RET.SUCCESS);
#else
            string FileName = args.FirstOrDefault();
            if (string.IsNullOrEmpty(FileName) || !File.Exists(FileName))
            {
                Help();
                Console.Error.WriteLine("File list:");
                Console.Error.WriteLine(
                    string.Join("\r\n", Directory.GetFiles(Environment.ExpandEnvironmentVariables(SAVEDIR), "*.sav"))
                    );
                return(Exit(RET.ARG));
            }

            using (var FS = File.OpenRead(FileName))
            {
                using (var BR = new BinaryReader(FS))
                {
                    var H = new SaveFile(BR);

                    //Important, change the session name to not f**k up your current game
                    H.SessionName = "EDITED_GAME";
                    H.Properties["sessionName"] = "EDITED_GAME";

                    //This is how you can read a specific entry and dump the hex contents:
                    //var Pod = H.Entries.First(m => m.ObjectData.Name == "/Game/FactoryGame/World/Benefit/DropPod/BP_DropPod.BP_DropPod_C");
                    //Console.Error.WriteLine(Tools.HexDump(Pod.Properties));

                    //Try some container black magic


                    //These seem to be inventories across all items
                    //var Inventory = H.Entries.Where(m => m.ObjectData.Name == "/Script/FactoryGame.FGInventoryComponent").Skip(20).First();
                    //Console.Error.WriteLine(Tools.HexDump(Inventory.Properties, 24));
                    //File.WriteAllBytes(@"C:\Users\AyrA\Desktop\Inventory.bin", Inventory.Properties);

                    //Example save file editing using SaveFileHelper
                    //Console.Error.WriteLine("Processed {0} Entries", SaveFileHelper.RestoreDropPods(H));

                    //* This will list all types from the save file
                    Console.Error.WriteLine("Count\tType");

                    var Containers = H.Entries.Where(m => m.ObjectData.Name == "/Game/FactoryGame/Buildable/Factory/StorageContainerMk1/Build_StorageContainerMk1.Build_StorageContainerMk1_C").ToArray();

                    var LastContainer       = Containers[0];
                    var SecondLastContainer = Containers[0];

                    int LastId       = int.Parse(LastContainer.ObjectData.InternalName.Split('_').Last());
                    int SecondLastId = int.Parse(SecondLastContainer.ObjectData.InternalName.Split('_').Last());

                    foreach (var Container in Containers)
                    {
                        var Id = int.Parse(Container.ObjectData.InternalName.Split('_').Last());
                        if (Id > LastId)
                        {
                            SecondLastContainer = LastContainer;
                            LastContainer       = Container;

                            SecondLastId = LastId;
                            LastId       = Id;
                        }
                        else if (Id > SecondLastId)
                        {
                            SecondLastContainer = Container;
                            SecondLastId        = Id;
                        }
                    }


                    Console.Error.WriteLine(Tools.HexDump(LastContainer.Properties, 24));
                    Console.Error.WriteLine(Tools.HexDump(SecondLastContainer.Properties, 24));

                    //Mess everything up
                    SecondLastContainer.Properties = LastContainer.Properties;

                    /*
                     * foreach (var E in H.Entries.OrderBy(m => m.ObjectData.Name).GroupBy(m => m.ObjectData.Name))
                     * {
                     *  Console.Error.WriteLine("{1}\t{0}", E.Key, E.Count());
                     * }
                     * //*/

                    /* This lists all strings in the string list.
                     * //The string list likely contains all entities removed from the map.
                     * foreach (var E in H.StringList.Select(m => m.Value).Distinct())
                     * {
                     *  Console.Error.WriteLine(E);
                     * }
                     * //*/

                    //* Writing back new save file
                    var NewFile = Path.Combine(Environment.ExpandEnvironmentVariables(SAVEDIR), "EDITED_GAME.SAV");
                    using (var FSW = File.Create(NewFile))
                    {
                        H.Export(FSW);
                    }
                    //*/
                }
            }

            return(Exit(RET.SUCCESS));
#endif
        }