Пример #1
0
        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);
        }
Пример #2
0
        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);
        }