]> git.lizzy.rs Git - dragonfireclient.git/blob - src/content/mods.h
Improve LBMManager::applyLBMs() code
[dragonfireclient.git] / src / content / mods.h
1 /*
2 Minetest
3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #pragma once
21
22 #include "irrlichttypes.h"
23 #include <list>
24 #include <set>
25 #include <vector>
26 #include <string>
27 #include <map>
28 #include <json/json.h>
29 #include <unordered_set>
30 #include "util/basic_macros.h"
31 #include "config.h"
32 #include "metadata.h"
33
34 class ModMetadataDatabase;
35
36 #define MODNAME_ALLOWED_CHARS "abcdefghijklmnopqrstuvwxyz0123456789_"
37
38 struct ModSpec
39 {
40         std::string name;
41         std::string author;
42         std::string path;
43         std::string desc;
44         int release = 0;
45
46         // if normal mod:
47         std::unordered_set<std::string> depends;
48         std::unordered_set<std::string> optdepends;
49         std::unordered_set<std::string> unsatisfied_depends;
50
51         bool part_of_modpack = false;
52         bool is_modpack = false;
53
54         /**
55          * A constructed canonical path to represent this mod's location.
56          * This intended to be used as an identifier for a modpath that tolerates file movement,
57          * and cannot be used to read the mod files.
58          *
59          * Note that `mymod` is the directory name, not the mod name specified in mod.conf.
60          *
61          * Ex:
62          *
63          * - mods/mymod
64          * - mods/mymod (1)
65          *     (^ this would have name=mymod in mod.conf)
66          * - mods/modpack1/mymod
67          * - games/mygame/mods/mymod
68          * - worldmods/mymod
69          */
70         std::string virtual_path;
71
72         // For logging purposes
73         std::vector<const char *> deprecation_msgs;
74
75         // if modpack:
76         std::map<std::string, ModSpec> modpack_content;
77
78         ModSpec()
79         {
80         }
81
82         ModSpec(const std::string &name, const std::string &path, bool part_of_modpack, const std::string &virtual_path) :
83                         name(name), path(path), part_of_modpack(part_of_modpack), virtual_path(virtual_path)
84         {
85         }
86
87         void checkAndLog() const;
88 };
89
90 // Retrieves depends, optdepends, is_modpack and modpack_content
91 void parseModContents(ModSpec &mod);
92
93 /**
94  * Gets a list of all mods and modpacks in path
95  *
96  * @param Path to search, should be absolute
97  * @param part_of_modpack Is this searching within a modpack?
98  * @param virtual_path Virtual path for this directory, see comment in ModSpec
99  * @returns map of mods
100  */
101 std::map<std::string, ModSpec> getModsInPath(const std::string &path,
102                 const std::string &virtual_path, bool part_of_modpack = false);
103
104 // replaces modpack Modspecs with their content
105 std::vector<ModSpec> flattenMods(const std::map<std::string, ModSpec> &mods);
106
107 // a ModConfiguration is a subset of installed mods, expected to have
108 // all dependencies fullfilled, so it can be used as a list of mods to
109 // load when the game starts.
110 class ModConfiguration
111 {
112 public:
113         // checks if all dependencies are fullfilled.
114         bool isConsistent() const { return m_unsatisfied_mods.empty(); }
115
116         const std::vector<ModSpec> &getMods() const { return m_sorted_mods; }
117
118         const std::vector<ModSpec> &getUnsatisfiedMods() const
119         {
120                 return m_unsatisfied_mods;
121         }
122
123         void printUnsatisfiedModsError() const;
124
125 protected:
126         ModConfiguration(const std::string &worldpath);
127
128         /**
129          * adds all mods in the given path. used for games, modpacks
130          * and world-specific mods (worldmods-folders)
131          *
132          * @param path To search, should be absolute
133          * @param virtual_path Virtual path for this directory, see comment in ModSpec
134          */
135         void addModsInPath(const std::string &path, const std::string &virtual_path);
136
137         // adds all mods in the set.
138         void addMods(const std::vector<ModSpec> &new_mods);
139
140         /**
141          * @param settings_path Path to world.mt
142          * @param modPaths Map from virtual name to mod path
143          */
144         void addModsFromConfig(const std::string &settings_path,
145                         const std::unordered_map<std::string, std::string> &modPaths);
146
147         void checkConflictsAndDeps();
148
149 protected:
150         // list of mods sorted such that they can be loaded in the
151         // given order with all dependencies being fullfilled. I.e.,
152         // every mod in this list has only dependencies on mods which
153         // appear earlier in the vector.
154         std::vector<ModSpec> m_sorted_mods;
155
156 private:
157         // move mods from m_unsatisfied_mods to m_sorted_mods
158         // in an order that satisfies dependencies
159         void resolveDependencies();
160
161         // mods with unmet dependencies. Before dependencies are resolved,
162         // this is where all mods are stored. Afterwards this contains
163         // only the ones with really unsatisfied dependencies.
164         std::vector<ModSpec> m_unsatisfied_mods;
165
166         // set of mod names for which an unresolved name conflict
167         // exists. A name conflict happens when two or more mods
168         // at the same level have the same name but different paths.
169         // Levels (mods in higher levels override mods in lower levels):
170         // 1. game mod in modpack; 2. game mod;
171         // 3. world mod in modpack; 4. world mod;
172         // 5. addon mod in modpack; 6. addon mod.
173         std::unordered_set<std::string> m_name_conflicts;
174
175         // Deleted default constructor
176         ModConfiguration() = default;
177 };
178
179 #ifndef SERVER
180 class ClientModConfiguration : public ModConfiguration
181 {
182 public:
183         ClientModConfiguration(const std::string &path);
184 };
185 #endif
186
187 class ModMetadata : public Metadata
188 {
189 public:
190         ModMetadata() = delete;
191         ModMetadata(const std::string &mod_name, ModMetadataDatabase *database);
192         ~ModMetadata() = default;
193
194         virtual void clear();
195
196         const std::string &getModName() const { return m_mod_name; }
197
198         virtual bool setString(const std::string &name, const std::string &var);
199
200 private:
201         std::string m_mod_name;
202         ModMetadataDatabase *m_database;
203 };