private static MemoryStream LoadStoryStreamFromSave(String path) { using (var packageReader = new PackageReader(path)) { Package package = packageReader.Read(); AbstractFileInfo globalsFile = package.Files.FirstOrDefault(p => p.Name.ToLowerInvariant() == "globals.lsf"); if (globalsFile == null) { throw new Exception("Could not find globals.lsf in savegame archive."); } Resource resource; Stream rsrcStream = globalsFile.MakeStream(); try { using (var rsrcReader = new LSFReader(rsrcStream)) { resource = rsrcReader.Read(); } } finally { globalsFile.ReleaseStream(); } LSLib.LS.Node storyNode = resource.Regions["Story"].Children["Story"][0]; var storyBlob = storyNode.Attributes["Story"].Value as byte[]; var storyStream = new MemoryStream(storyBlob); return(storyStream); } }
public static Resource LoadResourceFromSave(string path) { var packageReader = new PackageReader(path); Package package = packageReader.Read(); AbstractFileInfo abstractFileInfo = package.Files.FirstOrDefault(p => p.Name == "globals.lsf"); if (abstractFileInfo == null) { MessageBox.Show("The specified package is not a valid savegame (globals.lsf not found)", "Load Failed", MessageBoxButtons.OK, MessageBoxIcon.Error); return(null); } Resource resource; Stream rsrcStream = abstractFileInfo.MakeStream(); try { using (var rsrcReader = new LSFReader(rsrcStream)) { resource = rsrcReader.Read(); } } finally { abstractFileInfo.ReleaseStream(); } return(resource); }
private Resource LoadPackagedResource(string path) { AbstractFileInfo fileInfo = SavePackage.Files.FirstOrDefault(p => p.Name == path); if (fileInfo == null) { throw new ArgumentException($"Could not locate file in package: '{path}"); } Resource resource; Stream rsrcStream = fileInfo.MakeStream(); try { using (var rsrcReader = new LSFReader(rsrcStream)) { resource = rsrcReader.Read(); } } finally { fileInfo.ReleaseStream(); } return(resource); }
private void loadStoryBtn_Click(object sender, EventArgs e) { string extension = Path.GetExtension(storyFilePath.Text)?.ToLower(); switch (extension) { case ".lsv": { var packageReader = new PackageReader(storyFilePath.Text); Package package = packageReader.Read(); AbstractFileInfo abstractFileInfo = package.Files.FirstOrDefault(p => p.Name == "globals.lsf"); if (abstractFileInfo == null) { MessageBox.Show("The specified package is not a valid savegame (globals.lsf not found)", "Load Failed", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } Resource resource; Stream rsrcStream = abstractFileInfo.MakeStream(); try { using (var rsrcReader = new LSFReader(rsrcStream)) { resource = rsrcReader.Read(); } } finally { abstractFileInfo.ReleaseStream(); } LSLib.LS.Node storyNode = resource.Regions["Story"].Children["Story"][0]; var storyStream = new MemoryStream(storyNode.Attributes["Story"].Value as byte[] ?? throw new InvalidOperationException("Cannot proceed with null Story node")); LoadStory(storyStream); MessageBox.Show("Save game database loaded successfully."); break; } case ".osi": { using (var file = new FileStream(storyFilePath.Text, FileMode.Open, FileAccess.Read)) { LoadStory(file); } MessageBox.Show("Story file loaded successfully."); break; } default: { MessageBox.Show($"Unsupported file extension: {extension}", "Load Failed", MessageBoxButtons.OK, MessageBoxIcon.Error); break; } } }
private static void ExtractSingleFile(string packagePath, string destinationPath, string packagedPath) { try { using (var reader = new PackageReader(packagePath)) { Package package = reader.Read(); // Try to match by full path AbstractFileInfo file = package.Files.Find(fileInfo => string.Compare(fileInfo.Name, packagedPath, StringComparison.OrdinalIgnoreCase) == 0); if (file == null) { // Try to match by filename only file = package.Files.Find(fileInfo => string.Compare(Path.GetFileName(fileInfo.Name), packagedPath, StringComparison.OrdinalIgnoreCase) == 0); if (file == null) { CommandLineLogger.LogError($"Package doesn't contain file named '{packagedPath}'"); return; } } using (var fs = new FileStream(destinationPath, FileMode.Create, FileAccess.Write)) { try { Stream stream = file.MakeStream(); stream.CopyTo(fs); } finally { file.ReleaseStream(); } } } } catch (NotAPackageException) { CommandLineLogger.LogError("Failed to list package contents because the package is not an Original Sin package or savegame archive"); } catch (Exception e) { CommandLineLogger.LogFatal($"Failed to list package: {e.Message}", 2); CommandLineLogger.LogTrace($"{e.StackTrace}"); } }
private void SaveSavegameDatabase() { var packageReader = new PackageReader(storyFilePath.Text); Package package = packageReader.Read(); AbstractFileInfo globalsLsf = package.Files.FirstOrDefault(p => p.Name == "globals.lsf"); if (globalsLsf == null) { MessageBox.Show("The specified package is not a valid savegame (globals.lsf not found)", "Load Failed", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } // Load globals.lsf Resource resource; Stream rsrcStream = globalsLsf.MakeStream(); try { using (var rsrcReader = new LSFReader(rsrcStream)) { resource = rsrcReader.Read(); } } finally { globalsLsf.ReleaseStream(); } // Save story resource and pack into the Story.Story attribute in globals.lsf using (var storyStream = new MemoryStream()) { var storyWriter = new StoryWriter(); storyWriter.Write(storyStream, _story); LSLib.LS.Node storyNode = resource.Regions["Story"].Children["Story"][0]; storyNode.Attributes["Story"].Value = storyStream.ToArray(); } // Save globals.lsf var rewrittenStream = new MemoryStream(); // TODO: Resave using original version var rsrcWriter = new LSFWriter(rewrittenStream, FileVersion.CurrentVersion); rsrcWriter.Write(resource); rewrittenStream.Seek(0, SeekOrigin.Begin); // Re-package global.lsf var rewrittenPackage = new Package(); StreamFileInfo globalsRepacked = StreamFileInfo.CreateFromStream(rewrittenStream, "globals.lsf"); rewrittenPackage.Files.Add(globalsRepacked); List <AbstractFileInfo> files = package.Files.Where(x => x.Name != "globals.lsf").ToList(); rewrittenPackage.Files.AddRange(files); using (var packageWriter = new PackageWriter(rewrittenPackage, $"{storyFilePath.Text}.tmp")) { // TODO: Resave using original version and flags packageWriter.Version = PackageVersion.V13; packageWriter.Compression = CompressionMethod.Zlib; packageWriter.CompressionLevel = CompressionLevel.DefaultCompression; packageWriter.Write(); } rewrittenStream.Dispose(); packageReader.Dispose(); // Create a backup of the original .lsf string backupPath = $"{storyFilePath.Text}.backup"; if (!File.Exists(backupPath)) { File.Move(storyFilePath.Text, backupPath); } else { File.Delete(storyFilePath.Text); } // Replace original savegame with new one File.Move($"{storyFilePath.Text}.tmp", storyFilePath.Text); }
public bool Compile(string outputPath, string debugInfoPath, List <string> mods) { Logger.CompilationStarted(); HasErrors = false; Compiler.Game = Game; Compiler.AllowTypeCoercion = AllowTypeCoercion; if (mods.Count > 0) { Logger.TaskStarted("Discovering module files"); var visitor = new ModPathVisitor(Mods) { Game = Game, CollectStoryGoals = true, CollectGlobals = CheckGameObjects, CollectLevels = CheckGameObjects, LoadPackages = LoadPackages }; visitor.Discover(GameDataPath); Logger.TaskFinished(); Logger.TaskStarted("Loading module files"); if (CheckGameObjects) { var nullGameObject = new GameObjectInfo { Name = "NULL_00000000-0000-0000-0000-000000000000", Type = Compiler.Context.LookupType("GUIDSTRING") }; Compiler.Context.GameObjects.Add("00000000-0000-0000-0000-000000000000", nullGameObject); } foreach (var modName in mods) { LoadMod(modName); } AbstractFileInfo storyHeaderFile = null; AbstractFileInfo typeCoercionWhitelistFile = null; var modsSearchPath = mods.ToList(); modsSearchPath.Reverse(); foreach (var modName in modsSearchPath) { if (storyHeaderFile == null && Mods.Mods[modName].StoryHeaderFile != null) { storyHeaderFile = Mods.Mods[modName].StoryHeaderFile; } if (typeCoercionWhitelistFile == null && Mods.Mods[modName].TypeCoercionWhitelistFile != null) { typeCoercionWhitelistFile = Mods.Mods[modName].TypeCoercionWhitelistFile; } } if (storyHeaderFile != null) { var storyStream = storyHeaderFile.MakeStream(); LoadStoryHeaders(storyStream); storyHeaderFile.ReleaseStream(); } else { Logger.CompilationDiagnostic(new Diagnostic(null, MessageLevel.Error, "X00", "Unable to locate story header file (story_header.div)")); HasErrors = true; } if (typeCoercionWhitelistFile != null) { var typeCoercionStream = typeCoercionWhitelistFile.MakeStream(); LoadTypeCoercionWhitelist(typeCoercionStream); typeCoercionWhitelistFile.ReleaseStream(); Compiler.TypeCoercionWhitelist = TypeCoercionWhitelist; } Logger.TaskFinished(); } if (CheckGameObjects) { Logger.TaskStarted("Loading game objects"); LoadGlobals(); Logger.TaskFinished(); } else { Compiler.Context.Log.WarningSwitches[DiagnosticCode.UnresolvedGameObjectName] = false; } if (OsiExtender) { Logger.TaskStarted("Precompiling scripts"); ParallelPreprocess(); Logger.TaskFinished(); } var asts = new Dictionary <String, ASTGoal>(); var goalLoader = new IRGenerator(Compiler.Context); Logger.TaskStarted("Generating IR"); var orderedGoalAsts = ParallelBuildIR(); foreach (var goal in orderedGoalAsts) { Compiler.AddGoal(goal); } Logger.TaskFinished(); bool updated; var iter = 1; do { Logger.TaskStarted($"Propagating rule types {iter}"); updated = Compiler.PropagateRuleTypes(); Logger.TaskFinished(); if (iter++ > 10) { Compiler.Context.Log.Error(null, DiagnosticCode.InternalError, "Maximal number of rule propagation retries exceeded"); break; } } while (updated); Logger.TaskStarted("Checking for unresolved references"); Compiler.VerifyIR(); Logger.TaskFinished(); foreach (var message in Compiler.Context.Log.Log) { Logger.CompilationDiagnostic(message); if (message.Level == MessageLevel.Error) { HasErrors = true; } } if (!HasErrors && !CheckOnly) { Logger.TaskStarted("Generating story nodes"); var emitter = new StoryEmitter(Compiler.Context); if (debugInfoPath != null) { emitter.EnableDebugInfo(); } var story = emitter.EmitStory(); Logger.TaskFinished(); Logger.TaskStarted("Saving story binary"); using (var file = new FileStream(outputPath, FileMode.Create, FileAccess.Write)) { var writer = new StoryWriter(); writer.Write(file, story); } Logger.TaskFinished(); if (debugInfoPath != null) { Logger.TaskStarted("Saving debug info"); using (var file = new FileStream(debugInfoPath, FileMode.Create, FileAccess.Write)) { var writer = new DebugInfoSaver(); writer.Save(file, emitter.DebugInfo); } Logger.TaskFinished(); } } Logger.CompilationFinished(!HasErrors); return(!HasErrors); }