Beispiel #1
0
        private static void ValidateModManifests()
        {
            var registeredMods = ModRegistry.GetRegisteredItems();

            foreach (var mod in
                     registeredMods.Where(n => n.IsFarmhandMod && n.ModState == ModState.Unloaded).Cast <ModManifest>())
            {
                try
                {
                    if (mod.UniqueId == null)
                    {
                        mod.UniqueId = new UniqueId <string>(Guid.NewGuid().ToString());
                    }

                    if (!mod.UniqueId.ThisId.Contains("\\") &&
                        (!mod.HasContent || mod.Content.Textures == null ||
                         !mod.Content.Textures.Any(n => n.Id.Contains("\\"))))
                    {
                        continue;
                    }

                    Log.Error(
                        $"Error - {mod.Name} by {mod.Author} manifest is invalid. UniqueIDs cannot contain \"\\\"");
                    mod.ModState = ModState.InvalidManifest;
                }
                catch (Exception ex)
                {
                    Log.Error($"Error validating mod {mod.Name} by {mod.Author}\n\t-{ex.Message}");
                }
            }
        }
Beispiel #2
0
        private static void LoadFinalMods()
        {
            var registeredMods = ModRegistry.GetRegisteredItems();

            foreach (var mod in registeredMods.Where(n => n.ModState == ModState.Unloaded))
            {
                Log.Verbose($"Loading mod: {mod.Name} by {mod.Author}");
                try
                {
                    ApiEvents.InvokeModPreLoad(mod);
                    mod.OnBeforeLoaded();
                    if (mod.HasContent)
                    {
                        mod.LoadContent();
                    }
                    if (mod.HasDll)
                    {
                        mod.LoadModDll();
                    }
                    mod.ModState = ModState.Loaded;
                    mod.OnAfterLoaded();
                    Log.Success($"Loaded Mod: {mod.Name} v{mod.Version} by {mod.Author}");
                    ApiEvents.InvokeModPostLoad(mod);
                }
                catch (Exception ex)
                {
                    mod.ModState = ModState.Errored;
                    Log.Exception($"Error loading mod {mod.Name} by {mod.Author}", ex);
                    ApiEvents.InvokeModLoadError(mod);
                }
            }
        }
Beispiel #3
0
        private void SetUpPositions()
        {
            _labels.Clear();
            _modToggles.Clear();
            _currentItemIndex = 0;

            var mods = ModRegistry.GetRegisteredItems();

            for (var index = 0; index < 7; ++index)
            {
                _optionSlots.Add(new ClickableComponent(new Rectangle(xPositionOnScreen + Game1.tileSize / 4, yPositionOnScreen + Game1.tileSize * 6 / 4 + Game1.pixelZoom + index * ((height - Game1.tileSize * 2) / 7), width - Game1.tileSize / 2, (height - Game1.tileSize * 2) / 7 + Game1.pixelZoom), string.Concat(index)));
            }

            foreach (var mod in mods)
            {
                if (mod.UniqueId == ModLoader1.Instance.ModSettings.UniqueId)
                {
                    continue;
                }

                var checkbox = new DisableableOptionCheckbox($"{mod.Name} by {mod.Author}", 11)
                {
                    IsChecked = mod.ModState == ModState.Loaded
                };

                if (mod.ModState != ModState.Loaded && mod.ModState != ModState.Deactivated)
                {
                    ResolveLoadingIssue(checkbox, mod);
                }
                _modToggles.Add(checkbox);
                _modOptions[checkbox] = mod;
            }
        }
