public Type GetMixinType(string modelName) { FlatType entityType = index.GetType(modelName); // First try to directly lookup type as a library type Type mixinType = GetType($"I{modelName}"); if (mixinType != null) { return(mixinType); } List <FlatType> requiredMixins = entityType.RequiredMixin().ToList(); if (requiredMixins.Count != 1) { throw new InvalidOperationException($"Cannot find single mixin for: {entityType}"); } FlatType requiredMixin = requiredMixins.First(); mixinType = GetType($"I{requiredMixin.Name}"); if (mixinType == null) { throw new InvalidOperationException($"Mixin type: I{requiredMixin.Name} does not exist."); } return(mixinType); }
private IMapEntity CreateInstance(Entity entity) { Type entityType = lookup.GetClass(entity.modelName); var mapEntity = (IMapEntity)Activator.CreateInstance(entityType); if (mapEntity == null) { throw new InvalidOperationException($"Unable to create instance of: {entity.modelName}"); } var setPropertyValue = new List <(string, object)>(); foreach (var property in entity.property) { // Not setting any values if (property.set.Count == 0) { continue; } FlatType modelType = index.GetType(entity.modelName); FlatProperty modelProperty = modelType.GetProperty(property.name); object value; if (modelProperty.Type.StartsWith("Assoc")) { value = FlatProperty.ParseAssocType(modelProperty.Type, property.set.Select(set => (set.index, set.value))); } else { value = FlatProperty.ParseType(modelProperty.Type, property.set[0].value); } setPropertyValue.Add((property.name, value)); } setPropertyValue.Add(("EntityId", entity.id)); setPropertyValue.Add(("EntityName", entity.name)); foreach ((string name, object value) in setPropertyValue) { MethodInfo setter = entityType.GetMethod($"set_{name}"); if (setter == null) { throw new InvalidOperationException($"No function set_{name} on {entity.modelName}"); } setter.Invoke(mapEntity, new[] { value }); } return(mapEntity); }
private static void FlatIndexExplorer() { using var reader = new M2dReader(EXPORTED_PATH); var index = new FlatTypeIndex(reader); Console.WriteLine("Index is ready!"); while (true) { string[] input = (Console.ReadLine() ?? string.Empty).Split(" ", 2); switch (input[0]) { case "quit": return; case "type": case "prop": case "properties": if (input.Length < 2) { Console.WriteLine("Invalid input."); } else { string name = input[1]; FlatType type = index.GetType(name); if (type == null) { Console.WriteLine($"Invalid type: {name}"); continue; } Console.WriteLine(type); foreach (FlatProperty prop in type.GetProperties()) { Console.WriteLine($"{prop.Type,22}{prop.Name,30}: {prop.ValueString()}"); } Console.WriteLine("----------------------Inherited------------------------"); foreach (FlatProperty prop in type.GetInheritedProperties()) { Console.WriteLine($"{prop.Type,22}{prop.Name,30}: {prop.ValueString()}"); } } break; case "sub": case "children": if (input.Length < 2) { Console.WriteLine("Invalid input."); } else { string name = input[1]; FlatType type = index.GetType(name); if (type == null) { Console.WriteLine($"Invalid type: {name}"); continue; } Console.WriteLine(type); foreach (FlatType subType in index.GetSubTypes(name)) { Console.WriteLine($"{subType.Name,30} : {string.Join(',', subType.Mixin.Select(sub => sub.Name))}"); } } break; case "ls": try { bool recursive = input.Contains("-r"); string path = input.FirstOrDefault(arg => arg != "ls" && arg != "-r"); Console.WriteLine(string.Join(", ", index.Hierarchy.List(path, recursive).Select(type => type.Name))); } catch (DirectoryNotFoundException e) { Console.WriteLine(e.Message); } break; case "lsdir": try { string path = input.FirstOrDefault(arg => arg != "lsdir"); Console.WriteLine(string.Join(", ", index.Hierarchy.ListDirectories(path))); } catch (DirectoryNotFoundException e) { Console.WriteLine(e.Message); } break; default: Console.WriteLine($"Unknown command: {string.Join(' ', input)}"); break; } } }
public string GenerateInterface(string @namespace, FlatType type) { List <string> mixinTypes = type.RequiredMixin() .Select(mixin => mixin.Name) .ToList(); var inheritedProperties = new Dictionary <string, object>(); foreach (string mixinType in mixinTypes) { foreach (FlatProperty property in index.GetType(mixinType).GetAllProperties()) { if (inheritedProperties.ContainsKey(property.Name)) { inheritedProperties[property.Name] = null; } else { inheritedProperties.Add(property.Name, property.Value); } } } var builder = new StringBuilder(); builder.AppendLine($"namespace Maple2.File.Flat.{@namespace} {{"); List <string> mixinInterfaces = mixinTypes.Select(mixin => $"I{mixin}").ToList(); if (mixinInterfaces.Count > 0) { builder.AppendLine($"\tpublic interface I{type.Name} : {string.Join(",", mixinInterfaces)} {{"); } else { builder.AppendLine($"\tpublic interface I{type.Name} : IMapEntity {{"); } builder.AppendLine($"\t\tstring ModelName => \"{type.Name}\";"); foreach (FlatProperty property in type.GetProperties()) { // Inherited properties don't need to be declared on interface if (inheritedProperties.TryGetValue(property.Name, out object propertyValue)) { if (propertyValue != null) { if (Equals(propertyValue, property.Value)) { continue; } // Since the dictionaries are always empty, just doing count comparison to shortcut if (propertyValue is IDictionary dict1 && property.Value is IDictionary dict2 && dict1.Count == dict2.Count) { continue; } } } string typeStr = NormalizeType(property.Value.GetType().ToString()); string typeValue = property.ValueCodeString(); builder.AppendLine($"\t\t{typeStr} {property.Name} => {typeValue};"); } builder.AppendLine("\t}"); // class builder.AppendLine("}"); // namespace return(builder.ToString()); }