Beispiel #1
0
        private bool InitializeGameSupport(Assembly assembly)
        {
            var types         = assembly.GetTypes();
            var decoratedType = types.FirstOrDefault(
                t => t.GetCustomAttributes(
                    typeof(GameSupportLibraryEntryPointAttribute),
                    false
                    ).Length == 1
                );

            if (decoratedType == null)
            {
                Log.Error("The game support library is present, but doesn't contain a marked entry point.");
                return(false);
            }

            if (decoratedType.IsAssignableFrom(MonoBehaviourBridge.MonoBehaviourType))
            {
                Log.Error("The game support library has a decorated entry point but it doesn't inherit from MonoBehaviour.");
                return(false);
            }

            if (!decoratedType.Attributes.HasFlag(TypeAttributes.Sealed))
            {
                Log.Error("The game support library has an entry point but its class is not sealed.");
                return(false);
            }

            var attribute = decoratedType.GetCustomAttributes(
                typeof(GameSupportLibraryEntryPointAttribute),
                false
                ).First() as GameSupportLibraryEntryPointAttribute;

            if (IsGameSupportLibraryPresent(attribute.LibraryID))
            {
                Log.Error("The game support library has a duplicate ID. Contact the GSL developer for assistance.");
                return(false);
            }

            var gameObject = GameObjectBridge.CreateGameObject(attribute.LibraryID);

            if (attribute.AwakeAfterInitialize)
            {
                GameObjectBridge.SetActive(gameObject, false);
            }

            var component = GameObjectBridge.AttachComponentTo(gameObject, decoratedType);

            if (component != null)
            {
                var initializerMethod = decoratedType.GetMethod(
                    attribute.InitializerName,
                    new Type[] { typeof(IManager) }
                    );

                if (initializerMethod != null)
                {
                    Log.Debug($"Found initializer method '{attribute.InitializerName}' for {attribute.LibraryID}, calling.");
                    initializerMethod.Invoke(component, new object[] { Manager });
                }

                GameObjectBridge.DontDestroyOnLoad(gameObject);
                GameObjectBridge.SetActive(gameObject, true);

                var host = new GameSupportHost
                {
                    ID                = attribute.LibraryID,
                    Assembly          = assembly,
                    ComponentInstance = component,
                    UnityGameObject   = gameObject
                };

                GSLs.Add(host);
                return(true);
            }

            Log.Error("Game support library failed to initialize, for some reason your component was rejected by Unity Engine.\nLook in the output log of the game for more details.");
            return(false);
        }
