Add infos into target window
[ryzomcore.git] / ryzom / server / src / server_share / continent_container.cpp
blob281abbd4a9f48b92c0679f44ac996781bafeef65
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2014-2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
6 //
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "stdpch.h"
23 #include <memory>
25 #include "continent_container.h"
27 #include <memory>
29 #include "nel/misc/aabbox.h"
30 #include "nel/misc/path.h"
31 #include "nel/misc/file.h"
32 #include "nel/misc/command.h"
33 #include <nel/misc/algo.h>
35 #include "nel/georges/u_form_loader.h"
36 #include "nel/georges/load_form.h"
38 #include "light_ig_loader.h"
41 using namespace std;
42 using namespace NLMISC;
43 using namespace NLPACS;
44 using namespace NLGEORGES;
47 // Constructor
48 CContinentContainer::CContinentContainer()
53 void CContinentContainer::init(uint gridWidth, uint gridHeight, double primitiveMaxSize, uint nbWorldImages, const string &packedSheetsDirectory, double cellSize, bool loadPacsPrims)
55 _GridWidth = gridWidth;
56 _GridHeight = gridHeight;
57 _PrimitiveMaxSize = primitiveMaxSize;
58 _NbWorldImages = nbWorldImages;
59 _CellSize = cellSize;
60 _LoadPacsPrims = loadPacsPrims;
62 buildSheets(packedSheetsDirectory);
66 void CContinentContainer::buildSheets(const string &packedSheetsDirectory)
68 std::vector<std::string> filters;
69 filters.push_back("continent");
71 // if the 'GeorgePaths' config file var exists then we try to perform a mini-scan for sheet files
72 if (NLNET::IService::isServiceInitialized() && (NLNET::IService::getInstance()->ConfigFile.getVarPtr(std::string("GeorgePaths"))!=NULL))
74 loadForm(filters, packedSheetsDirectory+"continents.packed_sheets", _SheetMap, false, false);
77 // if we haven't succeeded in minimal scan (or 'GeorgePaths' wasn't found in config file) then perform standard scan
78 if (_SheetMap.empty())
80 loadForm(filters, packedSheetsDirectory+"continents.packed_sheets", _SheetMap, true);
85 void CContinentContainer::loadContinent(string name, string file, sint index, bool allowAutoSpawn)
87 nlinfo("loadContinent(\"%s\", \"%s\", %d)", name.c_str(), file.c_str(), index);
89 // check if the continent is already loaded
90 /* {
91 TContinentContainer::iterator first(_Continents.begin()), last(_Continents.end());
92 for (; first != last; ++first)
94 if (first->Name == name)
96 nlinfo("loadContinent(\"%s\", \"%s\", %d) : continent already loaded, ignoring second load.", name.c_str(), file.c_str(), index);
97 return;
102 nlassert(index >= 0);
104 TSheetMap::iterator its, found = _SheetMap.end();
106 for (its=_SheetMap.begin(); its!=_SheetMap.end(); ++its)
108 if (NLMISC::toLowerAscii((*its).second.Name) == NLMISC::toLowerAscii(name+".continent") ||
109 NLMISC::toLowerAscii((*its).second.PacsRBank) == NLMISC::toLowerAscii(name+".rbank"))
111 if (found == _SheetMap.end())
113 found = its;
115 else
117 nlinfo("Found 2 different possible continent sheets for %s: %s and %s, continent is not loaded twice", name.c_str(), (*its).second.Name.c_str(), (*found).second.Name.c_str());
122 if (found != _SheetMap.end())
124 name = (*found).second.Name;
125 file = CFile::getFilenameWithoutExtension((*found).second.PacsRBank);
127 else
129 nlwarning("Couldn't find continent sheet for '%s', use name instead", name.c_str());
132 for (uint i=0; i<_Continents.size(); ++i)
134 if (_Continents[i].Name == name)
136 nlinfo("Continent '%s' already loaded, loading aborted for this new continent.", name.c_str());
137 return;
141 if ((sint)_Continents.size() <= index)
142 _Continents.resize(index+1);
144 if (_Continents[index].RetrieverBank != NULL ||
145 _Continents[index].GlobalRetriever != NULL ||
146 _Continents[index].MoveContainer != NULL)
148 nlwarning("Init retriever bank failed, index %d already used by continent '%s'", index, _Continents[index].Name.c_str());
149 return;
152 _Continents[index].Name = name;
153 _Continents[index].AllowAutoSpawn = allowAutoSpawn;
155 string filename;
157 // load the rbank
158 filename = file+".rbank";
159 _Continents[index].RetrieverBank = URetrieverBank::createRetrieverBank ( filename.c_str(), true );
160 if( _Continents[index].RetrieverBank == NULL )
162 nlwarning("Init retriever bank failed, file load is %s", filename.c_str() );
163 return;
166 // load the gr
167 filename = file+".gr";
168 _Continents[index].GlobalRetriever = UGlobalRetriever::createGlobalRetriever ( filename.c_str(), _Continents[index].RetrieverBank );
169 if( _Continents[index].GlobalRetriever == NULL )
171 nlwarning("Init global retriever failed, file load is %s", filename.c_str() );
172 URetrieverBank::deleteRetrieverBank(_Continents[index].RetrieverBank);
173 _Continents[index].RetrieverBank = NULL;
174 return;
177 uint gw = _GridWidth;
178 uint gh = _GridHeight;
180 if (_CellSize != 0.0)
182 CAABBox cbox = _Continents[index].GlobalRetriever->getBBox();
184 gw = (uint)(cbox.getHalfSize().x*2.0 / _CellSize) + 1;
185 gh = (uint)(cbox.getHalfSize().y*2.0 / _CellSize) + 1;
188 // create the move container
189 /// \todo Ben : correct init for the move container cells count
190 _Continents[index].MoveContainer = UMoveContainer::createMoveContainer ( _Continents[index].GlobalRetriever, gw, gh, _PrimitiveMaxSize, _NbWorldImages);
192 if( _Continents[index].MoveContainer == NULL )
194 nlwarning("Init Move container failed, continent %s", name.c_str());
195 URetrieverBank::deleteRetrieverBank(_Continents[index].RetrieverBank);
196 UGlobalRetriever::deleteGlobalRetriever(_Continents[index].GlobalRetriever);
197 _Continents[index].GlobalRetriever = NULL;
198 _Continents[index].RetrieverBank = NULL;
199 _Continents[index].MoveContainer = NULL;
202 _Continents[index].MoveContainer->setAsStatic(0);
204 nlinfo("Loaded continent, initialized move container to %dx%d cells", gw, gh);
206 if (found != _SheetMap.end())
207 loadPacsPrims((*found).second, _Continents[index].MoveContainer);
212 void CContinentContainer::removeContinent(sint index)
214 nlassert(index >= 0);
216 if (index >= (sint)_Continents.size() ||
217 (_Continents[index].RetrieverBank == NULL &&
218 _Continents[index].GlobalRetriever == NULL &&
219 _Continents[index].MoveContainer == NULL))
221 //nlwarning("Can't remove continent, index %d not used", index);
222 return;
225 nlinfo("Remove continent %d '%s'... Entities shouldn't point any longer to this continent !", index, _Continents[index].Name.c_str());
227 _Continents[index].Name.clear();
229 if (_Continents[index].MoveContainer != NULL)
230 UMoveContainer::deleteMoveContainer(_Continents[index].MoveContainer);
231 _Continents[index].MoveContainer = NULL;
233 if (_Continents[index].GlobalRetriever != NULL)
234 UGlobalRetriever::deleteGlobalRetriever(_Continents[index].GlobalRetriever);
235 _Continents[index].GlobalRetriever = NULL;
237 if (_Continents[index].RetrieverBank != NULL)
238 URetrieverBank::deleteRetrieverBank(_Continents[index].RetrieverBank);
239 _Continents[index].RetrieverBank = NULL;
244 void CContinentContainer::initPacsPrim(const string &path)
246 vector<string> fileNames;
248 if (CFile::fileExists(CPath::lookup(path, false, false)))
250 nlinfo("Peeking into '%s' file for pacs_prim files", path.c_str());
251 CIFile primFile;
252 if (primFile.open(CPath::lookup(path, false, false)))
254 char primbuffer[1024];
255 while (!primFile.eof())
257 primFile.getline(primbuffer, 1024);
258 fileNames.push_back(CPath::lookup(primbuffer, false, false));
261 else
263 nlwarning("Couldn't open file '%s' to load pacs_prims", path.c_str());
266 else if (CFile::isExists(path))
268 nlinfo("Peeking into '%s' directory for pacs_prim files", path.c_str());
269 //CPath::getPathContent(path, true, false, true, fileNames);
270 CPath::addSearchPath(path, true, false);
271 CPath::getFileList("pacs_prim", fileNames);
273 else
275 nlwarning("CContinentContainer: can't initPacsPrim(), path '%s' for pacs primitives not found", path.c_str());
276 return;
279 nlinfo("%d file found at lookup", fileNames.size());
282 uint k;
283 uint numPrims = 0;
284 for(k=0; k<fileNames.size(); ++k)
286 // check extension
287 if (NLMISC::toLowerAscii(CFile::getExtension(fileNames[k])) != "pacs_prim")
289 // not a pacs primitive, skip it..
290 continue;
294 string ppName = NLMISC::toLowerAscii(CFile::getFilenameWithoutExtension(fileNames[k]));
296 if (_PacsPrimMap.find(ppName) != _PacsPrimMap.end())
297 continue;
299 CUniquePtr<UPrimitiveBlock> pb(UPrimitiveBlock::createPrimitiveBlockFromFile(CPath::lookup(fileNames[k], false)));
300 UPrimitiveBlock* ptr = pb.release();
301 if (ptr != NULL)
303 _PacsPrimMap[ppName] = ptr;
304 ++numPrims;
306 else
308 nlwarning("Couldn't load prim block '%s'", fileNames[k].c_str());
311 catch (const NLMISC::EStream &e)
313 nlwarning("Couldn't load Pacs Primitive Block file '%s': %s", fileNames[k].c_str(), e.what());
317 nlinfo("%d primitive blocs initialised", numPrims);
322 void CContinentContainer::loadPacsPrims(const CSheet &sheet, NLPACS::UMoveContainer *moveContainer)
324 vector<string> igs = sheet.ListIG;
326 string igFilename = CPath::lookup(sheet.LandscapeIG, false);
328 if(!igFilename.empty())
330 CIFile igFile;
331 if (igFile.open(igFilename))
333 char igbuffer[1024];
334 while (!igFile.eof())
336 igFile.getline(igbuffer, 1024);
337 if(strlen(igbuffer) > 0)
338 igs.push_back(igbuffer);
341 else
343 nlwarning("Couldn't open file '%s' to instantiate landscape pacs_prims", igFilename.c_str());
346 else
348 nlwarning("Couldn't find file '%s' to instantiate landscape pacs_prims", sheet.LandscapeIG.c_str());
351 nlinfo("Loading igs for continent %s", sheet.Name.c_str());
353 uint numAddedPrimBlocs = 0;
354 uint numFoundIgs = 0;
355 uint i;
356 for (i=0; i<igs.size(); ++i)
358 CLightIGLoader igLoader;
362 igLoader.loadIG(CFile::getFilenameWithoutExtension(igs[i])+".ig");
364 ++numFoundIgs;
366 uint numInstances = igLoader.getNumInstance();
367 for(uint k = 0; k < numInstances; ++k)
369 TPacsPrimMap::iterator pbIt;
371 string shapeName = NLMISC::toLowerAscii(CFile::getFilenameWithoutExtension(igLoader.getShapeName(k)));
372 string instanceName = NLMISC::toLowerAscii(CFile::getFilenameWithoutExtension(igLoader.getInstanceName(k)));
374 bool isTrigger = false;
375 bool isZC = false;
377 if ((pbIt = _PacsPrimMap.find(shapeName)) != _PacsPrimMap.end() ||
378 // nice hardcoded trick that allows graphists to spawn ghost collisions in ZC
379 // when shapename is like 'bat_zc_0?', spaw a pacs prim bloc called gen_bt_col_ext, so nice I just shit my pants
380 (isZC = (testWildCard(shapeName.c_str(), "bat_zc_0?") && shapeName != "bat_zc_00" && (pbIt = _PacsPrimMap.find("gen_bt_col_ext")) != _PacsPrimMap.end())) || // the magic hack
381 (isTrigger = ((pbIt = _PacsPrimMap.find(instanceName)) != _PacsPrimMap.end())))
383 if (_LoadPacsPrims || isTrigger)
385 // compute orientation and position
386 CMatrix instanceMatrix;
387 igLoader.getInstanceMatrix(k, instanceMatrix);
388 CVector pos;
389 float angle;
390 UMoveContainer::getPACSCoordsFromMatrix(pos, angle, instanceMatrix);
391 // insert the matching primitive block
392 vector<UMovePrimitive*> insertedPrimitives;
393 moveContainer->addCollisionnablePrimitiveBlock(pbIt->second, 0, 1, &insertedPrimitives, angle, pos, true);
395 if (isTrigger)
397 uint i;
398 for (i=0; i<insertedPrimitives.size(); ++i)
400 UMovePrimitive *prim = insertedPrimitives[i];
401 uint64 id = prim->UserData;
402 uint triggerId = (uint)((prim->UserData & 0xffff0000) >> 16);
403 _TriggerMap[triggerId] = prim->getFinalPosition(0);
407 ++numAddedPrimBlocs;
412 catch(const Exception &e)
414 nlwarning("Failed to load IG '%s': %s", igs[i].c_str(), e.what());
418 nlinfo("Loaded %d IGs", numFoundIgs);
419 nlinfo("Added %d primitive blocs", numAddedPrimBlocs);