mirror of
				https://github.com/TES3MP/openmw-tes3mp.git
				synced 2025-10-31 20:56:42 +00:00 
			
		
		
		
	Manually convert last changes in branch to upstream/master. Regular merge attempt resulted in everything being overwritten by fast-forward merging.
- Remove check for 255 master/plugin files.
This commit is contained in:
		
							parent
							
								
									bb6d9a329c
								
							
						
					
					
						commit
						28d4d7ea3f
					
				
					 12 changed files with 155 additions and 47 deletions
				
			
		|  | @ -212,18 +212,31 @@ void OMW::Engine::setCell (const std::string& cellName) | |||
| 
 | ||||
| // Set master file (esm)
 | ||||
| // - If the given name does not have an extension, ".esm" is added automatically
 | ||||
| // - Currently OpenMW only supports one master at the same time.
 | ||||
| 
 | ||||
| void OMW::Engine::addMaster (const std::string& master) | ||||
| { | ||||
|     assert (mMaster.empty()); | ||||
|     mMaster = master; | ||||
| 
 | ||||
|     mMaster.push_back(master); | ||||
|     std::string &str = mMaster.back(); | ||||
|   | ||||
|     // Append .esm if not already there
 | ||||
|     std::string::size_type sep = mMaster.find_last_of ("."); | ||||
|     std::string::size_type sep = str.find_last_of ("."); | ||||
|     if (sep == std::string::npos) | ||||
|     { | ||||
|         mMaster += ".esm"; | ||||
|         str += ".esm"; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // Add plugin file (esp)
 | ||||
| void OMW::Engine::addPlugin (const std::string& plugin) | ||||
| { | ||||
|     mPlugins.push_back(plugin); | ||||
|     std::string &str = mPlugins.back(); | ||||
| 
 | ||||
|     // Append .esp if not already there
 | ||||
|     std::string::size_type sep = str.find_last_of ("."); | ||||
|     if (sep == std::string::npos) | ||||
|     { | ||||
|         str += ".esp"; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -331,8 +344,8 @@ void OMW::Engine::go() | |||
|     MWGui::CursorReplace replacer; | ||||
| 
 | ||||
|     // Create the world
 | ||||
|     mEnvironment.setWorld (new MWWorld::World (*mOgre, mFileCollections, mMaster, | ||||
|         mResDir, mCfgMgr.getCachePath(), mNewGame, mEncoding, mFallbackMap)); | ||||
|     mEnvironment.setWorld( new MWWorld::World (*mOgre, mFileCollections, mMaster, mPlugins, | ||||
|         mResDir, mCfgMgr.getCachePath(), mNewGame, mEncoding, mFallbackMap) ); | ||||
| 
 | ||||
|     // Create window manager - this manages all the MW-specific GUI windows
 | ||||
|     MWScript::registerExtensions (mExtensions); | ||||
|  |  | |||
|  | @ -64,7 +64,8 @@ namespace OMW | |||
|             boost::filesystem::path mResDir; | ||||
|             OEngine::Render::OgreRenderer *mOgre; | ||||
|             std::string mCellName; | ||||
|             std::string mMaster; | ||||
|             std::vector<std::string> mMaster; | ||||
|             std::vector<std::string> mPlugins; | ||||
|             int mFpsLevel; | ||||
|             bool mDebug; | ||||
|             bool mVerboseScripts; | ||||
|  | @ -122,9 +123,12 @@ namespace OMW | |||
| 
 | ||||
|             /// Set master file (esm)
 | ||||
|             /// - If the given name does not have an extension, ".esm" is added automatically
 | ||||
|             /// - Currently OpenMW only supports one master at the same time.
 | ||||
|             void addMaster(const std::string& master); | ||||
| 
 | ||||
|             /// Same as "addMaster", but for plugin files (esp)
 | ||||
|             /// - If the given name does not have an extension, ".esp" is added automatically
 | ||||
|             void addPlugin(const std::string& plugin); | ||||
| 
 | ||||
|             /// Enable fps counter
 | ||||
|             void showFPS(int level); | ||||
| 
 | ||||
|  |  | |||
|  | @ -224,18 +224,19 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat | |||
|         master.push_back("Morrowind"); | ||||
|     } | ||||
| 
 | ||||
|     if (master.size() > 1) | ||||
|     { | ||||
|         std::cout | ||||
|             << "Ignoring all but the first master file (multiple master files not yet supported)." | ||||
|             << std::endl; | ||||
|     } | ||||
|     engine.addMaster(master[0]); | ||||
| 
 | ||||
|     StringsVector plugin = variables["plugin"].as<StringsVector>(); | ||||
|     if (!plugin.empty()) | ||||
|     // Removed check for 255 files, which would be the hard-coded limit in Morrowind.
 | ||||
|     //  I'll keep the following variable in, maybe we can use it for somethng different.
 | ||||
|     int cnt = master.size() + plugin.size(); | ||||
| 
 | ||||
|     // Prepare loading master/plugin files (i.e. send filenames to engine)
 | ||||
|     for (std::vector<std::string>::size_type i = 0; i < master.size(); i++) | ||||
|     { | ||||
|         std::cout << "Ignoring plugin files (plugins not yet supported)." << std::endl; | ||||
|         engine.addMaster(master[i]); | ||||
|     } | ||||
|     for (std::vector<std::string>::size_type i = 0; i < plugin.size(); i++) | ||||
|     { | ||||
|         engine.addPlugin(plugin[i]); | ||||
|     } | ||||
| 
 | ||||
|     // startup-settings
 | ||||
|  |  | |||
|  | @ -141,7 +141,7 @@ namespace MWRender | |||
|                 std::map<uint16_t, int> indexes; | ||||
|                 initTerrainTextures(&terrainData, cellX, cellY, | ||||
|                                     x * numTextures, y * numTextures, | ||||
|                                     numTextures, indexes); | ||||
|                                     numTextures, indexes, land->plugin); | ||||
| 
 | ||||
|                 if (mTerrainGroup.getTerrain(terrainX, terrainY) == NULL) | ||||
|                 { | ||||
|  | @ -200,8 +200,13 @@ namespace MWRender | |||
|     void TerrainManager::initTerrainTextures(Terrain::ImportData* terrainData, | ||||
|                                              int cellX, int cellY, | ||||
|                                              int fromX, int fromY, int size, | ||||
|                                              std::map<uint16_t, int>& indexes) | ||||
|                                              std::map<uint16_t, int>& indexes, size_t plugin) | ||||
|     { | ||||
|         // FIXME: In a multiple esm configuration, we have multiple palettes. Since this code
 | ||||
|         //  crosses cell boundaries, we no longer have a unique terrain palette. Instead, we need
 | ||||
|         //  to adopt the following code for a dynamic palette. And this is evil - the current design
 | ||||
|         //  does not work well for this task...
 | ||||
| 
 | ||||
|         assert(terrainData != NULL && "Must have valid terrain data"); | ||||
|         assert(fromX >= 0 && fromY >= 0 && | ||||
|                "Can't get a terrain texture on terrain outside the current cell"); | ||||
|  | @ -214,12 +219,20 @@ namespace MWRender | |||
|         //
 | ||||
|         //If we don't sort the ltex indexes, the splatting order may differ between
 | ||||
|         //cells which may lead to inconsistent results when shading between cells
 | ||||
|         int num = MWBase::Environment::get().getWorld()->getStore().landTexts.getSizePlugin(plugin); | ||||
|         std::set<uint16_t> ltexIndexes; | ||||
|         for ( int y = fromY - 1; y < fromY + size + 1; y++ ) | ||||
|         { | ||||
|             for ( int x = fromX - 1; x < fromX + size + 1; x++ ) | ||||
|             { | ||||
|                 ltexIndexes.insert(getLtexIndexAt(cellX, cellY, x, y)); | ||||
|                 int idx = getLtexIndexAt(cellX, cellY, x, y); | ||||
|                 // This is a quick hack to prevent the program from trying to fetch textures
 | ||||
|                 //  from a neighboring cell, which might originate from a different plugin,
 | ||||
|                 //  and use a separate texture palette. Right now, we simply cast it to the
 | ||||
|                 //  default texture (i.e. 0).
 | ||||
|                 if (idx > num) | ||||
|                   idx = 0; | ||||
|                 ltexIndexes.insert(idx); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|  | @ -231,7 +244,7 @@ namespace MWRender | |||
|               iter != ltexIndexes.end(); | ||||
|               ++iter ) | ||||
|         { | ||||
|             const uint16_t ltexIndex = *iter; | ||||
|             uint16_t ltexIndex = *iter; | ||||
|             //this is the base texture, so we can ignore this at present
 | ||||
|             if ( ltexIndex == baseTexture ) | ||||
|             { | ||||
|  | @ -244,8 +257,12 @@ namespace MWRender | |||
|             { | ||||
|                 //NB: All vtex ids are +1 compared to the ltex ids
 | ||||
| 
 | ||||
|                 assert( (int)MWBase::Environment::get().getWorld()->getStore().landTexts.getSize() >= (int)ltexIndex - 1 && | ||||
|                        "LAND.VTEX must be within the bounds of the LTEX array"); | ||||
|                 // NOTE: using the quick hack above, we should no longer end up with textures indices
 | ||||
|                 //  that are out of bounds. However, I haven't updated the test to a multi-palette
 | ||||
|                 //  system yet. We probably need more work here, so we skip it for now.
 | ||||
|                  | ||||
|                 //assert( (int)MWBase::Environment::get().getWorld()->getStore().landTexts.getSize() >= (int)ltexIndex - 1 &&
 | ||||
|                        //"LAND.VTEX must be within the bounds of the LTEX array");
 | ||||
| 
 | ||||
|                 std::string texture; | ||||
|                 if ( ltexIndex == 0 ) | ||||
|  | @ -254,7 +271,7 @@ namespace MWRender | |||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     texture = MWBase::Environment::get().getWorld()->getStore().landTexts.search(ltexIndex-1)->texture; | ||||
|                     texture = MWBase::Environment::get().getWorld()->getStore().landTexts.search(ltexIndex-1, plugin)->texture; | ||||
|                     //TODO this is needed due to MWs messed up texture handling
 | ||||
|                     texture = texture.substr(0, texture.rfind(".")) + ".dds"; | ||||
|                 } | ||||
|  |  | |||
|  | @ -75,7 +75,7 @@ namespace MWRender{ | |||
|         void initTerrainTextures(Ogre::Terrain::ImportData* terrainData, | ||||
|                                  int cellX, int cellY, | ||||
|                                  int fromX, int fromY, int size, | ||||
|                                  std::map<uint16_t, int>& indexes); | ||||
|                                  std::map<uint16_t, int>& indexes, size_t plugin); | ||||
| 
 | ||||
|         /**
 | ||||
|          * Creates the blend (splatting maps) for the given terrain from the ltex data. | ||||
|  |  | |||
|  | @ -164,7 +164,8 @@ namespace MWWorld | |||
| 
 | ||||
|     World::World (OEngine::Render::OgreRenderer& renderer, | ||||
|         const Files::Collections& fileCollections, | ||||
|         const std::string& master, const boost::filesystem::path& resDir, const boost::filesystem::path& cacheDir, bool newGame, | ||||
|         const std::vector<std::string>& master, const std::vector<std::string>& plugins, | ||||
| 	const boost::filesystem::path& resDir, const boost::filesystem::path& cacheDir, bool newGame, | ||||
|         const std::string& encoding, std::map<std::string,std::string> fallbackMap) | ||||
|     : mPlayer (0), mLocalScripts (mStore), mGlobalVariables (0), | ||||
|       mSky (true), mNextDynamicRecord (0), mCells (mStore, mEsm), | ||||
|  | @ -177,14 +178,32 @@ namespace MWWorld | |||
| 
 | ||||
|         mWeatherManager = new MWWorld::WeatherManager(mRendering); | ||||
| 
 | ||||
|         boost::filesystem::path masterPath (fileCollections.getCollection (".esm").getPath (master)); | ||||
|         int idx = 0; | ||||
|         for (std::vector<std::string>::size_type i = 0; i < master.size(); i++, idx++) | ||||
|         { | ||||
|             boost::filesystem::path masterPath (fileCollections.getCollection (".esm").getPath (master[i])); | ||||
|              | ||||
|             std::cout << "Loading ESM " << masterPath.string() << "\n"; | ||||
| 
 | ||||
|         std::cout << "Loading ESM " << masterPath.string() << "\n"; | ||||
|             // This parses the ESM file
 | ||||
|             mEsm.setEncoding(encoding); | ||||
|             mEsm.open (masterPath.string()); | ||||
|             mEsm.setIndex(idx); | ||||
|             mStore.load (mEsm); | ||||
|         } | ||||
|   | ||||
|         for (std::vector<std::string>::size_type i = 0; i < plugins.size(); i++, idx++) | ||||
|         { | ||||
|             boost::filesystem::path pluginPath (fileCollections.getCollection (".esp").getPath (plugins[i])); | ||||
|              | ||||
|             std::cout << "Loading ESP " << pluginPath.string() << "\n"; | ||||
| 
 | ||||
|         // This parses the ESM file and loads a sample cell
 | ||||
|         mEsm.setEncoding(encoding); | ||||
|         mEsm.open (masterPath.string()); | ||||
|         mStore.load (mEsm); | ||||
|             // This parses the ESP file
 | ||||
|             mEsm.setEncoding(encoding); | ||||
|             mEsm.open (pluginPath.string()); | ||||
|             mEsm.setIndex(idx); | ||||
|             mStore.load (mEsm); | ||||
|         } | ||||
| 
 | ||||
|         mPlayer = new MWWorld::Player (mStore.npcs.find ("player"), *this); | ||||
|         mRendering->attachCameraTo(mPlayer->getPlayer()); | ||||
|  |  | |||
|  | @ -96,7 +96,8 @@ namespace MWWorld | |||
| 
 | ||||
|             World (OEngine::Render::OgreRenderer& renderer, | ||||
|                 const Files::Collections& fileCollections, | ||||
|                 const std::string& master, const boost::filesystem::path& resDir, const boost::filesystem::path& cacheDir, bool newGame, | ||||
|                 const std::vector<std::string>& master, const std::vector<std::string>& plugins, | ||||
|         	const boost::filesystem::path& resDir, const boost::filesystem::path& cacheDir, bool newGame, | ||||
|                 const std::string& encoding, std::map<std::string,std::string> fallbackMap); | ||||
| 
 | ||||
|             virtual ~World(); | ||||
|  |  | |||
|  | @ -189,6 +189,14 @@ public: | |||
| 
 | ||||
|   void openRaw(const std::string &file); | ||||
| 
 | ||||
|   // This is a quick hack for multiple esm/esp files. Each plugin introduces its own
 | ||||
|   //  terrain palette, but ESMReader does not pass a reference to the correct plugin
 | ||||
|   //  to the individual load() methods. This hack allows to pass this reference
 | ||||
|   //  indirectly to the load() method.
 | ||||
|   int idx; | ||||
|   void setIndex(const int index) {idx = index;} | ||||
|   const int getIndex() {return idx;} | ||||
| 
 | ||||
|   /*************************************************************************
 | ||||
|    * | ||||
|    *  Medium-level reading shortcuts | ||||
|  |  | |||
|  | @ -23,6 +23,7 @@ Land::~Land() | |||
| void Land::load(ESMReader &esm) | ||||
| { | ||||
|     mEsm = &esm; | ||||
|     plugin = mEsm->getIndex(); | ||||
| 
 | ||||
|     // Get the grid location
 | ||||
|     esm.getSubNameIs("INTV"); | ||||
|  |  | |||
|  | @ -17,6 +17,7 @@ struct Land | |||
|     int flags; // Only first four bits seem to be used, don't know what
 | ||||
|     // they mean.
 | ||||
|     int X, Y; // Map coordinates.
 | ||||
|     int plugin; // Plugin index, used to reference the correct material palette.
 | ||||
| 
 | ||||
|     // File context. This allows the ESM reader to be 'reset' to this
 | ||||
|     // location later when we are ready to load the full data set.
 | ||||
|  |  | |||
|  | @ -26,6 +26,7 @@ namespace ESMS | |||
| 
 | ||||
|     virtual void load(ESMReader &esm, const std::string &id) = 0; | ||||
|     virtual int getSize() = 0; | ||||
|     virtual void remove(const std::string &id) {}; | ||||
|     virtual void listIdentifier (std::vector<std::string>& identifier) const = 0; | ||||
| 
 | ||||
|     static std::string toLower (const std::string& name) | ||||
|  | @ -57,6 +58,14 @@ namespace ESMS | |||
|       list[id2].load(esm); | ||||
|     } | ||||
| 
 | ||||
|     // Delete the given object ID. Plugin files support this, so we need to do this, too.
 | ||||
|     void remove(const std::string &id) | ||||
|     { | ||||
|         std::string id2 = toLower (id); | ||||
| 
 | ||||
|         list.erase(id2); | ||||
|     } | ||||
| 
 | ||||
|     // Find the given object ID, or return NULL if not found.
 | ||||
|     const X* search(const std::string &id) const | ||||
|     { | ||||
|  | @ -268,38 +277,63 @@ namespace ESMS | |||
|   { | ||||
|     virtual ~LTexList() {} | ||||
| 
 | ||||
|     // TODO: For multiple ESM/ESP files we need one list per file.
 | ||||
|     std::vector<LandTexture> ltex; | ||||
|     // For multiple ESM/ESP files we need one list per file.
 | ||||
|     typedef std::vector<LandTexture> LandTextureList; | ||||
|     std::vector<LandTextureList> ltex; | ||||
| 
 | ||||
|     LTexList() | ||||
|     { | ||||
|       // More than enough to hold Morrowind.esm.
 | ||||
|       ltex.reserve(128); | ||||
|       ltex.push_back(LandTextureList()); | ||||
|       LandTextureList <exl = ltex[0]; | ||||
|       // More than enough to hold Morrowind.esm. Extra lists for plugins will we
 | ||||
|       //  added on-the-fly in a different method.
 | ||||
|       ltexl.reserve(128); | ||||
|     } | ||||
| 
 | ||||
|     const LandTexture* search(size_t index) const | ||||
|     const LandTexture* search(size_t index, size_t plugin) const | ||||
|     { | ||||
|         assert(index < ltex.size()); | ||||
|         return <ex.at(index); | ||||
|       assert(plugin < ltex.size()); | ||||
|       const LandTextureList <exl = ltex[plugin]; | ||||
| 
 | ||||
|       assert(index < ltexl.size()); | ||||
|       return <exl.at(index); | ||||
|     } | ||||
| 
 | ||||
|     // "getSize" returns the number of individual terrain palettes.
 | ||||
|     // "getSizePlugin" returns the number of land textures in a specific palette.
 | ||||
|     int getSize() { return ltex.size(); } | ||||
|     int getSize() const { return ltex.size(); } | ||||
| 
 | ||||
|     int getSizePlugin(size_t plugin) { assert(plugin < ltex.size()); return ltex[plugin].size(); } | ||||
|     int getSizePlugin(size_t plugin) const { assert(plugin < ltex.size()); return ltex[plugin].size(); } | ||||
|      | ||||
|     virtual void listIdentifier (std::vector<std::string>& identifier) const {} | ||||
| 
 | ||||
|     void load(ESMReader &esm, const std::string &id) | ||||
|     void load(ESMReader &esm, const std::string &id, size_t plugin) | ||||
|     { | ||||
|       LandTexture lt; | ||||
|       lt.load(esm); | ||||
|       lt.id = id; | ||||
| 
 | ||||
|       // Make sure we have room for the structure
 | ||||
|       if(lt.index + 1 > (int)ltex.size()) | ||||
|         ltex.resize(lt.index+1); | ||||
|       if (plugin >= ltex.size()) { | ||||
| 	ltex.resize(plugin+1); | ||||
|       } | ||||
|       LandTextureList <exl = ltex[plugin]; | ||||
|       if(lt.index + 1 > (int)ltexl.size()) | ||||
|         ltexl.resize(lt.index+1); | ||||
| 
 | ||||
|       // Store it
 | ||||
|       ltex[lt.index] = lt; | ||||
|       ltexl[lt.index] = lt; | ||||
|     } | ||||
| 
 | ||||
|     // Load all terrain palettes at the same size. Inherited virtual function
 | ||||
|     //  from "RecList". Mostly useless, because we need the implementation
 | ||||
|     //  above this one.
 | ||||
|     void load(ESMReader &esm, const std::string &id) | ||||
|     { | ||||
|       size_t plugin = esm.getIndex(); | ||||
|       load(esm, id, plugin); | ||||
|     } | ||||
|   }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -67,6 +67,15 @@ void ESMStore::load(ESMReader &esm) | |||
|         { | ||||
|             // Load it
 | ||||
|             std::string id = esm.getHNOString("NAME"); | ||||
|             // ... unless it got deleted! This means that the following record
 | ||||
| 	    //  has been deleted, and trying to load it using standard assumptions
 | ||||
| 	    //  on the structure will (probably) fail.
 | ||||
|             if (esm.isNextSub("DELE")) { | ||||
|               esm.skipRecord(); | ||||
|               all.erase(id); | ||||
|               it->second->remove(id); | ||||
|               continue; | ||||
|             } | ||||
|             it->second->load(esm, id); | ||||
| 
 | ||||
|             if (n.val==ESM::REC_DIAL) | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue