diff --git a/code/nel/include/nel/gui/group_html.h b/code/nel/include/nel/gui/group_html.h
index 479fc7384..2dc5e80bc 100644
--- a/code/nel/include/nel/gui/group_html.h
+++ b/code/nel/include/nel/gui/group_html.h
@@ -820,7 +820,8 @@ namespace NLGUI
struct CDataDownload
{
public:
- CDataDownload(CURL *c, const std::string &u, const std::string &d, FILE *f, TDataType t, CViewBase *i, const std::string &s, const std::string &m, const CStyleParams &style = CStyleParams()) : curl(c), url(u), dest(d), luaScript(s), md5sum(m), type(t), fp(f)
+ CDataDownload(const std::string &u, const std::string &d, TDataType t, CViewBase *i, const std::string &s, const std::string &m, const CStyleParams &style = CStyleParams())
+ : curl(NULL), fp(NULL), url(u), dest(d), type(t), luaScript(s), md5sum(m)
{
if (t == ImgType) imgs.push_back(CDataImageDownload(i, style));
}
@@ -840,6 +841,8 @@ namespace NLGUI
CURLM *MultiCurl;
int RunningCurls;
+ bool startCurlDownload(CDataDownload &download);
+
void initImageDownload();
void checkImageDownload();
void addImageDownload(const std::string &url, CViewBase *img, const CStyleParams &style = CStyleParams());
diff --git a/code/nel/src/gui/group_html.cpp b/code/nel/src/gui/group_html.cpp
index a3cfd514f..418704262 100644
--- a/code/nel/src/gui/group_html.cpp
+++ b/code/nel/src/gui/group_html.cpp
@@ -265,6 +265,61 @@ namespace NLGUI
return dest;
}
+ // Add url to MultiCurl queue and return cURL handle
+ bool CGroupHTML::startCurlDownload(CDataDownload &download)
+ {
+ if (!MultiCurl)
+ {
+ nlwarning("Invalid MultiCurl handle, unable to download '%s'", download.url.c_str());
+ return false;
+ }
+
+ string tmpdest = download.dest + ".tmp";
+
+ // erase the tmp file if exists
+ if (CFile::fileExists(tmpdest))
+ CFile::deleteFile(tmpdest);
+
+ FILE *fp = nlfopen (tmpdest, "wb");
+ if (fp == NULL)
+ {
+ nlwarning("Can't open file '%s' for writing: code=%d '%s'", tmpdest.c_str (), errno, strerror(errno));
+ return false;
+ }
+
+ CURL *curl = curl_easy_init();
+ if (!curl)
+ {
+ fclose(fp);
+ CFile::deleteFile(tmpdest);
+
+ nlwarning("Creating cURL handle failed, unable to download '%s'", download.url.c_str());
+ return false;
+ }
+
+ download.curl = curl;
+ download.fp = fp;
+
+ curl_easy_setopt(curl, CURLOPT_NOPROGRESS, true);
+ curl_easy_setopt(curl, CURLOPT_URL, download.url.c_str());
+
+ // limit curl to HTTP and HTTPS protocols only
+ curl_easy_setopt(curl, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
+ curl_easy_setopt(curl, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
+
+ std::string userAgent = options.appName + "/" + options.appVersion;
+ curl_easy_setopt(curl, CURLOPT_USERAGENT, userAgent.c_str());
+
+ sendCookies(curl, _DocumentDomain, _TrustedDomain);
+
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fwrite);
+
+ curl_multi_add_handle(MultiCurl, curl);
+
+ return true;
+ }
+
// Add a image download request in the multi_curl
void CGroupHTML::addImageDownload(const string &url, CViewBase *img, const CStyleParams &style)
{
@@ -285,55 +340,29 @@ namespace NLGUI
// use requested url for local name
string dest = localImageName(url);
- string tmpdest = localImageName(url)+".tmp";
#ifdef LOG_DL
nlwarning("add to download '%s' dest '%s' img %p", finalUrl.c_str(), dest.c_str(), img);
#endif
- // erase the tmp file if exists
- if (NLMISC::CFile::fileExists(tmpdest))
- NLMISC::CFile::deleteFile(tmpdest);
-
if (!NLMISC::CFile::fileExists(dest))
{
- if (!MultiCurl)
- {
- nlwarning("Invalid MultiCurl handle, unable to download '%s'", finalUrl.c_str());
- return;
- }
+ Curls.push_back(CDataDownload(finalUrl, dest, ImgType, img, "", "", style));
+ if (Curls.size() < options.curlMaxConnections) {
+ if (!startCurlDownload(Curls.back()))
+ {
+ Curls.pop_back();
+ return;
+ }
- CURL *curl = curl_easy_init();
- if (!curl)
- {
- nlwarning("Creating cURL handle failed, unable to download '%s'", finalUrl.c_str());
- return;
- }
-
- FILE *fp = nlfopen(tmpdest, "wb");
- if (fp == NULL)
- {
- curl_easy_cleanup(curl);
-
- nlwarning("Can't open file '%s' for writing: code=%d '%s'", tmpdest.c_str (), errno, strerror(errno));
- return;
- }
- curl_easy_setopt(curl, CURLOPT_NOPROGRESS, true);
- curl_easy_setopt(curl, CURLOPT_URL, finalUrl.c_str());
-
- std::string userAgent = options.appName + "/" + options.appVersion;
- curl_easy_setopt(curl, CURLOPT_USERAGENT, userAgent.c_str());
-
- sendCookies(curl, _DocumentDomain, _TrustedDomain);
-
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fwrite);
-
- curl_multi_add_handle(MultiCurl, curl);
- Curls.push_back(CDataDownload(curl, finalUrl, dest, fp, ImgType, img, "", "", style));
+ RunningCurls++;
#ifdef LOG_DL
- nlwarning("adding handle %x, %d curls", curl, Curls.size());
+ nlwarning("(%s) adding handle %x, %d curls", _Id.c_str(), Curls.back().curl, Curls.size());
+ }
+ else
+ {
+ nlwarning("(%s) download queued, %d curls", _Id.c_str(), Curls.size());
#endif
- RunningCurls++;
+ }
}
else
{
@@ -378,14 +407,9 @@ namespace NLGUI
}
string dest = localBnpName(url);
- string tmpdest = localBnpName(url)+".tmp";
#ifdef LOG_DL
nlwarning("add to download '%s' dest '%s'", url.c_str(), dest.c_str());
#endif
-
- // erase the tmp file if exists
- if (NLMISC::CFile::fileExists(tmpdest))
- NLMISC::CFile::deleteFile(tmpdest);
// create/delete the local file
if (NLMISC::CFile::fileExists(dest))
@@ -402,39 +426,23 @@ namespace NLGUI
}
if (action != "delete")
{
- if (!MultiCurl)
+ Curls.push_back(CDataDownload(url, dest, BnpType, NULL, script, md5sum));
+ if (Curls.size() < options.curlMaxConnections)
{
- nlwarning("Invalid MultiCurl handle, unable to download '%s'", url.c_str());
- return false;
- }
-
- CURL *curl = curl_easy_init();
- if (!curl)
- {
- nlwarning("Creating cURL handle failed, unable to download '%s'", url.c_str());
- return false;
- }
-
- FILE *fp = nlfopen (tmpdest, "wb");
- if (fp == NULL)
- {
- curl_easy_cleanup(curl);
- nlwarning("Can't open file '%s' for writing: code=%d '%s'", tmpdest.c_str (), errno, strerror(errno));
- return false;
- }
-
- curl_easy_setopt(curl, CURLOPT_NOPROGRESS, true);
- curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
-
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fwrite);
-
- curl_multi_add_handle(MultiCurl, curl);
- Curls.push_back(CDataDownload(curl, url, dest, fp, BnpType, NULL, script, md5sum));
+ if (!startCurlDownload(Curls.back()))
+ {
+ Curls.pop_back();
+ return false;
+ }
+ RunningCurls++;
#ifdef LOG_DL
- nlwarning("adding handle %x, %d curls", curl, Curls.size());
+ nlwarning("(%s) adding handle %x, %d curls", _Id.c_str(), Curls.back().curl, Curls.size());
+ }
+ else
+ {
+ nlwarning("(%s) download queued, %d curls", _Id.c_str(), Curls.size());
#endif
- RunningCurls++;
+ }
}
else
return true;
@@ -631,7 +639,30 @@ namespace NLGUI
}
}
}
+
RunningCurls = NewRunningCurls;
+
+ if (RunningCurls < options.curlMaxConnections)
+ {
+ for (vector::iterator it=Curls.begin(); itcurl == NULL) {
+ #ifdef LOG_DL
+ nlwarning("(%s) starting new download '%s'", _Id.c_str(), it->url.c_str());
+ #endif
+ if (!startCurlDownload(*it))
+ {
+ Curls.erase(it);
+ break;
+ }
+
+ RunningCurls++;
+ if (RunningCurls >= options.curlMaxConnections)
+ break;
+ }
+ }
+ }
+
#ifdef LOG_DL
if (RunningCurls > 0 || !Curls.empty())
nlwarning("(%s) RunningCurls %d, _Curls %d", _Id.c_str(), RunningCurls, Curls.size());
@@ -4531,6 +4562,18 @@ namespace NLGUI
Curls[i].imgs.clear();
}
+ // remove download that are still queued
+ for (vector::iterator it=Curls.begin(); itcurl == NULL) {
+ #ifdef LOG_DL
+ nlwarning("Remove waiting curl download (%s)", it->url.c_str());
+ #endif
+ it = Curls.erase(it);
+ } else {
+ ++it;
+ }
+ }
}
// ***************************************************************************
@@ -4985,7 +5028,7 @@ namespace NLGUI
}
#if LOG_DL
- nlwarning("(%s) browse local file '%s'", filename.c_str());
+ nlwarning("browse local file '%s'", filename.c_str());
#endif
_TrustedDomain = true;
diff --git a/code/ryzom/common/src/game_share/time_weather_season/time_and_season.cpp b/code/ryzom/common/src/game_share/time_weather_season/time_and_season.cpp
index a71d71be4..609938f32 100644
--- a/code/ryzom/common/src/game_share/time_weather_season/time_and_season.cpp
+++ b/code/ryzom/common/src/game_share/time_weather_season/time_and_season.cpp
@@ -85,13 +85,16 @@ namespace WEEKDAY
void CRyzomTime::updateRyzomClock(uint32 gameCyle)
{
- static const uint32 ticksPerDay = (RYZOM_DAY_IN_HOUR * RYZOM_HOURS_IN_TICKS);
static const float ticksPerHour = (float)RYZOM_HOURS_IN_TICKS;
uint32 totalTicks = gameCyle + _TickOffset;
- uint32 days = totalTicks / ticksPerDay;
- uint32 dayCycle = totalTicks - (days * ticksPerDay);
- days -= RYZOM_START_SPRING;
+ uint32 days = totalTicks / RYZOM_DAY_IN_TICKS;
+ uint32 dayCycle = totalTicks - (days * RYZOM_DAY_IN_TICKS);
+ // Avoid rollover for low amount of days
+ if(days >= RYZOM_START_SPRING)
+ days -= RYZOM_START_SPRING;
+ else
+ days = 0;
float hours = (float)dayCycle / ticksPerHour;
_RyzomDay = days;
diff --git a/code/ryzom/server/src/entities_game_service/deposit.cpp b/code/ryzom/server/src/entities_game_service/deposit.cpp
index 0fbb7cdfc..6f6f7395e 100644
--- a/code/ryzom/server/src/entities_game_service/deposit.cpp
+++ b/code/ryzom/server/src/entities_game_service/deposit.cpp
@@ -36,6 +36,7 @@
#include "game_share/multi_target.h"
#include "phrase_manager/s_effect.h"
#include "projectile_stats.h"
+#include "primitives_parser.h"
using namespace std;
using namespace NLMISC;
@@ -293,11 +294,10 @@ struct TCompareStaticItemPtrBySheetId : public std::binary_functiongetPropertyByName( "name", name ) ) return malformed( "name", name );
_Name = name;
-
+ // Read alias
+ if(!CPrimitivesParser::getAlias(zone, _Alias))
+ {
+ nlwarning(" Could not find an alias for deposit %s", _Name.c_str());
+ }
// Read exact raw material codes to add
vector *exactRMCodesS = NULL;
if ( ! (zone->getPropertyByName( "exact_mp_item", exactRMCodesS ) && exactRMCodesS) ) return malformed( "exact_mp_item", name );
@@ -469,6 +473,21 @@ bool CDeposit::build( const NLLIGO::CPrimZone* zone )
return true;
}
+CDepositState CDeposit::currentState()
+{
+ CDepositState out;
+ //If we don't have an alias, don't send any information (it's better to be missing information than having wrong information)
+ if(_Alias == 0)
+ return out;
+ // We should never save the state of a spot without quantity constraint, this is just an additional safeguard against it
+ if(!_QuantityConstraintsPt)
+ return out;
+
+ out.alias = _Alias;
+ out.currentQuantity = _QuantityConstraintsPt->getCurrentQuantity();
+ out.nextRespawnDay = _QuantityConstraintsPt->NextRespawnDay;
+ return out;
+}
/*
* Select the raw materials, using the specified filters and _Ecotype
diff --git a/code/ryzom/server/src/entities_game_service/deposit.h b/code/ryzom/server/src/entities_game_service/deposit.h
index fee33662a..24ca5830d 100644
--- a/code/ryzom/server/src/entities_game_service/deposit.h
+++ b/code/ryzom/server/src/entities_game_service/deposit.h
@@ -195,6 +195,29 @@ namespace NLMISC
class CWordsDictionary;
}
+struct CDepositState {
+ uint32 alias;
+ float currentQuantity;
+ uint32 nextRespawnDay;
+ CDepositState() : alias(0), currentQuantity(0.f), nextRespawnDay(0) {}
+ void serial(NLMISC::IStream &f) throw(NLMISC::EStream)
+ {
+ if(f.isXML())
+ {
+ f.xmlSerial(alias, "ALIAS");
+ f.xmlSerial(currentQuantity, "CURRENT_QUANTITY");
+ f.xmlSerial(nextRespawnDay, "NEXT_RESPAWN_DAY");
+ }
+ else
+ {
+ f.serial(alias);
+ f.serial(currentQuantity);
+ f.serial(nextRespawnDay);
+ }
+ }
+};
+
+
/**
* \author Nicolas Brigand, Alain Saffray, Olivier Cado
* \author Nevrax France
@@ -205,7 +228,7 @@ class CDeposit : public NLLIGO::CPrimZone, public NLMISC::CRefCount
public:
/// Constructor
- CDeposit() : _AutoSpawnSourcePt(NULL), _QuantityConstraintsPt(NULL), _Ecotype(ECOSYSTEM::common_ecosystem), _FilterPhase(0), _KamiAnger(0.0f), _MinQuality(-1), _MaxQuality(-1), _SourceFXIndex(0), _CanProspect(false), _Enabled(false), _CurrentNbAutoSpawnedSources(0), _AllowDepletionRisk(true) {}
+ CDeposit() : _AutoSpawnSourcePt(NULL), _QuantityConstraintsPt(NULL), _Ecotype(ECOSYSTEM::common_ecosystem), _FilterPhase(0), _KamiAnger(0.0f), _MinQuality(-1), _MaxQuality(-1), _SourceFXIndex(0), _CanProspect(false), _Enabled(false), _CurrentNbAutoSpawnedSources(0), _AllowDepletionRisk(true), _Alias(0) {}
/// Destructor
~CDeposit();
@@ -214,7 +237,7 @@ public:
static void addEcotype( CEcotypeZone *ecotypeZone ) { _EcotypeZones.push_back( ecotypeZone ); }
/// Init deposit
- bool build( const NLLIGO::CPrimZone* zone );
+ bool build(const NLLIGO::CPrimZone* zone );
/// Clear all ecotype information, after having built the deposits
static void clearEcotypes();
@@ -319,7 +342,7 @@ public:
float getMaxQuantity() { return _QuantityConstraintsPt ? _QuantityConstraintsPt->getCurrentQuantity() : FLT_MAX; }
/// Consume. Return the actual consumed quantity (may be lower if there is no more to get)
- float consumeQuantity( float requested ) { if ( _QuantityConstraintsPt ) return _QuantityConstraintsPt->consumeQuantity( requested ); else return requested; }
+ float consumeQuantity( float requested ) { if ( _QuantityConstraintsPt )return _QuantityConstraintsPt->consumeQuantity( requested ); else return requested; }
/**
* Get a random RM from the neighbourhood of the specified position.
@@ -346,6 +369,13 @@ public:
// For auto-spawn source minimum number. Internaly used by CHarvestSource only
void decreaseAutoSpawnedSources();
void increaseAutoSpawnedSources();
+ /// Used to save the deposit
+ bool needSave() const { return _QuantityConstraintsPt && (_QuantityConstraintsPt->CurrentQuantity != _QuantityConstraintsPt->InitialQuantity || _QuantityConstraintsPt->NextRespawnDay != 0); }
+ CDepositState currentState();
+ uint32 getAlias() const { return _Alias;}
+ void setCurrentQuantity(uint32 currentQuantity) { _QuantityConstraintsPt->CurrentQuantity = currentQuantity; }
+ void setNextRespawnDay(uint32 nextRespawnDay) { _QuantityConstraintsPt->NextRespawnDay = nextRespawnDay; }
+
protected:
@@ -429,6 +459,9 @@ private:
/// Current Number of AutoSpawned Sources in this deposit
uint32 _CurrentNbAutoSpawnedSources;
+
+ /// CPrimAlias, needed to identify a deposit to restore its state between shutdown of the EGS
+ uint32 _Alias;
};
diff --git a/code/ryzom/server/src/entities_game_service/egs_variables.cpp b/code/ryzom/server/src/entities_game_service/egs_variables.cpp
index a96452aca..1891025c9 100644
--- a/code/ryzom/server/src/entities_game_service/egs_variables.cpp
+++ b/code/ryzom/server/src/entities_game_service/egs_variables.cpp
@@ -329,6 +329,10 @@ CVariable DodgeFactorForForageSkills("egs","DodgeFactorForForageSkills"
CVariable ForageExtractionTimeMinGC( "egs", "ForageExtractionTimeMinGC", "Minimum time of extraction in ticks", 230.0f, 0, true );
CVariable ForageExtractionTimeSlopeGC( "egs", "ForageExtractionTimeSlopeGC", "Slope of base extraction time curve", 2.0f, 0, true );
+CVariable RefillDepositOnStartup("egs", "RefillDepositOnStartup", "Ignore saved CurrentQuantity / NextRespawnDay in deposits", false, 0, true);
+CVariable DepositSaveInterval("egs", "DepositSaveInterval", "time *in tick* between two saves of a deposit", 10 * 60 * 10, 0, true);
+CVariable DepositStateUseXml("egs", "DepositStateUseXml", "Use xml instead of binary file to save deposit state", true, 0, true);
+
CVariable ForageQuantityBaseRate( "egs", "ForageQuantityBaseRate", "Base of extraction rate", 0.23f, 0, true ); // 0.23 doubles the previous minimum setting
diff --git a/code/ryzom/server/src/entities_game_service/egs_variables.h b/code/ryzom/server/src/entities_game_service/egs_variables.h
index 661564987..1b2b39d95 100644
--- a/code/ryzom/server/src/entities_game_service/egs_variables.h
+++ b/code/ryzom/server/src/entities_game_service/egs_variables.h
@@ -280,6 +280,9 @@ extern NLMISC::CVariable ForageQuantityXPDeltaLevelBonusRate;
extern NLMISC::CVariable ForageExtractionTimeMinGC;
extern NLMISC::CVariable ForageExtractionTimeSlopeGC;
+extern NLMISC::CVariable RefillDepositOnStartup;
+extern NLMISC::CVariable DepositSaveInterval;
+extern NLMISC::CVariable DepositStateUseXml;
// QUARTERING
extern NLMISC::CVariable QuarteringQuantityAverageForCraftHerbivore;
diff --git a/code/ryzom/server/src/entities_game_service/zone_manager.cpp b/code/ryzom/server/src/entities_game_service/zone_manager.cpp
index 400a00586..de2ede76d 100644
--- a/code/ryzom/server/src/entities_game_service/zone_manager.cpp
+++ b/code/ryzom/server/src/entities_game_service/zone_manager.cpp
@@ -530,8 +530,9 @@ void CZoneManager::release()
void CZoneManager::initInstance()
{
_NextDepositIndexUpdated = 0;
+ _NextDepositSave = CTickEventHandler::getGameCycle() + DepositSaveInterval;
_SpreadUpdateLoopBeginTick = CTickEventHandler::getGameCycle();
-
+
// get the loaded primitives
const CPrimitivesParser::TPrimitivesList & primsList = CPrimitivesParser::getInstance().getPrimitives();
@@ -589,6 +590,8 @@ void CZoneManager::initInstance()
nlwarning(" Error while building the zones");
}
}
+ // Ask Bsi for saved deposit states
+ Bsi.requestFile(DepositStateFileName, new CDepositCallback());
// Don't keep ecotypes in memory, the information is already in the deposits
CDeposit::clearEcotypes();
@@ -1417,6 +1420,59 @@ bool CZoneManager::parsePVPSafeZones( const NLLIGO::IPrimitive * prim )
return result;
} // CZoneManager parsePVPSafeZones
+//-----------------------------------------------
+// CZoneManager receivedDepositState
+//-----------------------------------------------
+void CZoneManager::receivedDepositState(const CFileDescription& fileDescription, NLMISC::IStream& dataStream)
+{
+ if(fileDescription.FileName.empty())
+ {
+ nlwarning("Got no deposit state file from backup service, probably because no deposit need to be saved");
+ return;
+ }
+ NLMISC::CMemStream& memStream = dynamic_cast(dataStream);
+ if (&memStream != NULL)
+ {
+ try
+ {
+ std::vector states;
+ if(DepositStateUseXml)
+ {
+ CIXml xml;
+ xml.init(memStream);
+ xml.serialCont(states);
+ }
+ else
+ {
+ memStream.serialCont(states);
+ }
+ nldebug("Got %d CDepositState from backup service", states.size());
+ //If we don't want to use state, stop here
+ if(RefillDepositOnStartup) return;
+ for(int i=0; i < states.size(); i++)
+ {
+ //Find the matching deposit
+ for(int j = 0 ; j < _Deposits.size(); j++)
+ {
+ CDeposit* dep = _Deposits[j];
+ if(dep->getAlias() == states[i].alias)
+ {
+ dep->setCurrentQuantity(states[i].currentQuantity);
+ dep->setNextRespawnDay(states[i].nextRespawnDay);
+ }
+ }
+ nldebug("CDepositState for alias %d : currentQuantity=%f, nextRespawn=%d", states[i].alias, states[i].currentQuantity, states[i].nextRespawnDay);
+ }
+
+ }
+ catch (const Exception& e)
+ {
+ nlwarning("Could not parse deposit state file, reason : %s", e.what());
+ }
+ }
+}// CZoneManager receivedDepositState
+
+
//-----------------------------------------------
// CZoneManager getContinent
//-----------------------------------------------
@@ -2021,9 +2077,63 @@ void CZoneManager::tickUpdate()
_DepositNeedingAutoSpawnUpdate.erase(itDeposit);
itDeposit= itNext;
}
+ // Save the deposits
+ if(_NextDepositSave < CTickEventHandler::getGameCycle())
+ {
+ _NextDepositSave = CTickEventHandler::getGameCycle() + DepositSaveInterval;
+ saveDeposits();
+ }
}// CZoneManager tickUpdate
+
+//-----------------------------------------------
+// CZoneManager saveDeposits
+//-----------------------------------------------
+void CZoneManager::saveDeposits()
+{
+ std::vector toSave;
+ for(int i=0; i < _Deposits.size(); i++)
+ {
+ if (!_Deposits[i]->needSave()) continue;
+ CDepositState tmp = _Deposits[i]->currentState();
+ //Don't save if for some reason we couldn't get an alias for the deposit
+ if(tmp.alias == 0) continue;
+ toSave.push_back(tmp);
+ }
+ // No need to save if we have 0 states
+ if(toSave.size() == 0) return;
+ CMemStream stream;
+ try
+ {
+ if(DepositStateUseXml)
+ {
+ COXml output;
+ if (!output.init(&stream))
+ {
+ nlwarning(" cannot init XML output for file %s", DepositStateFileName.c_str());
+ return;
+ }
+ output.serialCont(toSave);
+ output.flush();
+ }
+ else
+ {
+ stream.serialCont(toSave);
+ }
+ }
+ catch (const Exception & e)
+ {
+ nlwarning(" cannot save file %s : %s", DepositStateFileName.c_str(), e.what());
+ }
+
+ nldebug(": sending %d states to BIS (total of %d deposits available).", toSave.size(), _Deposits.size());
+ CBackupMsgSaveFile msg( DepositStateFileName, CBackupMsgSaveFile::SaveFile, Bsi );
+ msg.DataMsg.serialBuffer((uint8*)stream.buffer(), stream.length());
+ Bsi.sendFile( msg );
+
+}// CZoneManager saveDeposits
+
//-----------------------------------------------
// CZoneManager dumpWorld
//-----------------------------------------------
diff --git a/code/ryzom/server/src/entities_game_service/zone_manager.h b/code/ryzom/server/src/entities_game_service/zone_manager.h
index 8390f2387..4134e0cb7 100644
--- a/code/ryzom/server/src/entities_game_service/zone_manager.h
+++ b/code/ryzom/server/src/entities_game_service/zone_manager.h
@@ -31,6 +31,7 @@
#include "game_share/string_manager_sender.h"
#include "mission_manager/ai_alias_translator.h"
#include "deposit.h"
+#include "game_share/backup_service_interface.h"
class CCharacter;
extern NLMISC::CRandom RandomGenerator;
@@ -39,6 +40,7 @@ static const uint16 InvalidSpawnZoneId = 0xFFFF;
static const uint16 InvalidPlaceId = 0xFFFF;
+static const std::string DepositStateFileName = "deposits_state";
/**
* A teleport destination zone
* \author Nicolas Brigand
@@ -539,6 +541,11 @@ public:
*/
void clearEcotypes();
+ // Save deposit to primitive file, if needed
+ void saveDeposits();
+ /// Callback for deposit state
+ void receivedDepositState(CFileDescription const &fileDescription, NLMISC::IStream &dataStream);
+
private:
/**
@@ -640,6 +647,24 @@ private:
/// The ecotype zones
static CEcotypeZones _EcotypeZones;
+
+ /// Next cycle where we'll save deposits
+ NLMISC::TGameCycle _NextDepositSave;
+};
+
+class CDepositCallback : public IBackupFileReceiveCallback
+{
+public:
+ CDepositCallback() : processed(false) {}
+ bool processed;
+ void callback(const CFileDescription& fileDescription, NLMISC::IStream& dataStream)
+ {
+ if (!processed)
+ {
+ CZoneManager::getInstance().receivedDepositState(fileDescription, dataStream);
+ processed = true;
+ }
+ }
};