예제 #1
0
        private void RegisterSpellTargetSelectors([NotNull] ActorAssemblyDefinitionConfiguration actorAssemblyConfig, [NotNull] ContainerBuilder builder)
        {
            if (actorAssemblyConfig == null)
            {
                throw new ArgumentNullException(nameof(actorAssemblyConfig));
            }
            if (builder == null)
            {
                throw new ArgumentNullException(nameof(builder));
            }

            //SingletonSpellEffectTargetSelectorFactory : ISpellEffectTargetSelectorFactory
            builder.RegisterType <SingletonSpellEffectTargetSelectorFactory>()
            .As <ISpellEffectTargetSelectorFactory>()
            .SingleInstance();

            foreach (Assembly assemblyToParse in actorAssemblyConfig.AssemblyNames
                     .Select(d => AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => d == a.GetName().Name.ToLower()))
                     .Where(a => a != null))
            {
                foreach (Type t in assemblyToParse.GetTypes())
                {
                    //If they have the handler attribute, we should just register it.
                    if (typeof(ISpellEffectTargetSelector).IsAssignableFrom(t) && t.GetCustomAttributes <SpellEffectTargetingStrategyAttribute>().Any() && !t.IsAbstract)
                    {
                        builder.RegisterType(t)
                        .As <ISpellEffectTargetSelector>()
                        .SingleInstance();
                    }
                }
            }
        }
예제 #2
0
        private void RegisterSpellCastAttemptValidators(ActorAssemblyDefinitionConfiguration actorAssemblyConfig, ContainerBuilder builder)
        {
            //SingletonSpellCastAttemptValidator : ISpellCastAttemptValidator
            builder.RegisterType <SingletonSpellCastAttemptValidator>()
            .As <ISpellCastAttemptValidator>()
            .SingleInstance();

            foreach (Assembly assemblyToParse in actorAssemblyConfig.AssemblyNames
                     .Select(d => AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => d == a.GetName().Name.ToLower()))
                     .Where(a => a != null))
            {
                foreach (Type t in assemblyToParse.GetTypes())
                {
                    //If they have the handler attribute, we should just register it.
                    if (typeof(ISpellCastValidator).IsAssignableFrom(t) && t.GetCustomAttributes <SpellCastValidatorAttribute>().Any() && !t.IsAbstract)
                    {
                        builder.RegisterType(t)
                        .As <ISpellCastValidator>()
                        .SingleInstance();
                    }
                }
            }
        }
예제 #3
0
        protected override void Load([NotNull] ContainerBuilder builder)
        {
            if (builder == null)
            {
                throw new ArgumentNullException(nameof(builder));
            }

            //TODO: Expose and register this as appart of configuration system
            ActorAssemblyDefinitionConfiguration actorAssemblyConfig = new ActorAssemblyDefinitionConfiguration(Array.Empty <string>());

            RegisterSpellTargetValidators(actorAssemblyConfig, builder);
            RegisterSpellTargetSelectors(actorAssemblyConfig, builder);
            RegisterSpellEffectHandlers(actorAssemblyConfig, builder);
            RegisterSpellCastAttemptValidators(actorAssemblyConfig, builder);

            //EffectTargetSelectorRoutedSpellCastDispatcher
            builder.RegisterType <EffectTargetSelectorRoutedSpellCastDispatcher>()
            .As <ISpellCastDispatcher>()
            .SingleInstance();

            //DefaultPendingSpellCastFactory : IPendingSpellCastFactory
            builder.RegisterType <DefaultPendingSpellCastFactory>()
            .As <IPendingSpellCastFactory>()
            .SingleInstance();

            //DefaultSpellEffectApplicationMessageFactory : ISpellEffectApplicationMessageFactory
            builder.RegisterType <DefaultSpellEffectApplicationMessageFactory>()
            .As <ISpellEffectApplicationMessageFactory>()
            .SingleInstance();

            //DefaultLearnedSpellsCollection : ILearnedSpellsCollection, IReadonlyLearnedSpellsCollection
            builder.RegisterType <DefaultLearnedSpellsCollection>()
            .As <ILearnedSpellsCollection>()
            .As <IReadonlyLearnedSpellsCollection>()
            .SingleInstance();
        }