Beispiel #4
0
        private static void LoadFinalMods()
        {
            var registeredMods = ModRegistry.GetRegisteredItems();

            foreach (var mod in registeredMods.Where(n => n.ModState == ModState.Unloaded))
            {
                Log.Verbose($"Loading mod: {mod.Name} by {mod.Author}");
                try
                {
                    mod.OnBeforeLoaded();
                    if (mod.HasContent)
                    {
                        mod.LoadContent();
                    }
                    if (mod.HasDll)
                    {
                        mod.LoadModDll();
                    }
                    mod.ModState = ModState.Loaded;
                    mod.OnAfterLoaded();
                    Log.Success($"Loaded Mod: {mod.Name} v{mod.Version} by {mod.Author}");
                }
                catch (Exception ex)
                {
                    Log.Exception($"Error loading mod {mod.Name} by {mod.Author}", ex);
                    mod.ModState = ModState.Errored;
                    //TODO, well something broke. Do summut' 'bout it!
                }
            }
        }
        public void OnAfterGameInitialise(object sender, EventArgsOnGameInitialised e)
        {
            var test    = ModRegistry.GetRegisteredItems();
            var texture = ModSettings.GetTexture("icon_menuModsButton");

            Farmhand.UI.TitleMenu.RegisterNewTitleButton(new Farmhand.UI.TitleMenu.CustomTitleOption
            {
                Key               = "Mods",
                Texture           = texture,
                TextureSourceRect = new Rectangle(222, 187, 74, 58),
                OnClick           = OnModMenuItemClicked
            });
        }
Beispiel #6
0
        public void OnAfterGameInitialise(object sender, EventArgsOnGameInitialised e)
        {
            var test    = ModRegistry.GetRegisteredItems();
            var texture = ModSettings.GetTexture("icon_menuModsButton");

            //var texture2 = Texture2D.FromStream(Game1.graphics.GraphicsDevice, new FileStream("FarmhandContent\\customUI.png", FileMode.Open));

            Farmhand.UI.TitleMenu.RegisterNewTitleButton(new Farmhand.UI.TitleMenu.CustomTitleOption
            {
                Key               = "Mods",
                Texture           = texture,
                TextureSourceRect = new Rectangle(222, 187, 74, 58),
                OnClick           = OnModMenuItemClicked
            });
        }
Beispiel #7
0
        private static void ApiEvents_OnModError(object sender, Events.Arguments.EventArgsOnModError e)
        {
            var mod = ModRegistry.GetRegisteredItems().FirstOrDefault(n => n.ModAssembly == e.Assembly);

            if (mod != null)
            {
                Log.Exception($"Exception thrown by mod: {mod.Name} - {mod.Author}", e.Exception);
                DeactivateMod(mod, ModState.Errored, e.Exception);
            }
            else
            {
                Log.Exception($"Exception thrown by unknown mod with assembly: {e.Assembly.FullName}", e.Exception);
                DetachAssemblyDelegates(e.Assembly);
            }
        }
Beispiel #8
0
        /// <summary>
        ///     Forces the game to reload mod configurations which use save specific settings.
        /// </summary>
        public static void ReloadConfigurations()
        {
            var mods = ModRegistry.GetRegisteredItems().Where(n => n.IsFarmhandMod).Cast <ModManifest>();

            foreach (var mod in mods)
            {
                var config = mod.Instance?.ConfigurationSettings;
                if (config != null)
                {
                    if (config.UseSaveSpecificConfiguration)
                    {
                        config.Load();
                    }
                }
            }
        }
Beispiel #9
0
        internal static void LoadMods()
        {
            Log.Info($"Stardew Valley v{Game1.version}");
            Log.Info($"Stardew Farmhand v{Constants.Version}");

            ApiEvents.OnModError += ApiEvents_OnModError;
            AppDomain currentDomain = AppDomain.CurrentDomain;

            currentDomain.AssemblyResolve += CurrentDomainOnAssemblyResolve;


            Log.Success("Initializing Mappings");
            GlobalRouteManager.InitialiseMappings();
            Log.Success("Mappings Initialized");

            Log.Info("Loading Mods...");
            try
            {
                Log.Verbose("Loading Mod Manifests");
                LoadModManifests();
                Log.Verbose("Validating Mod Manifests");
                ValidateModManifests();
                Log.Verbose("Resolving Mod Dependencies");
                ResolveDependencies();
                Log.Verbose("Importing Mod DLLs, Settings, and Content");
                LoadFinalMods();

                if (UsingSmapiMods)
                {
                    Log.Verbose("Using SMAPI - Attaching SMAPI events");
                    ModEventManager.AttachSmapiEvents();
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex.Message);
                Log.Error(ex.StackTrace);
            }
            var numModsLoaded = ModRegistry.GetRegisteredItems().Count(n => n.ModState == ModState.Loaded);

            Log.Info($"{numModsLoaded} Mods Loaded!");

            Game1.version += $"Stardew Farmhand v{Constants.Version}: {numModsLoaded} mods loaded";
        }
