示例#1
0
        /*********
        ** Public methods
        *********/
        /// <summary>The mod entry point, called after the mod is first loaded.</summary>
        /// <param name="helper">Provides simplified APIs for writing mods.</param>
        public override void Entry(IModHelper helper)
        {
            // read config
            this.Config = helper.ReadConfig <ModConfig>();
            this.Keys   = this.Config.Controls.ParseControls(helper.Input, this.Monitor);

            // init
            I18n.Init(helper.Translation);
            this.TractorManager = new TractorManager(this.Config, this.Keys, this.Helper.Reflection);
            this.UpdateConfig();

            // hook events
            IModEvents events = helper.Events;

            events.GameLoop.GameLaunched          += this.OnGameLaunched;
            events.GameLoop.SaveLoaded            += this.OnSaveLoaded;
            events.GameLoop.DayStarted            += this.OnDayStarted;
            events.GameLoop.DayEnding             += this.OnDayEnding;
            events.GameLoop.Saving                += this.OnSaving;
            events.Display.Rendered               += this.OnRendered;
            events.Display.MenuChanged            += this.OnMenuChanged;
            events.Input.ButtonPressed            += this.OnButtonPressed;
            events.World.NpcListChanged           += this.OnNpcListChanged;
            events.World.LocationListChanged      += this.OnLocationListChanged;
            events.GameLoop.UpdateTicked          += this.OnUpdateTicked;
            events.Multiplayer.ModMessageReceived += this.OnModMessageReceived;
            events.Player.Warped += this.OnWarped;

            // validate translations
            if (!helper.Translation.GetTranslations().Any())
            {
                this.Monitor.Log("The translation files in this mod's i18n folder seem to be missing. The mod will still work, but you'll see 'missing translation' messages. Try reinstalling the mod to fix this.", LogLevel.Warn);
            }
        }
示例#2
0
        /****
        ** Helper methods
        ****/
        /// <summary>Apply the mod configuration if it changed.</summary>
        private void UpdateConfig()
        {
            this.Keys = this.Config.Controls.ParseControls(this.Helper.Input, this.Monitor);

            var modRegistry = this.Helper.ModRegistry;
            var reflection  = this.Helper.Reflection;
            var toolConfig  = this.Config.StandardAttachments;

            this.TractorManager.UpdateConfig(this.Config, this.Keys, new IAttachment[]
            {
                new CustomAttachment(this.Config.CustomAttachments, modRegistry, reflection), // should be first so it can override default attachments
                new AxeAttachment(toolConfig.Axe, modRegistry, reflection),
                new FertilizerAttachment(toolConfig.Fertilizer, modRegistry, reflection),
                new GrassStarterAttachment(toolConfig.GrassStarter, modRegistry, reflection),
                new HoeAttachment(toolConfig.Hoe, modRegistry, reflection),
                new MeleeWeaponAttachment(toolConfig.MeleeWeapon, modRegistry, reflection),
                new MilkPailAttachment(toolConfig.MilkPail, modRegistry, reflection),
                new PickaxeAttachment(toolConfig.PickAxe, modRegistry, reflection),
                new ScytheAttachment(toolConfig.Scythe, modRegistry, reflection),
                new SeedAttachment(toolConfig.Seeds, modRegistry, reflection),
                modRegistry.IsLoaded(SeedBagAttachment.ModId) ? new SeedBagAttachment(toolConfig.SeedBagMod, modRegistry, reflection) : null,
                new ShearsAttachment(toolConfig.Shears, modRegistry, reflection),
                new SlingshotAttachment(toolConfig.Slingshot, modRegistry, reflection),
                new WateringCanAttachment(toolConfig.WateringCan, modRegistry, reflection)
            });
        }
示例#3
0
        /*********
        ** Public methods
        *********/
        /// <summary>The mod entry point, called after the mod is first loaded.</summary>
        /// <param name="helper">Provides simplified APIs for writing mods.</param>
        public override void Entry(IModHelper helper)
        {
            this.Config = helper.ReadConfig <ModConfig>();
            this.Keys   = this.Config.Controls.ParseControls(helper.Input, this.Monitor);

            helper.Events.GameLoop.UpdateTicked += this.OnUpdateTicked;
        }
示例#4
0
        /*********
        ** Public methods
        *********/
        /// <summary>The mod entry point, called after the mod is first loaded.</summary>
        /// <param name="helper">Provides methods for interacting with the mod directory, such as read/writing a config file or custom JSON files.</param>
        public override void Entry(IModHelper helper)
        {
            // toggle mod compatibility
            bool hasBetterJunimos  = helper.ModRegistry.IsLoaded("hawkfalcon.BetterJunimos");
            bool hasAutoGrabberMod = helper.ModRegistry.IsLoaded("Jotser.AutoGrabberMod");

            // init
            this.Config  = helper.ReadConfig <ModConfig>();
            this.Keys    = this.Config.Controls.ParseControls(this.Monitor);
            this.Factory = new MachineGroupFactory();
            this.Factory.Add(new AutomationFactory(this.Config.Connectors, this.Config.AutomateShippingBin, this.Monitor, helper.Reflection, hasBetterJunimos, hasAutoGrabberMod));

            // hook events
            helper.Events.GameLoop.SaveLoaded       += this.OnSaveLoaded;
            helper.Events.Player.Warped             += this.OnWarped;
            helper.Events.World.LocationListChanged += this.World_LocationListChanged;
            helper.Events.World.ObjectListChanged   += this.World_ObjectListChanged;
            helper.Events.GameLoop.UpdateTicked     += this.OnUpdateTicked;
            helper.Events.Input.ButtonPressed       += this.OnButtonPressed;

            if (this.Config.Connectors.Any(p => p.Type == ObjectType.Floor))
            {
                helper.Events.World.TerrainFeatureListChanged += this.World_TerrainFeatureListChanged;
            }

            // log info
            this.Monitor.VerboseLog($"Initialised with automation every {this.Config.AutomationInterval} ticks.");
        }
