Crossfire Server, Trunk
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;
63  static std::function<void(BufferReader *, const char *)> dummy = [this] (BufferReader *reader, const char *filename) { myLicenseManager.readLicense(reader, filename); };
64  settings.add_hook(".LICENSE", [] (BufferReader *reader, const char *filename) { dummy(reader, filename); });
65  settings.add_hook("", [] (BufferReader *, const char *) { QCoreApplication::processEvents(); });
68 
69  QStringList log;
70  bool hasWarningOrError = false;
71  static std::function<void(LogLevel, const char *, va_list)> lc = [&] (LogLevel logLevel, const char *format, va_list va) {
72  if (logLevel > llevInfo) {
73  return;
74  }
75  char buf[8192];
76  vsnprintf(buf, sizeof(buf), format, va);
77  QString l(tr("%1%2").arg(loglevel_names[logLevel], buf));
78  log.append(l);
79  if (logLevel == llevError) {
80  hasWarningOrError = true;
81  }
82  };
83  settings.log_callback = [] (LogLevel logLevel, const char *format, va_list va) { lc(logLevel, format, va); };
84 
85  init_globals();
86  init_library();
87  settings.fatal_hook = nullptr;
88  init_gods();
89  init_readable();
90  settings.log_callback = nullptr;
91 
92  if (hasWarningOrError) {
93  QString msg(tr("The following errors occurred during asset collection:\n") + log.join(""));
94  QMessageBox::warning(nullptr, tr("Errors during asset collection!"), msg);
95  }
96 
97  QString key;
98 
99  for (int ing = 1; ; ing++)
100  {
102  if (!list)
103  break;
104 
105  QHash<QString, recipe*> recipes;
106  for (recipe* rec = list->items; rec; rec = rec->next)
107  {
108  key = QString("%1_%2").arg(rec->arch_name[0], rec->title);
109  recipes[key] = rec;
110  }
111  myRecipes.append(recipes);
112  }
113 }
114 
116 {
117  return myRecipes.size();
118 }
119 
120 QStringList ResourcesManager::recipes(int count) const
121 {
122  if (count < 1 || count > myRecipes.size())
123  return QStringList();
124 
125  QStringList keys = myRecipes[count - 1].keys();
126  qSort(keys);
127  return keys;
128 }
129 
130 const recipe* ResourcesManager::getRecipe(int ingredients, const QString& name) const
131 {
132  if (ingredients < 1 || ingredients > myRecipes.size())
133  return NULL;
134 
135  return myRecipes[ingredients - 1][name];
136 }
137 
139 {
140  bool goOn = true;
141  getManager()->archetypes()->each([&item, &callback, &goOn] (archetype *arch) {
142  if (!goOn)
143  return;
144 
145  if (arch->clone.other_arch == item)
146  {
147  goOn = callback(OTHER_ARCH, arch, nullptr, nullptr, nullptr);
148  }
149 
150  sstring death_anim = NULL;
151  if (goOn && (death_anim = object_get_value(&arch->clone, "death_animation")) && strcmp(death_anim, item->name) == 0)
152  {
153  goOn = callback(DEATH_ANIM, arch, nullptr, nullptr, nullptr);
154  }
155  });
156 
157  getManager()->treasures()->each([&item, callback, &goOn] (treasurelist *list) {
158  if (!goOn)
159  return;
160  for (auto t = list->items; t; t = t->next)
161  {
162  if (t->item == item)
163  {
164  goOn = callback(TREASURE_USE, nullptr, list, nullptr, nullptr);
165  }
166  }
167  });
168 
169  QList<CREMapInformation*> mapuse = store->getArchetypeUse(item);
170  foreach(CREMapInformation* information, mapuse)
171  {
172  if (!goOn)
173  continue;
174  goOn = callback(MAP_USE, nullptr, nullptr, information, nullptr);
175  }
176  auto allMaps = store->allMaps();
177  foreach(CREMapInformation *information, allMaps)
178  {
179  if (!goOn)
180  return;
181  foreach(RandomMap* rm, information->randomMaps())
182  {
183  if (strcmp(item->name, rm->parameters()->final_exit_archetype) == 0)
184  {
185  goOn = callback(RANDOM_MAP_FINAL_EXIT, nullptr, nullptr, information, nullptr);
186  }
187  if (!goOn)
188  return;
189  }
190  }
191 
192  int count = 1;
193  recipelist* list;
194  while ((list = get_formulalist(count++)))
195  {
196  if (!goOn)
197  break;
198  recipe* rec = list->items;
199  while (goOn && rec)
200  {
201  for (size_t ing = 0; ing < rec->arch_names; ing++)
202  {
203  if (strcmp(rec->arch_name[ing], item->name) == 0)
204  {
205  goOn = callback(ALCHEMY_PRODUCT, nullptr, nullptr, nullptr, rec);
206  break;
207  }
208  }
209  rec = rec->next;
210  }
211  }
212 }
213 
216 }
217 
220 }
221 
224 }
225 
228 }
229 
232 }
233 
236  while (!no.empty()) {
237  auto list = no.back();
238  auto origins = myTreasures.files();
239  while (true) {
241  origins, std::vector<std::string>());
242  if (dlg.exec() == QDialog::Accepted) {
243  myTreasures.assetDefined(list, dlg.file().toStdString());
244  break;
245  } else {
246  if (QMessageBox::question(nullptr, tr("Lose changes to treasure list %1?").arg(list->name),
247  tr("Really discard changes to treasure list %1?").arg(list->name)) == QMessageBox::Yes) {
248  break;
249  }
250  }
251  }
252  no.pop_back();
253  }
255 }
256 
259 }
260 
263 }
264 
267 }
init_globals
void init_globals(void)
Definition: init.cpp:395
ResourcesManager::archetypeUse
static void archetypeUse(const archetype *item, CREMapInformationManager *store, AssetUseCallback callback)
Definition: ResourcesManager.cpp:138
ResourcesManager::myLicenseManager
LicenseManager myLicenseManager
Definition: ResourcesManager.h:190
global.h
ArchetypeWrapper.h
RandomMap::parameters
const RMParms * parameters() const
Definition: RandomMap.cpp:39
settings
struct Settings settings
Definition: init.cpp:139
TreasureWriter
Definition: TreasureWriter.h:19
banquet.l
l
Definition: banquet.py:164
get_formulalist
recipelist * get_formulalist(int i)
Definition: recipe.cpp:98
LicenseManager.h
llevError
@ llevError
Definition: logger.h:11
log_born.log
log
Definition: log_born.py:28
ResourcesManager::getRecipe
const recipe * getRecipe(int ingredients, const QString &name) const
Definition: ResourcesManager.cpp:130
recipe::arch_names
size_t arch_names
Definition: recipe.h:12
archininventory.arch
arch
DIALOGCHECK MINARGS 1 MAXARGS 1
Definition: archininventory.py:16
logger.h
guildoracle.list
list
Definition: guildoracle.py:87
recipe.h
ArtifactWriter.h
onFatalInit
static void onFatalInit(enum fatal_error)
Definition: ResourcesManager.cpp:53
RandomMap.h
ResourcesManager::generalMessageModified
void generalMessageModified(GeneralMessage *message)
Definition: ResourcesManager.cpp:257
Settings::ignore_assets_errors
int ignore_assets_errors
Definition: global.h:335
SoundFiles.h
MessageWriter
Definition: MessageWriter.h:19
hall_of_fame.keys
keys
Definition: hall_of_fame.py:43
MAP_USE
@ MAP_USE
Definition: ResourcesManager.h:70
CREMapInformationManager
Definition: CREMapInformationManager.h:27
recipe::arch_name
char ** arch_name
Definition: recipe.h:13
ArchetypeWriter
Definition: ArchetypeWriter.h:19
ResourcesManager::ResourcesManager
ResourcesManager()
Definition: ResourcesManager.cpp:44
npc_dialog.filename
filename
Definition: npc_dialog.py:99
object_get_value
const char * object_get_value(const object *op, const char *const key)
Definition: object.cpp:4337
AssetsManager.h
ResourcesManager::origins
const std::map< std::string, std::set< const archetype * > > & origins() const
Definition: ResourcesManager.h:109
MessageWriter.h
add_server_collect_hooks
void add_server_collect_hooks()
Definition: init.cpp:1069
buf
StringBuffer * buf
Definition: readable.cpp:1552
AnimationWrapper.h
getManager
AssetsManager * getManager()
Definition: assets.cpp:305
TreasureWriter.h
Settings::fatal_hook
fatalHook fatal_hook
Definition: global.h:337
ResourcesManager::saveQuests
void saveQuests()
Definition: ResourcesManager.cpp:226
name
Plugin animator file specs[Config] name
Definition: animfiles.txt:4
new
Install Bug reporting Credits so make sure you have version or later There are files involved in the automatic convert convertall and filelist py GuildList has the list of guilds for the server GuildLocations is what is used by the install script for setting up the maps It has columns in the first is the name of the no spaces The second is the region of the the third is the destination folder for the the fourth is the exit the fifth and sixth are the x and y coords within the exit the seventh eighth and ninth are the exit location for the storage hall If field seven is then it uses the same exit map as for the guild hall itself filelist py has a list of which files to process for each guild hall convert py takes all the files in filelist py and customises them to the specific guild then outputs them into a new(or overwrites an existing) folder in the current working directory. The output folder is the name of the guildhall. It also writes them into the destination dir. It takes the arguments from argv
init_gods
void init_gods(void)
Definition: holy.cpp:59
ResourcesManager::myArtifacts
ModifiedAssetsManager< artifact > myArtifacts
Definition: ResourcesManager.h:172
quest
Definition: quest.py:1
GeneralMessage
Definition: book.h:44
ResourcesManager::questModified
void questModified(quest_definition *quest)
Definition: ResourcesManager.cpp:222
ResourcesManager::recipes
QStringList recipes(int count) const
Definition: ResourcesManager.cpp:120
ResourcesManager::saveTreasures
void saveTreasures()
Definition: ResourcesManager.cpp:234
recipelist
Definition: recipe.h:37
RandomMap
Definition: RandomMap.h:24
ModifiedAssetsManager::assetDefined
void assetDefined(const T *asset, const std::string &filename)
Definition: ModifiedAssetsManager.h:48
FaceWrapper.h
treasurelist
Definition: treasure.h:85
AssetOriginAndCreationDialog::file
QString file() const
Definition: AssetOriginAndCreationDialog.h:38
ArchetypeWriter.h
ResourcesManager::recipeMaxIngredients
int recipeMaxIngredients() const
Definition: ResourcesManager.cpp:115
init_readable
void init_readable(void)
Definition: readable.cpp:895
navar-midane_pickup.msg
list msg
Definition: navar-midane_pickup.py:13
QuestWriter
Definition: QuestWriter.h:19
Settings::add_hook
void add_hook(const char *name, collectorHook hook)
Definition: global.h:339
nlohmann::detail::cbor_tag_handler_t::store
@ store
store tags as binary type
ResourcesManager::myArchetypes
ModifiedAssetsManager< archetype > myArchetypes
Definition: ResourcesManager.h:168
AssetOriginAndCreationDialog
Definition: AssetOriginAndCreationDialog.h:21
AssetsManager::archetypes
Archetypes * archetypes()
Definition: AssetsManager.h:44
disinfect.count
int count
Definition: disinfect.py:7
ResourcesManager::saveGeneralMessages
void saveGeneralMessages()
Definition: ResourcesManager.cpp:261
archetype
Definition: object.h:474
Settings::assets_tracker
class AssetsTracker * assets_tracker
Definition: global.h:336
sproto.h
AssetOriginAndCreationDialog::Treasure
@ Treasure
Definition: AssetOriginAndCreationDialog.h:24
ResourcesManager::load
void load()
Definition: ResourcesManager.cpp:57
ResourcesManager::myQuests
ModifiedAssetsManager< quest_definition > myQuests
Definition: ResourcesManager.h:169
ResourcesManager::saveArchetypes
void saveArchetypes()
Definition: ResourcesManager.cpp:218
nlohmann::detail::void
j template void())
Definition: json.hpp:4099
image.h
Settings::log_callback
logHook log_callback
Definition: global.h:244
ModifiedAssetsManager::dirtyAssetsWithNoOrigin
std::vector< T * > dirtyAssetsWithNoOrigin() const
Definition: ModifiedAssetsManager.h:75
recipe
Definition: recipe.h:10
ModifiedAssetsManager::files
std::vector< std::string > files() const
Definition: ModifiedAssetsManager.h:31
ResourcesManager.h
AssetOriginAndCreationDialog.h
ResourcesManager::~ResourcesManager
virtual ~ResourcesManager()
Definition: ResourcesManager.cpp:49
LicenseManager::readLicense
void readLicense(BufferReader *reader, const char *filename)
Definition: LicenseManager.cpp:25
AssetUseCallback
std::function< bool(ArchetypeUse use, const archetype *, const treasurelist *, const CREMapInformation *, recipe *)> AssetUseCallback
Definition: ResourcesManager.h:75
llevInfo
@ llevInfo
Definition: logger.h:12
AssetOriginAndCreationDialog::DefineOrigin
@ DefineOrigin
Definition: AssetOriginAndCreationDialog.h:25
CREMapInformation
Definition: CREMapInformation.h:27
init_library
void init_library(void)
Definition: init.cpp:323
ALCHEMY_PRODUCT
@ ALCHEMY_PRODUCT
Definition: ResourcesManager.h:72
AssetsCollection::each
void each(std::function< void(T *)> op)
Definition: AssetsCollection.h:158
loglevel_names
const char *const loglevel_names[]
Definition: logger.cpp:31
ArtifactWriter
Definition: ArtifactWriter.h:19
CREMapInformationManager.h
ResourcesManager::saveArtifacts
void saveArtifacts()
Definition: ResourcesManager.cpp:265
QuestWriter.h
item
Definition: item.py:1
BufferReader
Definition: bufferreader.cpp:21
sstring
const typedef char * sstring
Definition: sstring.h:2
ModifiedAssetsManager::assetModified
void assetModified(T *asset)
Definition: ModifiedAssetsManager.h:55
Floor.t
t
Definition: Floor.py:62
quest_definition
Definition: quest.h:37
ResourcesManager::myGeneralMessages
ModifiedAssetsManager< GeneralMessage > myGeneralMessages
Definition: ResourcesManager.h:171
CREMapInformation::randomMaps
QList< RandomMap * > randomMaps() const
Definition: CREMapInformation.cpp:268
format
Python Guilds Quick outline Add a guild(mapmakers) this is still a problem *after dropping the token to gain access to the stove a woodfloor now appears which is Toolshed Token(found in Guild_HQ) *Note also have multiple gates in place to protect players and items from the mana explosion drop x for Jewelers room *Jewelers room works just need to determine what x is drop x for Thaumaturgy room *Thaumaturgy room works just need to determine what x is drop gold dropping the Firestar named fearless allows access to but I suspect that the drop location of the chest is not as intended because the player is in the way once you enter the chest the exit back to the basement is things such as the message et al reside on teleporters which then transport items to the map as they are when the map is already purchased items reappear in that area From my this does not cause any problems at the moment But this should be corrected fixed Major it s now possible to buy guilds Ryo Update Uploaded guild package to CVS Changes the cauldrons and the charging room I spent a while agonizing over They were natural guild enhancements but much too much value for any reasonable expense to buy them Then I thought that they should be pay access but at a greatly reduced rate SO when you buy a forge or whatever for your guild it is available on a perplayer daily rate but it will be accessable for testing and to DMs to play with Like I said lots still to do with the especially comingt up with quest items for buying things like the new workshops and stuff One of the things I would like some input on would be proposals for additional fields for either the guildhouses or guild datafiles to play with Currently the Guildhouse but there is no reason we can t have more than one measure of a guild perhaps have dues relate to Dues and use points for some other suspended or inactive or when a guild is founded inactive active Guilds have the format
Definition: README.txt:140
AssetsManager::treasures
Treasures * treasures()
Definition: AssetsManager.h:54
ResourcesManager::treasureModified
void treasureModified(treasurelist *treasure)
Definition: ResourcesManager.cpp:230
assets.h
castle_read.key
key
Definition: castle_read.py:64
ResourcesManager::myRecipes
QList< QHash< QString, recipe * > > myRecipes
Definition: ResourcesManager.h:167
fatal_error
fatal_error
Definition: define.h:47
RMParms::final_exit_archetype
char final_exit_archetype[RM_SIZE]
Definition: random_map.h:59
ResourcesManager::myTreasures
ModifiedAssetsManager< treasurelist > myTreasures
Definition: ResourcesManager.h:170
recipe::next
recipe * next
Definition: recipe.h:24
treasure
Definition: treasure.h:63
LogLevel
LogLevel
Definition: logger.h:10
ResourcesManager::archetypeModified
void archetypeModified(archetype *arch)
Definition: ResourcesManager.cpp:214
ModifiedAssetsManager::saveModifiedAssets
void saveModifiedAssets()
Definition: ModifiedAssetsManager.h:57
ObjectWrapper.h
if
if(!(yy_init))
Definition: loader.c:2626
RANDOM_MAP_FINAL_EXIT
@ RANDOM_MAP_FINAL_EXIT
Definition: ResourcesManager.h:71
libproto.h