summaryrefslogtreecommitdiff
path: root/src/SMAPI/Framework/ModHelpers/ModHelper.cs
blob: 531289d003c90cd69aa2515c91b6aa6d7b5694de (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
using System;
using System.IO;
using StardewModdingAPI.Events;
#if SMAPI_DEPRECATED
using StardewModdingAPI.Framework.Deprecations;
#endif
using StardewModdingAPI.Framework.Input;

namespace StardewModdingAPI.Framework.ModHelpers
{
    /// <summary>Provides simplified APIs for writing mods.</summary>
    internal class ModHelper : BaseHelper, IModHelper, IDisposable
    {
#if SMAPI_DEPRECATED
        /*********
        ** Fields
        *********/
        /// <summary>The backing field for <see cref="Content"/>.</summary>
        [Obsolete("This only exists to support legacy code and will be removed in SMAPI 4.0.0.")]
        private readonly ContentHelper ContentImpl;
#endif


        /*********
        ** Accessors
        *********/
        /// <inheritdoc />
        public string DirectoryPath { get; }

        /// <inheritdoc />
        public IModEvents Events { get; }

#if SMAPI_DEPRECATED
        /// <inheritdoc />
        [Obsolete($"Use {nameof(IGameContentHelper)} or {nameof(IModContentHelper)} instead.")]
        public IContentHelper Content
        {
            get
            {
                SCore.DeprecationManager.Warn(
                    source: this.Mod,
                    nounPhrase: $"{nameof(IModHelper)}.{nameof(IModHelper.Content)}",
                    version: "3.14.0",
                    severity: DeprecationLevel.PendingRemoval
                );

                return this.ContentImpl;
            }
        }
#endif

        /// <inheritdoc />
        public IGameContentHelper GameContent { get; }

        /// <inheritdoc />
        public IModContentHelper ModContent { get; }

        /// <inheritdoc />
        public IContentPackHelper ContentPacks { get; }

        /// <inheritdoc />
        public IDataHelper Data { get; }

        /// <inheritdoc />
        public IInputHelper Input { get; }

        /// <inheritdoc />
        public IReflectionHelper Reflection { get; }

        /// <inheritdoc />
        public IModRegistry ModRegistry { get; }

        /// <inheritdoc />
        public ICommandHelper ConsoleCommands { get; }

        /// <inheritdoc />
        public IMultiplayerHelper Multiplayer { get; }

        /// <inheritdoc />
        public ITranslationHelper Translation { get; }


        /*********
        ** Public methods
        *********/
        /// <summary>Construct an instance.</summary>
        /// <param name="mod">The mod using this instance.</param>
        /// <param name="modDirectory">The full path to the mod's folder.</param>
        /// <param name="currentInputState">Manages the game's input state for the current player instance. That may not be the main player in split-screen mode.</param>
        /// <param name="events">Manages access to events raised by SMAPI.</param>
        /// <param name="contentHelper">An API for loading content assets.</param>
        /// <param name="gameContentHelper">An API for loading content assets from the game's <c>Content</c> folder or via <see cref="IModEvents.Content"/>.</param>
        /// <param name="modContentHelper">An API for loading content assets from your mod's files.</param>
        /// <param name="contentPackHelper">An API for managing content packs.</param>
        /// <param name="commandHelper">An API for managing console commands.</param>
        /// <param name="dataHelper">An API for reading and writing persistent mod data.</param>
        /// <param name="modRegistry">an API for fetching metadata about loaded mods.</param>
        /// <param name="reflectionHelper">An API for accessing private game code.</param>
        /// <param name="multiplayer">Provides multiplayer utilities.</param>
        /// <param name="translationHelper">An API for reading translations stored in the mod's <c>i18n</c> folder.</param>
        /// <exception cref="ArgumentNullException">An argument is null or empty.</exception>
        /// <exception cref="InvalidOperationException">The <paramref name="modDirectory"/> path does not exist on disk.</exception>
        public ModHelper(
            IModMetadata mod, string modDirectory, Func<SInputState> currentInputState, IModEvents events,
#if SMAPI_DEPRECATED
            ContentHelper contentHelper,
#endif
            IGameContentHelper gameContentHelper, IModContentHelper modContentHelper, IContentPackHelper contentPackHelper, ICommandHelper commandHelper, IDataHelper dataHelper, IModRegistry modRegistry, IReflectionHelper reflectionHelper, IMultiplayerHelper multiplayer, ITranslationHelper translationHelper
        )
            : base(mod)
        {
            // validate directory
            if (string.IsNullOrWhiteSpace(modDirectory))
                throw new ArgumentNullException(nameof(modDirectory));
            if (!Directory.Exists(modDirectory))
                throw new InvalidOperationException("The specified mod directory does not exist.");

            // initialize
            this.DirectoryPath = modDirectory;
#if SMAPI_DEPRECATED
            this.ContentImpl = contentHelper ?? throw new ArgumentNullException(nameof(contentHelper));
#endif
            this.GameContent = gameContentHelper ?? throw new ArgumentNullException(nameof(gameContentHelper));
            this.ModContent = modContentHelper ?? throw new ArgumentNullException(nameof(modContentHelper));
            this.ContentPacks = contentPackHelper ?? throw new ArgumentNullException(nameof(contentPackHelper));
            this.Data = dataHelper ?? throw new ArgumentNullException(nameof(dataHelper));
            this.Input = new InputHelper(mod, currentInputState);
            this.ModRegistry = modRegistry ?? throw new ArgumentNullException(nameof(modRegistry));
            this.ConsoleCommands = commandHelper ?? throw new ArgumentNullException(nameof(commandHelper));
            this.Reflection = reflectionHelper ?? throw new ArgumentNullException(nameof(reflectionHelper));
            this.Multiplayer = multiplayer ?? throw new ArgumentNullException(nameof(multiplayer));
            this.Translation = translationHelper ?? throw new ArgumentNullException(nameof(translationHelper));
            this.Events = events;
        }

#if SMAPI_DEPRECATED
        /// <summary>Get the underlying instance for <see cref="IContentHelper"/>.</summary>
        [Obsolete("This only exists to support legacy code and will be removed in SMAPI 4.0.0.")]
        public ContentHelper GetLegacyContentHelper()
        {
            return this.ContentImpl;
        }
#endif

        /****
        ** Mod config file
        ****/
        /// <inheritdoc />
        public TConfig ReadConfig<TConfig>()
            where TConfig : class, new()
        {
            TConfig config = this.Data.ReadJsonFile<TConfig>("config.json") ?? new TConfig();
            this.WriteConfig(config); // create file or fill in missing fields
            return config;
        }

        /// <inheritdoc />
        public void WriteConfig<TConfig>(TConfig config)
            where TConfig : class, new()
        {
            this.Data.WriteJsonFile("config.json", config);
        }

        /****
        ** Disposal
        ****/
        /// <inheritdoc />
        public void Dispose()
        {
            // nothing to dispose yet
        }
    }
}