Beispiel #10
0
        private static void BubbleDependencyLoadError(ModManifest erroredMod)
        {
            Log.Error($"Marking {erroredMod.Name} dependency hierarchy as failed");

            var problemMods = new Stack <IModManifest>();

            // We use this one to avoid circular resolution issues
            var resolvedMods = new List <IModManifest>();

            problemMods.Push(erroredMod);

            do
            {
                var mod = problemMods.Pop();
                resolvedMods.Add(mod);
                var dependants =
                    ModRegistry.GetRegisteredItems()
                    .Where(n => n.IsFarmhandMod)
                    .Cast <ModManifest>()
                    .Where(
                        n =>
                        n.Dependencies != null &&
                        n.Dependencies.Any(d => d.IsRequired && mod.UniqueId.Equals(d.UniqueId)));

                foreach (var dependant in dependants)
                {
                    dependant.ModState = ModState.DependencyLoadError;
                    if (!resolvedMods.Contains(dependant))
                    {
                        Log.Verbose(
                            $"\tDisabling {dependant.Name} due to {mod.Name} failure."
                            + (mod == erroredMod ? string.Empty : $" (Cascaded failure loading {erroredMod.Name}"));
                        problemMods.Push(dependant);
                    }
                }
            }while (problemMods.Count > 0);

            Log.Verbose($"{erroredMod.Name} all marked failed");
        }
