RigsofRods
Soft-body Physics Simulation
ContentManager.cpp
Go to the documentation of this file.
1 /*
2  This source file is part of Rigs of Rods
3  Copyright 2005-2012 Pierre-Michel Ricordel
4  Copyright 2007-2012 Thomas Fischer
5  Copyright 2013-2018 Petr Ohlidal
6 
7  For more information, see http://www.rigsofrods.org/
8 
9  Rigs of Rods is free software: you can redistribute it and/or modify
10  it under the terms of the GNU General Public License version 3, as
11  published by the Free Software Foundation.
12 
13  Rigs of Rods is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with Rigs of Rods. If not, see <http://www.gnu.org/licenses/>.
20 */
21 
22 #include "ContentManager.h"
23 
24 
25 #include <Overlay/OgreOverlayManager.h>
26 #include <Overlay/OgreOverlay.h>
27 #include <Plugins/ParticleFX/OgreBoxEmitterFactory.h>
28 
29 
30 #include "Application.h"
32 #include "ErrorUtils.h"
33 #include "SoundScriptManager.h"
34 #include "SkinFileFormat.h"
35 #include "Language.h"
36 #include "PlatformUtils.h"
37 
38 #include "CacheSystem.h"
39 
41 
42 // Removed by Skybon as part of OGRE 1.9 port
43 // Disabling temporarily for 1.8.1 as well. ~ only_a_ptr, 2015-11
44 // TODO: Study the system, then re-enable or remove entirely.
45 //#include "OgreBoxEmitterFactory.h"
46 
47 #ifdef USE_ANGELSCRIPT
50 #endif // USE_ANGELSCRIPT
51 
52 #include "Utils.h"
53 
54 #include <OgreFileSystem.h>
55 #include <regex>
56 #include <rapidjson/stringbuffer.h>
57 #include <rapidjson/writer.h>
58 #include <sstream>
59 
60 using namespace Ogre;
61 using namespace RoR;
62 
63 // ================================================================================
64 // Static variables
65 // ================================================================================
66 
67 #define DECLARE_RESOURCE_PACK(_FIELD_, _NAME_, _RESOURCE_GROUP_) \
68  const ContentManager::ResourcePack ContentManager::ResourcePack::_FIELD_(_NAME_, _RESOURCE_GROUP_);
69 
70 DECLARE_RESOURCE_PACK( OGRE_CORE, "OgreCore", "OgreCoreRG");
71 DECLARE_RESOURCE_PACK( WALLPAPERS, "wallpapers", "Wallpapers");
72 DECLARE_RESOURCE_PACK( AIRFOILS, "airfoils", "AirfoilsRG");
73 DECLARE_RESOURCE_PACK( CAELUM, "caelum", "CaelumRG");
74 DECLARE_RESOURCE_PACK( CUBEMAPS, "cubemaps", "CubemapsRG");
75 DECLARE_RESOURCE_PACK( DASHBOARDS, "dashboards", "DashboardsRG");
76 DECLARE_RESOURCE_PACK( FAMICONS, "famicons", "FamiconsRG");
77 DECLARE_RESOURCE_PACK( FLAGS, "flags", "FlagsRG");
78 DECLARE_RESOURCE_PACK( FONTS, "fonts", "FontsRG");
79 DECLARE_RESOURCE_PACK( HYDRAX, "hydrax", "HydraxRG");
80 DECLARE_RESOURCE_PACK( ICONS, "icons", "IconsRG");
81 DECLARE_RESOURCE_PACK( MATERIALS, "materials", "MaterialsRG");
82 DECLARE_RESOURCE_PACK( MESHES, "meshes", "MeshesRG");
83 DECLARE_RESOURCE_PACK( MYGUI, "mygui", "MyGuiRG");
84 DECLARE_RESOURCE_PACK( OVERLAYS, "overlays", "OverlaysRG");
85 DECLARE_RESOURCE_PACK( PAGED, "paged", "PagedRG");
86 DECLARE_RESOURCE_PACK( PARTICLES, "particles", "ParticlesRG");
87 DECLARE_RESOURCE_PACK( PSSM, "pssm", "PssmRG");
88 DECLARE_RESOURCE_PACK( RTSHADER, "rtshader", "RtShaderRG");
89 DECLARE_RESOURCE_PACK( SCRIPTS, "scripts", "ScriptsRG");
90 DECLARE_RESOURCE_PACK( SOUNDS, "sounds", "SoundsRG");
91 DECLARE_RESOURCE_PACK( TEXTURES, "textures", "TexturesRG");
92 DECLARE_RESOURCE_PACK( SKYX, "SkyX", "SkyXRG");
93 
94 // ================================================================================
95 // Functions
96 // ================================================================================
97 
98 void ContentManager::AddResourcePack(ResourcePack const& resource_pack, std::string const& override_rgn)
99 {
100  Ogre::ResourceGroupManager& rgm = Ogre::ResourceGroupManager::getSingleton();
101 
102  Ogre::String rg_name;
103  if (!override_rgn.empty()) // Custom RG defined?
104  {
105  rg_name = override_rgn;
106  }
107  else // Use default RG
108  {
109  if (rgm.resourceGroupExists(resource_pack.resource_group_name)) // Already loaded?
110  {
111  return; // Nothing to do, nothing to report
112  }
113  rg_name = resource_pack.resource_group_name;
114  }
115 
116  std::stringstream log_msg;
117  log_msg << "[RoR|ContentManager] Loading resource pack \"" << resource_pack.name << "\" to group \"" << rg_name << "\"";
118  std::string dir_path = PathCombine(App::sys_resources_dir->getStr(), resource_pack.name);
119  std::string zip_path = dir_path + ".zip";
120  if (FileExists(zip_path))
121  {
122  log_msg << " (ZIP archive)";
123  LOG(log_msg.str());
124  rgm.addResourceLocation(zip_path, "Zip", rg_name);
125  }
126  else
127  {
128  if (FolderExists(dir_path))
129  {
130  log_msg << " (directory)";
131  LOG(log_msg.str());
132  rgm.addResourceLocation(dir_path, "FileSystem", rg_name);
133  }
134  else
135  {
136  log_msg << " failed, data not found.";
137  throw std::runtime_error(log_msg.str());
138  }
139  }
140 
141  if (override_rgn.empty()) // Only init the default RG
142  {
143  rgm.initialiseResourceGroup(rg_name);
144  }
145 }
146 
147 void ContentManager::InitContentManager()
148 {
149  ResourceGroupManager::getSingleton().addResourceLocation(
150  App::sys_config_dir->getStr(), "FileSystem", RGN_CONFIG, /*recursive=*/false, /*readOnly=*/false);
151  ResourceGroupManager::getSingleton().addResourceLocation(
152  App::sys_savegames_dir->getStr(), "FileSystem", RGN_SAVEGAMES, /*recursive=*/false, /*readOnly=*/false);
153  ResourceGroupManager::getSingleton().addResourceLocation(
154  App::sys_scripts_dir->getStr(), "FileSystem", RGN_SCRIPTS, /*recursive:*/false, /*readonly:*/false);
155  ResourceGroupManager::getSingleton().addResourceLocation(
156  App::sys_logs_dir->getStr(), "FileSystem", RGN_LOGS, /*recursive:*/false, /*readonly:*/false);
157 
158  Ogre::ScriptCompilerManager::getSingleton().setListener(this);
159 
160  // Initialize "managed materials" first
161  // These are base materials referenced by user content
162  // They must be initialized before any content is loaded,
163  // otherwise material links are unresolved and loading ends with an exception
164  this->InitManagedMaterials(RGN_MANAGED_MATS);
165 
166  // set listener if none has already been set
167  if (!Ogre::ResourceGroupManager::getSingleton().getLoadingListener())
168  Ogre::ResourceGroupManager::getSingleton().setLoadingListener(this);
169 
170  // by default, display everything in the depth map
171  Ogre::MovableObject::setDefaultVisibilityFlags(DEPTHMAP_ENABLED);
172 
173 
174  this->AddResourcePack(ResourcePack::MYGUI);
175  this->AddResourcePack(ResourcePack::DASHBOARDS);
176 
177 
178 #ifdef _WIN32
179  // TODO: FIX UNDER LINUX!
180  // register particle classes
181  LOG("RoR|ContentManager: Registering Particle Box Emitter");
182  ParticleSystemRendererFactory* mParticleSystemRendererFact = OGRE_NEW ShaderParticleRendererFactory();
183  ParticleSystemManager::getSingleton().addRendererFactory(mParticleSystemRendererFact);
184 
185  // Removed by Skybon as part of OGRE 1.9 port
186  // Disabling temporarily for 1.8.1 as well. ~ only_a_ptr, 2015-11
187  //ParticleEmitterFactory *mParticleEmitterFact = OGRE_NEW BoxEmitterFactory();
188  //ParticleSystemManager::getSingleton().addEmitterFactory(mParticleEmitterFact);
189 
190 #endif // _WIN32
191 
192 #ifdef USE_ANGELSCRIPT
193  // FireExtinguisherAffector
194  ParticleAffectorFactory* pAffFact = OGRE_NEW FireExtinguisherAffectorFactory();
195  ParticleSystemManager::getSingleton().addAffectorFactory(pAffFact);
196 
197  // ExtinguishableFireAffector
198  pAffFact = OGRE_NEW ExtinguishableFireAffectorFactory();
199  ParticleSystemManager::getSingleton().addAffectorFactory(pAffFact);
200 #endif // USE_ANGELSCRIPT
201 
202  // sound is a bit special as we mark the base sounds so we don't clear them accidentally later on
203 #ifdef USE_OPENAL
204  LOG("RoR|ContentManager: Creating Sound Manager");
207 #endif // USE_OPENAL
208 
209  AddResourcePack(ResourcePack::SOUNDS);
210 
211  // streams path, to be processed later by the cache system
212  LOG("RoR|ContentManager: Loading filesystems");
213 
214  LOG("RoR|ContentManager: Registering colored text overlay factory");
216  OverlayManager::getSingleton().addOverlayElementFactory(pCT);
217 
218  // set default mipmap level (NB some APIs ignore this)
219  if (TextureManager::getSingletonPtr())
220  TextureManager::getSingleton().setDefaultNumMipmaps(5);
221 
222  TextureFilterOptions tfo = TFO_NONE;
223  switch (App::gfx_texture_filter->getEnum<GfxTexFilter>())
224  {
225  case GfxTexFilter::ANISOTROPIC: tfo = TFO_ANISOTROPIC; break;
226  case GfxTexFilter::TRILINEAR: tfo = TFO_TRILINEAR; break;
227  case GfxTexFilter::BILINEAR: tfo = TFO_BILINEAR; break;
228  case GfxTexFilter::NONE: tfo = TFO_NONE; break;
229  }
230  MaterialManager::getSingleton().setDefaultAnisotropy(Math::Clamp(App::gfx_anisotropy->getInt(), 1, 16));
231  MaterialManager::getSingleton().setDefaultTextureFiltering(tfo);
232 
233  // load all resources now, so the zip files are also initiated
234  LOG("RoR|ContentManager: Calling initialiseAllResourceGroups()");
235  try
236  {
237  ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
238  }
239  catch (Ogre::Exception& e)
240  {
241  LOG("RoR|ContentManager: catched error while initializing Resource groups: " + e.getFullDescription());
242  }
243 #ifdef USE_OPENAL
245 #endif // USE_OPENAL
246 }
247 
248 void ContentManager::InitModCache(CacheValidity validity)
249 {
250  // Sets up RGN_CONTENT which encompasses all mods, scans it for changes and deletes it again.
251  // IMPORTANT NOTE ON 'readOnly' FLAG:
252  // We need mods in subdirs to be writable for the Tuning menu to work.
253  // Apart from `Resources` and resource groups, OGRE also keeps `Archives` in `ArchiveManager`
254  // These aren't unloaded on destroying resource groups, and keep a 'readOnly' flag (defaults to true).
255  // Upon loading/creating new resource groups, OGRE complains (=assert on Debug, exception on Release) if the submitted flag doesn't match.
256  // It's possible to manually unload archives to reset the flag, but for simplicity we just always load subdirs as 'writable', even during modcache update.
257  // ------------------------------------------------------------------------------------------
258 
259  ResourceGroupManager::getSingleton().addResourceLocation(
260  App::sys_cache_dir->getStr(), "FileSystem", RGN_CACHE, /*recursive=*/false, /*readOnly=*/false);
261  ResourceGroupManager::getSingleton().addResourceLocation(
262  App::sys_thumbnails_dir->getStr(), "FileSystem", RGN_REPO, /*recursive=*/false, /*readOnly=*/false);
263 
264  // Add top-level ZIPs/directories to RGN_CONTENT (non-recursive)
265 
266  if (!App::app_extra_mod_path->getStr().empty())
267  {
268  std::string extra_mod_path = App::app_extra_mod_path->getStr();
269  ResourceGroupManager::getSingleton().addResourceLocation(extra_mod_path , "FileSystem", RGN_CONTENT);
270  }
271  for (const std::string& dirname : App::GetCacheSystem()->GetContentDirs())
272  {
273  ResourceGroupManager::getSingleton().addResourceLocation(PathCombine(App::sys_user_dir->getStr(), dirname), "FileSystem", RGN_CONTENT);
274  }
275  ResourceGroupManager::getSingleton().addResourceLocation(PathCombine(App::sys_process_dir->getStr(), "content") , "FileSystem", RGN_CONTENT);
276  std::string objects = PathCombine("resources", "beamobjects.zip");
277  ResourceGroupManager::getSingleton().addResourceLocation(PathCombine(App::sys_process_dir->getStr(), objects) , "Zip" , RGN_CONTENT);
278 
279  // Create RGN_TEMP in recursive mode to find all subdirectories.
280 
281  ResourceGroupManager::getSingleton().createResourceGroup(RGN_TEMP, false);
282  if (!App::app_extra_mod_path->getStr().empty())
283  {
284  std::string extra_mod_path = App::app_extra_mod_path->getStr();
285  ResourceGroupManager::getSingleton().addResourceLocation(extra_mod_path , "FileSystem", RGN_TEMP, true);
286  }
287  for (const std::string& dirname : App::GetCacheSystem()->GetContentDirs())
288  {
289  ResourceGroupManager::getSingleton().addResourceLocation(PathCombine(App::sys_user_dir->getStr(), dirname), "FileSystem", RGN_TEMP, true);
290  }
291  ResourceGroupManager::getSingleton().addResourceLocation(PathCombine(App::sys_process_dir->getStr(), "content") , "FileSystem", RGN_TEMP, true);
292 
293  // Traverse RGN_TEMP and add all subdirectories to RGN_CONTENT.
294  // (TBD: why not just make RGN_CONTENT itself recursive? -- ohlidalp, 10/2023)
295 
296  FileInfoListPtr dirs = ResourceGroupManager::getSingleton().findResourceFileInfo(RGN_TEMP, "*", /*dirs:*/true);
297  for (const auto& dir_fileinfo : *dirs)
298  {
299  if (!dir_fileinfo.archive)
300  continue;
301  String fullpath = PathCombine(dir_fileinfo.archive->getName(), dir_fileinfo.filename);
302  ResourceGroupManager::getSingleton().addResourceLocation(fullpath, "FileSystem", RGN_CONTENT, /*recursive:*/false, /*readonly:*/false);
303  }
304  ResourceGroupManager::getSingleton().destroyResourceGroup(RGN_TEMP);
305 
306  // Traverse RGN_CONTENT and detect updates
307 
308  if (validity == CacheValidity::UNKNOWN)
309  {
310  validity = App::GetCacheSystem()->EvaluateCacheValidity(); // Must be called while RGN_CONTENT is alive.
311  }
312  App::GetCacheSystem()->LoadModCache(validity);
313 
314  ResourceGroupManager::getSingleton().destroyResourceGroup(RGN_CONTENT);
315 
316 }
317 
318 Ogre::DataStreamPtr ContentManager::resourceLoading(const Ogre::String& name, const Ogre::String& group, Ogre::Resource* resource)
319 {
320  return Ogre::DataStreamPtr();
321 }
322 
323 void ContentManager::resourceStreamOpened(const Ogre::String& name, const Ogre::String& group, Ogre::Resource* resource, Ogre::DataStreamPtr& dataStream)
324 {
325 }
326 
327 bool ContentManager::resourceCollision(Ogre::Resource* resource, Ogre::ResourceManager* resourceManager)
328 {
329  // RoR loads each resource bundle (see CacheSystem.h for info)
330  // into dedicated resource group outside the global pool [see CacheSystem::LoadResource()]
331  // This means resource collision is pretty much content creator's fault, with 2 exceptions:
332  // * asset packs (introduced 2024) are mixed into the requesting mod's resource group.
333  // * bundled resources (e.g. beamobjects.zip) are also mixed into the mod's resource group.
334  RoR::LogFormat("[RoR|ContentManager] Skipping resource with duplicate name: '%s' (origin: '%s')",
335  resource->getName().c_str(), resource->getOrigin().c_str());
336  return false; // Instruct OGRE to drop the new resource and keep the original.
337 }
338 
339 bool ContentManager::handleEvent(ScriptCompiler *compiler, ScriptCompilerEvent *evt, void *retval)
340 {
341  if (evt->mType == CreateMaterialScriptCompilerEvent::eventType)
342  {
343  // Workaround for OGRE script compiler not properly checking that material name is not empty.
344  // See https://github.com/RigsOfRods/rigs-of-rods/issues/2349
345  auto* matEvent = static_cast<CreateMaterialScriptCompilerEvent*>(evt);
346  if (matEvent->mName.empty())
347  {
348  RoR::LogFormat("[RoR] Got malformed material (empty name) from file: '%s' - forcing OGRE to fail loading.",
349  matEvent->mFile.c_str());
350  // Report "handled" but create nothing -> OGRE will interrupt the loading
351  // with message "failed to find or create material" [in MaterialTranslator::translate()]
352  return true;
353  }
354  }
355  else if (evt->mType == CreateParticleSystemScriptCompilerEvent::eventType)
356  {
357  // Workaround for OGRE ignoring resource groups when registering particle templates
358  // See https://github.com/RigsOfRods/rigs-of-rods/pull/2398
359  auto* particleEvent = static_cast<CreateParticleSystemScriptCompilerEvent*>(evt);
360  if (Ogre::ParticleSystemManager::getSingleton().getTemplate(particleEvent->mName) != nullptr)
361  {
362  // Duplicate name -> OGRE would throw exception and fail initializing whole resource group
363  RoR::LogFormat("[RoR] Duplicate particle system name '%s' in file: '%s' - forcing OGRE to fail loading.",
364  particleEvent->mName.c_str(), particleEvent->mFile.c_str());
365  return true; // Instruct OGRE to skip the particle system
366  }
367  }
368 
369  return false; // Report "not handled"
370 }
371 
372 void ContentManager::InitManagedMaterials(std::string const & rg_name)
373 {
374  Ogre::String managed_materials_dir = PathCombine(App::sys_resources_dir->getStr(), "managed_materials");
375 
376  //Dirty, needs to be improved
377  if (App::gfx_shadow_type->getEnum<GfxShadowType>() == GfxShadowType::PSSM)
378  {
379  if (rg_name == RGN_MANAGED_MATS) // Only load shared resources on startup
380  {
381  ResourceGroupManager::getSingleton().addResourceLocation(PathCombine(managed_materials_dir, "shadows/pssm/on/shared"), "FileSystem", rg_name);
382  }
383  ResourceGroupManager::getSingleton().addResourceLocation(PathCombine(managed_materials_dir, "shadows/pssm/on"), "FileSystem", rg_name);
384  }
385  else
386  {
387  ResourceGroupManager::getSingleton().addResourceLocation(PathCombine(managed_materials_dir,"shadows/pssm/off"), "FileSystem", rg_name);
388  }
389 
390  ResourceGroupManager::getSingleton().addResourceLocation(PathCombine(managed_materials_dir, "texture"), "FileSystem", rg_name);
391 
392  // Last
393  ResourceGroupManager::getSingleton().addResourceLocation(managed_materials_dir, "FileSystem", rg_name);
394 
395  if (rg_name == RGN_MANAGED_MATS) // Only initialize the global resource group
396  ResourceGroupManager::getSingleton().initialiseResourceGroup(rg_name);
397 }
398 
399 void ContentManager::LoadGameplayResources()
400 {
401  if (!m_base_resource_loaded)
402  {
403  this->AddResourcePack(ContentManager::ResourcePack::AIRFOILS);
404  this->AddResourcePack(ContentManager::ResourcePack::TEXTURES);
405  this->AddResourcePack(ContentManager::ResourcePack::FAMICONS);
406  this->AddResourcePack(ContentManager::ResourcePack::MATERIALS);
407  this->AddResourcePack(ContentManager::ResourcePack::MESHES);
408  this->AddResourcePack(ContentManager::ResourcePack::OVERLAYS);
409  this->AddResourcePack(ContentManager::ResourcePack::PARTICLES);
410 
411  m_base_resource_loaded = true;
412  }
413 
414  if (App::gfx_water_mode->getEnum<GfxWaterMode>() == GfxWaterMode::HYDRAX)
415  this->AddResourcePack(ContentManager::ResourcePack::HYDRAX);
416 
417  if (App::gfx_sky_mode->getEnum<GfxSkyMode>() == GfxSkyMode::CAELUM)
418  this->AddResourcePack(ContentManager::ResourcePack::CAELUM);
419 
420  if (App::gfx_sky_mode->getEnum<GfxSkyMode>() == GfxSkyMode::SKYX)
421  this->AddResourcePack(ContentManager::ResourcePack::SKYX);
422 
423  if (App::gfx_vegetation_mode->getEnum<GfxVegetation>() != RoR::GfxVegetation::NONE)
424  this->AddResourcePack(ContentManager::ResourcePack::PAGED);
425 }
426 
427 std::string ContentManager::ListAllUserContent()
428 {
429  std::stringstream buf;
430 
431  auto dir_list = Ogre::ResourceGroupManager::getSingleton().listResourceFileInfo(RGN_CONTENT, true);
432  for (auto dir: *dir_list)
433  {
434  buf << dir.filename << std::endl;
435  }
436 
437  // Any filename + listed extensions, ignore case
438  std::regex file_whitelist("^.\\.(airplane|boat|car|fixed|load|machine|skin|terrn2|train|truck)$", std::regex::icase);
439 
440  auto file_list = Ogre::ResourceGroupManager::getSingleton().listResourceFileInfo(RGN_CONTENT, false);
441  for (auto file: *file_list)
442  {
443  if ((file.archive != nullptr) || std::regex_match(file.filename, file_whitelist))
444  {
445  buf << file.filename << std::endl;
446  }
447  }
448 
449  return buf.str();
450 }
451 
452 bool ContentManager::LoadAndParseJson(std::string const& filename, std::string const& rg_name, rapidjson::Document& j_doc)
453 {
454  try
455  {
456  Ogre::DataStreamPtr stream = Ogre::ResourceGroupManager::getSingleton().openResource(filename, rg_name);
457  Ogre::String json_str = stream->getAsString();
458  rapidjson::MemoryStream j_stream(json_str.data(), json_str.length());
459  j_doc.ParseStream<rapidjson::kParseNanAndInfFlag>(j_stream);
460  }
461  catch (Ogre::FileNotFoundException)
462  {
463  return false; // Error already logged by OGRE
464  }
465  catch (std::exception& e)
466  {
467  RoR::LogFormat("[RoR] Failed to open or read json file '%s' (resource group '%s'), message: '%s'",
468  filename.c_str(), rg_name.c_str(), e.what());
469  return false;
470  }
471 
472  if (j_doc.HasParseError())
473  {
474  RoR::LogFormat("[RoR] Error parsing JSON file '%s' (resource group '%s')",
475  filename.c_str(), rg_name.c_str());
476  return false;
477  }
478 
479  return true;
480 }
481 
482 bool ContentManager::SerializeAndWriteJson(std::string const& filename, std::string const& rg_name, rapidjson::Document& j_doc)
483 {
484  // Serialize JSON to string
485  rapidjson::StringBuffer buffer;
486  rapidjson::Writer<rapidjson::StringBuffer, rapidjson::UTF8<>, rapidjson::UTF8<>,
487  rapidjson::CrtAllocator, rapidjson::kWriteNanAndInfFlag>
488  writer(buffer);
489  j_doc.Accept(writer);
490 
491  // Write JSON to file
492  try
493  {
494  Ogre::DataStreamPtr stream
495  = Ogre::ResourceGroupManager::getSingleton().createResource(
496  filename, rg_name, /*overwrite=*/true);
497  size_t written = stream->write(buffer.GetString(), buffer.GetSize());
498  if (written < buffer.GetSize())
499  {
500  RoR::LogFormat("[RoR] Error writing JSON file '%s' (resource group '%s'), ",
501  "only written %u out of %u bytes!",
502  filename.c_str(), rg_name.c_str(), written, buffer.GetSize());
503  return false;
504  }
505  return true;
506  }
507  catch (std::exception& e)
508  {
509  RoR::LogFormat("[RoR] Error writing JSON file '%s' (resource group '%s'), message: '%s'",
510  filename.c_str(), rg_name.c_str(), e.what());
511  return false;
512  }
513 }
514 
515 bool ContentManager::DeleteDiskFile(std::string const& filename, std::string const& rg_name)
516 {
517  try
518  {
519  Ogre::ResourceGroupManager::getSingleton().deleteResource(filename, rg_name);
520  return true;
521  }
522  catch (std::exception& e)
523  {
524  RoR::LogFormat("[RoR|ModCache] Error deleting file '%s' (resource group '%s'), message: '%s'",
525  filename.c_str(), rg_name.c_str(), e.what());
526  return false;
527  }
528 }
529 
RoR::App::sys_user_dir
CVar * sys_user_dir
Definition: Application.cpp:163
ColoredTextAreaOverlayElementFactory.h
RoR::App::GetSoundScriptManager
SoundScriptManager * GetSoundScriptManager()
Definition: Application.cpp:277
RGN_CONFIG
#define RGN_CONFIG
Definition: Application.h:48
RGN_CACHE
#define RGN_CACHE
Definition: Application.h:46
RoR::App::sys_resources_dir
CVar * sys_resources_dir
Definition: Application.cpp:168
RoR::App::sys_scripts_dir
CVar * sys_scripts_dir
Definition: Application.cpp:172
RGN_LOGS
#define RGN_LOGS
Definition: Application.h:53
file
This is a raw Ogre binding for Imgui No project cmake file
Definition: README-OgreImGui.txt:3
ContentManager.h
RoR::CacheSystem::LoadModCache
void LoadModCache(CacheValidity validity)
Definition: CacheSystem.cpp:151
RoR::App::gfx_shadow_type
CVar * gfx_shadow_type
Definition: Application.cpp:217
RoR::App::CreateSoundScriptManager
void CreateSoundScriptManager()
Definition: Application.cpp:334
RoR::LogFormat
void LogFormat(const char *format,...)
Improved logging utility. Uses fixed 2Kb buffer.
Definition: Application.cpp:424
RoR::FolderExists
bool FolderExists(const char *path)
Path must be UTF-8 encoded.
Definition: PlatformUtils.cpp:169
RoR::App::sys_logs_dir
CVar * sys_logs_dir
Definition: Application.cpp:167
Utils.h
RoR::App::gfx_texture_filter
CVar * gfx_texture_filter
Definition: Application.cpp:222
Language.h
RoR::App::sys_savegames_dir
CVar * sys_savegames_dir
Definition: Application.cpp:170
RoR::App::app_extra_mod_path
CVar * app_extra_mod_path
Definition: Application.cpp:87
RoR::ContentManager::ResourcePack
Definition: ContentManager.h:41
RoR::SoundScriptManager::setLoadingBaseSounds
void setLoadingBaseSounds(bool value)
Definition: SoundScriptManager.h:330
RGN_REPO
#define RGN_REPO
Definition: Application.h:47
RoR::ContentManager::ResourcePack::name
const char * name
Definition: ContentManager.h:72
OgreShaderParticleRenderer.h
RGN_MANAGED_MATS
#define RGN_MANAGED_MATS
Definition: Application.h:51
RoR::CVar::getStr
std::string const & getStr() const
Definition: CVar.h:95
RoR::PathCombine
std::string PathCombine(std::string a, std::string b)
Definition: PlatformUtils.h:48
CacheSystem.h
A database of user-installed content alias 'mods' (vehicles, terrains...)
RoR::CacheValidity
CacheValidity
Definition: CacheSystem.h:203
ErrorUtils.h
RGN_TEMP
#define RGN_TEMP
Definition: Application.h:45
Ogre::ShaderParticleRendererFactory
Factory class for ShaderParticleRenderer.
Definition: OgreShaderParticleRenderer.h:234
RoR::GfxVegetation::NONE
@ NONE
RoR::App::sys_thumbnails_dir
CVar * sys_thumbnails_dir
Definition: Application.cpp:166
RoR::App::sys_cache_dir
CVar * sys_cache_dir
Definition: Application.cpp:165
PlatformUtils.h
Platform-specific utilities. We use narrow UTF-8 encoded strings as paths. Inspired by http://utf8eve...
Application.h
Central state/object manager and communications hub.
SoundScriptManager.h
FireExtinguisherAffectorFactory.h
RGN_CONTENT
#define RGN_CONTENT
Definition: Application.h:49
RoR::App::gfx_water_mode
CVar * gfx_water_mode
Definition: Application.cpp:224
RoR::CacheSystem::EvaluateCacheValidity
CacheValidity EvaluateCacheValidity()
Definition: CacheSystem.cpp:215
RoR::App::gfx_sky_mode
CVar * gfx_sky_mode
Definition: Application.cpp:219
RoR::App::sys_config_dir
CVar * sys_config_dir
Definition: Application.cpp:164
ExtinguishableFireAffectorFactory.h
ColoredTextAreaOverlayElementFactory
Factory for creating TextAreaOverlayElement instances.
Definition: ColoredTextAreaOverlayElementFactory.h:31
RoR::App::GetCacheSystem
CacheSystem * GetCacheSystem()
Definition: Application.cpp:272
RoR::DEPTHMAP_ENABLED
@ DEPTHMAP_ENABLED
Definition: Application.h:284
Ogre::ExtinguishableFireAffectorFactory
Factory class for DeflectorPlaneAffector.
Definition: ExtinguishableFireAffectorFactory.h:37
SkinFileFormat.h
Ogre::FireExtinguisherAffectorFactory
Factory class for DeflectorPlaneAffector.
Definition: FireExtinguisherAffectorFactory.h:37
RoR::ContentManager::ResourcePack::resource_group_name
const char * resource_group_name
Definition: ContentManager.h:73
RGN_SCRIPTS
#define RGN_SCRIPTS
Definition: Application.h:52
RGN_SAVEGAMES
#define RGN_SAVEGAMES
Definition: Application.h:50
Ogre
Definition: ExtinguishableFireAffector.cpp:35
RoR::App::sys_process_dir
CVar * sys_process_dir
Definition: Application.cpp:162
RoR::App::gfx_vegetation_mode
CVar * gfx_vegetation_mode
Definition: Application.cpp:223
DECLARE_RESOURCE_PACK
#define DECLARE_RESOURCE_PACK(_FIELD_, _NAME_, _RESOURCE_GROUP_)
Definition: ContentManager.cpp:67
RoR::App::gfx_anisotropy
CVar * gfx_anisotropy
Definition: Application.cpp:225
RoR
Definition: AppContext.h:36
RoR::FileExists
bool FileExists(const char *path)
Path must be UTF-8 encoded.
Definition: PlatformUtils.cpp:163