1 /*
2  * This file is part of the Colobot: Gold Edition source code
3  * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam
4  * http://epsitec.ch; http://colobot.info; http://github.com/colobot
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14  * See the GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see http://gnu.org/licenses
18  */
19 
20 #pragma once
21 
22 #include <string>
23 #include <unordered_map>
24 #include <vector>
25 
26 class CApplication;
27 class CPathManager;
28 
29 struct ModData
30 {
31     std::string displayName{};
32     std::string author{};
33     std::string version{};
34     std::string website{};
35     std::string summary{};
36     std::vector<std::string> changes{};
37 };
38 
39 struct Mod
40 {
41     std::string name{};
42     std::string path{};
43     bool enabled = false;
44     ModData data{};
45 };
46 
47 /**
48  * \class CModManager
49  * \brief This class handles the list of mods.
50  *
51  * The order matters since the order in which files are loaded matters,
52  * because some files can be overwritten.
53  *
54  * The changes in the list do not immediately apply.
55  */
56 class CModManager
57 {
58 public:
59     CModManager(CApplication* app, CPathManager* pathManager);
60 
61     //! Finds all the mods along with their metadata
62     void FindMods();
63 
64     //! Applies the current configuration and reloads the application
65     void ReloadMods();
66 
67     //! Removes a mod from the list of loaded mods
68     void EnableMod(size_t i);
69 
70     //! Adds a mod to the list of loaded mods
71     void DisableMod(size_t i);
72 
73     //! Moves the selected mod up in the list so that it's loaded sooner than others, returns the new index
74     size_t MoveUp(size_t i);
75 
76     //! Moves the selected mod down in the list so that it's loaded later than others, returns the new index
77     size_t MoveDown(size_t i);
78 
79     //! Checks if the list of currently used mods differs from the current configuration or there were changes made by the user
80     bool Changes();
81 
82     //! Saves the current configuration of mods to the config file
83     void SaveMods();
84 
85     //! Number of mods loaded
86     size_t CountMods() const;
87 
88     //! Returns the reference to the mod in given position
89     const Mod& GetMod(size_t i) const;
90 
91     //! Returns the list of mods
92     const std::vector<Mod>& GetMods() const;
93 
94 private:
95     // Allow access to MountAllMods() as CApplication doesn't want to reload itself during initialization
96     friend CApplication;
97 
98     //! Reloads application resources so the enabled mods are applied
99     void ReloadResources();
100 
101     //! Load mod data into mod
102     void LoadModData(Mod& mod);
103 
104     //! Updates the paths in Path Manager according to the current mod configuration
105     void MountAllMods();
106 
107     void MountMod(const Mod& mod, const std::string& mountPoint = "");
108     void MountMod(const std::string& path, const std::string& mountPoint = "");
109     void UnmountMod(const Mod& mod);
110     void UnmountMod(const std::string& path);
111     void UnmountAllMountedMods();
112 
113 private:
114     CApplication* m_app;
115     CPathManager* m_pathManager;
116 
117     //! Paths to mods already in the virtual filesystem
118     std::vector<std::string> m_mountedModPaths;
119 
120     //! List of mods
121     std::vector<Mod> m_mods;
122 
123     bool m_userChanges = false;
124 };
125