Beispiel #11
0
        private void SetUpPositions()
        {
            _labels.Clear();
            _modToggles.Clear();
            _currentItemIndex = 0;

            upArrow         = new ClickableTextureComponent(new Rectangle(xPositionOnScreen + width + Game1.tileSize / 4, yPositionOnScreen + Game1.tileSize / 4, 11 * Game1.pixelZoom, 12 * Game1.pixelZoom), Game1.mouseCursors, new Rectangle(421, 459, 11, 12), Game1.pixelZoom);
            downArrow       = new ClickableTextureComponent(new Rectangle(xPositionOnScreen + width + Game1.tileSize / 4, yPositionOnScreen + height - Game1.tileSize, 11 * Game1.pixelZoom, 12 * Game1.pixelZoom), Game1.mouseCursors, new Rectangle(421, 472, 11, 12), Game1.pixelZoom);
            scrollBar       = new ClickableTextureComponent(new Rectangle(upArrow.bounds.X + Game1.pixelZoom * 3, upArrow.bounds.Y + upArrow.bounds.Height + Game1.pixelZoom, 6 * Game1.pixelZoom, 10 * Game1.pixelZoom), Game1.mouseCursors, new Rectangle(435, 463, 6, 10), Game1.pixelZoom);
            scrollBarRunner = new Rectangle(scrollBar.bounds.X, upArrow.bounds.Y + upArrow.bounds.Height + Game1.pixelZoom, scrollBar.bounds.Width, height - Game1.tileSize - upArrow.bounds.Height - Game1.pixelZoom * 7);

            var mods = ModRegistry.GetRegisteredItems();

            for (var index = 0; index < 4; ++index)
            {
                _optionSlots.Add(new ClickableComponent(new Rectangle(xPositionOnScreen + Game1.tileSize / 4, yPositionOnScreen + Game1.tileSize / 4 + index * (height / 4) - (index * 7), width - Game1.tileSize / 2, (height / 4 + Game1.pixelZoom) - 11), string.Concat(index)));
            }

            foreach (var mod in mods)
            {
                if (Equals(mod.UniqueId, ModLoader1.Instance.ModSettings.UniqueId))
                {
                    continue;
                }

                var checkbox = new DisableableOptionCheckbox("", 11)
                {
                    IsChecked = mod.ModState == ModState.Loaded
                };

                if (mod.IsFarmhandMod && mod.ModState != ModState.Loaded && mod.ModState != ModState.Deactivated)
                {
                    ResolveLoadingIssue(checkbox, (ModManifest)mod);
                }
                _modToggles.Add(checkbox);
                _modOptions[checkbox] = mod;
            }
        }
        private static void LoadFinalMods()
        {
            var registeredMods = ModRegistry.GetRegisteredItems();

            foreach (var mod in registeredMods.Where(n => n.ModState == ModState.Unloaded))
            {
                Log.Verbose($"Loading mod: {mod.Name} by {mod.Author}");
                try
                {
                    ApiEvents.InvokeModPreLoad(mod);
                    mod.OnBeforeLoaded();
                    if (mod.HasContent)
                    {
                        mod.LoadContent();
                    }
                    if (mod.HasDll)
                    {
                        mod.LoadModDll();
                    }
                    mod.ModState = ModState.Loaded;
                    mod.OnAfterLoaded();
                    Log.Success($"Loaded Mod: {mod.Name} v{mod.Version} by {mod.Author}");
                    ApiEvents.InvokeModPostLoad(mod);
                }
                catch (Exception ex)
                {
                    mod.ModState = ModState.Errored;
                    Log.Exception($"Error loading mod {mod.Name} by {mod.Author}", ex);
                    ApiEvents.InvokeModLoadError(mod);
                }
            }

            // See ReferenceFix.Data.BuildXnaTypeCache()
            // Since mod loading is done we don't need this anymore.
            // There are a lot of types, so might as well save the memory.
            ReferenceHelper.XnaTypes.Clear();
        }
Beispiel #13
0
        private static void ResolveDependencies()
        {
            var registeredMods = ModRegistry.GetRegisteredItems().Where(n => n.IsFarmhandMod).Cast <ModManifest>();

            // Loop to verify every dependent mod is available.
            bool stateChange;
            var  modInfos = registeredMods as ModManifest[] ?? registeredMods.ToArray();

            do
            {
                stateChange = false;
                foreach (var mod in modInfos)
                {
                    if (mod.ModState == ModState.MissingDependency || mod.Dependencies == null)
                    {
                        continue;
                    }

                    foreach (var dependency in mod.Dependencies.Where(n => n.IsRequired))
                    {
                        var dependencyMatch = modInfos.FirstOrDefault(n => n.UniqueId.Equals(dependency.UniqueId));
                        dependency.DependencyState = DependencyState.Ok;
                        if (dependencyMatch == null)
                        {
                            mod.ModState = ModState.MissingDependency;
                            dependency.DependencyState = DependencyState.Missing;
                            stateChange = true;
                            Log.Error($"Failed to load {mod.Name} due to missing dependency: {dependency.UniqueId}");
                        }
                        else if (dependencyMatch.ModState == ModState.MissingDependency)
                        {
                            mod.ModState = ModState.MissingDependency;
                            dependency.DependencyState = DependencyState.ParentMissing;
                            stateChange = true;
                            Log.Error(
                                $"Failed to load {mod.Name} due to missing dependency missing dependency: {dependency.UniqueId}");
                        }
                        else
                        {
                            var dependencyVersion = dependencyMatch.Version;
                            if (dependencyVersion == null)
                            {
                                continue;
                            }

                            if (dependency.MinimumVersion != null && dependency.MinimumVersion > dependencyVersion)
                            {
                                mod.ModState = ModState.MissingDependency;
                                dependency.DependencyState = DependencyState.TooLowVersion;
                                stateChange = true;
                                Log.Error(
                                    $"Failed to load {mod.Name} due to minimum version incompatibility with {dependency.UniqueId}: "
                                    + $"v.{dependencyMatch.Version} < v.{dependency.MinimumVersion}");
                            }
                            else if (dependency.MaximumVersion != null && dependency.MaximumVersion < dependencyVersion)
                            {
                                mod.ModState = ModState.MissingDependency;
                                dependency.DependencyState = DependencyState.TooHighVersion;
                                stateChange = true;
                                Log.Error(
                                    $"Failed to load {mod.Name} due to maximum version incompatibility with {dependency.UniqueId}: "
                                    + $"v.{dependencyMatch.Version} > v.{dependency.MaximumVersion}");
                            }
                        }
                    }
                }
            }while (stateChange);
        }
