Пример #1
0
        /// <param name="fieldInfo">An annotated field metadata.</param>
        /// <param name="fieldAttr">An annotation of the field.</param>
        internal PersistentField(FieldInfo fieldInfo, PersistentFieldAttribute fieldAttr)
        {
            this.fieldInfo = fieldInfo;
            cfgPath        = fieldAttr.path;
            var ordinaryType = fieldInfo.FieldType;

            if (fieldAttr.collectionTypeProto != null)
            {
                collectionFieldHandler =
                    new CollectionFieldHandler(this, fieldInfo.FieldType, fieldAttr.collectionTypeProto);
                ordinaryType = collectionFieldHandler.GetItemType();
            }

            ordinaryFieldHandler =
                new OrdinaryFieldHandler(this, ordinaryType, fieldAttr.ordinaryTypeProto);

            if (ordinaryFieldHandler.IsCompound())
            {
                // Ignore static fields of the compound type since it can be used by multiple persistent
                // fields or as an item in a collection field.
                // Also, ignore groups in the compound types to reduce configuration complexity.
                compoundTypeFields =
                    PersistentFieldsFactory.GetPersistentFields(
                        ordinaryType, false /* needStatic */, true /* needInstance */, null /* group */)
                    // Parent nodes have to be handled before children!
                    .OrderBy(x => string.Join("/", x.cfgPath))
                    .ToArray();
            }
        }
Пример #2
0
        /// <param name="fieldInfo">An annotated field metadata.</param>
        /// <param name="fieldAttr">An annotation of the field.</param>
        public PersistentField(FieldInfo fieldInfo, PersistentFieldAttribute fieldAttr)
        {
            this.fieldInfo = fieldInfo;
            cfgPath        = fieldAttr.path;
            var ordinaryType = fieldInfo.FieldType;

            if (fieldAttr.collectionTypeProto != null)
            {
                collectionProto =
                    Activator.CreateInstance(fieldAttr.collectionTypeProto, new[] { fieldInfo.FieldType })
                    as AbstractCollectionTypeProto;
                ordinaryType = collectionProto.GetItemType();
            }
            simpleTypeProto =
                Activator.CreateInstance(fieldAttr.ordinaryTypeProto)
                as AbstractOrdinaryValueTypeProto;
            isCustomSimpleType = typeof(IPersistentField).IsAssignableFrom(ordinaryType);

            // Determine if field's or collection item's type is a class (compound type).
            isCompound = !simpleTypeProto.CanHandle(ordinaryType) && !isCustomSimpleType &&
                         (ordinaryType.IsValueType && !ordinaryType.IsEnum || // IsStruct
                          ordinaryType.IsClass && ordinaryType != typeof(string) &&
                          !ordinaryType.IsEnum); // IsClass

            if (!isCompound && !simpleTypeProto.CanHandle(ordinaryType) && !isCustomSimpleType)
            {
                Debug.LogErrorFormat(
                    "Proto {0} cannot handle value in field {1}.{2}",
                    ordinaryType.FullName, fieldInfo.DeclaringType.FullName, fieldInfo.Name);
                isDisabled = true;
            }

            // For a compound type retrieve all its persisted fields.
            if (isCompound && !isDisabled)
            {
                // Ignore static fields of the compound type since it can be used by multiple persistent
                // fields or as an item in a collection field.
                // Also, ignore groups in the compound types to reduce configuration complexity.
                compoundTypeFields =
                    PersistentFieldsFactory.GetPersistentFields(
                        ordinaryType, false /* needStatic */, true /* needInstance */, null /* group */)
                    // Parent nodes have to be handled before children!
                    .OrderBy(x => string.Join("/", x.cfgPath))
                    .ToArray();

                // Disable if cannot deal with the field anyways.
                if (compoundTypeFields.Length == 0 && !typeof(IConfigNode).IsAssignableFrom(ordinaryType))
                {
                    Debug.LogErrorFormat(
                        "Compound type in field {0}.{1} has no persistent fields and doesn't implement"
                        + " IConfigNode",
                        fieldInfo.DeclaringType.FullName, fieldInfo.Name);
                    isDisabled = true;
                }
            }
        }