예제 #4
0
        protected override void Load(ContainerBuilder builder)
        {
            //TODO: Expose and register this as appart of configuration system
            ActorAssemblyDefinitionConfiguration actorAssemblyConfig = new ActorAssemblyDefinitionConfiguration(Array.Empty <string>());

            foreach (var s in actorAssemblyConfig.AssemblyNames)
            {
                Debug.Log($"Actor Assembly: {s}");
            }

            Debug.Log(AppDomain.CurrentDomain.GetAssemblies().Aggregate("Loaded Assemblies: ", (s, assembly) => $"{s} {assembly.GetName().Name}"));

            //The below loads the actor assemblies defined in the configuration.
            //It then searches for all message handlers and then registers them.
            //It's a complicated process.
            //TODO: Support actually loading unloaded assemblies (like 3rd party user assemblies)
            foreach (Assembly actorAssemblyToParse in actorAssemblyConfig.AssemblyNames
                     .Select(d => AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => d == a.GetName().Name.ToLower()))
                     .Where(a => a != null))
            {
                Debug.Log($"Parsing ActorAssembly: {actorAssemblyToParse.GetName().Name}");
                foreach (Type t in actorAssemblyToParse.GetTypes())
                {
                    //If they have the handler attribute, we should just register it.
                    if (t.GetCustomAttributes <EntityActorMessageHandlerAttribute>().Any())
                    {
                        Debug.Log($"Register ActorMessageHandler: {t.Name}");

                        //Now we need to find the actor state type
                        Type actorStateType = t.GetInterfaces()
                                              .First(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IEntityActorMessageHandler <,>))
                                              .GenericTypeArguments.First();

                        var handlerRegisteration = builder.RegisterType(t)
                                                   .AsSelf()
                                                   .As(typeof(IEntityActorMessageHandler <,>).MakeGenericType(new Type[2] {
                            actorStateType, typeof(EntityActorMessage)
                        }))
                                                   .As <IEntityActorMessageHandler>()
                                                   .SingleInstance();

                        foreach (var attri in t.GetCustomAttributes <EntityActorMessageHandlerAttribute>())
                        {
                            //TODO: Support multiple level inherited types.
                            //If the actor has a different state type we should assume it's valid if it can be assigned.
                            Type specificActorStateType = attri.TargetActorType.BaseType.GenericTypeArguments.Reverse().First();

                            if (specificActorStateType != actorStateType)
                            {
                                if (actorStateType.IsAssignableFrom(specificActorStateType))
                                {
                                    handlerRegisteration = handlerRegisteration
                                                           .As(typeof(IEntityActorMessageHandler <,>).MakeGenericType(new Type[2] {
                                        specificActorStateType, typeof(EntityActorMessage)
                                    }));
                                }
                                else
                                {
                                    throw new InvalidOperationException($"Actor: {attri.TargetActorType.Name} attempted to use Handler: {t.Name} but had non-matching state Types: {actorStateType.Name}/{specificActorStateType.Name}");
                                }
                            }
                        }
                    }
                    else if (typeof(IEntityActor).IsAssignableFrom(t))
                    {
                        //Don't want to register abstract entities.
                        if (!t.IsAbstract)
                        {
                            Debug.Log($"Register Actor: {t.Name}");
                            builder.RegisterType(t)
                            .AsSelf();
                        }
                    }
                }
            }

            //Below is an open generic registeration of the generic router
            //this makes it EASY to inject into the actors
            builder.RegisterGeneric(typeof(ReflectionBasedGenericMessageRouter <,>))
            .As(typeof(IEntityActorMessageRouteable <,>))
            .SingleInstance();

            //Create the root of the actor system.
            builder.RegisterInstance(ActorSystem.Create("Root"))
            .AsSelf()
            .As <ActorSystem>()
            .As <IActorRefFactory>()
            .SingleInstance();

            builder.Register <IScheduler>(context =>
            {
                ActorSystem actorSystem = context.Resolve <ActorSystem>();

                return(actorSystem.Scheduler);
            })
            .As <IScheduler>()
            .SingleInstance();

            //Creates the autofac dependency resolver that can be used to actually resolve
            //the Actor's dependencies.
            builder.Register(context =>
            {
                if (!context.IsRegistered <IEntityActorMessageRouteable <DefaultWorldActor, WorldActorState> >())
                {
                    Debug.LogError($"CRITICAL dependency for Actor IOC not registered.");
                }

                if (!context.IsRegistered <DefaultWorldActor>())
                {
                    Debug.LogError($"CRITICAL dependency for Actor IOC not registered.");
                }

                return(new AutoFacDependencyResolver(context.Resolve <ILifetimeScope>(), context.Resolve <ActorSystem>()));
            })
            .As <IDependencyResolver>()
            .AsSelf()
            .SingleInstance();

            builder.RegisterType <DefaultWorldActor>()
            .AsSelf();

            builder.RegisterType <UnityAkkaActorLoggerAdapter>()
            .AsSelf()
            .As <ILoggingAdapter>()
            .SingleInstance();

            builder.RegisterType <UnityLoggerActor>()
            .AsSelf();

            builder.RegisterType <DefaultGameObjectEntityActorFactory>()
            .As <IGameObjectEntityActorFactory>()
            .SingleInstance();

            //This creates the World actor.
            builder.Register(context =>
            {
                try
                {
                    IDependencyResolver resolver = context.Resolve <IDependencyResolver>();
                    ActorSystem actorSystem      = context.Resolve <ActorSystem>();
                    actorSystem.ActorOf(resolver.Create <UnityLoggerActor>(), "Logger");
                    IActorRef worldActorReference = actorSystem.ActorOf(resolver.Create <DefaultWorldActor>(), "World");

                    if (worldActorReference.IsNobody())
                    {
                        Debug.LogError($"FAILED TO CREATE WORLD ACTOR.");
                    }

                    return(new WorldActorReferenceAdapter(worldActorReference));
                }
                catch (Exception e)
                {
                    Debug.LogError($"Failed to create WorldActor in IoC. Reason: {e.Message}\n\nStack: {e.StackTrace}");
                    throw;
                }
            })
            .As <IWorldActorRef>()
            .SingleInstance();
        }