示例#5
0
        /*********
        ** Public methods
        *********/
        /// <summary>The mod entry point, called after the mod is first loaded.</summary>
        /// <param name="helper">Provides methods for interacting with the mod directory, such as read/writing a config file or custom JSON files.</param>
        public override void Entry(IModHelper helper)
        {
            // load config
            this.Config = this.Helper.ReadConfig <ModConfig>();
            this.Keys   = this.Config.Controls.ParseControls(helper.Input, this.Monitor);

            // load translations
            L10n.Init(helper.Translation);

            // load & validate database
            this.LoadMetadata();
            this.IsDataValid = this.Metadata.LooksValid();
            if (!this.IsDataValid)
            {
                this.Monitor.Log("The data.json file seems to be missing or corrupt. Lookups will be disabled.", LogLevel.Error);
                this.IsDataValid = false;
            }

            // validate translations
            if (!helper.Translation.GetTranslations().Any())
            {
                this.Monitor.Log("The translation files in this mod's i18n folder seem to be missing. The mod will still work, but you'll see 'missing translation' messages. Try reinstalling the mod to fix this.", LogLevel.Warn);
            }

            // hook up events
            helper.Events.GameLoop.GameLaunched += this.OnGameLaunched;
            helper.Events.GameLoop.DayStarted   += this.OnDayStarted;
            helper.Events.Display.RenderedHud   += this.OnRenderedHud;
            helper.Events.Display.MenuChanged   += this.OnMenuChanged;
            helper.Events.Input.ButtonPressed   += this.OnButtonPressed;
            if (this.Config.HideOnKeyUp)
            {
                helper.Events.Input.ButtonReleased += this.OnButtonReleased;
            }
        }
示例#6
0
 /*********
 ** Public methods
 *********/
 /// <summary>Construct an instance.</summary>
 /// <param name="config">The mod settings.</param>
 /// <param name="keys">The configured key bindings.</param>
 /// <param name="translation">Provides translations from the mod's i18n folder.</param>
 /// <param name="reflection">Simplifies access to private game code.</param>
 public TractorManager(ModConfig config, ModConfigKeys keys, ITranslationHelper translation, IReflectionHelper reflection)
 {
     this.Config      = config;
     this.Keys        = keys;
     this.Translation = translation;
     this.Reflection  = reflection;
 }
示例#7
0
        /*********
        ** Public methods
        *********/
        /// <summary>The mod entry point, called after the mod is first loaded.</summary>
        /// <param name="helper">Provides methods for interacting with the mod directory, such as read/writing a config file or custom JSON files.</param>
        public override void Entry(IModHelper helper)
        {
            // init
            this.Config  = helper.ReadConfig <ModConfig>();
            this.Keys    = this.Config.Controls.ParseControls(this.Monitor);
            this.Factory = new MachineGroupFactory();
            this.Factory.Add(new AutomationFactory(
                                 connectors: this.Config.ConnectorNames,
                                 automateShippingBin: this.Config.AutomateShippingBin,
                                 monitor: this.Monitor,
                                 reflection: helper.Reflection,
                                 data: this.Helper.Data.ReadJsonFile <DataModel>("data.json"),
                                 betterJunimosCompat: this.Config.ModCompatibility.BetterJunimos && helper.ModRegistry.IsLoaded("hawkfalcon.BetterJunimos"),
                                 autoGrabberModCompat: this.Config.ModCompatibility.AutoGrabberMod && helper.ModRegistry.IsLoaded("Jotser.AutoGrabberMod")
                                 ));

            // hook events
            helper.Events.GameLoop.SaveLoaded             += this.OnSaveLoaded;
            helper.Events.Player.Warped                   += this.OnWarped;
            helper.Events.World.BuildingListChanged       += this.OnBuildingListChanged;
            helper.Events.World.LocationListChanged       += this.OnLocationListChanged;
            helper.Events.World.ObjectListChanged         += this.OnObjectListChanged;
            helper.Events.World.TerrainFeatureListChanged += this.OnTerrainFeatureListChanged;
            helper.Events.GameLoop.UpdateTicked           += this.OnUpdateTicked;
            helper.Events.Input.ButtonPressed             += this.OnButtonPressed;

            // log info
            this.Monitor.VerboseLog($"Initialised with automation every {this.Config.AutomationInterval} ticks.");
        }