Beispiel #2
0
        private void LoadMod(LoadData data)
        {
            var rootPath = data.RootDirectory;
            var manifest = data.Manifest;

            var targetModulePath = Path.Combine(rootPath, manifest.ModuleFileName);

            Log.Info($"Now trying to load '{targetModulePath}'");

            if (!File.Exists(targetModulePath))
            {
                Log.Error($"That was quick... Target DLL file does not exist.");
                return;
            }

            if (manifest.RequiredGSLs != null && manifest.RequiredGSLs.Length > 0)
            {
                foreach (var id in manifest.RequiredGSLs)
                {
                    if (!GameSupportLoader.IsGameSupportLibraryPresent(id))
                    {
                        Log.Error($"The mod requires a GSL with ID that is not present: {id}");
                        Log.Error("This mod will not be loaded. You need to install that GSL before loading that mod.");

                        return;
                    }
                }
            }

            if (manifest.Dependencies != null && manifest.Dependencies.Length > 0)
            {
                if (!LoadDependenciesForMod(rootPath, manifest.Dependencies))
                {
                    Log.Error("Failed to load dependencies.");
                    return;
                }
            }

            Assembly modAssembly;

            try
            {
                modAssembly = Assembly.LoadFrom(targetModulePath);
            }
            catch (ReflectionTypeLoadException rtle)
            {
                Log.ReflectionTypeLoadException(rtle);
                return;
            }
            catch (Exception e)
            {
                Log.Exception(e);
                return;
            }

            EnsureSingleEntryPoint(modAssembly);

            Type[] types;
            try
            {
                types = modAssembly.GetTypes();
            }
            catch (ReflectionTypeLoadException rtle)
            {
                Log.ReflectionTypeLoadException(rtle);
                return;
            }

            var entryPointType = FindEntryPointType(types);
            var entryPointInfo = GetEntryPointAttribute(entryPointType);

            EnsureModIdValid(entryPointInfo.ModID);

            var initMethodInfo = entryPointType.GetMethod(entryPointInfo.InitializerName, new Type[] { typeof(IManager) });

            if (initMethodInfo == null)
            {
                Log.Error($"Initializer method '{entryPointInfo.InitializerName}' accepting parameter of type 'IManager' not found.");
                return;
            }

            var messageHandlers = FindMessageHandlers(types);

            foreach (var messageHandler in messageHandlers)
            {
                Messenger.RegisterHandlerFor(messageHandler.ModID, messageHandler.MessageName, messageHandler.Method);
                Log.Info($"Registered message handler <{messageHandler.Method.Name}> for '{messageHandler.ModID}:{messageHandler.MessageName}'");
            }

            var modHost = new ModHost
            {
                Assembly   = modAssembly,
                ModID      = entryPointInfo.ModID,
                LoadData   = data,
                Instance   = null,
                GameObject = null
            };

            var dealingWithGameObject = MonoBehaviourBridge.MonoBehaviourType.IsAssignableFrom(entryPointType);

            if (dealingWithGameObject)
            {
                modHost.GameObject = GameObjectBridge.CreateGameObject(entryPointInfo.ModID);
                GameObjectBridge.DontDestroyOnLoad(modHost.GameObject);

                if (entryPointInfo.AwakeAfterInitialize)
                {
                    GameObjectBridge.SetActive(modHost.GameObject, false);
                }

                modHost.Instance = GameObjectBridge.AttachComponentTo(modHost.GameObject, entryPointType);
            }
            else
            {
                var instance = Activator.CreateInstance(entryPointType);
                modHost.Instance = instance;
            }

            var initializer = entryPointType.GetMethod(
                entryPointInfo.InitializerName,
                new Type[] { typeof(IManager) }
                );

            modHost.AssetLoaderMethod = entryPointType.GetMethod(
                entryPointInfo.LoaderMethodName,
                new Type[] { }
                );

            if (initializer != null)
            {
                Log.Info($"Now calling initializer method '{initializer.Name}' in '{modHost.Assembly.GetName().Name}'");

                try
                {
                    var args = new object[] { Manager };

                    if (initializer.IsStatic)
                    {
                        initializer.Invoke(null, args);
                    }
                    else
                    {
                        initializer.Invoke(modHost.Instance, args);
                    }
                }
                catch (Exception e)
                {
                    Log.Error("The initializer method has exploded spectacularly. Centrifuge and other mods will still work, though.");
                    Log.Exception(e);

                    if (dealingWithGameObject)
                    {
                        GameObjectBridge.Destroy(modHost.GameObject);
                    }

                    return;
                }
            }
            else
            {
                Log.Warning($"Did not find the initializer method '{entryPointInfo.InitializerName}' for Mod ID '{modHost.ModID}'. Seems like it doesn't exist. Loaded the mod anyway.");
            }

            if (dealingWithGameObject && entryPointInfo.AwakeAfterInitialize)
            {
                GameObjectBridge.SetActive(modHost.GameObject, true);
            }

            Registry.RegisterMod(modHost);
            Log.Info("Mod has been initialized and registered sucessfully.");

            Manager.OnModInitialized(modHost.ToExchangeableApiObject());
        }
