public override object Execute(List <string> args) { if (args.Count < 1 || args.Count > 2) { return(false); } if (args[0] == "new") { return(MatchShaderNew(args[1])); } else if (args.Count == 2) { return(false); } RenderMethodTemplate bmRmt2 = new RenderMethodTemplate(); CachedTag bmRmt2Instance; using (var blamStream = BlamCache.OpenCacheRead()) { if (BlamCache.TryGetCachedTag(args[0], out bmRmt2Instance)) { bmRmt2 = BlamCache.Deserialize <RenderMethodTemplate>(blamStream, bmRmt2Instance); } else { return(false); } } List <string> bmMaps = new List <string>(); List <string> bmArgs = new List <string>(); // Get a simple list of H3 bitmaps and arguments names foreach (var a in bmRmt2.TextureParameterNames) { bmMaps.Add(BlamCache.StringTable.GetString(a.Name)); } foreach (var a in bmRmt2.RealParameterNames) { bmArgs.Add(BlamCache.StringTable.GetString(a.Name)); } string result = null; using (var cacheStream = Cache.OpenCacheRead()) { ShaderMatcher Matcher = new ShaderMatcher(); Matcher.Init(cacheStream, Cache, BlamCache); // Find a HO equivalent rmt2 var edRmt2Instance = Matcher.FixRmt2Reference(cacheStream, bmRmt2Instance.Name, bmRmt2Instance, bmRmt2, bmMaps, bmArgs); result = edRmt2Instance.Name; } Console.WriteLine($"Blam template \"{bmRmt2Instance.Name}.rmt2\"\n matched with \"{result}.rmt2\"."); return(true); }
public static object ParseArgs(GameCache cache, Type type, TagFieldInfo info, List <string> args) { var input = args[0]; object output = null; if (type == typeof(byte)) { if (args.Count != 1) { return(false); } if (!byte.TryParse(input, out byte value)) { return(false); } output = value; } else if (type == typeof(sbyte)) { if (args.Count != 1) { return(false); } if (!sbyte.TryParse(input, out sbyte value)) { return(false); } output = value; } else if (type == typeof(short)) { if (args.Count != 1) { return(false); } if (!short.TryParse(input, out short value)) { return(false); } output = value; } else if (type == typeof(ushort)) { if (args.Count != 1) { return(false); } if (!ushort.TryParse(input, out ushort value)) { return(false); } output = value; } else if (type == typeof(int)) { if (args.Count != 1) { return(false); } if (!int.TryParse(input, out int value)) { return(false); } output = value; } else if (type == typeof(uint)) { if (args.Count != 1) { return(false); } if (!uint.TryParse(input, out uint value)) { return(false); } output = value; } else if (type == typeof(long)) { if (args.Count != 1) { return(false); } if (!long.TryParse(input, out long value)) { return(false); } output = value; } else if (type == typeof(ulong)) { if (args.Count != 1) { return(false); } if (!ulong.TryParse(input, out ulong value)) { return(false); } output = value; } else if (type == typeof(float)) { if (args.Count != 1) { return(false); } if (!float.TryParse(input, out float value)) { return(false); } output = value; } else if (type == typeof(string)) { if (args.Count != 1) { return(false); } output = input; } else if (type.IsEnum) { if (args.Count != 1) { return(false); } var query = args[0]; object found; try { found = Enum.Parse(type, query); } catch { found = null; } var names = Enum.GetNames(type).ToList(); if (found == null) { var nameLow = query.ToLower(); var namesLow = names.Select(i => i.ToLower()).ToList(); found = namesLow.Find(n => n == nameLow); if (found == null) { var nameSnake = query.ToSnakeCase(); var namesSnake = names.Select(i => i.ToSnakeCase()).ToList(); found = namesSnake.Find(n => n == nameSnake); if (found == null) { Console.WriteLine("Invalid {0} enum option: {1}", type.Name, args[0]); Console.WriteLine(""); Console.WriteLine("Valid options:"); foreach (var name in Enum.GetNames(type)) { var fieldName = $"{type.FullName}.{name}".Replace("+", "."); var documentationNode = EditTagContextFactory.Documentation.SelectSingleNode($"//member[starts-with(@name, 'F:{fieldName}')]"); Console.WriteLine("\t{0} {1}", name, documentationNode != null ? $":: {documentationNode.FirstChild.InnerText.Replace("\r\n", "").TrimStart().TrimEnd()}" : ""); } Console.WriteLine(); return(false); } else { found = Enum.Parse(type, names[namesSnake.IndexOf((string)found)]); } } else { found = Enum.Parse(type, names[namesLow.IndexOf((string)found)]); } } output = found; } else if (type.IsArray) { if (info?.FieldType == typeof(byte[]) && info?.Attribute.Length == 0) { // tag_data field if (args.Count != 1) { return(false); } if (input.Length % 2 != 0) { return(false); } List <byte> bytes = new List <byte>(); for (int i = 0; i < input.Length; i += 2) { bytes.Add(Convert.ToByte(input.Substring(i, 2), 16)); } output = bytes.ToArray(); } else { if (info == null || args.Count != info.Attribute.Length) { return(false); } var elementType = info.FieldType.GetElementType(); var values = Array.CreateInstance(elementType, info.Attribute.Length); for (var i = 0; i < info.Attribute.Length; i++) { values.SetValue(Convert.ChangeType(ParseArgs(cache, elementType, null, new List <string> { args[i] }), elementType), i); } return(values); } } else if (type.IsBlamType()) { if (type.IsGenericType) { var tDefinition = type.GetGenericTypeDefinition(); var tArguments = type.GetGenericArguments(); type = tDefinition.MakeGenericType(tArguments); } var blamType = Activator.CreateInstance(type) as IBlamType; if (!blamType.TryParse(cache, args, out blamType, out string error)) { Console.WriteLine(error); } return(blamType); } else if (type == typeof(CachedTag)) { if (args.Count != 1 || !cache.TryGetCachedTag(args[0], out var tagInstance)) { return(false); } output = tagInstance; } else if (cache is GameCacheHaloOnlineBase && type == typeof(PageableResource)) { if (args.Count < 1 || args.Count > 2) { return(false); } if (args.Count == 1) { switch (args[0].ToLower()) { case "null": output = null; break; default: output = new FileInfo(args[0]); if (!((FileInfo)output).Exists) { throw new FileNotFoundException(args[0]); } break; } } else if (args.Count == 2) { var resourceLocation = ResourceLocation.None; switch (args[0].ToSnakeCase()) { case "resources": resourceLocation = ResourceLocation.Resources; break; case "textures": resourceLocation = ResourceLocation.Textures; break; case "textures_b": resourceLocation = ResourceLocation.TexturesB; break; case "audio": resourceLocation = ResourceLocation.Audio; break; case "resources_b": resourceLocation = ResourceLocation.ResourcesB; break; case "render_models" when cache.Version >= CacheVersion.HaloOnline235640: resourceLocation = ResourceLocation.RenderModels; break; case "lightmaps" when cache.Version >= CacheVersion.HaloOnline235640: resourceLocation = ResourceLocation.Lightmaps; break; default: throw new FormatException($"Invalid resource location: {args[0]}"); } var resourceFile = new FileInfo(args[1]); if (!resourceFile.Exists) { throw new FileNotFoundException(args[1]); } output = (resourceLocation, resourceFile); } else { throw new NotImplementedException(); } } else if (typeof(IBounds).IsAssignableFrom(type)) { if (type.IsGenericType) { var tDefinition = type.GetGenericTypeDefinition(); var tArguments = type.GetGenericArguments(); type = tDefinition.MakeGenericType(tArguments); } var boundsType = Activator.CreateInstance(type) as IBounds; if (!boundsType.TryParse(cache, args, out boundsType, out string error)) { Console.WriteLine(error); } return(boundsType); } else { throw new NotImplementedException(); } return(output); }