Ejemplo n.º 1
0
        private static FieldComparer getComparer(XmlNode node, Type[] genericArguments)
        {
            FieldComparer comparer = null;

            XmlAttribute attribute = node.Attributes [ATTRIBUTE_COMPARE];

            if (attribute != null)
            {
                // explicit comparer, get from comparers or load from assembly
                comparers.TryGetValue(attribute.Value, out comparer);

                if (comparer == null)
                {
                    Type typeInAnyAssembly = GenTypes.GetTypeInAnyAssembly(attribute.Value);
                    if (typeInAnyAssembly != null && typeof(FieldComparer).IsAssignableFrom(typeInAnyAssembly))
                    {
                        comparer = (FieldComparer)Activator.CreateInstance(typeInAnyAssembly);
                    }
                }
            }

            if (comparer == null)
            {
                // try to infer comparer
                foreach (Type t in genericArguments)
                {
                    if (comparers.ContainsKey(t.Name))
                    {
                        comparer = comparers [t.Name];

                        break;
                    }
                }
            }

            return(comparer);
        }
Ejemplo n.º 2
0
 public static void RegisterComparer(Type type, FieldComparer comparer)
 {
     comparers.Add(type.Name, comparer);
 }
Ejemplo n.º 3
0
        private void OverrideDataFromXml(XmlNode xmlRoot, Verse.Def destinationDef, bool debug)
        {
            Type destinationType = destinationDef.GetType();

            string prefix = "Override :: " + destinationDef + " :: ";

            foreach (XmlNode node in xmlRoot.ChildNodes)
            {
                // field we are about to change
                string name = node.Name;

                if (name == null
                    // may cause save issues if these change
                    || name == "shortHash" ||
                    name == "index" ||
                    name == "debugRandomId")
                {
                    continue;
                }

                string text = node.InnerText;

                Mode mode = getMode(node);

                if (string.IsNullOrEmpty(text) && mode != Mode.Clear)
                {
                    // removal must be explicit replace or it's ignored
                    continue;
                }

                if (name == "defName")
                {
                    // not allowed to change target defName
                    // we use it for tracking
                    if (debug)
                    {
                        Log.Message(prefix + text);
                    }

                    prefix = "Override :: " + text + " :: ";

                    continue;
                }

                FieldInfo destinationField = destinationType.GetField(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);

                if (destinationField == null)
                {
                    Log.Warning(prefix + "\"" + name + "\" not found in target");

                    continue;
                }

                Type destinationFieldType = destinationField.FieldType;

                object destinationValue;
                if (mode == Mode.Clear && !destinationFieldType.IsPrimitive)
                {
                    // we are clearing
                    // primitives can't be null, set to 0 ?
                    destinationValue = null;

                    destinationField.SetValue(destinationDef, destinationValue);

                    if (debug)
                    {
                        Log.Message(prefix + "\"" + name + "\" has been set to null");
                    }
                }
                else
                {
                    destinationValue = destinationField.GetValue(destinationDef);
                }

                if (destinationFieldType.HasGenericDefinition(typeof(List <>)))
                {
                    // its a list, search the source and queue or insert

                    Type[] genericArguments = destinationFieldType.GetGenericArguments();
                    // Is it a def or derivate?
                    Type targetDefType = null;
                    foreach (Type t in genericArguments)
                    {
                        if (typeof(Verse.Def).IsAssignableFrom(t))
                        {
                            targetDefType = t;
                            break;
                        }
                    }

                    // sometimes, they don't exist. Don't worry, no one will interfere.
                    if (destinationValue == null)
                    {
                        destinationValue = Activator.CreateInstance(destinationFieldType);
                        destinationField.SetValue(destinationDef, destinationValue);

                        if (debug)
                        {
                            Log.Message(prefix + "\"" + name + "\" has been set to \"" + destinationValue + "\"");
                        }
                    }

                    FieldParser            parserFactory = getParserFactory(node);
                    Func <XmlNode, object> parser        = parserFactory.makeParser(genericArguments);

                    // compares destination and result. Only available for Replace mode
                    FieldComparer comparer = mode == Mode.Replace ? getComparer(node, genericArguments) : null;

                    if (targetDefType != null)
                    {
                        // Crossreferencing a List needs the generic method
                        MethodInfo crossRefLoader_RegisterListWantsCrossRef_generic = crossRefLoader_RegisterListWantsCrossRef.MakeGenericMethod(targetDefType);

                        foreach (XmlNode child in node.ChildNodes)
                        {
                            object[] parameters = new object[] {
                                destinationValue, child.InnerText
                            };
                            crossRefLoader_RegisterListWantsCrossRef_generic.Invoke(null, parameters);

                            if (debug)
                            {
                                Log.Message(prefix + "Registered into \"" + name + "\" the value \"" + child.InnerText + "\" of type \"" + targetDefType + "\"");
                            }
                        }
                    }
                    else
                    {
                        if (parser == null)
                        {
                            Log.Warning(prefix + "Parser is null");

                            continue;
                        }

                        IList destinationList = (IList)destinationValue;

                        foreach (XmlNode child in node.ChildNodes)
                        {
                            object result = parser(child);

                            if (result == null)
                            {
                                // no nulls allowed, they are troublemakers
                                Log.Warning(prefix + "Can't Add null into \"" + name + "\"");

                                continue;
                            }

                            if (mode == Mode.Replace)
                            {
                                if (comparer == null)
                                {
                                    Log.Warning(prefix + "No known comparer for \"" + name + "\"");

                                    break;
                                }

                                Action findAndReplace = delegate {
                                    bool found = false;

                                    int index;
                                    for (index = 0; index < destinationList.Count; index++)
                                    {
                                        if (comparer.Compare(result, destinationList [index]))
                                        {
                                            destinationList [index] = result;

                                            found = true;

                                            break;
                                        }
                                    }

                                    if (found)
                                    {
                                        if (debug)
                                        {
                                            Log.Message(prefix + "Replaced into postion " + index + " at \"" + name + "\" the value \"" + result + "\"");
                                        }
                                    }
                                    else
                                    {
                                        destinationList.Add(result);

                                        if (debug)
                                        {
                                            Log.Message(prefix + "Added into \"" + name + "\" the value \"" + result + "\"");
                                        }
                                    }
                                };

                                if (comparer.delay)
                                {
                                    resolveReferencesActionQueue.Enqueue(findAndReplace);
                                    if (debug)
                                    {
                                        Log.Message(prefix + "Delaying Replace of element in \"" + name + "\" list");
                                    }
                                }
                                else
                                {
                                    findAndReplace();
                                }
                            }
                            else if (mode == Mode.Append)
                            {
                                destinationList.Add(result);

                                if (debug)
                                {
                                    Log.Message(prefix + "Added into \"" + name + "\" the value \"" + result + "\"");
                                }
                            }
                            else
                            {
                                int index = mode == Mode.Insert ? getIndex(child, destinationList) : 0;

                                destinationList.Insert(index, result);

                                if (debug)
                                {
                                    Log.Message(prefix + "Inserted into position " + index + " at \"" + destinationField.Name + "\" the value \"" + result + "\"");
                                }
                            }
                        }
                    }
                }
                else if (destinationFieldType.HasGenericDefinition(typeof(Dictionary <, >)))
                {
                    // its a dict, what do we do?
                    Log.Warning(prefix + "We don't know how to override Dictionary yet...");
                }
                else if (typeof(Verse.Def).IsAssignableFrom(destinationFieldType))
                {
                    // its a Def, queue
                    CrossRefLoader.RegisterObjectWantsCrossRef(destinationDef, destinationField, text);

                    if (debug)
                    {
                        Log.Message(prefix + "Registered \"" + name + "\" with value \"" + destinationValue + "\" of type \"" + destinationFieldType.Name + "\" into \"" + text + "\"");
                    }
                }
                else if (ParseHelper.HandlesType(destinationFieldType))
                {
                    // it can be handled by ParserHelper

                    object result = ParseHelper.FromString(text, destinationFieldType);

                    destinationField.SetValue(destinationDef, result);

                    if (debug)
                    {
                        Log.Message(prefix + "Set \"" + name + "\" with value \"" + destinationValue + "\" of type \"" + destinationFieldType.Name + "\" into \"" + text + "\"");
                    }
                }
                else
                {
                    // it's most likely an object, try XmlToObject.
                    FieldParser            parserFactory = getParserFactory(node);
                    Func <XmlNode, object> parser        = parserFactory.makeParser(destinationFieldType);

                    object result = null;
                    if (parser != null)
                    {
                        result = parser(node);
                    }

                    if (result != null)
                    {
                        // this may fail, try catch?
                        destinationField.SetValue(destinationDef, result);

                        if (debug)
                        {
                            Log.Message(prefix + "Set \"" + name + "\" with value \"" + destinationValue + "\" of type \"" + destinationFieldType.Name + "\" into \"" + result + "\"");
                        }
                    }
                    else
                    {
                        // user entered null
                        Log.Warning(prefix + "Can't Set \"" + name + "\"");
                    }
                }
            }
        }