// Ryzom - MMORPG Framework // Copyright (C) 2010 Winch Gate Property Limited // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . #include "stdpch.h" #include #include #include "client_edition_module.h" #include "dmc.h" #include "../../interface_v3/interface_manager.h" #include "nel/net/unified_network.h" #include "nel/net/module_message.h" #include "nel/net/module_socket.h" #include "nel/net/module_builder_parts.h" #include "nel/net/module_manager.h" #include "nel/misc/command.h" #include "nel/misc/path.h" #include "nel/misc/types_nl.h" #include "nel/misc/sstring.h" #include "nel/ligo/primitive.h" #include "nel/ligo/ligo_config.h" #include "nel/ligo/primitive_utils.h" #include "game_share/utils.h" #include "game_share/object.h" #include "game_share/scenario.h" #include "game_share/r2_messages.h" #include "game_share/ring_access.h" #include "property_accessor.h" #include "palette.h" #include "../object_factory_client.h" #include "com_lua_module.h" #include "../../session_browser_impl.h" #include "../../client_cfg.h" #include "../../user_entity.h" #include "../../view.h" #include "../../init_main_loop.h" #include "../../continent_manager.h" #include "../../world_database_manager.h" #include "../../far_tp.h" #include "../../net_manager.h" #include using namespace std; using namespace NLMISC; using namespace NLLIGO; using namespace NLNET; CVariable UserComponentsExamplesDirectory ("DSS", "UserComponentsExampleDirectory", "", "examples/user_componts", 0, true ); CVariable UserComponentsComponentsDirectory ("DSS", "UserComponentsComponentsDirectory", "", "examples/user_componts", 0, true ); CVariable UserComponentsComponentExtension ("DSS", "UserComponentsComponentExtension", "", "gz", 0, true ); CVariable UserComponentsSourceExtension ("DSS", "UserComponentsSourceExtension", "", "lua", 0, true ); namespace R2 { // if client request an operation, and the server accept then the client do not need to received the same msg he send // other client must receive the answer class IServerAnswerMsg; class CServerAnswerForseener { public: typedef uint32 TMessageId ; public: CServerAnswerForseener():_MaxMessageId(0){} ~CServerAnswerForseener(); // if ok == true, then simulate the replay that The Server would do for other client // if ok == false, remove the Forseen Answer from the answer queue. void ack(CClientEditionModule* client, NLNET::IModuleProxy *server, TMessageId msgId, bool ok ); // Add to the Forssen Answer queue (we do not take the ownership of value) TMessageId onScenarioUploaded( const CObject* hlScenario) ; TMessageId onNodeSet(const std::string &instanceId, const std::string &attrName, const R2::CObject *value); TMessageId onNodeInserted(const std::string &instanceId, const std::string &attrName, sint32 position, const std::string &key, const R2::CObject *value); TMessageId onNodeErased(const std::string &instanceId, const std::string &attrName, sint32 position); TMessageId onNodeMoved(const std::string &instanceId1, const std::string &attrName1, sint32 position1, const std::string &instanceId2, const std::string &attrName2, sint32 position2); private: typedef std::map TAnswers; private: uint32 _MaxMessageId; TAnswers _Answers; }; class IServerAnswerMsg { public: virtual void ok(CClientEditionModule* client, NLNET::IModuleProxy *server) = 0; virtual ~IServerAnswerMsg() {} }; class CServerAnswerMsgScenarioUploaded: public IServerAnswerMsg { public: CServerAnswerMsgScenarioUploaded( const R2::CObject* value) :_Value( value?value->clone():0){} void ok(CClientEditionModule* client, NLNET::IModuleProxy *server) { client->onScenarioUploaded(server, _Value.get()); } private: std::auto_ptr _Value; }; class CServerAnswerMsgSet: public IServerAnswerMsg { public: CServerAnswerMsgSet(const std::string &instanceId, const std::string &attrName, const R2::CObject* value) :_InstanceId(instanceId), _AttrName(attrName), _Value( value?value->clone():0){} void ok(CClientEditionModule* client, NLNET::IModuleProxy *server) { client->onNodeSet(server, _InstanceId, _AttrName, _Value.get()); } private: std::string _InstanceId; std::string _AttrName; std::auto_ptr _Value; }; class CServerAnswerMsgInserted: public IServerAnswerMsg { public: CServerAnswerMsgInserted(const std::string &instanceId, const std::string &attrName, sint32 position, const std::string &key, const R2::CObject* value) :_InstanceId(instanceId), _AttrName(attrName), _Position(position), _Key(key), _Value( value?value->clone():0){} void ok(CClientEditionModule* client, NLNET::IModuleProxy *server) { client->onNodeInserted(server, _InstanceId, _AttrName, _Position, _Key, _Value.get()); } private: std::string _InstanceId; std::string _AttrName; sint32 _Position; std::string _Key; std::auto_ptr _Value; }; class CServerAnswerMsgErased: public IServerAnswerMsg { public: CServerAnswerMsgErased(const std::string &instanceId, const std::string &attrName, sint32 position) :_InstanceId(instanceId), _AttrName(attrName), _Position(position){} void ok(CClientEditionModule* client, NLNET::IModuleProxy *server) { client->onNodeErased(server, _InstanceId, _AttrName, _Position); } private: std::string _InstanceId; std::string _AttrName; sint32 _Position; }; class CServerAnswerMsgMoved : public IServerAnswerMsg { public: CServerAnswerMsgMoved(const std::string &instanceId1, const std::string &attrName1, sint32 position1, const std::string &instanceId2, const std::string &attrName2, sint32 position2) :_InstanceId1(instanceId1), _AttrName1(attrName1), _Position1(position1), _InstanceId2(instanceId2), _AttrName2(attrName2), _Position2(position2){} void ok(CClientEditionModule* client, NLNET::IModuleProxy *server) { client->onNodeMoved(server, _InstanceId1, _AttrName1, _Position1, _InstanceId2, _AttrName2, _Position2); } private: std::string _InstanceId1; std::string _AttrName1; sint32 _Position1; std::string _InstanceId2; std::string _AttrName2; sint32 _Position2; }; } using namespace R2; NLNET_REGISTER_MODULE_FACTORY(CClientEditionModule, "ClientEditionModule"); //----------------------------- ------------------------------- CServerAnswerForseener::~CServerAnswerForseener() { TAnswers::iterator first(_Answers.begin()), last(_Answers.end()); for (; first != last; ++first) { IServerAnswerMsg* msg = first->second; delete msg; } _Answers.clear(); } void CServerAnswerForseener::ack(CClientEditionModule* client, NLNET::IModuleProxy *server, TMessageId msgId, bool ok) { TAnswers::iterator found = _Answers.find(msgId); BOMB_IF( found == _Answers.end(), "Message not found", return); IServerAnswerMsg* msg = found->second; if (ok) { msg->ok(client, server); } delete msg; _Answers.erase(found); } // Add to the Forseen Answer queue CServerAnswerForseener::TMessageId CServerAnswerForseener::onScenarioUploaded( const R2::CObject* hlScenario) { bool ok = _Answers.insert( std::make_pair(++_MaxMessageId, new CServerAnswerMsgScenarioUploaded(hlScenario))).second; nlassert(ok); return _MaxMessageId; } CServerAnswerForseener::TMessageId CServerAnswerForseener::onNodeSet(const std::string &instanceId, const std::string &attrName, const R2::CObject* value) { bool ok = _Answers.insert(std::make_pair(++_MaxMessageId, new CServerAnswerMsgSet(instanceId, attrName, value))).second; nlassert(ok); return _MaxMessageId; } CServerAnswerForseener::TMessageId CServerAnswerForseener::onNodeInserted(const std::string &instanceId, const std::string &attrName, sint32 position, const std::string &key, const R2::CObject* value) { bool ok = _Answers.insert(std::make_pair(++_MaxMessageId, new CServerAnswerMsgInserted(instanceId, attrName, position, key, value))).second; nlassert(ok); return _MaxMessageId; } CServerAnswerForseener::TMessageId CServerAnswerForseener::onNodeErased(const std::string &instanceId, const std::string &attrName, sint32 position) { bool ok = _Answers.insert(std::make_pair(++_MaxMessageId, new CServerAnswerMsgErased(instanceId, attrName, position ))).second; nlassert(ok); return _MaxMessageId; } CServerAnswerForseener::TMessageId CServerAnswerForseener::onNodeMoved(const std::string &instanceId1, const std::string &attrName1, sint32 position1, const std::string &instanceId2, const std::string &attrName2, sint32 position2) { bool ok = _Answers.insert(std::make_pair(++_MaxMessageId, new CServerAnswerMsgMoved(instanceId1, attrName1, position1, instanceId2, attrName2, position2 ))).second; nlassert(ok); return _MaxMessageId; } //------------------------------- ------------------------------------------- std::map CEditorConfig::_NameToId; CEditorConfig::CEditorConfig() { if (_NameToId.empty()) { _NameToId["BossSpawner"] = 0; _NameToId["Timer"] = 1; _NameToId["ZoneTrigger"] = 2; _NameToId["UserTrigger"] = 3; _NameToId["TalkTo"] = 4; _NameToId["RequestItem"] = 5; _NameToId["GiveItem"] = 6; _NameToId["EasterEgg"] = 7; _NameToId["LootSpawner"] = 8; _NameToId["Fauna"] = 9; _NameToId["BanditCamp"] = 10; _NameToId["ChatSequence"] = 11; _NameToId["TimedSpawner"] = 12; _NameToId["Ambush"] = 13; _NameToId["ManHunt"] = 14; _NameToId["VisitZone"] = 15; _NameToId["KillNpc"] = 16; _NameToId["HuntTask"] = 17; _NameToId["DeliveryTask"] = 18; _NameToId["TargetMob"] = 19; _NameToId["HiddenChest"] = 20; _NameToId["RandomChest"] = 21; _NameToId["UserComponent"] = 22; _NameToId["Npc"] = 23; _NameToId["GetItemFromSceneryObjectTaskStep"] = 24; _NameToId["GetItemFromSceneryObject"] = 25; _NameToId["SceneryObjectInteractionTaskStep"] = 26; _NameToId["SceneryObjectInteraction"] = 27; _NameToId["SceneryObjectRemover"] = 28; _NameToId["RewardProvider"] = 29; _NameToId["NpcInteraction"] = 30; _NameToId["Quest"] = 31; _NameToId["ProximityDialog"] = 32; } } void CEditorConfig::setDisplayInfo(const std::string& formName, bool displayInfo) { //H_AUTO(R2_CEditorConfig_setDisplayInfo) CInterfaceManager *IM = CInterfaceManager::getInstance (); uint32 index = _NameToId[formName]; uint32 newValue = static_cast(NLGUI::CDBManager::getInstance()->getDbProp("UI:SAVE:R2:DISPLAYINFO")->getValue32()); if (displayInfo == false ) newValue &= ~(1 << index); else newValue |= (1 << index); NLGUI::CDBManager::getInstance()->getDbProp("UI:SAVE:R2:DISPLAYINFO")->setValue32(static_cast(newValue)); } void CEditorConfig::setDisplayInfo(uint32 displayInfo) { //H_AUTO(R2_CEditorConfig_setDisplayInfo) CInterfaceManager *IM = CInterfaceManager::getInstance (); NLGUI::CDBManager::getInstance()->getDbProp("UI:SAVE:R2:DISPLAYINFO")->setValue32(static_cast(displayInfo)); } bool CEditorConfig::mustDisplayInfo(const std::string& formName) const { //H_AUTO(R2_CEditorConfig_mustDisplayInfo) CInterfaceManager *IM = CInterfaceManager::getInstance (); std::map::const_iterator found = _NameToId.find(formName); if (found == _NameToId.end()) return false; uint32 index = (*found).second; uint32 newValue = static_cast(NLGUI::CDBManager::getInstance()->getDbProp("UI:SAVE:R2:DISPLAYINFO")->getValue32()); uint32 ok = (newValue >> index) & 0x00000001; if (ok != 0) return true; return false; } bool CEditorConfig::hasDisplayInfo(const std::string& formName) const { //H_AUTO(R2_CEditorConfig_hasDisplayInfo) std::map::const_iterator found = _NameToId.find(formName); if (found != _NameToId.end()) return true; return false; } uint32 CEditorConfig::getDisplayInfo() const { //H_AUTO(R2_CEditorConfig_getDisplayInfo) CInterfaceManager *IM = CInterfaceManager::getInstance (); return static_cast(NLGUI::CDBManager::getInstance()->getDbProp("UI:SAVE:R2:DISPLAYINFO")->getValue32()); } //----------------------------------------------------------------------------------------- CClientEditionModule::CClientEditionModule() { CShareClientEditionItfSkel::init(this); _Initialized = false; _ChannelId = TChanID::Unknown; _Mute = false; _ServerAnswerForseener = 0; } CClientEditionModule::~CClientEditionModule() { release(); } void CClientEditionModule::init(NLNET::IModuleSocket* clientGw, CDynamicMapClient* client) { //H_AUTO(R2_CClientEditionModule_init) _Client = client; // _ClientGw = clientGw; _Eid = "Client0"; _TranslationModule = 0; _SessionId = TSessionId(0); init(); this->plugModule(clientGw); } void CClientEditionModule::init() { //H_AUTO(R2_CClientEditionModule_init) if( _Initialized ) return; _Emotes.reset( new CEmoteBehavior() ); _Palette = new CPalette(); _Scenario = new CScenario(0); _Factory = new CObjectFactoryClient(_Eid); _PropertyAccessor = new CPropertyAccessor(_Client, _Factory); // CObjectSerializer::Factory = _Factory; CObjectSerializerClient::setClientObjectFactory(_Factory); _Initialized = true; _MaxNpcs = 100; _MaxStaticObjects = 100; _ClientEditorConfig = new CEditorConfig(); _MustStartScenario = false; _ScenarioUpToDate = false; _IsSessionOwner = false; _ServerAnswerForseener = new CServerAnswerForseener(); } // when server is launched locally, it shouldn't use the client factory, // this class disable when local server is called //class CSerialFactoryBackup //{ //public: // CSerialFactoryBackup(CObjectFactory *newValue = NULL) : ClientFactory(CObjectSerializer::Factory) // { // CObjectSerializer::Factory = newValue; // } // ~CSerialFactoryBackup() // { // CObjectSerializer::Factory = ClientFactory; // } // CObjectFactory *ClientFactory; //}; // void CClientEditionModule::release() { //H_AUTO(R2_CClientEditionModule_release) delete _ServerAnswerForseener; _ServerAnswerForseener = 0; delete _Palette; _Palette = 0; delete _Scenario; _Scenario = 0; delete _Factory; _Factory = 0; delete _PropertyAccessor; _PropertyAccessor = 0; _Initialized = false; _Emotes.reset(); } void CClientEditionModule::onModuleUp(NLNET::IModuleProxy *moduleProxy) { //H_AUTO(R2_CClientEditionModule_onModuleUp) std::string moduleClassName = moduleProxy->getModuleClassName(); if (moduleClassName == "ServerEditionModule") { _ServerEditionProxy = moduleProxy; return; } if (moduleClassName == "ServerAnimationModule") { _ServerAnimationProxy = moduleProxy; return; } } void CClientEditionModule::onModuleDown(NLNET::IModuleProxy *moduleProxy) { //H_AUTO(R2_CClientEditionModule_onModuleDown) std::string moduleClassName = moduleProxy->getModuleClassName(); if (moduleClassName == "ServerEditionModule") { _ServerEditionProxy = NULL; } else if ( moduleClassName == "ServerAnimationModule") { _ServerAnimationProxy = NULL; } else return; } bool CClientEditionModule::onProcessModuleMessage(IModuleProxy *senderModuleProxy, const CMessage &message) { //H_AUTO(R2_CClientEditionModule_onProcessModuleMessage) // CSerialFactoryBackup fb(_Factory); // restore client factory the time to process server msg ... // // if (CShareClientEditionItfSkel::onDispatchMessage(senderModuleProxy, message)) // { // return; // } // // // std::string operationName = message.getName(); if (operationName == "CUCD") //onUserComponentDownloaded { CUserComponent* component = new CUserComponent(); //message.serial(const_cast(*component)); component->serial( const_cast(message)); onUserComponentDownloaded(senderModuleProxy, component); return true; } if (operationName == "HELLO") { // this is just the firewall opening message, nothing to do return true; } if (operationName == "ADV_CONN") { CEditor::connexionMsg(""); CClientMessageAdventureUserConnection bodyConnection; nlRead(message,serial,bodyConnection); onRingAccessUpdated(0, bodyConnection.RingAccess); nlinfo("R2CED: user Connected as Client %d In Mode %d", bodyConnection.EditSlotId, bodyConnection.Mode); _SessionId = bodyConnection.SessionId; _AiInstanceId = bodyConnection.AiInstance; _SessionType = bodyConnection.SessionType; _IsSessionOwner = bodyConnection.IsSessionOwner; _EditSessionLink = bodyConnection.EditSessionLink; switch(bodyConnection.SessionType) { case st_edit: getEditor().setAccessMode(CEditor::AccessEditor); break; case st_anim: getEditor().setAccessMode(CEditor::AccessDM); break; default: nlassert(0 && "SessionType not handled."); } if (bodyConnection.SessionType == st_edit) { if (bodyConnection.Mode == 1) { _Client->onResetEditionMode(); } CObject* data = bodyConnection.HighLevel.getData(); if (!data && bodyConnection.InCache) { CScenarioValidator sv; CScenarioValidator::TValues values; std::string md5, signature; if ( sv.setScenarioToLoad("save/r2_buffer.dat", values, md5, signature, true) && !md5.empty() && CScenarioValidator::AutoSaveSignature == signature) { data = _Client->getComLuaModule().loadLocal("save/r2_buffer.dat", values); } else { nlinfo("Data corrupted (the server has refused to accept the scenario)."); } } _Client->onEditionModeConnected(bodyConnection.EditSlotId, bodyConnection.SessionId.asInt(), data, bodyConnection.VersionName, bodyConnection.MustTp, bodyConnection.InitialActIndex); if (bodyConnection.Mode == 2) { _Client->onEditionModeDisconnected(); _Client->onTestModeConnected(); } // warn server that adventure has been connected, so we are ready to receive the TP message CShareServerEditionItfProxy proxy(_ServerEditionProxy); proxy.advConnACK(this); } else if (bodyConnection.SessionType == st_anim) { // 0 -> wait loading animation // 1 -> waiting the other to load animation // 2 -> play (dm) // 3 -> play (simple player) _Client->onAnimationModeConnected(bodyConnection); // warn server that advneutre has been connected, so we are ready to receive the TP message } return true; } if (operationName == "EDITOR_STOP") { _Client->onEditionModeDisconnected(); _Client->onTestModeConnected(); return true; } if ( operationName=="stringTable") { nlwarning("received string table!"); uint32 nb,i; nlRead(message, serial, nb); i=nb; nlwarning("%d entries! ",nb); while(i) { std::string localId; std::string value; nlRead(message, serial,localId); nlRead(message,serial,value); nlwarning("{ %s , %s}",localId.c_str(),value.c_str()); i--; } return true; } if(operationName == "stringValue") { std::string localId; std::string value; nlRead(message,serial,localId); nlRead(message,serial,value); nlwarning("received {%s , %s}",localId.c_str(),value.c_str()); return true; } if (operationName == "idList") { uint32 nb,i; nlRead(message,serial,nb); i=nb; nlwarning("%d entries! ",nb); while(i) { std::string localId; nlRead(message,serial,localId); nlwarning("{ %s }",localId.c_str()); i--; } return true; } if (operationName == "HELLO") { // this is just the firewall opening message, nothing to do return true; } if (operationName == "NPC_APROP") { uint32 modes; nlRead(message,serial,modes); _Client->onNpcAnimationTargeted(modes); return true; } return false; } void CClientEditionModule::onTestModeDisconnected(NLNET::IModuleProxy * /* moduleProxy */, TSessionId sessionId, uint32 lastAct, TScenarioSessionType sessionType) { //H_AUTO(R2_CClientEditionModule_onTestModeDisconnected) // indicate the Editor that the animation has stopped. _Client->onTestModeDisconnected(sessionId, lastAct, sessionType); if ( sessionType == st_edit ) { this->requestReconnection(); } } void CClientEditionModule::onModuleSecurityChange(IModuleProxy * /* moduleProxy */) { //H_AUTO(R2_CClientEditionModule_onModuleSecurityChange) } void CClientEditionModule::requestCreateScenario(CObject* scenario) { //H_AUTO(R2_CClientEditionModule_requestCreateScenario) this->requestUploadScenario(scenario); } bool CClientEditionModule::requestTeleportOneCharacterToAnother(uint32 sessionId, uint32 sourceCharId, uint32 destCharId) { //H_AUTO(R2_CClientEditionModule_requestTeleportOneCharacterToAnother) BOMB_IF(_ServerEditionProxy == NULL, "Server Edition Module not connected", return false); CShareServerEditionItfProxy proxy(_ServerEditionProxy); proxy.teleportOneCharacterToAnother(this, (TSessionId)sessionId, sourceCharId, destCharId); return true; } void CClientEditionModule::requestUpdateRtScenario( CObject* scenario) { //H_AUTO(R2_CClientEditionModule_requestUpdateRtScenario) // CSerialFactoryBackup fb; CMessage message ("requestUpdateRtScenario"); BOMB_IF(_ServerEditionProxy == NULL, "Server Edition Module not connected", return); CObjectSerializerServer obj(scenario); obj.compress(); message.serial(obj); _ServerEditionProxy->sendModuleMessage(this, message ); } void CClientEditionModule::requestCreatePrimitives() { //H_AUTO(R2_CClientEditionModule_requestCreatePrimitives) CMessage message ("DBG_CREATE_PRIMITIVES"); BOMB_IF(_ServerEditionProxy == NULL, "Server Edition Module not connected", return); _ServerEditionProxy->sendModuleMessage(this, message ); } void CClientEditionModule::requestStopTest() { //H_AUTO(R2_CClientEditionModule_requestStopTest) CMessage message ("STOP_TEST"); BOMB_IF(_ServerEditionProxy == NULL, "Server Edition Module not connected", return); _ServerEditionProxy->sendModuleMessage(this, message ); } bool CClientEditionModule::requestUploadScenario(CObject* scenario) { //H_AUTO(R2_CClientEditionModule_requestUploadScenario) // CSerialFactoryBackup fb; BOMB_IF(_ServerEditionProxy == NULL, "Server Edition Module not connected", return false); CShareServerEditionItfProxy proxy(_ServerEditionProxy); CObjectSerializerServer body(scenario); body.compress(); /* proxy.onScenarioUploadAsked(this, body, true); */ uint32 messageId = _ServerAnswerForseener->onScenarioUploaded( scenario); NLNET::CMessage msg; sendMsgToDss(CShareServerEditionItfProxy::buildMessageFor_onScenarioUploadAsked(msg, messageId, body, true)); return true; } void CClientEditionModule::requestSetNode(const std::string& instanceId, const std::string& attrName, CObject* value) { //H_AUTO(R2_CClientEditionModule_requestSetNode) if (value) { CObject *clObj = getEditor().getDMC().find(instanceId, attrName); if (clObj && clObj->getGhost()) { value->setGhost(true); } if (value->getGhost()) { // this is a local value -> forward directly to client CObject *temp = value->clone(); getEditor().getDMC().nodeSet(instanceId, attrName, temp); delete temp; // AJM return; } } if (!attrName.empty()) { CObject* instance = _Scenario->find(instanceId); if (instance) { CObject* property = _PropertyAccessor->getPropertyValue(instance, attrName); if (property && property->equal(value)) { //nlinfo("R2Cl: Optimisation(message not send)"); return; } } } requestSetNodeNoTest(instanceId, attrName, value); } void CClientEditionModule::requestSetNodeNoTest(const std::string& instanceId, const std::string& attrName, CObject* value) { //H_AUTO(R2_CClientEditionModule_requestSetNodeNoTest) // CSerialFactoryBackup fb; BOMB_IF(_ServerEditionProxy == NULL, "Server Edition Module not connected", return); CShareServerEditionItfProxy proxy(_ServerEditionProxy); CObjectSerializerServer value2(value); value2.compress(); uint32 messageId = _ServerAnswerForseener->onNodeSet(instanceId, attrName, value); proxy.onNodeSetAsked(this, messageId, instanceId, attrName, value2); } void CClientEditionModule::requestEraseNode( const std::string& instanceId, const std::string& attrName, sint32 position) { //H_AUTO(R2_CClientEditionModule_requestEraseNode) CObject *clObj = getEditor().getDMC().find(instanceId, attrName, position); if (clObj && clObj->getGhost()) { // this is a ghost value -> forward directly to client getEditor().getDMC().nodeErased(instanceId, attrName, position); return; } // CSerialFactoryBackup fb; BOMB_IF(_ServerEditionProxy == NULL, "Server Edition Module not connected", return); CShareServerEditionItfProxy proxy(_ServerEditionProxy); uint32 messageId = _ServerAnswerForseener->onNodeErased(instanceId, attrName, position); proxy.onNodeEraseAsked(this, messageId, instanceId, attrName, position); } void CClientEditionModule::requestInsertNode(const std::string& instanceId, const std::string& attrName, sint32 position, const std::string& key, CObject* value) { //H_AUTO(R2_CClientEditionModule_requestInsertNode) if (value) { // if value is inserted in a ghost node, then it inherits the 'ghost' flag CObject *clObj = getEditor().getDMC().find(instanceId, attrName, -1); if (clObj && clObj->getGhost()) { value->setGhost(true); } if (value->getGhost()) { // this is a ghost value -> forward directly to client getEditor().getDMC().nodeInserted(instanceId, attrName, position, key, value->clone()); return; } } // CSerialFactoryBackup fb; BOMB_IF(_ServerEditionProxy == NULL, "Server Edition Module not connected", return); CShareServerEditionItfProxy proxy(_ServerEditionProxy); CObjectSerializerServer value2(value); value2.compress(); uint32 messageId = _ServerAnswerForseener->onNodeInserted(instanceId, attrName, position, key, value); proxy.onNodeInsertAsked(this, messageId, instanceId, attrName, position, key, value2); } void CClientEditionModule::requestMoveNode( const std::string& instanceId, const std::string& attrName, sint32 position, const std::string& destInstanceId, const std::string& destAttrName, sint32 destPosition) { //H_AUTO(R2_CClientEditionModule_requestMoveNode) CObject *src = getEditor().getDMC().find(instanceId, attrName, position); CObject *dest = getEditor().getDMC().find(destInstanceId, destAttrName); if (src && dest) { nlassert(src->getGhost() == dest->getGhost()); if (src->getGhost()) { // this is a ghost value -> forward directly to client getEditor().getDMC().nodeMoved(instanceId, attrName, position, destInstanceId, destAttrName, destPosition); return; } } if (src) nlassert(!src->getGhost()); if (dest) nlassert(!dest->getGhost()); // CSerialFactoryBackup fb; BOMB_IF(_ServerEditionProxy == NULL, "Server Edition Module not connected", return); CShareServerEditionItfProxy proxy(_ServerEditionProxy); uint32 messageId = _ServerAnswerForseener->onNodeMoved(instanceId, attrName, position, destInstanceId, destAttrName, destPosition); proxy.onNodeMoveAsked(this, messageId, instanceId, attrName, position, destInstanceId, destAttrName, destPosition); } void CClientEditionModule::requestMapConnection( uint32 scenarioId, bool mustTp, bool mustUpdateHighLevel) { //H_AUTO(R2_CClientEditionModule_requestMapConnection) // CSerialFactoryBackup fb; BOMB_IF(_ServerEditionProxy == NULL, "Server Edition Module not connected", return); CShareServerEditionItfProxy proxy(_ServerEditionProxy); proxy.onMapConnectionAsked(this, (TSessionId)scenarioId, mustTp, mustUpdateHighLevel, R2::TUserRole::ur_editor); } void CClientEditionModule::requestReconnection() { //H_AUTO(R2_CClientEditionModule_requestReconnection) if (_SessionId.asInt() != 0) { this->requestMapConnection(_SessionId.asInt(), false, false); } } CScenario* CClientEditionModule::getCurrentScenario() const {return _Scenario; } void CClientEditionModule::addPaletteElement(const std::string& attrName, CObject* paletteElement) { //H_AUTO(R2_CClientEditionModule_addPaletteElement) _Palette->addPaletteElement(attrName, paletteElement); } bool CClientEditionModule::isInPalette(const std::string& key) const { //H_AUTO(R2_CClientEditionModule_isInPalette) return _Palette->isInPalette(key); } CObject* CClientEditionModule::getPropertyValue(CObject* component, const std::string& attrName) const { //H_AUTO(R2_CClientEditionModule_getPropertyValue) return _PropertyAccessor->getPropertyValue(component, attrName); } CObject* CClientEditionModule::getPropertyValue(const std::string& instanceId, const std::string& attrName) const { //H_AUTO(R2_CClientEditionModule_getPropertyValue) CObject* component = _Scenario->find(instanceId); if (!component) return 0; return _PropertyAccessor->getPropertyValue(component, attrName); } CObject* CClientEditionModule::getPropertyList(CObject* component) const { //H_AUTO(R2_CClientEditionModule_getPropertyList) typedef std::list TContainer; TContainer properties; _PropertyAccessor->getPropertyList(component, properties); TContainer::const_iterator first(properties.begin()), last(properties.end()); for ( ; first != last; ++first) { component->add(new CObjectString(*first)); } return component; } CObject* CClientEditionModule::getPaletteElement(const std::string& key)const { //H_AUTO(R2_CClientEditionModule_getPaletteElement) return _Palette->getPaletteElement(key); } CObject* CClientEditionModule::newComponent(const std::string& type) const { //H_AUTO(R2_CClientEditionModule_newComponent) return _Factory->newComponent(type); } void CClientEditionModule::registerGenerator(CObject* classObject) { //H_AUTO(R2_CClientEditionModule_registerGenerator) _Factory->registerGenerator(classObject); } CPropertyAccessor& CClientEditionModule::getPropertyAccessor() const { //H_AUTO(R2_CClientEditionModule_getPropertyAccessor) nlassert(_PropertyAccessor); return *_PropertyAccessor; } void CClientEditionModule::updateScenario(CObject* scenario) { //H_AUTO(R2_CClientEditionModule_updateScenario) nlassert(_Scenario); _Scenario->setHighLevel(scenario); std::string eid = getEid(); _Factory->setMaxId(eid, _Scenario->getMaxId(eid)); } void CClientEditionModule::setEid(const std::string& eid) { //H_AUTO(R2_CClientEditionModule_setEid) _Eid = eid; _Factory->setPrefix(_Eid); } bool CClientEditionModule::askUpdateCharMode(R2::TCharMode mode) { //H_AUTO(R2_CClientEditionModule_askUpdateCharMode) // CSerialFactoryBackup fb; if (_ServerEditionProxy == NULL) { return false; }; CShareServerEditionItfProxy proxy(_ServerEditionProxy); proxy.onCharModeUpdateAsked(this, mode); return true; } void CClientEditionModule::onCharModeUpdated(NLNET::IModuleProxy * /* senderModuleProxy */, R2::TCharMode mode) { //H_AUTO(R2_CClientEditionModule_onCharModeUpdated) _CharMode = mode; if(UserEntity) UserEntity->setR2CharMode(mode); } void CClientEditionModule::startScenario(class NLNET::IModuleProxy * proxy, bool ok, uint32 /* startingAct */, const std::string& errorReason) { //H_AUTO(R2_CClientEditionModule_startScenario) if (ok) { if (_SessionType == st_edit) { _Client->onTestModeConnected(); R2::getEditor().setMode(CEditor::DMMode); } else if(_SessionType == st_anim) { this->connectAnimationModePlay(); CEditor::connexionMsg(""); if (_CharMode == TCharMode::Dm) { R2::getEditor().setMode(CEditor::AnimationModeDm); askMissionItemsDescription(); } else if (_CharMode == TCharMode::Tester || _CharMode == TCharMode::Player) { R2::getEditor().setMode(CEditor::AnimationModePlay); } else { nlwarning("Error Mode not handled %d", _CharMode.getValue()); R2::getEditor().setMode(CEditor::AnimationModePlay); } } //:TODO: must tp? } else { CEditor::connexionMsg("uiR2EDR2StartTestError"); requestReconnection(); } if (!ok && errorReason.empty()) { systemMsg(proxy, "ERR", "", errorReason); } } void CClientEditionModule::startingScenario(class NLNET::IModuleProxy * /* serverProxy */, uint32 charId) { //H_AUTO(R2_CClientEditionModule_startingScenario) CShareServerEditionItfProxy proxy(_ServerEditionProxy); bool ok = false; CObjectSerializerServer hlData; CObjectSerializerServer rtData; if (_Scenario) { // Some times save is refused: be NevraxScenario must not be changed { CScenarioValidator sv; CScenarioValidator::TValues values; std::string md5, signature; R2::getEditor().getLua().executeScriptNoThrow("r2.Translator.initStartingActIndex()"); sv.setScenarioToLoad("save/r2_buffer.dat", values, md5, signature, true); _LastReadHeader = values; uint32 lastActIndex = _StartingActIndex; CObject* hlScenario2 = _Client->getComLuaModule().loadLocal("save/r2_buffer.dat", _LastReadHeader); _StartingActIndex = lastActIndex; if (hlScenario2) { _Factory->clear(); _Client->scenarioUpdated(hlScenario2, false, lastActIndex); } _StartingActIndex = lastActIndex; } uint32 myUserId = NetMngr.getUserId(); std::string connectionState = ""; if (myUserId == (charId>>4) || ClientCfg.Local) { std::string errorMsg = ""; CObject* hlScenario = _Scenario->getHighLevel(); hlData.setData(hlScenario); // clone before modify by translateFeatures // translateFeatures change _StartingActIndex _Factory->setMaxId("RtAct", 0); _Factory->setMaxId("RtAiState", 0); _Factory->setMaxId("RtNpcGrp", 0); _Factory->setMaxId("RtNpcEventHandlerAction", 0); _Factory->setMaxId("RtNpcEventHandler", 0); _Factory->setMaxId("RtLocation", 0); _Factory->setMaxId("RtTextManager", 0); _Factory->setMaxId("RtScenario", 0); _Factory->setMaxId("RtUserTrigger", 0); _Factory->setMaxId("RtScenario", 0); _Factory->setMaxId("RtEntryText", 0); _Factory->setMaxId("RtPlotItem", 0); std::auto_ptr rtDataPtr( _Client->getComLuaModule().translateFeatures(hlScenario , errorMsg) ); rtData.setData(rtDataPtr.get()); if (rtDataPtr.get()) { ok = true; connectionState = "uiR2EDUploadScenario"; } else { nlwarning("%s",errorMsg.c_str()); connectionState = "uiR2EDR2StartTestError"; } TScenarioSessionType sessionType = _SessionType; if (ok && sessionType == st_anim) { hlData.compress(); NLNET::CMessage msg; uint32 messageId = _ServerAnswerForseener->onScenarioUploaded( hlScenario); sendMsgToDss(CShareServerEditionItfProxy::buildMessageFor_onScenarioUploadAsked(msg, messageId, hlData, false)); } rtData.compress(); TScenarioHeaderSerializer header(_LastReadHeader); { NLNET::CMessage msg; sendMsgToDss(CShareServerEditionItfProxy::buildMessageFor_startScenario(msg, ok, header, rtData, _StartingActIndex)); } } else { connectionState = "uiR2EDR2WaitUploadScenario"; } if (_SessionType == st_edit) { _Client->onEditionModeDisconnected(); R2::getEditor().setMode(CEditor::GoingToDMMode); } else if (_SessionType == st_anim) { _Client->onEditionModeDisconnected(); R2::getEditor().setMode(CEditor::AnimationModeGoingToDm); } CEditor::connexionMsg(connectionState); } } bool CClientEditionModule::requestStartScenario() { //H_AUTO(R2_CClientEditionModule_ ) BOMB_IF(_ServerEditionProxy == NULL, "Server Edition Module not connected", return false); CEditor::connexionMsg("uimR2EDGoToDMMode"); R2::getEditor().getLua().executeScriptNoThrow("r2.Version.save(\"save/r2_buffer.dat\")"); CShareServerEditionItfProxy proxy(_ServerEditionProxy); proxy.startingScenario(this); return true; } void CClientEditionModule::updateUserComponentsInfo(const std::string & filename, const std::string& name, const std::string & description, uint32 timestamp, const std::string& md5hash) { //H_AUTO(R2_CClientEditionModule_updateUserComponentsInfo) TUserComponents::iterator found = _UserComponents.find(filename); if (found == _UserComponents.end()) { nlwarning("Error: try to update information on a unknown component '%s'", filename.c_str() ); return; } found->second->Name = name; found->second->Description = description; found->second->TimeStamp = timestamp; found->second->Md5Id.fromString( md5hash ); } void CClientEditionModule::registerUserComponent(const std::string& filename) { //H_AUTO(R2_CClientEditionModule_registerUserComponent) BOMB_IF(_ServerEditionProxy == NULL, "Server Edition Module not connected", return); TUserComponents::iterator found = _UserComponents.find(filename); if (found == _UserComponents.end()) { nlwarning("Error: try to upload unknown component '%s'", filename.c_str() ); return; } CShareServerEditionItfProxy proxy(_ServerEditionProxy); proxy.onUserComponentRegistered(this, found->second->Md5); } CUserComponent* CClientEditionModule::getUserComponentByHashMd5( const NLMISC::CHashKeyMD5 & md5) const { //H_AUTO(R2_CClientEditionModule_getUserComponentByHashMd5) TUserComponents::const_iterator first(_UserComponents.begin()), last(_UserComponents.end()); for (; first != last && (first->second->Md5 != md5) ; ++first ) {} if (first == last) { nlwarning("Error: try to upload unknown component '%s'", md5.toString().c_str() ); return 0; } return first->second; } void CClientEditionModule::onUserComponentUploading(NLNET::IModuleProxy * /* senderModuleProxy */, const CHashKeyMD5 & md5) { //H_AUTO(R2_CClientEditionModule_onUserComponentUploading) BOMB_IF(_ServerEditionProxy == NULL, "Server Edition Module not connected", return); CUserComponent* userComponent = getUserComponentByHashMd5(md5); if (userComponent) { NLNET::CMessage message; message.setType("SUCU"); //onUserComponentUploaded userComponent->serial(message); _ServerEditionProxy->sendModuleMessage(this, message); } return; } void CClientEditionModule::onUserComponentRegistered(NLNET::IModuleProxy * /* senderModuleProxy */, const CHashKeyMD5 & md5) { //H_AUTO(R2_CClientEditionModule_onUserComponentRegistered) BOMB_IF(_ServerEditionProxy == NULL, "Server Edition Module not connected", return); CUserComponent* userComponent = getUserComponentByHashMd5(md5); if (!userComponent) { CShareServerEditionItfProxy proxy(_ServerEditionProxy); proxy.onUserComponentDownloading(this, md5); } else { std::string filename = userComponent->getFilename(); R2::getEditor().getLua().executeScriptNoThrow(NLMISC::toString("r2.UserComponentsManager:addUserComponent('%s')", filename.c_str())); } } void CClientEditionModule::onUserComponentDownloaded(NLNET::IModuleProxy *senderModuleProxy, CUserComponent* component) { //H_AUTO(R2_CClientEditionModule_onUserComponentDownloaded) // case 1 data are compressed component->UncompressedData = new uint8[component->UncompressedDataLength + 1]; uLongf dataLength = static_cast(component->UncompressedDataLength); sint32 decompressionState = uncompress (reinterpret_cast(component->UncompressedData), &dataLength , reinterpret_cast(component->CompressedData), component->CompressedDataLength); component->UncompressedDataLength = static_cast(dataLength); if (decompressionState != Z_OK) { delete component; nlwarning("Error: the downloaded user component is corrupted '%s' ", component->Filename.c_str()); return; } component->UncompressedData[component->UncompressedDataLength] = '\0'; // insert user component into user components map TUserComponents::iterator found = _UserComponents.find(component->Filename); if (found != _UserComponents.end()) { delete found->second; found->second = component; } _UserComponents[component->Filename] = component; saveUserComponentFile(component->Filename, true); onUserComponentRegistered(senderModuleProxy, component->Md5); } bool CClientEditionModule::loadUserComponent(const std::string& filename, bool mustReload) { //H_AUTO(R2_CClientEditionModule_loadUserComponent) if (! mustReload) { TUserComponents::const_iterator found = _UserComponents.find(filename); if (found != _UserComponents.end()) { return true;; } } std::string sourceExtension = UserComponentsSourceExtension; std::string componentExtension = UserComponentsComponentExtension; uint32 uncompressedFileLength = 0; uint8* uncompressedFile=0; uint32 compressedFileLength = 0; uint8* compressedFile=0; bool compressed = false; bool ok = false; if (CFile::getExtension(filename) == sourceExtension) { compressed = false; ok = true; } else if (CFile::getExtension(filename) == componentExtension) { compressed = true; ok = true; } if (!ok) { nlwarning("Wrong file extension '%s'", filename.c_str() ); nlwarning("Allowed file extension '%s' '%s'", sourceExtension.c_str(), componentExtension.c_str()); return false; } CHashKeyMD5 md5Id; uint32 timeStamp = 0; if (! compressed) { FILE* file = fopen(filename.c_str(),"rb"); if (!file) { nlwarning("Try to open an invalid file %s (access error)", filename.c_str()); return false; } // file length are the last uint32 of a file if (fseek(file,0, SEEK_END) != 0) { nlwarning("Try to open an invalid file %s (size error)", filename.c_str()); fclose(file); return false; } uncompressedFileLength = ftell(file); // size of file if (fseek(file, 0, SEEK_SET) != 0) { nlwarning("Try to open an invalid file %s (size error)", filename.c_str()); fclose(file); return false; } uncompressedFile = new uint8[uncompressedFileLength]; int length = (int)fread(uncompressedFile, sizeof(char), uncompressedFileLength, file); if (length <0) { nlwarning("Error while reading %s", filename.c_str()); delete[] uncompressedFile; fclose(file); return false; } if ( length < static_cast(uncompressedFileLength)) { nlwarning("Error while reading %s (corrupted data)", filename.c_str()); delete[] uncompressedFile; fclose(file); return false; } fclose(file); // Test if data are not too big if (uncompressedFileLength > 200*1024) { nlwarning("Try to open an invalid file %s (size error)", filename.c_str()); delete [] uncompressedFile; return false; } std::string compiledInfoHeader = "--COMPONENT HEADER\n"; std::string compiledInfoFooter = "--COMPONENT BODY\n"; // REMOVE HEADER std::string data((const char*)&uncompressedFile[0], (const char*)&uncompressedFile[uncompressedFileLength]); std::string::size_type start = data.find(compiledInfoHeader); if ( start != std::string::npos) { std::string::size_type finish = data.find(compiledInfoFooter, start + compiledInfoHeader.length()); if (finish != std::string::npos) { finish += compiledInfoFooter.size(); data = data.substr(0, start) + data.substr(finish, data.size() - finish); } } // REGENERATE HEADER md5Id = getMD5((uint8*)data.data(), (uint32)data.size()); timeStamp = NLMISC::CTime::getSecondsSince1970(); //std::stringstream ss; //ss << compiledInfoHeader; //ss << "local fileinfo = {}\n"; //ss << toString("fileinfo.Package='%s'\n", filename.c_str()); //ss << toString("fileinfo.Version='%s'\n", "1"); //ss << toString("fileinfo.MD5='%s'\n", md5Id.toString().c_str()); //ss << toString("fileinfo.TimeStamp='%u'\n", timeStamp); //ss << toString("r2.UserComponentsManager:registerFileInfo(fileinfo)\n"); //ss << compiledInfoFooter; //ss << data; //data = ss.str(); std::string str; str += compiledInfoHeader; str += "local fileinfo = {}\n"; str += toString("fileinfo.Package='%s'\n", filename.c_str()); str += toString("fileinfo.Version='%s'\n", "1"); str += toString("fileinfo.MD5='%s'\n", md5Id.toString().c_str()); str += toString("fileinfo.TimeStamp='%u'\n", timeStamp); str += toString("r2.UserComponentsManager:registerFileInfo(fileinfo)\n"); str += compiledInfoFooter; data = str + data; delete [] uncompressedFile; uncompressedFile = new uint8[ data.size() ]; memcpy(uncompressedFile, data.c_str(), data.size()); uncompressedFileLength = (uint32)data.size(); } else { // Get Uncompressed File length (4 last byte of a gz) FILE* file = fopen(filename.c_str(),"rb"); if (!file) { nlwarning("Try to open an invalid file %s (access error)", filename.c_str()); return false; } // file length are the last uint32 of a file if (fseek(file, -4, SEEK_END) != 0) { nlwarning("Try to open an invalid file %s (size error)", filename.c_str()); fclose(file); return false; } if (fread((void*)&uncompressedFileLength, sizeof(uncompressedFileLength), 1, file) != 1) { nlwarning("Error while reading %s", filename.c_str()); } fclose(file); // Test if data are not too big if (uncompressedFileLength > 200*1024) { nlwarning("Try to open an invalid file %s (size error)", filename.c_str()); delete [] compressedFile; return false; } // Read the compressed File { gzFile file = gzopen ( filename.c_str(), "rb"); uncompressedFile = new uint8[uncompressedFileLength+1]; int length = gzread(file, uncompressedFile, uncompressedFileLength); if (length <0) { nlwarning("Error while reading %s", filename.c_str()); delete [] uncompressedFile; delete [] compressedFile; gzclose(file); return false; } if ( length < static_cast(uncompressedFileLength)) { nlwarning("Error while reading %s (corrupted data)", filename.c_str()); delete [] uncompressedFile; delete [] compressedFile; gzclose(file); return false; } gzclose(file); } // Read the compressed File } delete [] compressedFile; compressedFile = 0; //size of the destination buffer, which must be at least 0.1% larger than sourceLen plus 12 bytes { uLongf destLen = uncompressedFileLength + uncompressedFileLength / 1000 + 12; Bytef *dest = new Bytef[destLen]; int ok = compress(dest, &destLen, (Bytef *)uncompressedFile, uncompressedFileLength); if (ok != Z_OK) { delete [] uncompressedFile; delete [] compressedFile; nlwarning("Error while reading %s (can't compress data)", filename.c_str()); return false; } compressedFile = reinterpret_cast(dest); compressedFileLength = static_cast(destLen); uncompressedFile[uncompressedFileLength] = '\0'; } // TODO: compute md5Id and timeStamp _UserComponents[filename] = new CUserComponent(filename, uncompressedFile, uncompressedFileLength, compressedFile, compressedFileLength); _UserComponents[filename]->Md5Id = md5Id; _UserComponents[filename]->TimeStamp = timeStamp; return true; } std::string CClientEditionModule::readUserComponentFile(const std::string& filename) { //H_AUTO(R2_CClientEditionModule_readUserComponentFile) if (!loadUserComponent(filename, false)) { return ""; } CUserComponent* component = getUserComponentByFilename(filename); if (component) { const char * str = (const char*)component->getUncompressedData(); std::string value(str); return str; } return ""; } CUserComponent* CClientEditionModule::getUserComponentByFilename(const std::string& filename) const { //H_AUTO(R2_CClientEditionModule_getUserComponentByFilename) TUserComponents::const_iterator found = _UserComponents.find(filename); if (found != _UserComponents.end()) { return found->second; } return 0; } void CClientEditionModule::saveUserComponentFile(const std::string& filename, bool mustCompress) { //H_AUTO(R2_CClientEditionModule_saveUserComponentFile) bool ok = loadUserComponent(filename); if (ok) { CUserComponent* component = getUserComponentByFilename(filename); std::string compressedName; std::string uncompressedName; if (CFile::getExtension(filename) == UserComponentsSourceExtension.toString()) { uncompressedName = filename; compressedName = toString("%s/%s.%s", UserComponentsComponentsDirectory.c_str(), component->Md5Id.toString().c_str(), UserComponentsComponentExtension.c_str()); } else if (CFile::getExtension(filename) == UserComponentsComponentExtension.toString()) { compressedName = filename; uncompressedName = toString("%s/%s.%s", UserComponentsExamplesDirectory.c_str(), CFile::getFilenameWithoutExtension(component->Filename).c_str(), UserComponentsSourceExtension.c_str()); } if (!mustCompress) { { FILE* output = fopen(uncompressedName.c_str(), "wb"); if (output) { fwrite(component->UncompressedData, sizeof(char) , component->UncompressedDataLength, output); fclose(output); } } } else { { gzFile output = gzopen(compressedName.c_str(), "wb"); if (output) { gzwrite(output, (const voidp) component->UncompressedData, component->UncompressedDataLength); gzclose(output); } } } } } void CClientEditionModule::refreshComponents() { //H_AUTO(R2_CClientEditionModule_refreshComponents) /* // verify directory exist bool createDirectorySuccess = false; if ( !CFile::isDirectory(_ScriptDirectory)) { createDirectorySuccess = CFile::createDirectory(_ScriptDirectory); } // verify content of directory has not changed uint32 lastDirectoryModificationDate = CFile::getFileModificationDate(const std::string &filename); if (_LastDirectoryModificationDate == lastDirectoryModificationDate ) { return; } _LastDirectoryModificationDate = lastDirectoryModificationDate // get Developper Component Script; std::vector result; CPath::getPathContent (_ScriptDirectory, false, false, true, result, false, false); CInterfaceManager *pIM= CInterfaceManager::getInstance(); std::vector script(1); bool ok = pIM->pars veInterface(script, true, false); _LastRefreshComponents = NLMISC::CTime::getLocalTime(); */ } void CClientEditionModule::ackMsg( NLNET::IModuleProxy *sender, uint32 msgId, bool ok) { _ServerAnswerForseener->ack(this, sender, msgId, ok); } void CClientEditionModule::onScenarioUploaded(NLNET::IModuleProxy * /* sender */, const R2::CObjectSerializerClient &hlScenario) { //H_AUTO(R2_CClientEditionModule_onScenarioUploaded) _Factory->clear(); _Client->scenarioUpdated(hlScenario.getData(), false, 1);//give ownership } // The client request to set a node on a hl scenario. void CClientEditionModule::onNodeSet(NLNET::IModuleProxy * /* sender */, const std::string &instanceId, const std::string &attrName, const R2::CObjectSerializerClient &value) { //H_AUTO(R2_CClientEditionModule_onNodeSet) if (_Mute) return; _Client->nodeSet(instanceId, attrName, value.getData()); //todo ownership } // The ServerEditionMode inserts a node on a hl scenario. void CClientEditionModule::onNodeInserted(NLNET::IModuleProxy * /* sender */, const std::string &instanceId, const std::string &attrName, sint32 position, const std::string &key, const R2::CObjectSerializerClient &value) { //H_AUTO(R2_CClientEditionModule_onNodeInserted) if (_Mute) return; _Client->nodeInserted( instanceId, attrName, position, key, value.getData()); //todo ownership } // The ServerEditionMode erases a node on a hl scenario. void CClientEditionModule::onNodeErased(NLNET::IModuleProxy * /* sender */, const std::string &instanceId, const std::string &attrName, sint32 position) { //H_AUTO(R2_CClientEditionModule_onNodeErased) if (_Mute) return; _Client->nodeErased( instanceId, attrName, position); } // The ServerEditionMode a move node on a hl scenario. void CClientEditionModule::onNodeMoved(NLNET::IModuleProxy * /* sender */, const std::string &instanceId1, const std::string &attrName1, sint32 position1, const std::string &instanceId2, const std::string &attrName2, sint32 position2) { //H_AUTO(R2_CClientEditionModule_onNodeMoved) if (_Mute) return; _Client->nodeMoved(instanceId1, attrName1, position1, instanceId2, attrName2, position2); } void CClientEditionModule::onQuotaUpdated(NLNET::IModuleProxy * /* senderModuleProxy */, uint32 maxNpcs, uint32 maxStaticObjects) { //H_AUTO(R2_CClientEditionModule_onQuotaUpdated) //R2::getEditor().getLua().executeScriptNoThrow(toString("r2.QuotaMgr.onQuotaUpdated(%u, %u)", maxNpcs, maxStaticObjects)); _MaxNpcs = maxNpcs; _MaxStaticObjects = maxStaticObjects; } uint32 CClientEditionModule::getCurrentMaxId() { //H_AUTO(R2_CClientEditionModule_getCurrentMaxId) if (_Scenario == NULL) return 1000; std::string eid = getEid(); sint32 currentId = _Factory->getMaxId(eid); nlassert(currentId >= -1); return static_cast(currentId + 1); } void CClientEditionModule::reserveIdRange(uint32 range) { //H_AUTO(R2_CClientEditionModule_reserveIdRange) nlassert(_Scenario); std::string eid = getEid(); sint32 currentId = _Scenario->getMaxId(eid); nlassert(currentId >= -1); sint32 maxId = currentId + static_cast(range + 1); //_Scenario->setMaxId(eid, maxId); _Factory->setMaxId(eid, maxId); } std::string CClientEditionModule::getEmoteBehaviorFromEmoteId(const std::string & emoteId) const { //H_AUTO(R2_CClientEditionModule_getEmoteBehaviorFromEmoteId) return _Emotes->get(emoteId); } void CClientEditionModule::resetDisplayInfo() { //H_AUTO(R2_CClientEditionModule_resetDisplayInfo) this->_ClientEditorConfig->setDisplayInfo(0xFFFFFFFF); } void CClientEditionModule::setDisplayInfo(const std::string& formName, bool displayInfo) { //H_AUTO(R2_CClientEditionModule_setDisplayInfo) this->_ClientEditorConfig->setDisplayInfo(formName, displayInfo); //CShareServerEditionItfProxy proxy(_ServerEditionProxy); //uint32 newDisplayInfo = this->_ClientEditorConfig->getDisplayInfo(); //proxy.setDisplayInfo(this, newDisplayInfo); } bool CClientEditionModule::mustDisplayInfo(const std::string& formName) const { //H_AUTO(R2_CClientEditionModule_mustDisplayInfo) bool ok = this->_ClientEditorConfig->mustDisplayInfo(formName); return ok; } bool CClientEditionModule::hasDisplayInfo(const std::string& formName) const { //H_AUTO(R2_CClientEditionModule_hasDisplayInfo) bool ok = this->_ClientEditorConfig->hasDisplayInfo(formName); return ok; } void CClientEditionModule::onDisplayInfoUpdated(NLNET::IModuleProxy * /* senderModuleProxy */, uint32 displayInfo) { //H_AUTO(R2_CClientEditionModule_onDisplayInfoUpdated) this->_ClientEditorConfig->setDisplayInfo(displayInfo); } void CClientEditionModule::setStartingActIndex(uint32 startingActIndex) { //H_AUTO(R2_CClientEditionModule_setStartingActIndex) _StartingActIndex = startingActIndex; } void CClientEditionModule::onTpPositionSimulated(NLNET::IModuleProxy * /* sender */, TSessionId /* sessionId */, uint64 /* characterId64 */, sint32 x, sint32 y, sint32 z, uint8 /* scenarioSeason */) { //H_AUTO(R2_CClientEditionModule_onTpPositionSimulated) CVector dest((float)x, (float)y, (float) z); //Season ? UserEntity->pos(dest); // change position in pacs // Select the closest continent from the new position. beginLoading (LoadingBackground); #define BAR_STEP_TP 2 // fixme : this define is duplicated.... ProgressBar.reset (BAR_STEP_TP); ucstring nmsg("Loading..."); ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) ); ProgressBar.progress(0); ContinentMngr.select(dest, ProgressBar); endLoading(); // Teleport the User. UserEntity->tp(dest); ProgressBar.finish(); } void CClientEditionModule::onDisconnected(NLNET::IModuleProxy * /* sender */) { //H_AUTO(R2_CClientEditionModule_onDisconnected) R2::getEditor().getLua().executeScriptNoThrow(NLMISC::toString("r2.onDisconnected()")); } void CClientEditionModule::onKicked(NLNET::IModuleProxy * /* sender */, uint32 timeBeforeDisconnection, bool mustKick) { //H_AUTO(R2_CClientEditionModule_onKicked) R2::getEditor().getLua().push((double)timeBeforeDisconnection); R2::getEditor().getLua().push((bool)mustKick); R2::getEditor().callEnvFunc( "onKicked", 2, 0); } // Target : Animation Module void CClientEditionModule::requestTalkAs(const std::string& npcname) { //H_AUTO(R2_CClientEditionModule_requestTalkAs) CMessage msg("talk_as"); msg.serial(const_cast(npcname)); _ServerAnimationProxy->sendModuleMessage(this, msg ); } void CClientEditionModule::requestStringTable() { //H_AUTO(R2_CClientEditionModule_requestStringTable) CMessage msg("requestStringTable"); _ServerAnimationProxy->sendModuleMessage(this, msg ); } void CClientEditionModule::requestSetStringValue(std::string& id,std::string& value ) { //H_AUTO(R2_CClientEditionModule_requestSetStringValue) CMessage msg("requestSetValue"); msg.serial(id); msg.serial(value); _ServerAnimationProxy->sendModuleMessage(this,msg); } void CClientEditionModule::requestStartAct(uint32 actId) { //H_AUTO(R2_CClientEditionModule_requestStartAct) CMessage message ("requestStartAct"); message.serial(actId); DROP_IF(_ServerAnimationProxy == NULL, "Server Animation Module not connected", return); _ServerAnimationProxy->sendModuleMessage(this, message ); } void CClientEditionModule::requestSetWeather(uint16 weatherValue) { //H_AUTO(R2_CClientEditionModule_requestSetWeather) CMessage message ("requestSetWeather"); message.serial(weatherValue); DROP_IF(_ServerAnimationProxy == NULL, "Server Animation Module not connected", return); _ServerAnimationProxy->sendModuleMessage(this, message ); } void CClientEditionModule::requestSetSeason(uint8 seasonValue) { //H_AUTO(R2_CClientEditionModule_requestSetSeason) CMessage message ("requestSetSeason"); message.serial(seasonValue); DROP_IF(_ServerAnimationProxy == NULL, "Server Animation Module not connected", return); _ServerAnimationProxy->sendModuleMessage(this, message ); } void CClientEditionModule::requestStopAct() { //H_AUTO(R2_CClientEditionModule_requestStopAct) CMessage message ("requestStopAct"); DROP_IF(_ServerAnimationProxy == NULL, "Server Animation Module not connected", return); _ServerAnimationProxy->sendModuleMessage(this, message ); } void CClientEditionModule::requestStopTalkAs() { //H_AUTO(R2_CClientEditionModule_requestStopTalkAs) DROP_IF(_ServerAnimationProxy == NULL, "Server Animation Module not connected", return); CMessage msg("stopTalk"); _ServerAnimationProxy->sendModuleMessage(this, msg ); } void CClientEditionModule::requestStringValue(std::string& localId ) { //H_AUTO(R2_CClientEditionModule_requestStringValue) DROP_IF(_ServerAnimationProxy == NULL, "Server Animation Module not connected", return); CMessage msg("requestStringValue"); msg.serial(localId); _ServerAnimationProxy->sendModuleMessage(this, msg ); } void CClientEditionModule::requestTpPosition(float x, float y, float z) { //H_AUTO(R2_CClientEditionModule_requestTpPosition) DROP_IF(_ServerEditionProxy == NULL, "Server Edition Module not connected", return); CShareServerEditionItfProxy serverEditionModule(_ServerEditionProxy); serverEditionModule.onTpPositionAsked(this, x, y, z); return ; } void CClientEditionModule::requestIdList() { //H_AUTO(R2_CClientEditionModule_requestIdList) DROP_IF(_ServerAnimationProxy == NULL, "Server Animation Module not connected", return); CMessage msg("requestIdList"); _ServerAnimationProxy->sendModuleMessage(this, msg ); } bool CClientEditionModule::requestTpToEntryPoint(uint32 actIndex) { //H_AUTO(R2_CClientEditionModule_requestTpToEntryPoint) DROP_IF(_ServerEditionProxy == NULL, "Server Edition Module not connected", return false); if (R2::getEditor().isClearingContent()) { return true;} CShareServerEditionItfProxy serverEditionModule(_ServerEditionProxy); serverEditionModule.tpToEntryPoint(this, actIndex); return true; } bool CClientEditionModule::requestSetStartingAct(uint32 actIndex) { //H_AUTO(R2_CClientEditionModule_requestSetStartingAct) DROP_IF(_ServerEditionProxy == NULL, "Server Edition Module not connected", return false); CShareServerEditionItfProxy serverEditionModule(_ServerEditionProxy); serverEditionModule.setStartingAct(this, actIndex); return true; } bool CClientEditionModule::connectAnimationModePlay() { //H_AUTO(R2_CClientEditionModule_connectAnimationModePlay) DROP_IF(_ServerAnimationProxy == NULL, "Server Animation Module not connected", return false); CShareServerAnimationItfProxy serverAnimationModule(_ServerAnimationProxy); serverAnimationModule.connectAnimationModePlay(this); return true; } void CClientEditionModule::onAnimationModePlayConnected(NLNET::IModuleProxy * /* senderModuleProxy */) { //H_AUTO(R2_CClientEditionModule_onAnimationModePlayConnected) _Client->onAnimationModePlayConnected(); } void CClientEditionModule::scheduleStartAct(NLNET::IModuleProxy * /* sender */, uint32 errorId, uint32 actId, uint32 nbSeconds) { //H_AUTO(R2_CClientEditionModule_scheduleStartAct) R2::getEditor().getLua().push((double)errorId); R2::getEditor().getLua().push((double)actId); R2::getEditor().getLua().push((double)nbSeconds); R2::getEditor().callEnvFunc( "onScheduleStartAct", 3, 0); } void CClientEditionModule::updateScenarioHeader(NLNET::IModuleProxy * /* sender */, const TScenarioHeaderSerializer& header) { //H_AUTO(R2_CClientEditionModule_updateScenarioHeader) _ScenarioHeader = header.Value; R2::getEditor().getLua().executeScriptNoThrow( "r2.onScenarioHeaderUpdated(r2.getScenarioHeader())" ); } void CClientEditionModule::updateMissionItemsDescription(NLNET::IModuleProxy * /* sender */, TSessionId /* sessionId */, const std::vector &missionItem) { //H_AUTO(R2_CClientEditionModule_updateMissionItemsDescription) uint i; uint maxNumPlotItems = CEditor::getMaxNumPlotItems(); for(i = 0; i < std::min((uint) missionItem.size(), maxNumPlotItems); ++i) { CCDBNodeLeaf *leaf = CEditor::getPlotItemSheetDBLeaf(i); if (leaf) { uint32 sheetId = (uint32) missionItem[i].SheetId.asInt(); leaf->setValue32(sheetId); getEditor().setPlotItemInfos(missionItem[i]); } } for(; i < maxNumPlotItems; ++i) { CCDBNodeLeaf *leaf = CEditor::getPlotItemSheetDBLeaf(i); if (leaf) { leaf->setValue32(0); } } } void CClientEditionModule::updateActPositionDescriptions(NLNET::IModuleProxy * /* sender */, const TActPositionDescriptions &actPositionDescriptions) { //H_AUTO(R2_CClientEditionModule_updateActPositionDescriptions) this->_ActPositionDescriptions = actPositionDescriptions; R2::getEditor().getLua().executeScriptNoThrow( "r2.onRuntimeActUpdated(r2.getRuntimeActs())" ); } void CClientEditionModule::updateUserTriggerDescriptions(NLNET::IModuleProxy * /* sender */, const TUserTriggerDescriptions &userTriggerDescriptions) { //H_AUTO(R2_CClientEditionModule_updateUserTriggerDescriptions) this->_UserTriggerDescriptions = userTriggerDescriptions; R2::getEditor().getLua().executeScriptNoThrow( "r2.onUserTriggerDescriptionUpdated(r2.getUserTriggers())" ); } bool CClientEditionModule::askMissionItemsDescription() { //H_AUTO(R2_CClientEditionModule_askMissionItemsDescription) DROP_IF(_ServerAnimationProxy == NULL, "Server Animation Module not connected", return false); CShareServerAnimationItfProxy serverAnimationModule(_ServerAnimationProxy); serverAnimationModule.askMissionItemsDescription(this); return true; } bool CClientEditionModule::requestTriggerUserTrigger(uint32 actId, uint triggerId) { //H_AUTO(R2_CClientEditionModule_requestTriggerUserTrigger) DROP_IF(_ServerAnimationProxy == NULL, "Server Animation Module not connected", return false); CShareServerAnimationItfProxy serverAnimationModule(_ServerAnimationProxy); serverAnimationModule.onUserTriggerTriggered(this, actId, triggerId); return true; } void CClientEditionModule::onCurrentActIndexUpdated(NLNET::IModuleProxy * /* sender */, uint32 actId) { //H_AUTO(R2_CClientEditionModule_onCurrentActIndexUpdated) this->_CurrentActIndex = actId; R2::getEditor().getLua().executeScriptNoThrow( "r2.onCurrentActIndexUpdated(r2.getCurrentActIndex())" ); } void CClientEditionModule::dssTarget( std::vector& args) { //H_AUTO(R2_CClientEditionModule_dssTarget) DROP_IF(_ServerAnimationProxy == NULL, "Server Animation Module not connected", return); CShareServerAnimationItfProxy serverAnimationModule(_ServerAnimationProxy); serverAnimationModule.onDssTarget(this, args); } void CClientEditionModule::updateIncarningList(NLNET::IModuleProxy * /* sender */, const std::vector & botId) { //H_AUTO(R2_CClientEditionModule_updateIncarningList) this->_IncarnatingList = botId; R2::getEditor().getLua().executeScriptNoThrow( "r2.onIncarnatingListUpdated()" ); } void CClientEditionModule::updateTalkingAsList(NLNET::IModuleProxy * /* sender */, const std::vector & botId) { //H_AUTO(R2_CClientEditionModule_updateTalkingAsList) this->_TalkingAsList = botId; R2::getEditor().getLua().executeScriptNoThrow( "r2.onTalkingAsListUpdated()" ); } std::vector CClientEditionModule::getIncarnatingList() const { //H_AUTO(R2_CClientEditionModule_getIncarnatingList) return this->_IncarnatingList; } std::vector CClientEditionModule::getTalkingAsList() const { //H_AUTO(R2_CClientEditionModule_getTalkingAsList) return this->_TalkingAsList; } void CClientEditionModule::systemMsg(NLNET::IModuleProxy * /* sender */, const std::string& msgType, const std::string& who, const std::string& msg) { //H_AUTO(R2_CClientEditionModule_systemMsg) R2::getEditor().getLua().push(msgType); R2::getEditor().getLua().push(who); R2::getEditor().getLua().push(msg); R2::getEditor().callEnvFunc("onSystemMessageReceived", 3 , 0); } void CClientEditionModule::updateScenarioRingAccess(bool ok, const std::string& ringAccess, const std::string& errMsg) { //H_AUTO(R2_CClientEditionModule_updateScenarioRingAccess) DROP_IF(_ServerEditionProxy == NULL, "Server Edition Module not connected", return); CShareServerEditionItfProxy serverEditionModule(_ServerEditionProxy); serverEditionModule.onScenarioRingAccessUpdated(this, ok, ringAccess, errMsg); } std::string CClientEditionModule::getCharacterRingAccess() const { //H_AUTO(R2_CClientEditionModule_getCharacterRingAccess) return _RingAccess; } void CClientEditionModule::onRingAccessUpdated(NLNET::IModuleProxy * /* moduleSocket */, const std::string& ringAccess) { //H_AUTO(R2_CClientEditionModule_onRingAccessUpdated) _RingAccess = ringAccess; //Remove first and last char if (!_RingAccess.empty()) { if (_RingAccess[0] == '\'' || _RingAccess[0] == '"') { _RingAccess = _RingAccess.substr(1); } } if (!_RingAccess.empty()) { if (_RingAccess[_RingAccess.size()-1] == '\'' || _RingAccess[_RingAccess.size()-1] == '"') { _RingAccess = _RingAccess.substr(0, _RingAccess.size()-1); } } R2::getEditor().getLua().push(_RingAccess); R2::getEditor().callEnvFunc( "onRingAccessUpdated",1 ,0); } /* */ void CClientEditionModule::addToSaveList(const std::string& filename, const std::vector< std::pair < std::string, std::string> >& values) { //H_AUTO(R2_CClientEditionModule_addToSaveList) std::string name = filename; // Must use prefix or suffix? NLMISC::COFile out; CObject* scenario = getCurrentScenario()->getHighLevel(); if (!scenario) { nlwarning("Can't save: no scenario yet"); return; } CScenarioValidator* sv = new CScenarioValidator(); CScenarioValidator::TValues v1(values); std::string md5; bool ok = true; ok = sv->setScenarioToSave(filename, scenario, v1, md5); if (!ok) { delete sv; } else { if ( !_ScenarioToSave.insert( std::make_pair(md5, sv)).second ) { nlwarning("Ask 2 time the save of the same scenario?"); delete sv; return; } DROP_IF(_ServerEditionProxy == NULL, "Server Edition Module not connected", return); CShareServerEditionItfProxy serverEditionModule(_ServerEditionProxy); serverEditionModule.saveScenarioFile(this, md5 ,R2::TScenarioHeaderSerializer (v1) ); } // :TODO: VIANNEY add all _LastReadHeader.clear(); _LastReadHeader.push_back( std::pair("BodyMD5", sv->getBodyMd5() )); _LastReadHeader.insert(_LastReadHeader.end(), values.begin(), values.end()); // sv.openHeader(filename, v2, true); return; } /**********************************************************/ /****** ADD TO USER COMPONENT SAVE LIST *******************/ /**********************************************************/ void CClientEditionModule::addToUserComponentSaveList(const std::string& filename, const std::vector< std::pair < std::string, std::string> >& values, std::string &body) { //H_AUTO(R2_CClientEditionModule_addToSaveList) std::string name = filename; // Must use prefix or suffix? NLMISC::COFile out; CUserComponentValidator* ucv = new CUserComponentValidator(); CUserComponentValidator::TValues v1(values); std::string md5; bool ok = true; ok = ucv->setUserComponentToSave(filename, v1, md5, body); if (!ok) { delete ucv; } else { if ( !_UserComponentToSave.insert( std::make_pair(md5, ucv)).second ) { nlwarning("Ask 2 time the save of the same user component?"); delete ucv; return; } DROP_IF(_ServerEditionProxy == NULL, "Server Edition Module not connected", return); CShareServerEditionItfProxy serverEditionModule(_ServerEditionProxy); serverEditionModule.saveUserComponentFile(this, md5 ,R2::TScenarioHeaderSerializer (v1) ); } return; } void CClientEditionModule::saveUserComponentFileAccepted(NLNET::IModuleProxy *senderModuleProxy, const std::string& md5, const std::string& signature, bool ok) { //H_AUTO(R2_CClientEditionModule_saveScenarioFileAccepted) TUserComponentToSave::iterator found(_UserComponentToSave.find(md5)); if (found == _UserComponentToSave.end()) { nlwarning("The client has ask more than one time to save the same file"); return; } CUserComponentValidator* userComponentToSave = found->second; _UserComponentToSave.erase(found); if (ok) { userComponentToSave->applySave(signature); addToUserComponentLoadList(userComponentToSave->getFilename(), new CLoadUserComponentSucceeded(this)); } else { systemMsg(senderModuleProxy, "ERR", "", "uiR2EDServerRefuseToSave"); } } bool CClientEditionModule::addToUserComponentLoadList( const std::string& filename, CUserComponentValidatorLoadSuccededCallback* cb) { //H_AUTO(R2_CClientEditionModule_addToLoadList) CUserComponentValidator* ucv = new CUserComponentValidator(cb); CUserComponentValidator::TValues values; std::string md5; std::string signature; bool ok = true; nlinfo("Adding user component '%s' to load list", filename.c_str()); ok = ucv->setUserComponentToLoad(filename, values, md5, signature, ClientCfg.CheckR2ScenarioMD5); if (!ok) { R2::getEditor().callEnvFunc( "displayModifiedUserComponentFileError", 0, 0); nlwarning("setUserComponentToLoad failed"); return false; } if ( !_UserComponentToLoad.insert( std::make_pair(md5, ucv)).second ) { nlwarning("Ask 2 time the load of the same user component?"); //or the same empty uc file delete ucv; return false; } DROP_IF(_ServerEditionProxy == NULL, "Server Edition Module not connected", return false); CShareServerEditionItfProxy serverEditionModule(_ServerEditionProxy); serverEditionModule.loadUserComponentFile(this, md5, signature); return true; } void CClientEditionModule::loadUserComponentFileAccepted(NLNET::IModuleProxy * /* senderModuleProxy */, const std::string& md5, bool ok) { //H_AUTO(R2_CClientEditionModule_loadScenarioFileAccepted) TUserComponentToLoad::iterator found(_UserComponentToLoad.find(md5)); if (found == _UserComponentToLoad.end()) { nlwarning("The client has ask more than one time to save the same file"); return; } auto_ptr userComponentToLoad(found->second); _UserComponentToLoad.erase(found); if (!ok) { nlwarning("The server has refuse the client to load the a file"); //should (can) not happen this->systemMsg(0, "ERR", "", "The server has refuse the client to load the a file"); return; } std::string filename; std::string body; CUserComponentValidator::TValues values; userComponentToLoad->applyLoad(filename, body, values); _LastReadHeader = values; //return body; } /**************************************************************************************/ void CClientEditionModule::saveScenarioFileAccepted(NLNET::IModuleProxy *senderModuleProxy, const std::string& md5, const std::string& signature, bool ok) { //H_AUTO(R2_CClientEditionModule_saveScenarioFileAccepted) TScenarioToSave::iterator found(_ScenarioToSave.find(md5)); if (found == _ScenarioToSave.end()) { nlwarning("The client has ask more than one time to save the same file"); return; } auto_ptr scenarioToSave(found->second); _ScenarioToSave.erase(found); if (ok) { scenarioToSave->applySave(signature); } else { systemMsg(senderModuleProxy, "ERR", "", "uiR2EDServerRefuseToSave"); } } bool CClientEditionModule::addToLoadList( const std::string& filename, CScenarioValidatorLoadSuccededCallback* cb) { //H_AUTO(R2_CClientEditionModule_addToLoadList) CScenarioValidator* sv = new CScenarioValidator(cb); CScenarioValidator::TValues values; std::string md5; std::string signature; bool ok = true; ok = sv->setScenarioToLoad(filename, values, md5, signature, ClientCfg.CheckR2ScenarioMD5); if (!ok){ return false; } if ( !_ScenarioToLoad.insert( std::make_pair(md5, sv)).second ) { nlwarning("Ask 2 time the load of the same scenario?"); //or the same empty scenario delete sv; return false; } DROP_IF(_ServerEditionProxy == NULL, "Server Edition Module not connected", return false); CShareServerEditionItfProxy serverEditionModule(_ServerEditionProxy); serverEditionModule.loadScenarioFile(this, md5, signature); return true; } void CClientEditionModule::loadScenarioSucceded(const std::string& filename, const std::string& body, const CScenarioValidator::TValues& values) { //H_AUTO(R2_CClientEditionModule_loadScenarioSucceded) string initialIsland="", initialEntryPoint="", initialSeason = ""; string creatorMD5 = "", modifiedByMD5=""; string name = ""; string locked = ""; for(uint i=0; i& pair = values[i]; if(pair.first == "InitialIsland") initialIsland = pair.second; else if(pair.first == "InitialEntryPoint") initialEntryPoint = pair.second; else if(pair.first == "InitialSeason") initialSeason = pair.second; else if(pair.first == "OwnerMd5") initialSeason = pair.second; else if(pair.first == "CreatorMD5") creatorMD5 = pair.second; else if(pair.first == "OtherCharAccess") locked = pair.second; else if(pair.first == "ModifierMD5") modifiedByMD5 = pair.second; else if(pair.first == "Name") name = pair.second; } if (!modifiedByMD5.empty() && !locked.empty() && locked == "RunOnly") { bool ok = hasCharacterSameCharacterIdMd5(modifiedByMD5); if (!ok) { this->systemMsg(0, "ERR", "", "uiR2EDLoadingLockedScenario"); return; } } R2::getEditor().getUI().displaySystemInfo(CI18N::get("uiR2EDLoadingScenario"), "BC"); CObject* object = _Client->getComLuaModule().loadFromBuffer(body, filename, values); _LastReadHeader = values; if (object) { if (!initialIsland.empty() && !initialEntryPoint.empty() && !initialSeason.empty()) { // CShareServerEditionItfProxy serverEditionModule(_ServerEditionProxy); // serverEditionModule.teleportWhileUploadingScenario(this, initialIsland, initialEntryPoint, initialSeason); R2::getEditor().clearContent(); } _Client->requestUploadScenario(object); if (!name.empty() && object && object->isTable() && object->isString("InstanceId")) { CObjectString objectName(name); _Client->requestSetNode(object->toString("InstanceId"), "Ghost_Name", &objectName); } } if (CFile::fileExists(filename)) { CFile::copyFile("save/r2_buffer.dat", filename.c_str()); } } void CClientEditionModule::loadAnimationSucceded(const std::string& filename, const std::string& body, const CScenarioValidator::TValues& values) { //H_AUTO(R2_CClientEditionModule_loadAnimationSucceded) std::string errMsg; _Client->loadAnimationFromBuffer(body, filename, errMsg, values); } void CClientEditionModule::loadScenarioFileAccepted(NLNET::IModuleProxy * /* senderModuleProxy */, const std::string& md5, bool ok) { //H_AUTO(R2_CClientEditionModule_loadScenarioFileAccepted) TScenarioToLoad::iterator found(_ScenarioToLoad.find(md5)); if (found == _ScenarioToLoad.end()) { nlwarning("The client has ask more than one time to save the same file"); return; } auto_ptr scenarioToLoad(found->second); _ScenarioToLoad.erase(found); if (!ok) { nlwarning("The server has refuse the client to load the a file"); //should (can) not append this->systemMsg(0, "ERR", "", "The server has refuse the client to load the a file"); return; } std::string filename; std::string body; CScenarioValidator::TValues values; scenarioToLoad->applyLoad(filename, body, values); _LastReadHeader = values; } void CClientEditionModule::setMute(bool mute) { //H_AUTO(R2_CClientEditionModule_setMute) _Mute = mute; } void CLoadUserComponentSucceeded::doOperation(const std::string& filename,const std::string& body,const CScenarioValidator::TValues& header) { CLuaState& state = R2::getEditor().getLua(); state.push((std::string)filename); state.push((std::string)body); state.newTable(); CClientEditionModule::TScenarioHeader::const_iterator first(header.begin()), last(header.end()); for ( ; first != last; ++first) { state.push(first->first); state.push(first->second); state.setTable(-3); } //R2::getEditor().getLua().push((bool)mustKick); R2::getEditor().callEnvFunc( "loadUserComponentCallback", 3, 0); } void CLoadAnimationSucceded::doOperation(const std::string& filename,const std::string& body,const CScenarioValidator::TValues& values) { //H_AUTO(R2_CLoadAnimationSucceded_doOperation) _Module->loadAnimationSucceded(filename, body, values); } void CLoadScenarioSucceded::doOperation(const std::string& filename,const std::string& body,const CScenarioValidator::TValues& values) { //H_AUTO(R2_CLoadScenarioSucceded_doOperation) _Module->loadScenarioSucceded(filename, body, values); } void CClientEditionModule::resetNameGiver() { //H_AUTO(R2_CClientEditionModule_resetNameGiver) _Factory->clear(); } bool CClientEditionModule::hasCharacterSameCharacterIdMd5(const std::string & charIdMd5) const { if (ClientCfg.Local == 1 ) { return true; } uint32 val = 0; uint32 first=0,last=(uint32)charIdMd5.size(); for (;first != last; ++first) { val *= 16; char c = charIdMd5[first]; if ('0' <= c && c <= '9') { val += (c-'0'); } else if ('A' <= c && c <= 'F') { val += 10+(c-'A'); } } uint32 charId = CRingAccess::uncypherCharId(val); uint32 myUserId = NetMngr.getUserId(); if ((charId>>4) != myUserId) { return false; } return true; } class CModuleMessageSender : public R2::IMessageSender { public: CModuleMessageSender(const NLNET::TModuleProxyPtr& proxy, NLNET::IModule* senderModule):_Proxy(proxy), _Sender(senderModule){} void operator()(const NLNET::CMessage & msg) { if (!_Proxy) { nlwarning("Can not send Message %s to destination", msg.getName().c_str()); return; } // Send msg to DSS (after cuting msg) if (ClientCfg.R2EDDssNetwork == 1) { _Proxy->sendModuleMessage(_Sender, msg); return; } TCharId charId = 0; if (ClientCfg.Local ) { charId = 999 << 4; } else { charId = CSessionBrowserImpl::getCharId(); } // Send msg to DSS (Simulate forward system) if (ClientCfg.R2EDDssNetwork == 2) { NLNET::CMessage handle; R2::CShareServerEditionItfProxy::buildMessageFor_forwardToDss(handle, charId, msg); _Proxy->sendModuleMessage(_Sender, handle); return; } // Send msg to DSS (Simulate forward system) if (ClientCfg.R2EDDssNetwork == 3) { NLNET::CMessage handle; R2::CShareServerEditionItfProxy::buildMessageFor_forwardToDss(handle, charId, msg); CSessionBrowserImpl::getInstance().send(handle); return; } // wrong value nlwarning("Error Msg lost"); return; } protected: NLNET::TModuleProxyPtr _Proxy; NLNET::IModule* _Sender; }; void CClientEditionModule::sendMsgToDss(const NLNET::CMessage& msg) { TCharId charId = 0; if (ClientCfg.Local ) { charId = 999 << 4; } else { charId = CSessionBrowserImpl::getCharId(); } // Direct send msg to DSS (not cut) if (ClientCfg.R2EDDssNetwork == 0) { _ServerEditionProxy->sendModuleMessage(this, msg); return; } CModuleMessageSender sender(_ServerEditionProxy, this); CMessageSpliter::sendSplitedMsg(charId, msg, sender); } //---------------------------------------------------------------------------------------------------------------- void CMessageSpliter::sendSplitedMsg(uint32 charId, const NLNET::CMessage& msg, IMessageSender& sender) { static const uint32 packetSize = 512; // 16K by packet uint32 size = msg.length(); uint32 nbPacket = 1 + (size-1) / packetSize; // :TODO: use the brodcast form of the message instead of manual message nldebug("Sending DSS message"); { NLNET::CMessage subMsg; R2::CShareServerEditionItfProxy::buildMessageFor_multiPartMsgHead(subMsg, charId, msg.getName(), nbPacket, size); // dssMsgForward sender(subMsg); } const uint8* buffer = msg.buffer(); uint32 i=0; for (; i != nbPacket; ++i) { // send packetSize octet except for the last packet that just send the remainings data uint32 dataSend = (i+1)*packetSize > size ? size - packetSize*i:packetSize; std::vector data(const_cast(&buffer[i*packetSize]), const_cast(&buffer[i*packetSize + dataSend]) ); NLNET::CMessage subMsg; R2::CShareServerEditionItfProxy::buildMessageFor_multiPartMsgBody(subMsg, charId, i, data); sender(subMsg); // TODO -> add callback send( (size - packetSize*i) / size) } // { NLNET::CMessage subMsg; R2::CShareServerEditionItfProxy::buildMessageFor_multiPartMsgFoot(subMsg, charId); sender(subMsg); } } // Messages from dss that notify that he has received data // We received first a multiPartMsgHead, then X multiPartMsgBody, then one multiPartMsgFoot void CClientEditionModule::multiPartMsgHead(NLNET::IModuleProxy * /* sender */, const std::string& msgName, uint32 nbPacket, uint32 size) { R2::getEditor().getLua().executeScriptNoThrow( NLMISC::toString("r2:onMessageSendingStart('%s', %u, %u)",msgName.c_str(), nbPacket, size ) ); } void CClientEditionModule::multiPartMsgBody(NLNET::IModuleProxy * /* sender */, uint32 packetId, uint32 packetSize) { R2::getEditor().getLua().executeScriptNoThrow( NLMISC::toString("r2:onMessageSendingUpdate(%u, %u)", packetId, packetSize)); } void CClientEditionModule::multiPartMsgFoot(NLNET::IModuleProxy * /* sender */) { R2::getEditor().getLua().executeScriptNoThrow( NLMISC::toString("r2:onMessageSendingFinish()")); }