private void ApplyInheritance(EntityTemplate template, EntityTemplate parentTemplate)
        {
            foreach (var parentComponent in parentTemplate.Components)
            {
                //don't override existing components
                if (template.Components.ContainsKey(parentComponent.Key))
                {
                    continue;
                }

                template.Components.Add(parentComponent.Key, parentComponent.Value);
            }

            foreach (var childrenTemplate in parentTemplate.Children)
            {
                if (template.Children.ContainsKey(childrenTemplate.Key))
                {
                    continue;
                }

                template.Children.Add(childrenTemplate.Key, childrenTemplate.Value);
            }
        }
        private void LoadTemplate(string filename)
        {
            if (!File.Exists(filename))
            {
                throw new FileNotFoundException("Couldn't find template file.", filename);
            }

            try
            {
                var template = EntityTemplate.Parse(File.ReadAllText(filename));

    #if NETSTANDARD2_1
                if (!_loadedTemplates.TryAdd(template.Id, template))
                {
                    throw new DuplicateTemplateException(template.Id, filename);
                }
    #else
                if (!_loadedTemplates.ContainsKey(template.Id))
                {
                    _loadedTemplates.Add(template.Id, template);
                }
                else
                {
                    throw new DuplicateTemplateException(template.Id, filename);
                }
    #endif
            }
            catch (Exception e)
            {
                _parsingFailures.Add(new TemplateParseFailedInfo
                {
                    Exception        = e,
                    TemplateFilePath = filename
                });
            }
        }
Example #3
0
        //TODO: think of generic interface to build ECS entity from the template-instantiated data
        private void InstantiateTemplate(EntityTemplate template, Entity entity, Entity?parentEntity)
        {
            if (parentEntity.HasValue)
            {
                entity.SetAsChildOf(parentEntity.Value);
            }

            foreach (var component in template.Components)
            {
                if (!_components.TryGetValue(component.Key, out var componentType))
                {
                    continue;
                }

                object componentInstance;
                if (componentType.GetInterfaces().Any(@interface => @interface.Name.StartsWith("IValueComponent")))
                {
                    componentInstance = FormatterServices.GetUninitializedObject(componentType);
                    var propInfo = componentType.GetProperty("Value");
                    if (propInfo == null)
                    {
                        throw new InvalidOperationException($"Tried to get Value property from {componentType.Name} but failed. This is not something that is supposed to happen and should be reported in the Github repo as an issue.");
                    }

                    var propertyType = propInfo.PropertyType;
                    if (propertyType.IsClass)
                    {
                        dynamic dest = Activator.CreateInstance(propertyType);
                        if (!(component.Value is Dictionary <string, object> dict))
                        {
                            throw new InvalidDataException(
                                      $"Expected deserialized component to be of type Dictionary<string, object>, but it was of type '{componentType.FullName}' - this is probably a bug.");
                        }

                        _mapper.Map(dict, dest, typeof(Dictionary <string, object>), propertyType);
                        ((dynamic)componentInstance).Value = Convert.ChangeType(dest, propertyType);
                    }
                    else
                    {
                        componentInstance = FormatterServices.GetUninitializedObject(componentType);
                        ((dynamic)componentInstance).Value = Convert.ChangeType(component.Value,
                                                                                ((dynamic)componentInstance).Value.GetType());
                    }
                }
                else if (component.Value is Dictionary <string, object> dict)
                {
                    componentInstance = FormatterServices.GetUninitializedObject(componentType);
                    _mapper.Map(dict, componentInstance, typeof(Dictionary <string, object>), componentType);
                }
                else
                {
                    throw new InvalidDataException($"Expected deserialized component to be of type Dictionary<string, object>, but it was of type '{componentType.FullName}' - this is probably a bug.");
                }
                var entitySetMethod = EntitySetMethodInfo.MakeGenericMethod(componentType);
                entitySetMethod.Invoke(entity, new[] { componentInstance });
            }

            foreach (var childTemplate in template.Children)
            {
                InstantiateTemplate(childTemplate.Value, _world.CreateEntity(), entity);
            }
        }