Beispiel #3
0
        public static void Initialize()
        {
            foreach (var arg in Environment.GetCommandLineArgs())
            {
                if (arg == StartupArguments.DisableFancyColors)
                {
                    ConsoleAllocator.FancyColorsEnabled = false;
                }

                if (arg == StartupArguments.AllocateConsole)
                {
                    ConsoleAllocator.Redirect();
                    ConsoleEnabled = true;
                }
            }

            var version = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).FileVersion;

            EarlyLog.Info($"Centrifuge bootstrap for Reactor Mod Loader and API. Version {version}. Unity {ApplicationBridge.UnityVersion}");

            if (ConsoleEnabled)
            {
                EarlyLog.Info($"Diagnostics mode enabled. Remove '{StartupArguments.AllocateConsole}' command line argument to disable.");
            }

            if (ApplicationBridge.GetRunningUnityGeneration() == UnityGeneration.Unity4OrOlder)
            {
                EarlyLog.Error("Centrifuge requires Unity 5 or newer. Terminating.");
                return;
            }

            EarlyLog.Info("Trying to find Centrifuge Reactor DLL...");
            var reactorPath = GetCrossPlatformCompatibleReactorPath();

            if (!File.Exists(reactorPath))
            {
                EarlyLog.Error($"Centrifuge Reactor DLL could not be found at '{reactorPath}'. Mods will not be loaded.");
                return;
            }

            Type proxyType;

            try
            {
                EarlyLog.Info("Validating and loading Centrifuge Reactor DLL...");
                Assembly.LoadFrom(reactorPath);

                EarlyLog.Info("Building manager proxy component for Unity Engine...");
                proxyType = new ManagerProxyBuilder().WriteDynamicAssemblyAndLoadProxyType();

                if (proxyType == null)
                {
                    EarlyLog.Info("Failed.");
                    return;
                }
            }
            catch (ReflectionTypeLoadException rtle)
            {
                EarlyLog.Exception(rtle);

                EarlyLog.Info(" --- LOADER EXCEPTIONS FOLLOW --- ");
                foreach (var lex in rtle.LoaderExceptions)
                {
                    EarlyLog.Exception(lex);
                }
                return;
            }
            catch (Exception ex)
            {
                EarlyLog.Exception(ex);
                return;
            }

            try
            {
                EarlyLog.Info("Creating Reactor Manager GameObject...");
                ReactorManagerObject = GameObjectBridge.CreateGameObject("com.github.ciastex/ReactorModLoaderProxy");
            }
            catch (Exception e)
            {
                EarlyLog.Exception(e);
                return;
            }

            EarlyLog.Info("About to add component to Reactor Manager GameObject.");
            object proxyComponent;

            try
            {
                proxyComponent = GameObjectBridge.AttachComponentTo(ReactorManagerObject, proxyType);
            }
            catch (Exception e)
            {
                EarlyLog.Exception(e);
                return;
            }

            if (proxyComponent == null)
            {
                EarlyLog.Error("Manager proxy component has failed to attach when it wasn't really supposed to fail on Unity 5+.");

                EarlyLog.Info("Report this stuff to https://github.com/Ciastex/Centrifuge/issues.");
                EarlyLog.Info("Make sure to check for and - if existing - include your game's output_log.txt (and/or Player.log) in the report.");
                EarlyLog.Info("Definitely include this entire log as well.");
                EarlyLog.Info("Otherwise I'll be very angry and ask you for this stuff in a very rude manner.");

                if (Platform.IsUnix())
                {
                    EarlyLog.Info("Look in ~/.config/unity3d/<CompanyName>/<GameName>/ for any .log and/or .txt files.");
                }
                else
                {
                    var path = Path.Combine(Environment.GetEnvironmentVariable("USERPROFILE"), "\\AppData\\LocalLow");
                    EarlyLog.Info($"Look in {path}\\<CompanyName>\\<GameName> for any .log and/or .txt files.");
                }
            }

            EarlyLog.Info(" --- BOOTSTRAPPER FINISHED --- ");
        }