Пример #3
0
        /// <summary>Reads the values of the annotated persistent fields from a config node.</summary>
        /// <param name="node">The config node to read data from.</param>
        /// <param name="type">
        /// The type to load fields for. In case of <paramref name="instance"/> is set and all the
        /// fields, that need to be read, are not private, it's OK to provide just the type of the
        /// instance. However, when reading the private and static fields, it's important to set the right
        /// type. That is, the type which actually defines the fields. Otherwise, they won't be found.
        /// </param>
        /// <param name="instance">
        /// The instance to look the fields in. If it's <c>null</c> then only the static fields will be
        /// loaded.
        /// </param>
        /// <param name="group">The group tag (see <see cref="BasePersistentFieldAttribute"/>).</param>
        /// <seealso cref="PersistentFieldAttribute"/>
        public static void ReadFieldsFromNode(ConfigNode node, Type type, object instance,
                                              string group = StdPersistentGroups.Default)
        {
            var fields = PersistentFieldsFactory.GetPersistentFields(
                type, true /* needStatic */, instance != null /* needInstance */, group).ToArray();

            DebugEx.Fine("Loading {0} persistent fields: group=\"{1}\", node={2}",
                         fields.Length, group ?? "<ALL>", node.name);
            foreach (var field in fields)
            {
                field.ReadFromConfig(node, instance);
            }
        }
Пример #4
0
        /// <summary>Writes values of the annotated persistent fields into a config node.</summary>
        /// <remarks>All persitent values are <b>added</b> into the node provided. I.e. if node had
        /// already had a value being persited then it either overwritten (ordinary fields) or extended
        /// (collection fields).</remarks>
        /// <param name="node">A config node to write data into.</param>
        /// <param name="type">A type to write fields for.</param>
        /// <param name="instance">An instance of type <paramref name="type"/>. If it's <c>null</c> then
        /// only static fields will be written.</param>
        /// <param name="group">A group tag (see <see cref="AbstractPersistentFieldAttribute"/>).</param>
        /// <seealso cref="PersistentFieldAttribute"/>
        public static void WriteFieldsIntoNode(ConfigNode node, Type type, object instance,
                                               string group = StdPersistentGroups.Default)
        {
            var fields = PersistentFieldsFactory.GetPersistentFields(
                type, true /* needStatic */, instance != null /* needInstance */, group).ToArray();

            Logger.logInfo("Writing {0} persistent fields: group=\"{1}\", node={2}",
                           fields.Length, group ?? "<ALL>", node.name);
            foreach (var field in fields)
            {
                field.WriteToConfig(node, instance);
            }
        }
Пример #5
0
        /// <summary>Copies the custom part fields from the prefab into the instance.</summary>
        /// <remarks>
        /// The consumer code must call this method from the <c>OnAwake</c> method to ensure the custom
        /// fields are properly initialized.
        /// </remarks>
        /// <param name="tgtModule">The module to copy the fields into.</param>
        /// <seealso cref="ReadPartConfig"/>
        /// <example>
        /// <code source="Examples/ConfigUtils/ConfigAccessor-Examples.cs" region="ReadPartConfigExample"/>
        /// </example>
        public static void CopyPartConfigFromPrefab(PartModule tgtModule)
        {
            var part = tgtModule.part;

            if (PartLoader.Instance.IsReady())
            {
                var moduleIdx = part.Modules.IndexOf(tgtModule);
                if (moduleIdx == -1)
                {
                    // Modules in the unloaded parts awake before being added into part.
                    moduleIdx = part.Modules.Count;
                }
                if (moduleIdx >= part.partInfo.partPrefab.Modules.Count)
                {
                    HostedDebugLog.Error(
                        tgtModule, "The prefab part doesn't have the module at {0}", moduleIdx);
                    return;
                }
                var srcModule = part.partInfo.partPrefab.Modules[moduleIdx];
                if (srcModule.moduleName != tgtModule.moduleName)
                {
                    HostedDebugLog.Error(
                        tgtModule, "Mismatched module in prefab at {0}: expected={1}, found={2}",
                        moduleIdx, tgtModule.moduleName, srcModule.moduleName);
                    if (GameSettings.VERBOSE_DEBUG_LOG)
                    {
                        HostedDebugLog.Fine(
                            tgtModule, "*** DUMP OF AVAILABLE MODULES: infoName={0}, prefabName{1}",
                            part.partInfo.name, part.partInfo.partPrefab.name);
                        for (var i = 0; i < part.partInfo.partPrefab.Modules.Count; i++)
                        {
                            DebugEx.Fine("* name={0}, id=#{1}", part.partInfo.partPrefab.Modules[i].moduleName, i);
                        }
                    }
                    return;
                }
                var fields = PersistentFieldsFactory.GetPersistentFields(
                    tgtModule.GetType(), false /* needStatic */, true /* needInstance */,
                    StdPersistentGroups.PartConfigLoadGroup);
                foreach (var field in fields)
                {
                    // We need a copy, so get it thru the persistence.
                    var copyNode = new ConfigNode();
                    field.WriteToConfig(copyNode, srcModule);
                    field.ReadFromConfig(copyNode, tgtModule);
                }
            }
        }