Crossfire Resources Editor
ResourcesManager.cpp
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 2022 the Crossfire Development Team
5  *
6  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
7  * welcome to redistribute it under certain conditions. For details, please
8  * see COPYING and LICENSE.
9  *
10  * The authors can be reached via e-mail at <crossfire@metalforge.org>.
11  */
12 
13 #include <QString>
14 #include <qlist.h>
15 #include <qhash.h>
16 #include <QStringList>
17 #include <QMessageBox>
18 #include "ResourcesManager.h"
19 #include <locale.h>
20 
21 #include "global.h"
22 #include "libproto.h"
23 #include "recipe.h"
24 #include "image.h"
25 #include "sproto.h"
26 #include "assets.h"
27 #include "logger.h"
28 #include "AssetsManager.h"
30 #include "random_maps/RandomMap.h"
31 #include "LicenseManager.h"
32 #include "ArchetypeWriter.h"
33 #include "QuestWriter.h"
34 #include "MessageWriter.h"
35 #include "TreasureWriter.h"
36 #include "ArtifactWriter.h"
39 #include "faces/FaceWrapper.h"
42 #include "sounds/SoundFiles.h"
43 
44 ResourcesManager::ResourcesManager() : myMapInformationManager(nullptr), myArchetypes(new ArchetypeWriter()), myQuests(new QuestWriter()), myTreasures(new TreasureWriter()),
45  myGeneralMessages(new MessageWriter()), myArtifacts(new ArtifactWriter()), myFaces(nullptr), myAnimations(nullptr)
46 {
47 }
48 
50 {
51 }
52 
53 static void onFatalInit(enum fatal_error) {
54  QMessageBox::critical(nullptr, "Fatal error", "Error while initializing Crossfire data, make sure you have maps and archetypes correctly installed.");
55 }
56 
58 {
59  setlocale(LC_NUMERIC, "C");
60 
61  settings.assets_tracker = this;
62  add_server_collect_hooks();
63  assets_add_collector_hook(".LICENSE", [this] (BufferReader *reader, const char *filename) { myLicenseManager.readLicense(reader, filename); });
64  assets_add_collector_hook("", [] (BufferReader *, const char *) { QCoreApplication::processEvents(); });
65  settings.fatal_hook = onFatalInit;
66  settings.ignore_assets_errors = 1;
67 
68  QStringList log;
69  bool hasWarningOrError = false;
70  auto log_callback = [&] (LogLevel logLevel, const char *format, va_list va) {
71  if (logLevel > llevInfo) {
72  return;
73  }
74  char buf[8192];
75  vsnprintf(buf, sizeof(buf), format, va);
76  QString l(tr("%1%2").arg(loglevel_names[logLevel], buf));
77  log.append(l);
78  if (logLevel == llevError) {
79  hasWarningOrError = true;
80  }
81  };
82  settings.log_callback = log_callback;
83 
84  init_globals();
85  init_library();
86  settings.fatal_hook = nullptr;
87  init_gods();
88  init_readable();
89  settings.log_callback = nullptr;
90 
91  if (hasWarningOrError) {
92  QString msg(tr("The following errors occurred during asset collection:\n") + log.join(""));
93  QMessageBox::warning(nullptr, tr("Errors during asset collection!"), msg);
94  }
95 
96  QString key;
97 
98  for (int ing = 1; ; ing++)
99  {
100  recipelist* list = get_formulalist(ing);
101  if (!list)
102  break;
103 
104  QHash<QString, recipe*> recipes;
105  for (recipe* rec = list->items; rec; rec = rec->next)
106  {
107  key = QString("%1_%2").arg(rec->arch_name[0], rec->title);
108  recipes[key] = rec;
109  }
110  myRecipes.append(recipes);
111  }
112 }
113 
115 {
116  return myRecipes.size();
117 }
118 
119 QStringList ResourcesManager::recipes(int count) const
120 {
121  if (count < 1 || count > myRecipes.size())
122  return QStringList();
123 
124  QStringList keys = myRecipes[count - 1].keys();
125  qSort(keys);
126  return keys;
127 }
128 
129 const recipe* ResourcesManager::getRecipe(int ingredients, const QString& name) const
130 {
131  if (ingredients < 1 || ingredients > myRecipes.size())
132  return NULL;
133 
134  return myRecipes[ingredients - 1][name];
135 }
136 
137 void ResourcesManager::archetypeUse(const archetype* item, CREMapInformationManager* store, AssetUseCallback callback)
138 {
139  bool goOn = true;
140  getManager()->archetypes()->each([&item, &callback, &goOn] (archetype *arch) {
141  if (!goOn)
142  return;
143 
144  if (arch->clone.other_arch == item)
145  {
146  goOn = callback(OTHER_ARCH, arch, nullptr, nullptr, nullptr);
147  }
148 
149  sstring death_anim = NULL;
150  if (goOn && (death_anim = object_get_value(&arch->clone, "death_animation")) && strcmp(death_anim, item->name) == 0)
151  {
152  goOn = callback(DEATH_ANIM, arch, nullptr, nullptr, nullptr);
153  }
154  });
155 
156  getManager()->treasures()->each([&item, callback, &goOn] (treasurelist *list) {
157  if (!goOn)
158  return;
159  for (auto t = list->items; t; t = t->next)
160  {
161  if (t->item == item)
162  {
163  goOn = callback(TREASURE_USE, nullptr, list, nullptr, nullptr);
164  }
165  }
166  });
167 
168  QList<CREMapInformation*> mapuse = store->getArchetypeUse(item);
169  foreach(CREMapInformation* information, mapuse)
170  {
171  if (!goOn)
172  continue;
173  goOn = callback(MAP_USE, nullptr, nullptr, information, nullptr);
174  }
175  auto allMaps = store->allMaps();
176  foreach(CREMapInformation *information, allMaps)
177  {
178  if (!goOn)
179  return;
180  foreach(RandomMap* rm, information->randomMaps())
181  {
182  if (strcmp(item->name, rm->parameters()->final_exit_archetype) == 0)
183  {
184  goOn = callback(RANDOM_MAP_FINAL_EXIT, nullptr, nullptr, information, nullptr);
185  }
186  if (!goOn)
187  return;
188  }
189  }
190 
191  int count = 1;
192  recipelist* list;
193  while ((list = get_formulalist(count++)))
194  {
195  if (!goOn)
196  break;
197  recipe* rec = list->items;
198  while (goOn && rec)
199  {
200  for (size_t ing = 0; ing < rec->arch_names; ing++)
201  {
202  if (strcmp(rec->arch_name[ing], item->name) == 0)
203  {
204  goOn = callback(ALCHEMY_PRODUCT, nullptr, nullptr, nullptr, rec);
205  break;
206  }
207  }
208  rec = rec->next;
209  }
210  }
211 }
212 
213 void ResourcesManager::archetypeModified(archetype *arch) {
215 }
216 
219 }
220 
221 void ResourcesManager::questModified(quest_definition *quest) {
222  myQuests.assetModified(quest);
223 }
224 
227 }
228 
229 void ResourcesManager::treasureModified(treasurelist *treasure) {
230  myTreasures.assetModified(treasure);
231 }
232 
235  while (!no.empty()) {
236  auto list = no.back();
237  auto origins = myTreasures.files();
238  while (true) {
240  origins, std::vector<std::string>());
241  if (dlg.exec() == QDialog::Accepted) {
242  myTreasures.assetDefined(list, dlg.file().toStdString());
243  break;
244  } else {
245  if (QMessageBox::question(nullptr, tr("Lose changes to treasure list %1?").arg(list->name),
246  tr("Really discard changes to treasure list %1?").arg(list->name)) == QMessageBox::Yes) {
247  break;
248  }
249  }
250  }
251  no.pop_back();
252  }
254 }
255 
256 void ResourcesManager::generalMessageModified(GeneralMessage *asset) {
258 }
259 
262 }
263 
266 }
ResourcesManager::treasureModified
void treasureModified(treasurelist *treasure)
Definition: ResourcesManager.cpp:229
ResourcesManager::myQuests
ModifiedAssetsManager< quest_definition > myQuests
Definition: ResourcesManager.h:172
RandomMap
Definition: RandomMap.h:24
RandomMap::parameters
const RMParms * parameters() const
Definition: RandomMap.cpp:39
ResourcesManager::ResourcesManager
ResourcesManager()
Definition: ResourcesManager.cpp:44
ResourcesManager::getRecipe
const recipe * getRecipe(int ingredients, const QString &name) const
Definition: ResourcesManager.cpp:129
ResourcesManager::saveArchetypes
void saveArchetypes()
Definition: ResourcesManager.cpp:217
ResourcesManager::questModified
void questModified(quest_definition *quest)
Definition: ResourcesManager.cpp:221
ResourcesManager::myArtifacts
ModifiedAssetsManager< artifact > myArtifacts
Definition: ResourcesManager.h:175
ModifiedAssetsManager::files
std::vector< std::string > files() const
Definition: ModifiedAssetsManager.h:29
ObjectWrapper.h
ResourcesManager::myLicenseManager
LicenseManager myLicenseManager
Definition: ResourcesManager.h:193
ResourcesManager::archetypeUse
static void archetypeUse(const archetype *item, CREMapInformationManager *store, AssetUseCallback callback)
Definition: ResourcesManager.cpp:137
ResourcesManager::recipeMaxIngredients
int recipeMaxIngredients() const
Definition: ResourcesManager.cpp:114
RandomMap.h
ResourcesManager::saveQuests
void saveQuests()
Definition: ResourcesManager.cpp:225
AssetOriginAndCreationDialog::DefineOrigin
@ DefineOrigin
Definition: AssetOriginAndCreationDialog.h:25
LicenseManager.h
ResourcesManager::myGeneralMessages
ModifiedAssetsManager< GeneralMessage > myGeneralMessages
Definition: ResourcesManager.h:174
ModifiedAssetsManager::dirtyAssetsWithNoOrigin
std::vector< T * > dirtyAssetsWithNoOrigin() const
Return the list of modified assets which has no origin defined.
Definition: ModifiedAssetsManager.h:73
ResourcesManager::saveArtifacts
void saveArtifacts()
Definition: ResourcesManager.cpp:264
CREMapInformation
Definition: CREMapInformation.h:27
ResourcesManager::origins
const std::map< std::string, std::set< const archetype * > > & origins() const
Definition: ResourcesManager.h:109
ModifiedAssetsManager::saveModifiedAssets
void saveModifiedAssets()
Definition: ModifiedAssetsManager.h:55
ResourcesManager::saveGeneralMessages
void saveGeneralMessages()
Definition: ResourcesManager.cpp:260
ResourcesManager::load
void load()
Definition: ResourcesManager.cpp:57
ResourcesManager::myRecipes
QList< QHash< QString, recipe * > > myRecipes
Definition: ResourcesManager.h:170
AssetOriginAndCreationDialog.h
AnimationWrapper.h
AssetOriginAndCreationDialog
Helper dialog to input origin of an asset, and maybe create a new one.
Definition: AssetOriginAndCreationDialog.h:21
AssetUseCallback
std::function< bool(ArchetypeUse use, const archetype *, const treasurelist *, const CREMapInformation *, recipe *)> AssetUseCallback
Definition: ResourcesManager.h:75
ArchetypeWrapper.h
ResourcesManager::recipes
QStringList recipes(int count) const
Definition: ResourcesManager.cpp:119
SoundFiles.h
LicenseManager::readLicense
void readLicense(BufferReader *reader, const char *filename)
Process a license file.
Definition: LicenseManager.cpp:25
FaceWrapper.h
MAP_USE
@ MAP_USE
Definition: ResourcesManager.h:70
CREMapInformationManager.h
ResourcesManager.h
AssetOriginAndCreationDialog::Treasure
@ Treasure
Definition: AssetOriginAndCreationDialog.h:24
ResourcesManager::archetypeModified
void archetypeModified(archetype *arch)
Definition: ResourcesManager.cpp:213
CREMapInformation::randomMaps
QList< RandomMap * > randomMaps() const
Definition: CREMapInformation.cpp:268
ModifiedAssetsManager::assetModified
void assetModified(T *asset)
Definition: ModifiedAssetsManager.h:53
ModifiedAssetsManager::assetDefined
void assetDefined(const T *asset, const std::string &filename)
Definition: ModifiedAssetsManager.h:46
onFatalInit
static void onFatalInit(enum fatal_error)
Definition: ResourcesManager.cpp:53
ALCHEMY_PRODUCT
@ ALCHEMY_PRODUCT
Definition: ResourcesManager.h:72
ResourcesManager::generalMessageModified
void generalMessageModified(GeneralMessage *message)
Definition: ResourcesManager.cpp:256
RANDOM_MAP_FINAL_EXIT
@ RANDOM_MAP_FINAL_EXIT
Definition: ResourcesManager.h:71
ResourcesManager::myArchetypes
ModifiedAssetsManager< archetype > myArchetypes
Definition: ResourcesManager.h:171
ResourcesManager::saveTreasures
void saveTreasures()
Definition: ResourcesManager.cpp:233
ResourcesManager::myTreasures
ModifiedAssetsManager< treasurelist > myTreasures
Definition: ResourcesManager.h:173
CREMapInformationManager
Definition: CREMapInformationManager.h:27
ResourcesManager::~ResourcesManager
virtual ~ResourcesManager()
Definition: ResourcesManager.cpp:49
AssetOriginAndCreationDialog::file
QString file() const
Definition: AssetOriginAndCreationDialog.h:38