示例#8
0
        /// <summary>The method invoked when the player presses a button.</summary>
        /// <param name="sender">The event sender.</param>
        /// <param name="e">The event arguments.</param>
        private void OnButtonPressed(object sender, ButtonPressedEventArgs e)
        {
            try
            {
                ModConfigKeys keys = this.Keys;

                // open menu
                if (keys.Toggle.Contains(e.Button))
                {
                    // open if no conflict
                    if (Game1.activeClickableMenu == null)
                    {
                        this.OpenMenu();
                    }

                    // open from inventory if it's safe to close the inventory screen
                    else if (Game1.activeClickableMenu is GameMenu gameMenu && gameMenu.currentTab == GameMenu.inventoryTab)
                    {
                        IClickableMenu inventoryPage = this.Helper.Reflection.GetField <List <IClickableMenu> >(gameMenu, "pages").GetValue()[GameMenu.inventoryTab];
                        if (inventoryPage.readyToClose())
                        {
                            this.OpenMenu();
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                this.HandleError(ex, "handling key input");
            }
        }
示例#9
0
        /// <summary>The method invoked when the player presses a button.</summary>
        /// <param name="sender">The event sender.</param>
        /// <param name="e">The event data.</param>
        private void OnButtonPressed(object sender, ButtonPressedEventArgs e)
        {
            this.Monitor.InterceptErrors("handling your input", $"handling input '{e.Button}'", () =>
            {
                ModConfigKeys keys = this.Keys;

                if (keys.ToggleSearch.JustPressedUnique())
                {
                    this.ToggleSearch();
                }
                if (keys.ToggleLookup.JustPressedUnique())
                {
                    this.ToggleLookup(LookupMode.Cursor);
                }
                else if (keys.ToggleLookupInFrontOfPlayer.JustPressedUnique() && Context.IsWorldReady)
                {
                    this.ToggleLookup(LookupMode.FacingPlayer);
                }
                else if (keys.ScrollUp.JustPressedUnique())
                {
                    (Game1.activeClickableMenu as LookupMenu)?.ScrollUp();
                }
                else if (keys.ScrollDown.JustPressedUnique())
                {
                    (Game1.activeClickableMenu as LookupMenu)?.ScrollDown();
                }
                else if (keys.ToggleDebug.JustPressedUnique() && Context.IsPlayerFree)
                {
                    this.DebugInterface.Enabled = !this.DebugInterface.Enabled;
                }
            });
        }
示例#10
0
        /*********
        ** Public methods
        *********/
        /// <summary>The mod entry point, called after the mod is first loaded.</summary>
        /// <param name="helper">Provides simplified APIs for writing mods.</param>
        public override void Entry(IModHelper helper)
        {
            this.Config = helper.ReadConfig <ModConfig>();
            this.Keys   = this.Config.Controls.ParseControls(helper.Input, this.Monitor);

            helper.Events.GameLoop.UpdateTicked      += this.OnUpdateTicked;
            LocalizedContentManager.OnLanguageChange += this.OnLocaleChanged;
        }
示例#11
0
 /*********
 ** Public methods
 *********/
 /// <summary>Construct an instance.</summary>
 /// <param name="config">The mod settings.</param>
 /// <param name="keys">The configured key bindings.</param>
 /// <param name="translation">Provides translations from the mod's i18n folder.</param>
 /// <param name="reflection">Simplifies access to private game code.</param>
 /// <param name="attachments">The tractor attachments to apply.</param>
 public TractorManager(ModConfig config, ModConfigKeys keys, ITranslationHelper translation, IReflectionHelper reflection, IEnumerable <IAttachment> attachments)
 {
     this.Config              = config;
     this.Keys                = keys;
     this.Translation         = translation;
     this.Reflection          = reflection;
     this.Attachments         = attachments.ToArray();
     this.AttachmentCooldowns = this.Attachments.Where(p => p.RateLimit > this.TicksPerAction).ToDictionary(p => p, p => 0);
 }
示例#12
0
        /*********
        ** Public methods
        *********/
        /// <summary>The mod entry point, called after the mod is first loaded.</summary>
        /// <param name="helper">Provides methods for interacting with the mod directory, such as read/writing a config file or custom JSON files.</param>
        public override void Entry(IModHelper helper)
        {
            // read data file
            const string dataPath = "assets/data.json";
            DataModel    data     = null;

            try
            {
                data = this.Helper.Data.ReadJsonFile <DataModel>(dataPath);
                if (data?.FloorNames == null)
                {
                    this.Monitor.Log($"The {dataPath} file seems to be missing or invalid. Floor connectors will be disabled.", LogLevel.Error);
                }
            }
            catch (Exception ex)
            {
                this.Monitor.Log($"The {dataPath} file seems to be invalid. Floor connectors will be disabled.\n{ex}", LogLevel.Error);
            }

            // read config
            this.Config = this.LoadConfig();

            // init
            this.Keys    = this.Config.Controls.ParseControls(helper.Input, this.Monitor);
            this.Factory = new MachineGroupFactory(this.Config);
            this.Factory.Add(new AutomationFactory(
                                 connectors: this.Config.ConnectorNames,
                                 monitor: this.Monitor,
                                 reflection: helper.Reflection,
                                 data: data,
                                 betterJunimosCompat: this.Config.ModCompatibility.BetterJunimos && helper.ModRegistry.IsLoaded("hawkfalcon.BetterJunimos"),
                                 autoGrabberModCompat: this.Config.ModCompatibility.AutoGrabberMod && helper.ModRegistry.IsLoaded("Jotser.AutoGrabberMod"),
                                 pullGemstonesFromJunimoHuts: this.Config.PullGemstonesFromJunimoHuts
                                 ));
            this.CommandHandler = new CommandHandler(this.Monitor, this.Config, this.Factory, this.ActiveMachineGroups);

            // hook events
            helper.Events.GameLoop.SaveLoaded             += this.OnSaveLoaded;
            helper.Events.Player.Warped                   += this.OnWarped;
            helper.Events.World.BuildingListChanged       += this.OnBuildingListChanged;
            helper.Events.World.LocationListChanged       += this.OnLocationListChanged;
            helper.Events.World.ObjectListChanged         += this.OnObjectListChanged;
            helper.Events.World.TerrainFeatureListChanged += this.OnTerrainFeatureListChanged;
            helper.Events.GameLoop.UpdateTicked           += this.OnUpdateTicked;
            helper.Events.Input.ButtonPressed             += this.OnButtonPressed;
            helper.Events.Multiplayer.ModMessageReceived  += this.OnModMessageReceived;

            // hook commands
            helper.ConsoleCommands.Add("automate", "Run commands from the Automate mod. Enter 'automate help' for more info.", this.CommandHandler.HandleCommand);

            // log info
            this.Monitor.VerboseLog($"Initialized with automation every {this.Config.AutomationInterval} ticks.");
            if (this.Config.ModCompatibility.WarnForMissingBridgeMod)
            {
                this.ReportMissingBridgeMods(data?.SuggestedIntegrations);
            }
        }
示例#13
0
        /*********
        ** Public methods
        *********/
        /// <summary>The mod entry point, called after the mod is first loaded.</summary>
        /// <param name="helper">Provides methods for interacting with the mod directory, such as read/writing a config file or custom JSON files.</param>
        public override void Entry(IModHelper helper)
        {
            // read config
            this.Config = helper.ReadConfig <ModConfig>();
            this.Keys   = this.Config.Controls.ParseControls(helper.Input, this.Monitor);

            // hook events
            helper.Events.Input.ButtonPressed += this.OnButtonPressed;
        }
示例#14
0
        /// <summary>The method invoked when the player presses an input button.</summary>
        /// <param name="sender">The event sender.</param>
        /// <param name="e">The event arguments.</param>
        private void OnButtonPressed(object sender, ButtonPressedEventArgs e)
        {
            if (this.Layers == null)
            {
                return;
            }

            // perform bound action
            this.Monitor.InterceptErrors("handling your input", $"handling input '{e.Button}'", () =>
            {
                // check context
                if (!this.CanOverlayNow())
                {
                    return;
                }
                bool overlayVisible = this.CurrentOverlay != null;
                ModConfigKeys keys  = this.Keys;

                // toggle overlay
                if (keys.ToggleLayer.JustPressedUnique())
                {
                    if (overlayVisible)
                    {
                        this.CurrentOverlay.Dispose();
                        this.CurrentOverlay = null;
                    }
                    else
                    {
                        this.CurrentOverlay = new DataLayerOverlay(this.Helper.Events, this.Helper.Input, this.Helper.Reflection, this.Layers, this.CanOverlayNow, this.Config.CombineOverlappingBorders, this.Config.ShowGrid);
                    }
                    this.Helper.Input.Suppress(e.Button);
                }

                // cycle layers
                else if (overlayVisible && keys.NextLayer.JustPressedUnique())
                {
                    this.CurrentOverlay.NextLayer();
                    this.Helper.Input.Suppress(e.Button);
                }
                else if (overlayVisible && keys.PrevLayer.JustPressedUnique())
                {
                    this.CurrentOverlay.PrevLayer();
                    this.Helper.Input.Suppress(e.Button);
                }

                // shortcut to layer
                else if (overlayVisible)
                {
                    ILayer layer = this.ShortcutMap.Where(p => p.Key.JustPressedUnique()).Select(p => p.Value).FirstOrDefault();
                    if (layer != null && layer != this.CurrentOverlay.CurrentLayer)
                    {
                        this.CurrentOverlay.SetLayer(layer);
                        this.Helper.Input.Suppress(e.Button);
                    }
                }
            });
        }
示例#15
0
        /*********
        ** Public methods
        *********/
        /// <summary>The mod entry point, called after the mod is first loaded.</summary>
        /// <param name="helper">Provides simplified APIs for writing mods.</param>
        public override void Entry(IModHelper helper)
        {
            // read config
            this.Config = helper.ReadConfig <ModConfig>();
            this.Keys   = this.Config.Controls.ParseControls(helper.Input, this.Monitor);

            // init tractor logic
            {
                IModRegistry              modRegistry = this.Helper.ModRegistry;
                IReflectionHelper         reflection  = this.Helper.Reflection;
                StandardAttachmentsConfig toolConfig  = this.Config.StandardAttachments;
                this.TractorManager = new TractorManager(this.Config, this.Keys, this.Helper.Translation, this.Helper.Reflection, attachments: new IAttachment[]
                {
                    new CustomAttachment(this.Config.CustomAttachments, modRegistry, reflection), // should be first so it can override default attachments
                    new AxeAttachment(toolConfig.Axe, modRegistry, reflection),
                    new FertilizerAttachment(toolConfig.Fertilizer, modRegistry, reflection),
                    new GrassStarterAttachment(toolConfig.GrassStarter, modRegistry, reflection),
                    new HoeAttachment(toolConfig.Hoe, modRegistry, reflection),
                    new MeleeWeaponAttachment(toolConfig.MeleeWeapon, modRegistry, reflection),
                    new MilkPailAttachment(toolConfig.MilkPail, modRegistry, reflection),
                    new PickaxeAttachment(toolConfig.PickAxe, modRegistry, reflection),
                    new ScytheAttachment(toolConfig.Scythe, modRegistry, reflection),
                    new SeedAttachment(toolConfig.Seeds, modRegistry, reflection),
                    new SeedBagAttachment(toolConfig.SeedBagMod, modRegistry, reflection),
                    new ShearsAttachment(toolConfig.Shears, modRegistry, reflection),
                    new SlingshotAttachment(toolConfig.Slingshot, modRegistry, reflection),
                    new WateringCanAttachment(toolConfig.WateringCan, modRegistry, reflection)
                });
            }

            // hook events
            IModEvents events = helper.Events;

            events.GameLoop.GameLaunched += this.OnGameLaunched;
            events.GameLoop.SaveLoaded   += this.OnSaveLoaded;
            events.GameLoop.DayStarted   += this.OnDayStarted;
            events.GameLoop.DayEnding    += this.OnDayEnding;
            events.GameLoop.Saving       += this.OnSaving;
            if (this.Config.HighlightRadius)
            {
                events.Display.Rendered += this.OnRendered;
            }
            events.Display.MenuChanged            += this.OnMenuChanged;
            events.Input.ButtonPressed            += this.OnButtonPressed;
            events.World.NpcListChanged           += this.OnNpcListChanged;
            events.World.LocationListChanged      += this.OnLocationListChanged;
            events.GameLoop.UpdateTicked          += this.OnUpdateTicked;
            events.Multiplayer.ModMessageReceived += this.OnModMessageReceived;

            // validate translations
            if (!helper.Translation.GetTranslations().Any())
            {
                this.Monitor.Log("The translation files in this mod's i18n folder seem to be missing. The mod will still work, but you'll see 'missing translation' messages. Try reinstalling the mod to fix this.", LogLevel.Warn);
            }
        }
示例#16
0
        /*********
        ** Public methods
        *********/
        /// <summary>The mod entry point, called after the mod is first loaded.</summary>
        /// <param name="helper">Provides methods for interacting with the mod directory, such as read/writing a config file or custom JSON files.</param>
        public override void Entry(IModHelper helper)
        {
            // read config
            this.Config = helper.ReadConfig <ModConfig>();
            this.Keys   = this.Config.Controls.ParseControls(this.Monitor);

            // hook up events
            helper.Events.GameLoop.GameLaunched    += this.OnGameLaunched;
            helper.Events.GameLoop.ReturnedToTitle += this.OnReturnedToTitle;
            helper.Events.GameLoop.UpdateTicked    += this.OnUpdateTicked;
            helper.Events.Input.ButtonPressed      += this.OnButtonPressed;
        }
示例#17
0
        /// <summary>The method invoked when the player releases a button.</summary>
        /// <param name="sender">The event sender.</param>
        /// <param name="e">The event data.</param>
        private void OnButtonReleased(object sender, ButtonReleasedEventArgs e)
        {
            // perform bound action
            this.Monitor.InterceptErrors("handling your input", $"handling input release '{e.Button}'", () =>
            {
                ModConfigKeys keys = this.Keys;

                if (keys.ToggleLookup.JustPressedUnique() || keys.ToggleLookupInFrontOfPlayer.JustPressedUnique())
                {
                    this.HideLookup();
                }
            });
        }
示例#18
0
        /*********
        ** Public methods
        *********/
        /// <summary>The mod entry point, called after the mod is first loaded.</summary>
        /// <param name="helper">Provides methods for interacting with the mod directory, such as read/writing a config file or custom JSON files.</param>
        public override void Entry(IModHelper helper)
        {
            // read data file
            const string dataPath = "assets/data.json";
            DataModel    data     = null;

            try
            {
                data = this.Helper.Data.ReadJsonFile <DataModel>(dataPath);
                if (data?.FloorNames == null)
                {
                    this.Monitor.Log($"The {dataPath} file seems to be missing or invalid. Floor connectors will be disabled.", LogLevel.Error);
                }
            }
            catch (Exception ex)
            {
                this.Monitor.Log($"The {dataPath} file seems to be invalid. Floor connectors will be disabled.\n{ex}", LogLevel.Error);
            }

            // read config
            this.Config = helper.ReadConfig <ModConfig>();
            this.Config.MachinePriority = new Dictionary <string, int>(this.Config.MachinePriority, StringComparer.OrdinalIgnoreCase);

            // init
            this.Keys    = this.Config.Controls.ParseControls(helper.Input, this.Monitor);
            this.Factory = new MachineGroupFactory(this.Config);
            this.Factory.Add(new AutomationFactory(
                                 connectors: this.Config.ConnectorNames,
                                 automateShippingBin: this.Config.AutomateShippingBin,
                                 monitor: this.Monitor,
                                 reflection: helper.Reflection,
                                 data: data,
                                 betterJunimosCompat: this.Config.ModCompatibility.BetterJunimos && helper.ModRegistry.IsLoaded("hawkfalcon.BetterJunimos"),
                                 autoGrabberModCompat: this.Config.ModCompatibility.AutoGrabberMod && helper.ModRegistry.IsLoaded("Jotser.AutoGrabberMod"),
                                 pullGemstonesFromJunimoHuts: this.Config.PullGemstonesFromJunimoHuts
                                 ));

            // hook events
            helper.Events.GameLoop.SaveLoaded             += this.OnSaveLoaded;
            helper.Events.Player.Warped                   += this.OnWarped;
            helper.Events.World.BuildingListChanged       += this.OnBuildingListChanged;
            helper.Events.World.LocationListChanged       += this.OnLocationListChanged;
            helper.Events.World.ObjectListChanged         += this.OnObjectListChanged;
            helper.Events.World.TerrainFeatureListChanged += this.OnTerrainFeatureListChanged;
            helper.Events.GameLoop.UpdateTicked           += this.OnUpdateTicked;
            helper.Events.Input.ButtonPressed             += this.OnButtonPressed;
            helper.Events.Multiplayer.ModMessageReceived  += this.OnModMessageReceived;

            // log info
            this.Monitor.VerboseLog($"Initialized with automation every {this.Config.AutomationInterval} ticks.");
        }
示例#19
0
        /// <summary>Update mod configuration if it changed.</summary>
        /// <param name="config">The new mod configuration.</param>
        /// <param name="keys">The new key bindings.</param>
        /// <param name="attachments">The tractor attachments to apply.</param>
        public void UpdateConfig(ModConfig config, ModConfigKeys keys, IEnumerable <IAttachment> attachments)
        {
            // update config
            this.Config              = config;
            this.Keys                = keys;
            this.Attachments         = attachments.Where(p => p != null).ToArray();
            this.AttachmentCooldowns = this.Attachments.Where(p => p.RateLimit > this.TicksPerAction).ToDictionary(p => p, p => 0);

            // clear buff so it's reapplied with new values
            Game1.buffsDisplay?.otherBuffs?.RemoveAll(p => p.which == this.BuffUniqueID);

            // reset cooldowns
            this.SkippedActionTicks = 0;
        }
示例#20
0
        /*********
        ** Public methods
        *********/
        /// <summary>The mod entry point, called after the mod is first loaded.</summary>
        /// <param name="helper">Provides methods for interacting with the mod directory, such as read/writing a config file or custom JSON files.</param>
        public override void Entry(IModHelper helper)
        {
            // read config
            this.Config = helper.ReadConfig <ModConfig>();
            this.Keys   = this.Config.Controls.ParseControls(this.Monitor);

            // hook up events
            helper.Events.GameLoop.GameLaunched    += this.OnGameLaunched;
            helper.Events.GameLoop.ReturnedToTitle += this.OnReturnedToTitle;
            helper.Events.GameLoop.UpdateTicked    += this.OnUpdateTicked;
            helper.Events.Input.ButtonPressed      += this.OnButtonPressed;

            // hook up commands
            var commandHandler = new CommandHandler(this.Monitor, () => this.CurrentOverlay?.CurrentLayer);

            helper.ConsoleCommands.Add(commandHandler.CommandName, $"Starts a Data Layers command. Type '{commandHandler.CommandName} help' for details.", (name, args) => commandHandler.Handle(args));
        }
示例#21
0
        public override void Entry(IModHelper helper)
        {
            Config = helper.ReadConfig <ModConfig>();
            Keys   = Config.Controls.ParseControls(Monitor);

            helper.Events.Input.ButtonPressed += OnButtonPressed;

            SmoothPanningHelper.Initialize(helper);
            StaticReflectionHelper.Initialize(helper);

            _inputHelper = helper.Input;
            _keyHandlers = new IKeyHandler[]
            {
                new ChestKeyHandler(Keys.AddToExistingStacks),
                new PanScreenHandler(Keys.PanScreenScrollLeft, Keys.PanScreenScrollRight, Keys.PanScreenScrollUp, Keys.PanScreenScrollDown, Keys.PanScreenPreviousBuilding,
                                     Keys.PanScreenNextBuilding)
            };
        }
示例#22
0
        /*********
        ** Public methods
        *********/
        /// <summary>The mod entry point, called after the mod is first loaded.</summary>
        /// <param name="helper">Provides simplified APIs for writing mods.</param>
        public override void Entry(IModHelper helper)
        {
            this.Config = helper.ReadConfig <ModConfig>();
            this.Keys   = this.Config.Controls.ParseControls(this.Monitor);

            // init migrations
            IMigration[] migrations = this.Migrations();

            // fetch content packs
            RawContentPack[] contentPacks  = this.GetContentPacks(migrations).ToArray();
            string[]         installedMods =
                (contentPacks.Select(p => p.Manifest.UniqueID))
                .Concat(helper.ModRegistry.GetAll().Select(p => p.Manifest.UniqueID))
                .OrderByIgnoreCase(p => p)
                .ToArray();

            // load content packs
            this.TokenManager = new TokenManager(helper.Content, installedMods);
            this.PatchManager = new PatchManager(this.Monitor, this.TokenManager, this.AssetValidators());
            this.LoadContentPacks(contentPacks);

            // set initial context once patches & dynamic tokens are loaded
            this.UpdateContext();

            // register patcher
            helper.Content.AssetLoaders.Add(this.PatchManager);
            helper.Content.AssetEditors.Add(this.PatchManager);

            // set up events
            if (this.Config.EnableDebugFeatures)
            {
                helper.Events.Input.ButtonPressed += this.OnButtonPressed;
            }
            helper.Events.GameLoop.ReturnedToTitle     += this.OnReturnedToTitle;
            helper.Events.GameLoop.DayStarted          += this.OnDayStarted;
            helper.Events.Player.Warped                += this.OnWarped;
            helper.Events.Specialised.LoadStageChanged += this.OnLoadStageChanged;

            // set up commands
            this.CommandHandler = new CommandHandler(this.TokenManager, this.PatchManager, this.Monitor, () => this.UpdateContext());
            helper.ConsoleCommands.Add(this.CommandHandler.CommandName, $"Starts a Content Patcher command. Type '{this.CommandHandler.CommandName} help' for details.", (name, args) => this.CommandHandler.Handle(args));
        }
示例#23
0
        /// <summary>The method invoked when the player presses an input button.</summary>
        /// <param name="sender">The event sender.</param>
        /// <param name="e">The event arguments.</param>
        private void OnButtonPressed(object sender, ButtonPressedEventArgs e)
        {
            // perform bound action
            this.Monitor.InterceptErrors("handling your input", $"handling input '{e.Button}'", () =>
            {
                // check context
                if (!this.CanOverlayNow())
                {
                    return;
                }
                bool overlayVisible = this.CurrentOverlay != null;
                ModConfigKeys keys  = this.Keys;

                // toggle overlay
                if (keys.ToggleLayer.Contains(e.Button))
                {
                    if (overlayVisible)
                    {
                        this.CurrentOverlay.Dispose();
                        this.CurrentOverlay = null;
                    }
                    else
                    {
                        this.CurrentOverlay = new DataLayerOverlay(this.Helper.Events, this.Helper.Input, this.Layers, this.CanOverlayNow, this.Config.CombineOverlappingBorders);
                    }
                    this.Helper.Input.Suppress(e.Button);
                }

                // cycle layers
                else if (overlayVisible && keys.NextLayer.Contains(e.Button))
                {
                    this.CurrentOverlay.NextLayer();
                    this.Helper.Input.Suppress(e.Button);
                }
                else if (overlayVisible && keys.PrevLayer.Contains(e.Button))
                {
                    this.CurrentOverlay.PrevLayer();
                    this.Helper.Input.Suppress(e.Button);
                }
            });
        }
示例#24
0
        /*********
        ** Public methods
        *********/
        /// <summary>The mod entry point, called after the mod is first loaded.</summary>
        /// <param name="helper">Provides methods for interacting with the mod directory, such as read/writing a config file or custom JSON files.</param>
        public override void Entry(IModHelper helper)
        {
            // initialize
            this.Config = helper.ReadConfig <ModConfig>();
            this.Config.AllowDangerousCommands = this.Config.AllowGameDebug && this.Config.AllowDangerousCommands; // normalize for convenience
            this.Keys = this.Config.Controls.ParseControls(this.Monitor);

            // hook events
            helper.Events.Input.ButtonPressed += this.OnButtonPressed;
            helper.Events.Display.Rendered    += this.OnRendered;
            if (this.Config.AllowGameDebug)
            {
                helper.Events.Player.Warped += this.OnWarped;
            }

            // validate translations
            if (!helper.Translation.GetTranslations().Any())
            {
                this.Monitor.Log("The translation files in this mod's i18n folder seem to be missing. The mod will still work, but you'll see 'missing translation' messages. Try reinstalling the mod to fix this.", LogLevel.Warn);
            }
        }
示例#25
0
        private void OnButtonsChanged(object sender, ButtonsChangedEventArgs e)
        {
            if (!Context.IsWorldReady)
            {
                return;
            }

            // perform bound action
            this.Monitor.InterceptErrors("handling your input", () =>
            {
                ModConfigKeys keys = this.Keys;
                if (keys.ShiftToNext.JustPressed())
                {
                    this.RotateToolbar(true, this.Config.DeselectItemOnRotate);
                }
                else if (keys.ShiftToPrevious.JustPressed())
                {
                    this.RotateToolbar(false, this.Config.DeselectItemOnRotate);
                }
            });
        }
示例#26
0
        /*********
        ** Public methods
        *********/
        /// <summary>The mod entry point, called after the mod is first loaded.</summary>
        /// <param name="helper">Provides methods for interacting with the mod directory, such as read/writing a config file or custom JSON files.</param>
        public override void Entry(IModHelper helper)
        {
            // initialise
            this.Config       = helper.ReadConfig <ModConfig>();
            this.Keys         = this.Config.Controls.ParseControls(this.Monitor);
            this.Data         = helper.Data.ReadJsonFile <ModData>("data.json") ?? new ModData();
            this.ChestFactory = new ChestFactory(helper.Translation, helper.Data, this.Config.EnableShippingBin);

            // hook events
            helper.Events.GameLoop.SaveLoaded    += this.OnSaveLoaded;
            helper.Events.GameLoop.UpdateTicked  += this.OnUpdateTicked;
            helper.Events.GameLoop.UpdateTicking += this.OnUpdateTicking;
            helper.Events.Display.RenderedHud    += this.OnRenderedHud;
            helper.Events.Input.ButtonPressed    += this.OnButtonPressed;

            // validate translations
            if (!helper.Translation.GetTranslations().Any())
            {
                this.Monitor.Log("The translation files in this mod's i18n folder seem to be missing. The mod will still work, but you'll see 'missing translation' messages. Try reinstalling the mod to fix this.", LogLevel.Warn);
            }
        }
示例#27
0
        /// <summary>The method invoked when the player presses a button.</summary>
        /// <param name="sender">The event sender.</param>
        /// <param name="e">The event arguments.</param>
        private void OnButtonPressed(object sender, ButtonPressedEventArgs e)
        {
            if (!Context.IsWorldReady)
            {
                return;
            }

            try
            {
                ModConfigKeys keys = this.Keys;

                // open menu
                if (keys.Toggle.Contains(e.Button))
                {
                    // open if no conflict
                    if (Game1.activeClickableMenu == null)
                    {
                        if (Context.IsPlayerFree && !Game1.player.UsingTool)
                        {
                            this.OpenMenu();
                        }
                    }

                    // open from inventory if it's safe to close the inventory screen
                    else if (Game1.activeClickableMenu is GameMenu gameMenu && gameMenu.currentTab == GameMenu.inventoryTab)
                    {
                        IClickableMenu inventoryPage = gameMenu.pages[GameMenu.inventoryTab];
                        if (inventoryPage.readyToClose())
                        {
                            this.OpenMenu();
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                this.HandleError(ex, "handling key input");
            }
        }
示例#28
0
 /*********
 ** Public methods
 *********/
 /// <summary>Construct an instance.</summary>
 /// <param name="menu">The underlying chest menu.</param>
 /// <param name="chest">The selected chest.</param>
 /// <param name="chests">The available chests.</param>
 /// <param name="config">The mod configuration.</param>
 /// <param name="keys">The configured key bindings.</param>
 /// <param name="events">The SMAPI events available for mods.</param>
 /// <param name="input">An API for checking and changing input state.</param>
 /// <param name="reflection">Simplifies access to private code.</param>
 /// <param name="showAutomateOptions">Whether to show Automate options.</param>
 public ShopMenuOverlay(ShopMenu menu, ManagedChest chest, ManagedChest[] chests, ModConfig config, ModConfigKeys keys, IModEvents events, IInputHelper input, IReflectionHelper reflection, bool showAutomateOptions)
     : base(menu, chest, chests, config, keys, events, input, reflection, showAutomateOptions, keepAlive: () => Game1.activeClickableMenu is ShopMenu, topOffset: Game1.pixelZoom * 6)
 {
     this.Menu = menu;
     this.DefaultPurchaseFilter       = menu.canPurchaseCheck;
     this.DefaultInventoryHighlighter = menu.inventory.highlightMethod;
 }
示例#29
0
 /*********
 ** Public methods
 *********/
 /// <summary>Construct an instance.</summary>
 /// <param name="menu">The underlying chest menu.</param>
 /// <param name="chest">The selected chest.</param>
 /// <param name="chests">The available chests.</param>
 /// <param name="config">The mod configuration.</param>
 /// <param name="keys">The configured key bindings.</param>
 /// <param name="events">The SMAPI events available for mods.</param>
 /// <param name="input">An API for checking and changing input state.</param>
 /// <param name="translations">Provides translations stored in the mod's folder.</param>
 /// <param name="showAutomateOptions">Whether to show Automate options.</param>
 public ChestOverlay(ItemGrabMenu menu, ManagedChest chest, ManagedChest[] chests, ModConfig config, ModConfigKeys keys, IModEvents events, IInputHelper input, ITranslationHelper translations, bool showAutomateOptions)
     : base(menu, chest, chests, config, keys, events, input, translations, showAutomateOptions, keepAlive: () => Game1.activeClickableMenu is ItemGrabMenu, topOffset: -Game1.pixelZoom * 9)
 {
     this.Menu = menu;
     this.MenuInventoryMenu           = menu.ItemsToGrabMenu;
     this.DefaultChestHighlighter     = menu.inventory.highlightMethod;
     this.DefaultInventoryHighlighter = this.MenuInventoryMenu.highlightMethod;
 }