public GetDepModels(OpenTagCache info) : base(CommandFlags.None, "getdepmodels", "Extracts the render models of gameobjects referenced by a map.", "getdepmodels <map-file-path> <output-dir-path>", "Extract the render models of all game-objects referenced by a map." + "The map-file-path arg must be of an existing map (i.e in HaloOnline\\maps\\)") { _info = info; }
static void Main(string[] args) { ConsoleHistory.Initialize(); // Get the file path from the first argument // If no argument is given, load tags.dat var filePath = (args.Length > 0) ? args[0] : "tags.dat"; // If there are extra arguments, use them to automatically execute a command List<string> autoexecCommand = null; if (args.Length > 1) autoexecCommand = args.Skip(1).ToList(); if (autoexecCommand == null) { Console.WriteLine("Halo Online Tag Tool [{0}]", Assembly.GetExecutingAssembly().GetName().Version); Console.WriteLine(); Console.WriteLine("Please report any bugs and feature requests at"); Console.WriteLine("<https://github.com/ElDewrito/HaloOnlineTagTool/issues>."); Console.WriteLine(); Console.Write("Reading tags..."); } // Load the tag cache FileInfo fileInfo = null; TagCache cache = null; try { fileInfo = new FileInfo(filePath); using (var stream = fileInfo.Open(FileMode.Open, FileAccess.Read)) cache = new TagCache(stream); } catch(Exception e) { Console.WriteLine("ERROR: " + e.Message); ConsoleHistory.Dump("hott_*_tags_init.log"); return; } if (autoexecCommand == null) Console.WriteLine("{0} tags loaded.", cache.Tags.Count); // Version detection EngineVersion closestVersion; var version = VersionDetection.DetectVersion(cache, out closestVersion); if (version != EngineVersion.Unknown) { if (autoexecCommand == null) { var buildDate = DateTime.FromFileTime(cache.Timestamp); Console.WriteLine("- Detected target engine version {0}.", VersionDetection.GetVersionString(closestVersion)); Console.WriteLine("- This cache file was built on {0} at {1}.", buildDate.ToShortDateString(), buildDate.ToShortTimeString()); } } else { Console.WriteLine("WARNING: The cache file's version was not recognized!"); Console.WriteLine("Using the closest known version {0}.", VersionDetection.GetVersionString(closestVersion)); version = closestVersion; } // Load stringIDs Console.Write("Reading stringIDs..."); var stringIdPath = Path.Combine(fileInfo.DirectoryName ?? "", "string_ids.dat"); var resolver = StringIdResolverFactory.Create(version); StringIdCache stringIds = null; try { using (var stream = File.OpenRead(stringIdPath)) stringIds = new StringIdCache(stream, resolver); } catch (IOException) { Console.WriteLine("Warning: unable to open string_ids.dat!"); Console.WriteLine("Commands which require stringID values will be unavailable."); } catch (Exception e) { Console.WriteLine("ERROR: " + e.Message); ConsoleHistory.Dump("hott_*_string_ids_init.log"); return; } if (autoexecCommand == null && stringIds != null) { Console.WriteLine("{0} strings loaded.", stringIds.Strings.Count); Console.WriteLine(); } var info = new OpenTagCache { Cache = cache, CacheFile = fileInfo, StringIds = stringIds, StringIdsFile = (stringIds != null) ? new FileInfo(stringIdPath) : null, Version = version, Serializer = new TagSerializer(version), Deserializer = new TagDeserializer(version), }; // Create command context var contextStack = new CommandContextStack(); var tagsContext = TagCacheContextFactory.Create(contextStack, info); contextStack.Push(tagsContext); // If autoexecuting a command, just run it and return if (autoexecCommand != null) { if (!ExecuteCommand(contextStack.Context, autoexecCommand)) Console.WriteLine("Unrecognized command: {0}", autoexecCommand[0]); return; } Console.WriteLine("Enter \"help\" to list available commands. Enter \"exit\" to quit."); while (true) { // Read and parse a command Console.WriteLine(); Console.Write("{0}> ", contextStack.GetPath()); var commandLine = Console.ReadLine(); if (commandLine == null) break; string redirectFile; var commandArgs = ArgumentParser.ParseCommand(commandLine, out redirectFile); if (commandArgs.Count == 0) continue; // If "exit" or "quit" is given, pop the current context if (commandArgs[0] == "exit" || commandArgs[0] == "quit") { if (!contextStack.Pop()) break; // No more contexts - quit continue; } // Handle redirection var oldOut = Console.Out; StreamWriter redirectWriter = null; if (redirectFile != null) { redirectWriter = new StreamWriter(File.Open(redirectFile, FileMode.Create, FileAccess.Write)); Console.SetOut(redirectWriter); } // Try to execute it if (!ExecuteCommand(contextStack.Context, commandArgs)) { Console.WriteLine("Unrecognized command: {0}", commandArgs[0]); Console.WriteLine("Use \"help\" to list available commands."); } // Undo redirection if (redirectFile != null) { Console.SetOut(oldOut); redirectWriter.Dispose(); Console.WriteLine("Wrote output to {0}.", redirectFile); } } }
/// <summary> /// Creates a CollisionModel bsp from a Scenario StructureBsp. /// This does not work for sbsps with > 65536 planes, which use a /// larger encoding for their bsp related structs differing from the /// struct used in common with collision model bsps. /// </summary> /// <returns></returns> public static BSP fromSbsp(ScenarioStructureBsp sbsp, OpenTagCache info) { // Need to work out how to do that class attribute enumeration thing // so all of this folds down to < 10 lines BSP bsp = fromSbspInit(sbsp); var resource = sbsp.Resource3; var resourceManager = new ResourceDataManager(); try { resourceManager.LoadCachesFromDirectory(info.CacheFile.DirectoryName); } catch { Console.WriteLine("Unable to load the resource .dat files."); Console.WriteLine("Make sure that they all exist and are valid."); } //Create a binary reader for the resource Stream stream = new MemoryStream(); resourceManager.Extract(sbsp.Resource3, stream); BinaryReader reader = new BinaryReader(stream); reader.BaseStream.Position = 0; Console.WriteLine("Stream position: {0:X8}", reader.BaseStream.Position); for (int i = 0; i < bsp.Bsp3dNodes.Count; ++i) { BSP.Bsp3dNode node = new BSP.Bsp3dNode(); node.Plane = reader.ReadInt16(); node.BackChildLower = reader.ReadByte(); node.BackChildMid = reader.ReadByte(); node.BackChildUpper = reader.ReadByte(); node.FrontChildLower = reader.ReadByte(); node.FrontChildMid = reader.ReadByte(); node.FrontChildUpper = reader.ReadByte(); bsp.Bsp3dNodes[i] = node; } //Align to the next multiple of 16 reader.BaseStream.Position = -((-reader.BaseStream.Position) & ~0xf); Console.WriteLine("Stream position: {0:X8}", reader.BaseStream.Position); for (int i = 0; i < bsp.Planes.Count; ++i) { BSP.Plane plane = new BSP.Plane(); plane.PlaneI = reader.ReadSingle(); plane.PlaneJ = reader.ReadSingle(); plane.PlaneK = reader.ReadSingle(); plane.PlaneD = reader.ReadSingle(); bsp.Planes[i] = plane; } //Put here for consistency reader.BaseStream.Position = -((-reader.BaseStream.Position) & ~0xf); Console.WriteLine("Stream position: {0:X8}", reader.BaseStream.Position); for (int i = 0; i < bsp.Leaves.Count; ++i) { BSP.Leaf leaf = new BSP.Leaf(); leaf.Flags = reader.ReadInt16(); leaf.Bsp2dReferenceCount = reader.ReadInt16(); leaf.Unknown = reader.ReadInt16(); leaf.FirstBsp2dReference = reader.ReadInt16(); bsp.Leaves[i] = leaf; } //Align to the next multiple of 16 reader.BaseStream.Position = -((-reader.BaseStream.Position) & ~0xf); Console.WriteLine("Stream position: {0:X8}", reader.BaseStream.Position); for (int i = 0; i < bsp.Bsp2dReferences.Count; ++i) { BSP.Bsp2dReference bsp2dref = new BSP.Bsp2dReference(); bsp2dref.Plane = reader.ReadInt16(); bsp2dref.Bsp2dNode = reader.ReadInt16(); bsp.Bsp2dReferences[i] = bsp2dref; } //Align to the next multiple of 16 reader.BaseStream.Position = -((-reader.BaseStream.Position) & ~0xf); Console.WriteLine("Stream position: {0:X8}", reader.BaseStream.Position); for (int i = 0; i < bsp.Bsp2dNodes.Count; ++i) { BSP.Bsp2dNode node = new BSP.Bsp2dNode(); node.PlaneI = reader.ReadSingle(); node.PlaneJ = reader.ReadSingle(); node.PlaneD = reader.ReadSingle(); node.LeftChild = reader.ReadInt16(); node.RightChild = reader.ReadInt16(); bsp.Bsp2dNodes[i] = node; } //Put here for consistency reader.BaseStream.Position = -((-reader.BaseStream.Position) & ~0xf); Console.WriteLine("Stream position: {0:X8}", reader.BaseStream.Position); for (int i = 0; i < bsp.Surfaces.Count; ++i) { BSP.Surface surface = new BSP.Surface(); surface.Plane = reader.ReadUInt16(); surface.FirstEdge = reader.ReadUInt16(); surface.Material = reader.ReadInt16(); surface.Unknown = reader.ReadInt16(); surface.BreakableSurface = reader.ReadInt16(); surface.Unknown2 = reader.ReadInt16(); bsp.Surfaces[i] = surface; } //Align to the next multiple of 16 reader.BaseStream.Position = -((-reader.BaseStream.Position) & ~0xf); Console.WriteLine("Stream position: {0:X8}", reader.BaseStream.Position); for (int i = 0; i < bsp.Edges.Count; ++i) { BSP.Edge edge = new BSP.Edge(); edge.StartVertex = reader.ReadUInt16(); edge.EndVertex = reader.ReadUInt16(); edge.ForwardEdge = reader.ReadUInt16(); edge.ReverseEdge = reader.ReadUInt16(); edge.LeftSurface = reader.ReadUInt16(); edge.RightSurface = reader.ReadUInt16(); bsp.Edges[i] = edge; } //Align to the next multiple of 16 reader.BaseStream.Position = -((-reader.BaseStream.Position) & ~0xf); Console.WriteLine("Stream position: {0:X8}", reader.BaseStream.Position); for (int i = 0; i < bsp.Vertices.Count; ++i) { BSP.Vertex vert = new BSP.Vertex(); vert.PointX = reader.ReadSingle(); vert.PointY = reader.ReadSingle(); vert.PointZ = reader.ReadSingle(); vert.FirstEdge = reader.ReadInt16(); vert.Unknown = reader.ReadInt16(); bsp.Vertices[i] = vert; } return bsp; }