Beispiel #14
0
        private static void LoadFinalMods()
        {
            Func <ModManifest[], List <ModManifest>, List <ModManifest>, List <ModManifest>, ModManifest[]> getModsForThisPass = (mods, modsLoaded, modsErrored, modsProcessed) =>
            {
                Func <ModDependency, bool> isDependencyLoaded = dependency =>
                {
                    if (dependency.IsRequired)
                    {
                        return(modsLoaded.Any(ld => ld.UniqueId.Equals(dependency.UniqueId)));
                    }

                    var dependentMod = mods.FirstOrDefault(n => n.UniqueId.Equals(dependency.UniqueId));
                    return(dependentMod?.ModState != ModState.Unloaded);
                };

                return
                    (mods.Where(
                         n =>
                         n.ModState == ModState.Unloaded &&
                         (n.Dependencies == null || n.Dependencies.All(d => isDependencyLoaded(d))))
                     .ToArray());
            };

            var modsToLoad    = ModRegistry.GetRegisteredItems().Where(n => n.IsFarmhandMod).Cast <ModManifest>().ToArray();
            var loadedMods    = new List <ModManifest>();
            var erroredMods   = new List <ModManifest>();
            var processedMods = new List <ModManifest>();

            var modsThisPass = getModsForThisPass(modsToLoad, loadedMods, erroredMods, processedMods);

            while (modsThisPass.Any())
            {
                foreach (var mod in modsThisPass)
                {
                    processedMods.Add(mod);
                    if (mod.ModState == ModState.DependencyLoadError)
                    {
                        erroredMods.Add(mod);
                        continue;
                    }

                    Log.Verbose($"Loading mod: {mod.Name} by {mod.Author}");
                    try
                    {
                        ApiEvents.InvokeModPreLoad(mod);
                        mod.OnBeforeLoaded();
                        if (mod.HasContent)
                        {
                            mod.LoadContent();
                        }

                        if (mod.HasDll)
                        {
                            if (!mod.LoadModDll())
                            {
                                mod.ModState = ModState.Errored;
                                ApiEvents.InvokeModLoadError(mod);
                                erroredMods.Add(mod);
                                BubbleDependencyLoadError(mod);
                                continue;
                            }
                        }

                        mod.ModState = ModState.Loaded;
                        mod.OnAfterLoaded();
                        Log.Success($"Loaded Mod: {mod.Name} v{mod.Version} by {mod.Author}");
                        ApiEvents.InvokeModPostLoad(mod);
                        loadedMods.Add(mod);
                    }
                    catch (Exception ex)
                    {
                        mod.ModState = ModState.Errored;
                        Log.Exception($"Error loading mod {mod.Name} by {mod.Author}", ex);
                        ApiEvents.InvokeModLoadError(mod);
                        erroredMods.Add(mod);
                        BubbleDependencyLoadError(mod);
                        break;
                    }
                }

                modsThisPass = getModsForThisPass(modsToLoad, loadedMods, erroredMods, processedMods);
            }

            // See ReferenceFix.Data.BuildXnaTypeCache()
            // Since mod loading is done we don't need this anymore.
            // There are a lot of types, so might as well save the memory.
            ReferenceHelper.XnaTypes.Clear();
        }