Linux multi-monitor fullscreen support
[ryzomcore.git] / ryzom / client / src / r2 / dmc / client_edition_module.cpp
blob0898711eb330e997c87e7798a4075a5c92ba0832
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2013 Laszlo KIS-ADAM (dfighter) <dfighter1985@gmail.com>
6 // Copyright (C) 2015-2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
7 //
8 // This program is free software: you can redistribute it and/or modify
9 // it under the terms of the GNU Affero General Public License as
10 // published by the Free Software Foundation, either version 3 of the
11 // License, or (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU Affero General Public License for more details.
18 // You should have received a copy of the GNU Affero General Public License
19 // along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "stdpch.h"
24 #include <sstream>
25 #include <map>
27 #include "client_edition_module.h"
29 #include "dmc.h"
31 #include "../../interface_v3/interface_manager.h"
34 #include "nel/net/unified_network.h"
35 #include "nel/net/module_message.h"
36 #include "nel/net/module_socket.h"
37 #include "nel/net/module_builder_parts.h"
38 #include "nel/net/module_manager.h"
40 #include "nel/misc/command.h"
41 #include "nel/misc/path.h"
42 #include "nel/misc/types_nl.h"
43 #include "nel/misc/sstring.h"
45 #include "nel/ligo/primitive.h"
46 #include "nel/ligo/ligo_config.h"
47 #include "nel/ligo/primitive_utils.h"
49 #include "game_share/utils.h"
51 #include "game_share/object.h"
52 #include "game_share/scenario.h"
53 #include "game_share/r2_messages.h"
54 #include "game_share/ring_access.h"
56 #include "property_accessor.h"
57 #include "palette.h"
59 #include "../object_factory_client.h"
61 #include "com_lua_module.h"
63 #include "../../session_browser_impl.h"
64 #include "../../client_cfg.h"
65 #include "../../user_entity.h"
66 #include "../../view.h"
67 #include "../../init_main_loop.h"
68 #include "../../continent_manager.h"
69 #include "../../world_database_manager.h"
70 #include "../../far_tp.h"
71 #include "../../net_manager.h"
73 #include <zlib.h>
75 #ifdef DEBUG_NEW
76 #define new DEBUG_NEW
77 #endif
80 using namespace std;
81 using namespace NLMISC;
82 using namespace NLLIGO;
83 using namespace NLNET;
85 CVariable<std::string> UserComponentsExamplesDirectory ("DSS", "UserComponentsExampleDirectory", "", "examples/user_componts", 0, true );
86 CVariable<std::string> UserComponentsComponentsDirectory ("DSS", "UserComponentsComponentsDirectory", "", "examples/user_componts", 0, true );
87 CVariable<std::string> UserComponentsComponentExtension ("DSS", "UserComponentsComponentExtension", "", "gz", 0, true );
88 CVariable<std::string> UserComponentsSourceExtension ("DSS", "UserComponentsSourceExtension", "", "lua", 0, true );
91 namespace R2 {
93 // if client request an operation, and the server accept then the client do not need to received the same msg he send
94 // other client must receive the answer
95 class IServerAnswerMsg;
96 class CServerAnswerForseener
98 public:
99 typedef uint32 TMessageId ;
101 public:
102 CServerAnswerForseener():_MaxMessageId(0){}
103 ~CServerAnswerForseener();
104 // if ok == true, then simulate the replay that The Server would do for other client
105 // if ok == false, remove the Forseen Answer from the answer queue.
106 void ack(CClientEditionModule* client, NLNET::IModuleProxy *server, TMessageId msgId, bool ok );
108 // Add to the Forssen Answer queue (we do not take the ownership of value)
109 TMessageId onScenarioUploaded( const CObject* hlScenario) ;
110 TMessageId onNodeSet(const std::string &instanceId, const std::string &attrName, const R2::CObject *value);
111 TMessageId onNodeInserted(const std::string &instanceId, const std::string &attrName, sint32 position, const std::string &key, const R2::CObject *value);
112 TMessageId onNodeErased(const std::string &instanceId, const std::string &attrName, sint32 position);
113 TMessageId onNodeMoved(const std::string &instanceId1, const std::string &attrName1, sint32 position1, const std::string &instanceId2, const std::string &attrName2, sint32 position2);
115 private:
116 typedef std::map<TMessageId, IServerAnswerMsg*> TAnswers;
118 private:
119 uint32 _MaxMessageId;
120 TAnswers _Answers;
124 class IServerAnswerMsg
126 public:
127 virtual void ok(CClientEditionModule* client, NLNET::IModuleProxy *server) = 0;
128 virtual ~IServerAnswerMsg() {}
131 class CServerAnswerMsgScenarioUploaded: public IServerAnswerMsg
133 public:
134 CServerAnswerMsgScenarioUploaded( const R2::CObject* value)
135 :_Value( value?value->clone():0){}
137 void ok(CClientEditionModule* client, NLNET::IModuleProxy *server)
139 client->onScenarioUploaded(server, _Value.get());
141 private:
142 CUniquePtr<R2::CObject> _Value;
145 class CServerAnswerMsgSet: public IServerAnswerMsg
147 public:
148 CServerAnswerMsgSet(const std::string &instanceId, const std::string &attrName, const R2::CObject* value)
149 :_InstanceId(instanceId), _AttrName(attrName), _Value( value?value->clone():0){}
151 void ok(CClientEditionModule* client, NLNET::IModuleProxy *server)
153 client->onNodeSet(server, _InstanceId, _AttrName, _Value.get());
155 private:
156 std::string _InstanceId;
157 std::string _AttrName;
158 CUniquePtr<R2::CObject> _Value;
161 class CServerAnswerMsgInserted: public IServerAnswerMsg
163 public:
164 CServerAnswerMsgInserted(const std::string &instanceId, const std::string &attrName, sint32 position, const std::string &key, const R2::CObject* value)
165 :_InstanceId(instanceId), _AttrName(attrName), _Position(position), _Key(key), _Value( value?value->clone():0){}
167 void ok(CClientEditionModule* client, NLNET::IModuleProxy *server)
169 client->onNodeInserted(server, _InstanceId, _AttrName, _Position, _Key, _Value.get());
171 private:
172 std::string _InstanceId;
173 std::string _AttrName;
174 sint32 _Position;
175 std::string _Key;
176 CUniquePtr<R2::CObject> _Value;
179 class CServerAnswerMsgErased: public IServerAnswerMsg
181 public:
182 CServerAnswerMsgErased(const std::string &instanceId, const std::string &attrName, sint32 position)
183 :_InstanceId(instanceId), _AttrName(attrName), _Position(position){}
185 void ok(CClientEditionModule* client, NLNET::IModuleProxy *server)
187 client->onNodeErased(server, _InstanceId, _AttrName, _Position);
189 private:
190 std::string _InstanceId;
191 std::string _AttrName;
192 sint32 _Position;
195 class CServerAnswerMsgMoved : public IServerAnswerMsg
197 public:
198 CServerAnswerMsgMoved(const std::string &instanceId1, const std::string &attrName1, sint32 position1,
199 const std::string &instanceId2, const std::string &attrName2, sint32 position2)
200 :_InstanceId1(instanceId1), _AttrName1(attrName1), _Position1(position1),
201 _InstanceId2(instanceId2), _AttrName2(attrName2), _Position2(position2){}
203 void ok(CClientEditionModule* client, NLNET::IModuleProxy *server)
205 client->onNodeMoved(server, _InstanceId1, _AttrName1, _Position1, _InstanceId2, _AttrName2, _Position2);
207 private:
208 std::string _InstanceId1;
209 std::string _AttrName1;
210 sint32 _Position1;
211 std::string _InstanceId2;
212 std::string _AttrName2;
213 sint32 _Position2;
219 using namespace R2;
222 NLNET_REGISTER_MODULE_FACTORY(CClientEditionModule, "ClientEditionModule");
225 //----------------------------- <CServerAnswer> -------------------------------
226 CServerAnswerForseener::~CServerAnswerForseener()
228 TAnswers::iterator first(_Answers.begin()), last(_Answers.end());
229 for (; first != last; ++first)
231 IServerAnswerMsg* msg = first->second;
232 delete msg;
234 _Answers.clear();
239 void CServerAnswerForseener::ack(CClientEditionModule* client, NLNET::IModuleProxy *server, TMessageId msgId, bool ok)
241 TAnswers::iterator found = _Answers.find(msgId);
242 BOMB_IF( found == _Answers.end(), "Message not found", return);
244 IServerAnswerMsg* msg = found->second;
245 if (ok)
247 msg->ok(client, server);
249 delete msg;
250 _Answers.erase(found);
253 // Add to the Forseen Answer queue
254 CServerAnswerForseener::TMessageId CServerAnswerForseener::onScenarioUploaded( const R2::CObject* hlScenario)
256 bool ok = _Answers.insert( std::make_pair(++_MaxMessageId, new CServerAnswerMsgScenarioUploaded(hlScenario))).second;
257 nlassert(ok);
258 return _MaxMessageId;
261 CServerAnswerForseener::TMessageId CServerAnswerForseener::onNodeSet(const std::string &instanceId, const std::string &attrName, const R2::CObject* value)
263 bool ok = _Answers.insert(std::make_pair(++_MaxMessageId, new CServerAnswerMsgSet(instanceId, attrName, value))).second;
264 nlassert(ok);
265 return _MaxMessageId;
268 CServerAnswerForseener::TMessageId CServerAnswerForseener::onNodeInserted(const std::string &instanceId, const std::string &attrName, sint32 position, const std::string &key, const R2::CObject* value)
270 bool ok = _Answers.insert(std::make_pair(++_MaxMessageId, new CServerAnswerMsgInserted(instanceId, attrName, position, key, value))).second;
271 nlassert(ok);
272 return _MaxMessageId;
275 CServerAnswerForseener::TMessageId CServerAnswerForseener::onNodeErased(const std::string &instanceId, const std::string &attrName, sint32 position)
277 bool ok = _Answers.insert(std::make_pair(++_MaxMessageId, new CServerAnswerMsgErased(instanceId, attrName, position ))).second;
278 nlassert(ok);
279 return _MaxMessageId;
282 CServerAnswerForseener::TMessageId CServerAnswerForseener::onNodeMoved(const std::string &instanceId1, const std::string &attrName1, sint32 position1, const std::string &instanceId2, const std::string &attrName2, sint32 position2)
284 bool ok = _Answers.insert(std::make_pair(++_MaxMessageId, new CServerAnswerMsgMoved(instanceId1, attrName1, position1, instanceId2, attrName2, position2 ))).second;
285 nlassert(ok);
286 return _MaxMessageId;
289 //------------------------------- <CEditorConfig> -------------------------------------------
292 std::map<std::string, uint32> CEditorConfig::_NameToId;
294 CEditorConfig::CEditorConfig()
296 if (_NameToId.empty())
298 _NameToId["BossSpawner"] = 0;
299 _NameToId["Timer"] = 1;
300 _NameToId["ZoneTrigger"] = 2;
301 _NameToId["UserTrigger"] = 3;
302 _NameToId["TalkTo"] = 4;
303 _NameToId["RequestItem"] = 5;
304 _NameToId["GiveItem"] = 6;
305 _NameToId["EasterEgg"] = 7;
306 _NameToId["LootSpawner"] = 8;
307 _NameToId["Fauna"] = 9;
308 _NameToId["BanditCamp"] = 10;
309 _NameToId["ChatSequence"] = 11;
310 _NameToId["TimedSpawner"] = 12;
311 _NameToId["Ambush"] = 13;
312 _NameToId["ManHunt"] = 14;
313 _NameToId["VisitZone"] = 15;
314 _NameToId["KillNpc"] = 16;
315 _NameToId["HuntTask"] = 17;
316 _NameToId["DeliveryTask"] = 18;
317 _NameToId["TargetMob"] = 19;
318 _NameToId["HiddenChest"] = 20;
319 _NameToId["RandomChest"] = 21;
320 _NameToId["UserComponent"] = 22;
321 _NameToId["Npc"] = 23;
322 _NameToId["GetItemFromSceneryObjectTaskStep"] = 24;
323 _NameToId["GetItemFromSceneryObject"] = 25;
324 _NameToId["SceneryObjectInteractionTaskStep"] = 26;
325 _NameToId["SceneryObjectInteraction"] = 27;
326 _NameToId["SceneryObjectRemover"] = 28;
327 _NameToId["RewardProvider"] = 29;
328 _NameToId["NpcInteraction"] = 30;
329 _NameToId["Quest"] = 31;
330 _NameToId["ProximityDialog"] = 32;
335 void CEditorConfig::setDisplayInfo(const std::string& formName, bool displayInfo)
337 //H_AUTO(R2_CEditorConfig_setDisplayInfo)
338 CInterfaceManager *IM = CInterfaceManager::getInstance ();
339 uint32 index = _NameToId[formName];
340 uint32 newValue = static_cast<uint32>(NLGUI::CDBManager::getInstance()->getDbProp("UI:SAVE:R2:DISPLAYINFO")->getValue32());
341 if (displayInfo == false )
342 newValue &= ~(1 << index);
343 else
344 newValue |= (1 << index);
345 NLGUI::CDBManager::getInstance()->getDbProp("UI:SAVE:R2:DISPLAYINFO")->setValue32(static_cast<sint32>(newValue));
349 void CEditorConfig::setDisplayInfo(uint32 displayInfo)
351 //H_AUTO(R2_CEditorConfig_setDisplayInfo)
352 CInterfaceManager *IM = CInterfaceManager::getInstance ();
353 NLGUI::CDBManager::getInstance()->getDbProp("UI:SAVE:R2:DISPLAYINFO")->setValue32(static_cast<sint32>(displayInfo));
358 bool CEditorConfig::mustDisplayInfo(const std::string& formName) const
360 //H_AUTO(R2_CEditorConfig_mustDisplayInfo)
361 CInterfaceManager *IM = CInterfaceManager::getInstance ();
362 std::map<std::string, uint32>::const_iterator found = _NameToId.find(formName);
363 if (found == _NameToId.end())
364 return false;
365 uint32 index = (*found).second;
366 uint32 newValue = static_cast<uint32>(NLGUI::CDBManager::getInstance()->getDbProp("UI:SAVE:R2:DISPLAYINFO")->getValue32());
367 uint32 ok = (newValue >> index) & 0x00000001;
368 if (ok != 0)
369 return true;
370 return false;
373 bool CEditorConfig::hasDisplayInfo(const std::string& formName) const
375 //H_AUTO(R2_CEditorConfig_hasDisplayInfo)
376 std::map<std::string, uint32>::const_iterator found = _NameToId.find(formName);
377 if (found != _NameToId.end())
378 return true;
379 return false;
382 uint32 CEditorConfig::getDisplayInfo() const
384 //H_AUTO(R2_CEditorConfig_getDisplayInfo)
385 CInterfaceManager *IM = CInterfaceManager::getInstance ();
386 return static_cast<uint32>(NLGUI::CDBManager::getInstance()->getDbProp("UI:SAVE:R2:DISPLAYINFO")->getValue32());
391 //----------------------------<CClientEditionModule>-------------------------------------------------------------
392 CClientEditionModule::CClientEditionModule()
395 CShareClientEditionItfSkel::init(this);
396 _Initialized = false;
397 _ChannelId = TChanID::Unknown;
398 _Mute = false;
400 _ServerAnswerForseener = 0;
403 CClientEditionModule::~CClientEditionModule()
405 release();
408 void CClientEditionModule::init(NLNET::IModuleSocket* clientGw, CDynamicMapClient* client)
410 //H_AUTO(R2_CClientEditionModule_init)
411 _Client = client;
413 // _ClientGw = clientGw;
415 _Eid = "Client0";
416 _TranslationModule = 0;
417 _SessionId = TSessionId(0);
420 init();
421 this->plugModule(clientGw);
424 void CClientEditionModule::init()
426 //H_AUTO(R2_CClientEditionModule_init)
427 if( _Initialized )
428 return;
429 _Emotes.reset( new CEmoteBehavior() );
430 _Palette = new CPalette();
431 _Scenario = new CScenario(0);
432 _Factory = new CObjectFactoryClient(_Eid);
433 _PropertyAccessor = new CPropertyAccessor(_Client, _Factory);
434 // CObjectSerializer::Factory = _Factory;
435 CObjectSerializerClient::setClientObjectFactory(_Factory);
436 _Initialized = true;
437 _MaxNpcs = 100;
438 _MaxStaticObjects = 100;
440 _ClientEditorConfig = new CEditorConfig();
442 _MustStartScenario = false;
443 _ScenarioUpToDate = false;
444 _IsSessionOwner = false;
445 _ServerAnswerForseener = new CServerAnswerForseener();
449 // when server is launched locally, it shouldn't use the client factory,
450 // this class disable when local server is called
451 //class CSerialFactoryBackup
453 //public:
454 // CSerialFactoryBackup(CObjectFactory *newValue = NULL) : ClientFactory(CObjectSerializer::Factory)
455 // {
456 // CObjectSerializer::Factory = newValue;
457 // }
458 // ~CSerialFactoryBackup()
459 // {
460 // CObjectSerializer::Factory = ClientFactory;
461 // }
462 // CObjectFactory *ClientFactory;
463 //};
466 void CClientEditionModule::release()
468 //H_AUTO(R2_CClientEditionModule_release)
469 delete _ServerAnswerForseener; _ServerAnswerForseener = 0;
470 delete _Palette; _Palette = 0;
471 delete _Scenario; _Scenario = 0;
472 delete _Factory; _Factory = 0;
473 delete _PropertyAccessor; _PropertyAccessor = 0;
474 _Initialized = false;
475 _Emotes.reset();
480 void CClientEditionModule::onModuleUp(NLNET::IModuleProxy *moduleProxy)
482 //H_AUTO(R2_CClientEditionModule_onModuleUp)
483 std::string moduleClassName = moduleProxy->getModuleClassName();
485 if (moduleClassName == "ServerEditionModule")
487 _ServerEditionProxy = moduleProxy;
488 return;
491 if (moduleClassName == "ServerAnimationModule")
493 _ServerAnimationProxy = moduleProxy;
494 return;
500 void CClientEditionModule::onModuleDown(NLNET::IModuleProxy *moduleProxy)
502 //H_AUTO(R2_CClientEditionModule_onModuleDown)
503 std::string moduleClassName = moduleProxy->getModuleClassName();
505 if (moduleClassName == "ServerEditionModule")
507 _ServerEditionProxy = NULL;
509 else if ( moduleClassName == "ServerAnimationModule")
511 _ServerAnimationProxy = NULL;
513 else
514 return;
517 bool CClientEditionModule::onProcessModuleMessage(IModuleProxy *senderModuleProxy, const CMessage &message)
519 //H_AUTO(R2_CClientEditionModule_onProcessModuleMessage)
521 // CSerialFactoryBackup fb(_Factory); // restore client factory the time to process server msg ...
523 // if (CShareClientEditionItfSkel::onDispatchMessage(senderModuleProxy, message))
524 // {
525 // return;
526 // }
530 std::string operationName = message.getName();
532 if (operationName == "CUCD") //onUserComponentDownloaded
534 CUserComponent* component = new CUserComponent();
535 //message.serial(const_cast<CUserComponent&>(*component));
536 component->serial( const_cast<CMessage&>(message));
537 onUserComponentDownloaded(senderModuleProxy, component);
538 return true;
541 if (operationName == "HELLO")
543 // this is just the firewall opening message, nothing to do
544 return true;
547 if (operationName == "ADV_CONN")
549 CEditor::connectionMsg("");
550 CClientMessageAdventureUserConnection bodyConnection;
551 nlRead(message,serial,bodyConnection);
552 onRingAccessUpdated(0, bodyConnection.RingAccess);
554 nlinfo("R2CED: user Connected as Client %d In Mode %d", bodyConnection.EditSlotId, bodyConnection.Mode);
555 _SessionId = bodyConnection.SessionId;
556 _AiInstanceId = bodyConnection.AiInstance;
557 _SessionType = bodyConnection.SessionType;
558 _IsSessionOwner = bodyConnection.IsSessionOwner;
559 _EditSessionLink = bodyConnection.EditSessionLink;
561 switch(bodyConnection.SessionType)
563 case st_edit: getEditor().setAccessMode(CEditor::AccessEditor); break;
564 case st_anim: getEditor().setAccessMode(CEditor::AccessDM); break;
565 default: nlassert(0 && "SessionType not handled.");
568 if (bodyConnection.SessionType == st_edit)
571 if (bodyConnection.Mode == 1)
573 _Client->onResetEditionMode();
577 CObject* data = bodyConnection.HighLevel.getData();
578 if (!data && bodyConnection.InCache)
581 CScenarioValidator sv;
582 CScenarioValidator::TValues values;
583 std::string md5, signature;
585 if ( sv.setScenarioToLoad("save/r2_buffer.dat", values, md5, signature, true)
586 && !md5.empty()
587 && CScenarioValidator::AutoSaveSignature == signature)
589 data = _Client->getComLuaModule().loadLocal("save/r2_buffer.dat", values);
591 else
593 nlinfo("Data corrupted (the server has refused to accept the scenario).");
596 _Client->onEditionModeConnected(bodyConnection.EditSlotId, bodyConnection.SessionId.asInt(), data, bodyConnection.VersionName, bodyConnection.MustTp, bodyConnection.InitialActIndex);
597 if (bodyConnection.Mode == 2)
599 _Client->onEditionModeDisconnected();
600 _Client->onTestModeConnected();
602 // warn server that adventure has been connected, so we are ready to receive the TP message
603 CShareServerEditionItfProxy proxy(_ServerEditionProxy);
604 proxy.advConnACK(this);
606 else if (bodyConnection.SessionType == st_anim)
608 // 0 -> wait loading animation
609 // 1 -> waiting the other to load animation
610 // 2 -> play (dm)
611 // 3 -> play (simple player)
612 _Client->onAnimationModeConnected(bodyConnection);
614 // warn server that advneutre has been connected, so we are ready to receive the TP message
616 return true;
621 if (operationName == "EDITOR_STOP")
623 _Client->onEditionModeDisconnected();
624 _Client->onTestModeConnected();
625 return true;
629 if ( operationName=="stringTable")
631 nlwarning("received string table!");
632 uint32 nb,i;
633 nlRead(message, serial, nb);
634 i=nb;
635 nlwarning("%d entries! ",nb);
636 while(i)
638 std::string localId;
639 std::string value;
640 nlRead(message, serial,localId);
641 nlRead(message,serial,value);
642 nlwarning("{ %s , %s}",localId.c_str(),value.c_str());
643 i--;
645 return true;
648 if(operationName == "stringValue")
650 std::string localId;
651 std::string value;
652 nlRead(message,serial,localId);
653 nlRead(message,serial,value);
654 nlwarning("received {%s , %s}",localId.c_str(),value.c_str());
655 return true;
658 if (operationName == "idList")
660 uint32 nb,i;
661 nlRead(message,serial,nb);
662 i=nb;
663 nlwarning("%d entries! ",nb);
664 while(i)
666 std::string localId;
667 nlRead(message,serial,localId);
668 nlwarning("{ %s }",localId.c_str());
669 i--;
671 return true;
673 if (operationName == "HELLO")
675 // this is just the firewall opening message, nothing to do
676 return true;
679 if (operationName == "NPC_APROP")
681 uint32 modes;
682 nlRead(message,serial,modes);
683 _Client->onNpcAnimationTargeted(modes);
684 return true;
688 return false;
692 void CClientEditionModule::onTestModeDisconnected(NLNET::IModuleProxy * /* moduleProxy */, TSessionId sessionId, uint32 lastAct, TScenarioSessionType sessionType)
694 //H_AUTO(R2_CClientEditionModule_onTestModeDisconnected)
695 // indicate the Editor that the animation has stopped.
696 _Client->onTestModeDisconnected(sessionId, lastAct, sessionType);
699 if ( sessionType == st_edit )
701 this->requestReconnection();
708 void CClientEditionModule::onModuleSecurityChange(IModuleProxy * /* moduleProxy */)
710 //H_AUTO(R2_CClientEditionModule_onModuleSecurityChange)
713 void CClientEditionModule::requestCreateScenario(CObject* scenario)
715 //H_AUTO(R2_CClientEditionModule_requestCreateScenario)
716 this->requestUploadScenario(scenario);
720 bool CClientEditionModule::requestTeleportOneCharacterToAnother(uint32 sessionId, uint32 sourceCharId, uint32 destCharId)
722 //H_AUTO(R2_CClientEditionModule_requestTeleportOneCharacterToAnother)
723 BOMB_IF(_ServerEditionProxy == NULL, "Server Edition Module not connected", return false);
725 CShareServerEditionItfProxy proxy(_ServerEditionProxy);
726 proxy.teleportOneCharacterToAnother(this, (TSessionId)sessionId, sourceCharId, destCharId);
727 return true;
731 void CClientEditionModule::requestUpdateRtScenario( CObject* scenario)
733 //H_AUTO(R2_CClientEditionModule_requestUpdateRtScenario)
734 // CSerialFactoryBackup fb;
735 CMessage message ("requestUpdateRtScenario");
736 BOMB_IF(_ServerEditionProxy == NULL, "Server Edition Module not connected", return);
737 CObjectSerializerServer obj(scenario);
738 obj.compress();
739 message.serial(obj);
741 _ServerEditionProxy->sendModuleMessage(this, message );
746 void CClientEditionModule::requestCreatePrimitives()
748 //H_AUTO(R2_CClientEditionModule_requestCreatePrimitives)
749 CMessage message ("DBG_CREATE_PRIMITIVES");
750 BOMB_IF(_ServerEditionProxy == NULL, "Server Edition Module not connected", return);
751 _ServerEditionProxy->sendModuleMessage(this, message );
755 void CClientEditionModule::requestStopTest()
757 //H_AUTO(R2_CClientEditionModule_requestStopTest)
758 CMessage message ("STOP_TEST");
759 BOMB_IF(_ServerEditionProxy == NULL, "Server Edition Module not connected", return);
760 _ServerEditionProxy->sendModuleMessage(this, message );
766 bool CClientEditionModule::requestUploadScenario(CObject* scenario)
768 //H_AUTO(R2_CClientEditionModule_requestUploadScenario)
769 // CSerialFactoryBackup fb;
770 BOMB_IF(_ServerEditionProxy == NULL, "Server Edition Module not connected", return false);
772 CShareServerEditionItfProxy proxy(_ServerEditionProxy);
773 CObjectSerializerServer body(scenario);
774 body.compress();
776 proxy.onScenarioUploadAsked(this, body, true);
779 uint32 messageId = _ServerAnswerForseener->onScenarioUploaded( scenario);
780 NLNET::CMessage msg;
781 sendMsgToDss(CShareServerEditionItfProxy::buildMessageFor_onScenarioUploadAsked(msg, messageId, body, true));
782 return true;
786 void CClientEditionModule::requestSetNode(const std::string& instanceId, const std::string& attrName, CObject* value)
788 //H_AUTO(R2_CClientEditionModule_requestSetNode)
789 if (value)
791 CObject *clObj = getEditor().getDMC().find(instanceId, attrName);
792 if (clObj && clObj->getGhost())
794 value->setGhost(true);
796 if (value->getGhost())
798 // this is a local value -> forward directly to client
799 CObject *temp = value->clone();
800 getEditor().getDMC().nodeSet(instanceId, attrName, temp);
801 delete temp; // AJM
802 return;
805 if (!attrName.empty())
807 CObject* instance = _Scenario->find(instanceId);
809 if (instance)
811 CObject* property = _PropertyAccessor->getPropertyValue(instance, attrName);
812 if (property && property->equal(value))
814 //nlinfo("R2Cl: Optimisation(message not send)");
815 return;
820 requestSetNodeNoTest(instanceId, attrName, value);
824 void CClientEditionModule::requestSetNodeNoTest(const std::string& instanceId, const std::string& attrName, CObject* value)
826 //H_AUTO(R2_CClientEditionModule_requestSetNodeNoTest)
827 // CSerialFactoryBackup fb;
828 BOMB_IF(_ServerEditionProxy == NULL, "Server Edition Module not connected", return);
829 CShareServerEditionItfProxy proxy(_ServerEditionProxy);
830 CObjectSerializerServer value2(value);
831 value2.compress();
832 uint32 messageId = _ServerAnswerForseener->onNodeSet(instanceId, attrName, value);
833 proxy.onNodeSetAsked(this, messageId, instanceId, attrName, value2);
837 void CClientEditionModule::requestEraseNode( const std::string& instanceId, const std::string& attrName, sint32 position)
839 //H_AUTO(R2_CClientEditionModule_requestEraseNode)
840 CObject *clObj = getEditor().getDMC().find(instanceId, attrName, position);
841 if (clObj && clObj->getGhost())
843 // this is a ghost value -> forward directly to client
844 getEditor().getDMC().nodeErased(instanceId, attrName, position);
845 return;
848 // CSerialFactoryBackup fb;
849 BOMB_IF(_ServerEditionProxy == NULL, "Server Edition Module not connected", return);
850 CShareServerEditionItfProxy proxy(_ServerEditionProxy);
851 uint32 messageId = _ServerAnswerForseener->onNodeErased(instanceId, attrName, position);
852 proxy.onNodeEraseAsked(this, messageId, instanceId, attrName, position);
855 void CClientEditionModule::requestInsertNode(const std::string& instanceId, const std::string& attrName, sint32 position, const std::string& key, CObject* value)
857 //H_AUTO(R2_CClientEditionModule_requestInsertNode)
858 if (value)
860 // if value is inserted in a ghost node, then it inherits the 'ghost' flag
861 CObject *clObj = getEditor().getDMC().find(instanceId, attrName, -1);
862 if (clObj && clObj->getGhost())
864 value->setGhost(true);
866 if (value->getGhost())
868 // this is a ghost value -> forward directly to client
869 getEditor().getDMC().nodeInserted(instanceId, attrName, position, key, value->clone());
870 return;
873 // CSerialFactoryBackup fb;
874 BOMB_IF(_ServerEditionProxy == NULL, "Server Edition Module not connected", return);
875 CShareServerEditionItfProxy proxy(_ServerEditionProxy);
876 CObjectSerializerServer value2(value);
877 value2.compress();
878 uint32 messageId = _ServerAnswerForseener->onNodeInserted(instanceId, attrName, position, key, value);
879 proxy.onNodeInsertAsked(this, messageId, instanceId, attrName, position, key, value2);
883 void CClientEditionModule::requestMoveNode(
884 const std::string& instanceId, const std::string& attrName, sint32 position,
885 const std::string& destInstanceId, const std::string& destAttrName, sint32 destPosition)
887 //H_AUTO(R2_CClientEditionModule_requestMoveNode)
888 CObject *src = getEditor().getDMC().find(instanceId, attrName, position);
889 CObject *dest = getEditor().getDMC().find(destInstanceId, destAttrName);
890 if (src && dest)
892 nlassert(src->getGhost() == dest->getGhost());
893 if (src->getGhost())
895 // this is a ghost value -> forward directly to client
896 getEditor().getDMC().nodeMoved(instanceId, attrName, position,
897 destInstanceId, destAttrName, destPosition);
898 return;
901 if (src) nlassert(!src->getGhost());
902 if (dest) nlassert(!dest->getGhost());
903 // CSerialFactoryBackup fb;
905 BOMB_IF(_ServerEditionProxy == NULL, "Server Edition Module not connected", return);
906 CShareServerEditionItfProxy proxy(_ServerEditionProxy);
907 uint32 messageId = _ServerAnswerForseener->onNodeMoved(instanceId, attrName, position, destInstanceId, destAttrName, destPosition);
908 proxy.onNodeMoveAsked(this, messageId, instanceId, attrName, position, destInstanceId, destAttrName, destPosition);
912 void CClientEditionModule::requestMapConnection( uint32 scenarioId, bool mustTp, bool mustUpdateHighLevel)
914 //H_AUTO(R2_CClientEditionModule_requestMapConnection)
915 // CSerialFactoryBackup fb;
916 BOMB_IF(_ServerEditionProxy == NULL, "Server Edition Module not connected", return);
917 CShareServerEditionItfProxy proxy(_ServerEditionProxy);
918 proxy.onMapConnectionAsked(this, (TSessionId)scenarioId, mustTp, mustUpdateHighLevel, R2::TUserRole::ur_editor);
922 void CClientEditionModule::requestReconnection()
924 //H_AUTO(R2_CClientEditionModule_requestReconnection)
925 if (_SessionId.asInt() != 0)
927 this->requestMapConnection(_SessionId.asInt(), false, false);
932 CScenario* CClientEditionModule::getCurrentScenario() const {return _Scenario; }
935 void CClientEditionModule::addPaletteElement(const std::string& attrName, CObject* paletteElement)
937 //H_AUTO(R2_CClientEditionModule_addPaletteElement)
938 _Palette->addPaletteElement(attrName, paletteElement);
941 bool CClientEditionModule::isInPalette(const std::string& key) const
943 //H_AUTO(R2_CClientEditionModule_isInPalette)
944 return _Palette->isInPalette(key);
947 CObject* CClientEditionModule::getPropertyValue(CObject* component, const std::string& attrName) const
949 //H_AUTO(R2_CClientEditionModule_getPropertyValue)
950 return _PropertyAccessor->getPropertyValue(component, attrName);
953 CObject* CClientEditionModule::getPropertyValue(const std::string& instanceId, const std::string& attrName) const
955 //H_AUTO(R2_CClientEditionModule_getPropertyValue)
956 CObject* component = _Scenario->find(instanceId);
957 if (!component) return 0;
958 return _PropertyAccessor->getPropertyValue(component, attrName);
961 CObject* CClientEditionModule::getPropertyList(CObject* component) const
963 //H_AUTO(R2_CClientEditionModule_getPropertyList)
964 typedef std::list<std::string> TContainer;
966 TContainer properties;
968 _PropertyAccessor->getPropertyList(component, properties);
969 TContainer::const_iterator first(properties.begin()), last(properties.end());
970 for ( ; first != last; ++first)
972 component->add(new CObjectString(*first));
974 return component;
977 CObject* CClientEditionModule::getPaletteElement(const std::string& key)const
979 //H_AUTO(R2_CClientEditionModule_getPaletteElement)
980 return _Palette->getPaletteElement(key);
984 CObject* CClientEditionModule::newComponent(const std::string& type) const
986 //H_AUTO(R2_CClientEditionModule_newComponent)
987 return _Factory->newComponent(type);
990 void CClientEditionModule::registerGenerator(CObject* classObject)
992 //H_AUTO(R2_CClientEditionModule_registerGenerator)
993 _Factory->registerGenerator(classObject);
996 CPropertyAccessor& CClientEditionModule::getPropertyAccessor() const
998 //H_AUTO(R2_CClientEditionModule_getPropertyAccessor)
999 nlassert(_PropertyAccessor);
1000 return *_PropertyAccessor;
1003 void CClientEditionModule::updateScenario(CObject* scenario)
1005 //H_AUTO(R2_CClientEditionModule_updateScenario)
1006 nlassert(_Scenario);
1007 _Scenario->setHighLevel(scenario);
1008 std::string eid = getEid();
1009 _Factory->setMaxId(eid, _Scenario->getMaxId(eid));
1012 void CClientEditionModule::setEid(const std::string& eid)
1014 //H_AUTO(R2_CClientEditionModule_setEid)
1015 _Eid = eid;
1016 _Factory->setPrefix(_Eid);
1020 bool CClientEditionModule::askUpdateCharMode(R2::TCharMode mode)
1022 //H_AUTO(R2_CClientEditionModule_askUpdateCharMode)
1023 // CSerialFactoryBackup fb;
1024 if (_ServerEditionProxy == NULL) { return false; };
1026 CShareServerEditionItfProxy proxy(_ServerEditionProxy);
1027 proxy.onCharModeUpdateAsked(this, mode);
1028 return true;
1032 void CClientEditionModule::onCharModeUpdated(NLNET::IModuleProxy * /* senderModuleProxy */, R2::TCharMode mode)
1034 //H_AUTO(R2_CClientEditionModule_onCharModeUpdated)
1035 _CharMode = mode;
1036 if(UserEntity)
1037 UserEntity->setR2CharMode(mode);
1043 void CClientEditionModule::startScenario(class NLNET::IModuleProxy * proxy, bool ok, uint32 /* startingAct */, const std::string& errorReason)
1045 //H_AUTO(R2_CClientEditionModule_startScenario)
1046 if (ok)
1048 if (_SessionType == st_edit)
1050 _Client->onTestModeConnected();
1051 R2::getEditor().setMode(CEditor::DMMode);
1053 else if(_SessionType == st_anim)
1056 this->connectAnimationModePlay();
1058 CEditor::connectionMsg("");
1060 if (_CharMode == TCharMode::Dm)
1062 R2::getEditor().setMode(CEditor::AnimationModeDm);
1063 askMissionItemsDescription();
1065 else if (_CharMode == TCharMode::Tester || _CharMode == TCharMode::Player)
1067 R2::getEditor().setMode(CEditor::AnimationModePlay);
1069 else
1071 nlwarning("Error Mode not handled %d", _CharMode.getValue());
1072 R2::getEditor().setMode(CEditor::AnimationModePlay);
1075 //:TODO: must tp?
1077 else
1079 CEditor::connectionMsg("uiR2EDR2StartTestError");
1080 requestReconnection();
1083 if (!ok && errorReason.empty())
1085 systemMsg(proxy, "ERR", "", errorReason);
1091 void CClientEditionModule::startingScenario(class NLNET::IModuleProxy * /* serverProxy */, uint32 charId)
1093 //H_AUTO(R2_CClientEditionModule_startingScenario)
1094 CShareServerEditionItfProxy proxy(_ServerEditionProxy);
1095 bool ok = false;
1096 CObjectSerializerServer hlData;
1097 CObjectSerializerServer rtData;
1100 if (_Scenario)
1102 // Some times save is refused: be NevraxScenario must not be changed
1104 CScenarioValidator sv;
1105 CScenarioValidator::TValues values;
1106 std::string md5, signature;
1107 R2::getEditor().getLua().executeScriptNoThrow("r2.Translator.initStartingActIndex()");
1109 sv.setScenarioToLoad("save/r2_buffer.dat", values, md5, signature, true);
1110 _LastReadHeader = values;
1111 uint32 lastActIndex = _StartingActIndex;
1112 CObject* hlScenario2 = _Client->getComLuaModule().loadLocal("save/r2_buffer.dat", _LastReadHeader);
1113 _StartingActIndex = lastActIndex;
1114 if (hlScenario2)
1116 _Factory->clear();
1117 _Client->scenarioUpdated(hlScenario2, false, lastActIndex);
1119 _StartingActIndex = lastActIndex;
1125 uint32 myUserId = NetMngr.getUserId();
1126 std::string connectionState;
1128 if (myUserId == (charId>>4) || ClientCfg.Local)
1131 std::string errorMsg;
1133 CObject* hlScenario = _Scenario->getHighLevel();
1134 hlData.setData(hlScenario); // clone before modify by translateFeatures
1135 // translateFeatures change _StartingActIndex
1137 _Factory->setMaxId("RtAct", 0);
1138 _Factory->setMaxId("RtAiState", 0);
1139 _Factory->setMaxId("RtNpcGrp", 0);
1140 _Factory->setMaxId("RtNpcEventHandlerAction", 0);
1141 _Factory->setMaxId("RtNpcEventHandler", 0);
1142 _Factory->setMaxId("RtLocation", 0);
1143 _Factory->setMaxId("RtTextManager", 0);
1144 _Factory->setMaxId("RtScenario", 0);
1145 _Factory->setMaxId("RtUserTrigger", 0);
1146 _Factory->setMaxId("RtScenario", 0);
1147 _Factory->setMaxId("RtEntryText", 0);
1148 _Factory->setMaxId("RtPlotItem", 0);
1150 CUniquePtr<CObject> rtDataPtr( _Client->getComLuaModule().translateFeatures(hlScenario , errorMsg) );
1151 rtData.setData(rtDataPtr.get());
1153 if (rtDataPtr.get())
1155 ok = true;
1156 connectionState = "uiR2EDUploadScenario";
1158 #if !FINAL_VERSION
1159 string filename = CFile::findNewFile("scenario.rt.txt");
1160 COFile output(filename);
1161 std::string ss;
1162 rtDataPtr->serialize(ss);
1163 output.serialBuffer((uint8*)ss.c_str(),(uint)ss.size());
1164 output.flush();
1165 #endif
1167 else
1169 nlwarning("%s",errorMsg.c_str());
1170 connectionState = "uiR2EDR2StartTestError";
1173 TScenarioSessionType sessionType = _SessionType;
1175 if (ok && sessionType == st_anim)
1177 hlData.compress();
1179 NLNET::CMessage msg;
1180 uint32 messageId = _ServerAnswerForseener->onScenarioUploaded( hlScenario);
1181 sendMsgToDss(CShareServerEditionItfProxy::buildMessageFor_onScenarioUploadAsked(msg, messageId, hlData, false));
1184 rtData.compress();
1186 TScenarioHeaderSerializer header(_LastReadHeader);
1188 NLNET::CMessage msg;
1189 sendMsgToDss(CShareServerEditionItfProxy::buildMessageFor_startScenario(msg, ok, header, rtData, _StartingActIndex));
1192 else
1194 connectionState = "uiR2EDR2WaitUploadScenario";
1197 if (_SessionType == st_edit)
1199 _Client->onEditionModeDisconnected();
1200 R2::getEditor().setMode(CEditor::GoingToDMMode);
1202 else if (_SessionType == st_anim)
1204 _Client->onEditionModeDisconnected();
1205 R2::getEditor().setMode(CEditor::AnimationModeGoingToDm);
1209 CEditor::connectionMsg(connectionState);
1213 bool CClientEditionModule::requestStartScenario()
1215 //H_AUTO(R2_CClientEditionModule_ )
1217 BOMB_IF(_ServerEditionProxy == NULL, "Server Edition Module not connected", return false);
1219 CEditor::connectionMsg("uimR2EDGoToDMMode");
1221 R2::getEditor().getLua().executeScriptNoThrow("r2.Version.save(\"save/r2_buffer.dat\")");
1222 CShareServerEditionItfProxy proxy(_ServerEditionProxy);
1223 proxy.startingScenario(this);
1224 return true;
1228 void CClientEditionModule::updateUserComponentsInfo(const std::string & filename, const std::string& name, const std::string & description, uint32 timestamp, const std::string& md5hash)
1230 //H_AUTO(R2_CClientEditionModule_updateUserComponentsInfo)
1231 TUserComponents::iterator found = _UserComponents.find(filename);
1232 if (found == _UserComponents.end())
1234 nlwarning("Error: try to update information on a unknown component '%s'", filename.c_str() );
1235 return;
1237 found->second->Name = name;
1238 found->second->Description = description;
1239 found->second->TimeStamp = timestamp;
1240 found->second->Md5Id.fromString( md5hash );
1244 void CClientEditionModule::registerUserComponent(const std::string& filename)
1246 //H_AUTO(R2_CClientEditionModule_registerUserComponent)
1247 BOMB_IF(_ServerEditionProxy == NULL, "Server Edition Module not connected", return);
1249 TUserComponents::iterator found = _UserComponents.find(filename);
1250 if (found == _UserComponents.end())
1252 nlwarning("Error: try to upload unknown component '%s'", filename.c_str() );
1253 return;
1256 CShareServerEditionItfProxy proxy(_ServerEditionProxy);
1257 proxy.onUserComponentRegistered(this, found->second->Md5);
1261 CUserComponent* CClientEditionModule::getUserComponentByHashMd5( const NLMISC::CHashKeyMD5 & md5) const
1263 //H_AUTO(R2_CClientEditionModule_getUserComponentByHashMd5)
1265 TUserComponents::const_iterator first(_UserComponents.begin()), last(_UserComponents.end());
1266 for (; first != last && (first->second->Md5 != md5) ; ++first ) {}
1267 if (first == last)
1269 nlwarning("Error: try to upload unknown component '%s'", md5.toString().c_str() );
1270 return 0;
1273 return first->second;
1277 void CClientEditionModule::onUserComponentUploading(NLNET::IModuleProxy * /* senderModuleProxy */, const CHashKeyMD5 & md5)
1279 //H_AUTO(R2_CClientEditionModule_onUserComponentUploading)
1280 BOMB_IF(_ServerEditionProxy == NULL, "Server Edition Module not connected", return);
1282 CUserComponent* userComponent = getUserComponentByHashMd5(md5);
1284 if (userComponent)
1286 NLNET::CMessage message;
1287 message.setType("SUCU"); //onUserComponentUploaded
1288 userComponent->serial(message);
1289 _ServerEditionProxy->sendModuleMessage(this, message);
1292 return;
1296 void CClientEditionModule::onUserComponentRegistered(NLNET::IModuleProxy * /* senderModuleProxy */, const CHashKeyMD5 & md5)
1298 //H_AUTO(R2_CClientEditionModule_onUserComponentRegistered)
1299 BOMB_IF(_ServerEditionProxy == NULL, "Server Edition Module not connected", return);
1300 CUserComponent* userComponent = getUserComponentByHashMd5(md5);
1301 if (!userComponent)
1303 CShareServerEditionItfProxy proxy(_ServerEditionProxy);
1304 proxy.onUserComponentDownloading(this, md5);
1306 else
1308 std::string filename = userComponent->getFilename();
1309 R2::getEditor().getLua().executeScriptNoThrow(NLMISC::toString("r2.UserComponentsManager:addUserComponent('%s')", filename.c_str()));
1314 void CClientEditionModule::onUserComponentDownloaded(NLNET::IModuleProxy *senderModuleProxy, CUserComponent* component)
1316 //H_AUTO(R2_CClientEditionModule_onUserComponentDownloaded)
1318 // case 1 data are compressed
1319 component->UncompressedData = new uint8[component->UncompressedDataLength + 1];
1320 uLongf dataLength = static_cast<uLongf>(component->UncompressedDataLength);
1321 sint32 decompressionState = uncompress (reinterpret_cast<Bytef*>(component->UncompressedData), &dataLength ,
1322 reinterpret_cast<Bytef*>(component->CompressedData), component->CompressedDataLength);
1324 component->UncompressedDataLength = static_cast<uint32>(dataLength);
1326 if (decompressionState != Z_OK)
1328 nlwarning("Error: the downloaded user component is corrupted '%s'", component->Filename.c_str());
1329 delete component;
1330 return;
1332 component->UncompressedData[component->UncompressedDataLength] = '\0';
1334 // insert user component into user components map
1336 TUserComponents::iterator found = _UserComponents.find(component->Filename);
1337 if (found != _UserComponents.end())
1339 delete found->second;
1340 found->second = component;
1343 _UserComponents[component->Filename] = component;
1346 saveUserComponentFile(component->Filename, true);
1348 onUserComponentRegistered(senderModuleProxy, component->Md5);
1355 bool CClientEditionModule::loadUserComponent(const std::string& filename, bool mustReload)
1357 //H_AUTO(R2_CClientEditionModule_loadUserComponent)
1358 if (! mustReload)
1360 TUserComponents::const_iterator found = _UserComponents.find(filename);
1361 if (found != _UserComponents.end())
1363 return true;;
1367 std::string sourceExtension = UserComponentsSourceExtension.get();
1368 std::string componentExtension = UserComponentsComponentExtension.get();
1371 uint32 uncompressedFileLength = 0;
1372 uint8* uncompressedFile=0;
1373 uint32 compressedFileLength = 0;
1374 uint8* compressedFile=0;
1375 bool compressed = false;
1376 bool ok = false;
1378 if (CFile::getExtension(filename) == sourceExtension)
1380 compressed = false;
1381 ok = true;
1383 else if (CFile::getExtension(filename) == componentExtension)
1385 compressed = true;
1386 ok = true;
1388 if (!ok)
1390 nlwarning("Wrong file extension '%s'", filename.c_str() );
1391 nlwarning("Allowed file extension '%s' '%s'", sourceExtension.c_str(), componentExtension.c_str());
1392 return false;
1395 CHashKeyMD5 md5Id;
1396 uint32 timeStamp = 0;
1397 if (! compressed)
1399 FILE* file = nlfopen(filename, "rb");
1400 if (!file)
1402 nlwarning("Try to open an invalid file %s (access error)", filename.c_str());
1403 return false;
1406 // file length are the last uint32 of a file
1407 if (fseek(file,0, SEEK_END) != 0)
1409 nlwarning("Try to open an invalid file %s (size error)", filename.c_str());
1410 fclose(file);
1411 return false;
1413 uncompressedFileLength = ftell(file); // size of file
1416 if (fseek(file, 0, SEEK_SET) != 0)
1418 nlwarning("Try to open an invalid file %s (size error)", filename.c_str());
1419 fclose(file);
1420 return false;
1423 uncompressedFile = new uint8[uncompressedFileLength];
1424 int length = (int)fread(uncompressedFile, sizeof(char), uncompressedFileLength, file);
1425 if (length <0)
1427 nlwarning("Error while reading %s", filename.c_str());
1428 delete[] uncompressedFile;
1429 fclose(file);
1430 return false;
1434 if ( length < static_cast<sint32>(uncompressedFileLength))
1436 nlwarning("Error while reading %s (corrupted data)", filename.c_str());
1437 delete[] uncompressedFile;
1438 fclose(file);
1439 return false;
1442 fclose(file);
1445 // Test if data are not too big
1446 if (uncompressedFileLength > 200*1024)
1448 nlwarning("Try to open an invalid file %s (size error)", filename.c_str());
1449 delete [] uncompressedFile;
1450 return false;
1453 std::string compiledInfoHeader = "--COMPONENT HEADER\n";
1454 std::string compiledInfoFooter = "--COMPONENT BODY\n";
1456 // REMOVE HEADER
1457 std::string data((const char*)&uncompressedFile[0], (const char*)&uncompressedFile[uncompressedFileLength]);
1458 std::string::size_type start = data.find(compiledInfoHeader);
1459 if ( start != std::string::npos)
1461 std::string::size_type finish = data.find(compiledInfoFooter, start + compiledInfoHeader.length());
1462 if (finish != std::string::npos)
1464 finish += compiledInfoFooter.size();
1465 data = data.substr(0, start) + data.substr(finish, data.size() - finish);
1469 // REGENERATE HEADER
1470 md5Id = getMD5((uint8*)data.data(), (uint32)data.size());
1471 timeStamp = NLMISC::CTime::getSecondsSince1970();
1473 //std::stringstream ss;
1474 //ss << compiledInfoHeader;
1475 //ss << "local fileinfo = {}\n";
1476 //ss << toString("fileinfo.Package='%s'\n", filename.c_str());
1477 //ss << toString("fileinfo.Version='%s'\n", "1");
1478 //ss << toString("fileinfo.MD5='%s'\n", md5Id.toString().c_str());
1479 //ss << toString("fileinfo.TimeStamp='%u'\n", timeStamp);
1480 //ss << toString("r2.UserComponentsManager:registerFileInfo(fileinfo)\n");
1481 //ss << compiledInfoFooter;
1482 //ss << data;
1484 //data = ss.str();
1486 std::string str;
1487 str += compiledInfoHeader;
1488 str += "local fileinfo = {}\n";
1489 str += toString("fileinfo.Package='%s'\n", filename.c_str());
1490 str += toString("fileinfo.Version='%s'\n", "1");
1491 str += toString("fileinfo.MD5='%s'\n", md5Id.toString().c_str());
1492 str += toString("fileinfo.TimeStamp='%u'\n", timeStamp);
1493 str += toString("r2.UserComponentsManager:registerFileInfo(fileinfo)\n");
1494 str += compiledInfoFooter;
1496 data = str + data;
1498 delete [] uncompressedFile;
1499 uncompressedFile = new uint8[ data.size() ];
1500 memcpy(uncompressedFile, data.c_str(), data.size());
1501 uncompressedFileLength = (uint32)data.size();
1503 else
1505 // Get Uncompressed File length (4 last byte of a gz)
1506 FILE* file = nlfopen(filename, "rb");
1507 if (!file)
1509 nlwarning("Try to open an invalid file %s (access error)", filename.c_str());
1510 return false;
1513 // file length are the last uint32 of a file
1514 if (fseek(file, -4, SEEK_END) != 0)
1516 nlwarning("Try to open an invalid file %s (size error)", filename.c_str());
1517 fclose(file);
1518 return false;
1521 if (fread((void*)&uncompressedFileLength, sizeof(uncompressedFileLength), 1, file) != 1)
1523 nlwarning("Error while reading %s", filename.c_str());
1526 #ifdef NL_BIG_ENDIAN
1527 NLMISC_BSWAP32(uncompressedFileLength);
1528 #endif
1530 fclose(file);
1532 // Test if data are not too big
1533 if (uncompressedFileLength > 200*1024)
1535 nlwarning("Try to open an invalid file %s (size error)", filename.c_str());
1536 delete [] compressedFile;
1537 return false;
1540 // Read the compressed File
1542 gzFile file = gzopen ( filename.c_str(), "rb");
1543 uncompressedFile = new uint8[uncompressedFileLength+1];
1545 int length = gzread(file, uncompressedFile, uncompressedFileLength);
1546 if (length <0)
1548 nlwarning("Error while reading %s", filename.c_str());
1549 delete [] uncompressedFile;
1550 delete [] compressedFile;
1551 gzclose(file);
1552 return false;
1556 if ( length < static_cast<sint32>(uncompressedFileLength))
1558 nlwarning("Error while reading %s (corrupted data)", filename.c_str());
1559 delete [] uncompressedFile;
1560 delete [] compressedFile;
1561 gzclose(file);
1562 return false;
1564 gzclose(file);
1566 // Read the compressed File
1570 delete [] compressedFile; compressedFile = 0;
1572 //size of the destination buffer, which must be at least 0.1% larger than sourceLen plus 12 bytes
1575 uLongf destLen = uncompressedFileLength + uncompressedFileLength / 1000 + 12;
1576 Bytef *dest = new Bytef[destLen];
1577 int ok = compress(dest, &destLen, (Bytef *)uncompressedFile, uncompressedFileLength);
1578 if (ok != Z_OK)
1580 delete [] uncompressedFile;
1581 delete [] compressedFile;
1582 nlwarning("Error while reading %s (can't compress data)", filename.c_str());
1583 return false;
1585 compressedFile = reinterpret_cast<uint8*>(dest);
1586 compressedFileLength = static_cast<uint32>(destLen);
1588 uncompressedFile[uncompressedFileLength] = '\0';
1591 // TODO: compute md5Id and timeStamp
1593 _UserComponents[filename] = new CUserComponent(filename, uncompressedFile, uncompressedFileLength, compressedFile, compressedFileLength);
1594 _UserComponents[filename]->Md5Id = md5Id;
1595 _UserComponents[filename]->TimeStamp = timeStamp;
1597 return true;
1600 std::string CClientEditionModule::readUserComponentFile(const std::string& filename)
1602 //H_AUTO(R2_CClientEditionModule_readUserComponentFile)
1604 if (!loadUserComponent(filename, false))
1606 return "";
1609 CUserComponent* component = getUserComponentByFilename(filename);
1612 if (component)
1614 const char * str = (const char*)component->getUncompressedData();
1615 std::string value(str);
1616 return str;
1618 return "";
1621 CUserComponent* CClientEditionModule::getUserComponentByFilename(const std::string& filename) const
1623 //H_AUTO(R2_CClientEditionModule_getUserComponentByFilename)
1624 TUserComponents::const_iterator found = _UserComponents.find(filename);
1625 if (found != _UserComponents.end())
1627 return found->second;
1629 return 0;
1632 void CClientEditionModule::saveUserComponentFile(const std::string& filename, bool mustCompress)
1634 //H_AUTO(R2_CClientEditionModule_saveUserComponentFile)
1636 bool ok = loadUserComponent(filename);
1638 if (ok)
1640 CUserComponent* component = getUserComponentByFilename(filename);
1643 std::string compressedName;
1644 std::string uncompressedName;
1647 if (CFile::getExtension(filename) == UserComponentsSourceExtension.toString())
1649 uncompressedName = filename;
1650 compressedName = toString("%s/%s.%s",
1651 UserComponentsComponentsDirectory.c_str(),
1652 component->Md5Id.toString().c_str(),
1653 UserComponentsComponentExtension.c_str());
1655 else if (CFile::getExtension(filename) == UserComponentsComponentExtension.toString())
1657 compressedName = filename;
1658 uncompressedName = toString("%s/%s.%s",
1659 UserComponentsExamplesDirectory.c_str(),
1660 CFile::getFilenameWithoutExtension(component->Filename).c_str(),
1661 UserComponentsSourceExtension.c_str());
1665 if (!mustCompress)
1668 FILE* output = nlfopen(uncompressedName, "wb");
1669 if (output)
1671 if (fwrite(component->UncompressedData, sizeof(char), component->UncompressedDataLength, output) != component->UncompressedDataLength)
1673 nlwarning("Unable to write %s", component->UncompressedData);
1676 fclose(output);
1680 else
1683 gzFile output = gzopen(compressedName.c_str(), "wb");
1684 if (output)
1686 gzwrite(output, (const voidp) component->UncompressedData, component->UncompressedDataLength);
1687 gzclose(output);
1694 void CClientEditionModule::refreshComponents()
1696 //H_AUTO(R2_CClientEditionModule_refreshComponents)
1698 // verify directory exist
1699 bool createDirectorySuccess = false;
1700 if ( !CFile::isDirectory(_ScriptDirectory))
1702 createDirectorySuccess = CFile::createDirectory(_ScriptDirectory);
1705 // verify content of directory has not changed
1706 uint32 lastDirectoryModificationDate = CFile::getFileModificationDate(const std::string &filename);
1707 if (_LastDirectoryModificationDate == lastDirectoryModificationDate )
1709 return;
1711 _LastDirectoryModificationDate = lastDirectoryModificationDate
1713 // get Developper Component Script;
1714 std::vector<std::string> result;
1715 CPath::getPathContent (_ScriptDirectory, false, false, true, result, false, false);
1717 CInterfaceManager *pIM= CInterfaceManager::getInstance();
1718 std::vector<std::string> script(1);
1719 bool ok = pIM->pars veInterface(script, true, false);
1722 _LastRefreshComponents = NLMISC::CTime::getLocalTime();
1726 void CClientEditionModule::ackMsg( NLNET::IModuleProxy *sender, uint32 msgId, bool ok)
1728 _ServerAnswerForseener->ack(this, sender, msgId, ok);
1731 void CClientEditionModule::onScenarioUploaded(NLNET::IModuleProxy * /* sender */, const R2::CObjectSerializerClient &hlScenario)
1733 //H_AUTO(R2_CClientEditionModule_onScenarioUploaded)
1734 _Factory->clear();
1735 _Client->scenarioUpdated(hlScenario.getData(), false, 1);//give ownership
1738 // The client request to set a node on a hl scenario.
1739 void CClientEditionModule::onNodeSet(NLNET::IModuleProxy * /* sender */, const std::string &instanceId, const std::string &attrName, const R2::CObjectSerializerClient &value)
1741 //H_AUTO(R2_CClientEditionModule_onNodeSet)
1742 if (_Mute) return;
1743 _Client->nodeSet(instanceId, attrName, value.getData()); //todo ownership
1746 // The ServerEditionMode inserts a node on a hl scenario.
1747 void CClientEditionModule::onNodeInserted(NLNET::IModuleProxy * /* sender */, const std::string &instanceId, const std::string &attrName, sint32 position, const std::string &key, const R2::CObjectSerializerClient &value)
1749 //H_AUTO(R2_CClientEditionModule_onNodeInserted)
1750 if (_Mute) return;
1751 _Client->nodeInserted( instanceId, attrName, position, key, value.getData()); //todo ownership
1754 // The ServerEditionMode erases a node on a hl scenario.
1755 void CClientEditionModule::onNodeErased(NLNET::IModuleProxy * /* sender */, const std::string &instanceId, const std::string &attrName, sint32 position)
1757 //H_AUTO(R2_CClientEditionModule_onNodeErased)
1758 if (_Mute) return;
1759 _Client->nodeErased( instanceId, attrName, position);
1762 // The ServerEditionMode a move node on a hl scenario.
1763 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)
1765 //H_AUTO(R2_CClientEditionModule_onNodeMoved)
1766 if (_Mute) return;
1767 _Client->nodeMoved(instanceId1, attrName1, position1,
1768 instanceId2, attrName2, position2);
1771 void CClientEditionModule::onQuotaUpdated(NLNET::IModuleProxy * /* senderModuleProxy */, uint32 maxNpcs, uint32 maxStaticObjects)
1773 //H_AUTO(R2_CClientEditionModule_onQuotaUpdated)
1774 //R2::getEditor().getLua().executeScriptNoThrow(toString("r2.QuotaMgr.onQuotaUpdated(%u, %u)", maxNpcs, maxStaticObjects));
1775 _MaxNpcs = maxNpcs;
1776 _MaxStaticObjects = maxStaticObjects;
1780 uint32 CClientEditionModule::getCurrentMaxId()
1782 //H_AUTO(R2_CClientEditionModule_getCurrentMaxId)
1783 if (_Scenario == NULL)
1784 return 1000;
1785 std::string eid = getEid();
1786 sint32 currentId = _Factory->getMaxId(eid);
1787 nlassert(currentId >= -1);
1789 return static_cast<uint32>(currentId + 1);
1793 void CClientEditionModule::reserveIdRange(uint32 range)
1795 //H_AUTO(R2_CClientEditionModule_reserveIdRange)
1796 nlassert(_Scenario);
1797 std::string eid = getEid();
1798 sint32 currentId = _Scenario->getMaxId(eid);
1799 nlassert(currentId >= -1);
1801 sint32 maxId = currentId + static_cast<sint32>(range + 1);
1803 //_Scenario->setMaxId(eid, maxId);
1804 _Factory->setMaxId(eid, maxId);
1807 std::string CClientEditionModule::getEmoteBehaviorFromEmoteId(const std::string & emoteId) const
1809 //H_AUTO(R2_CClientEditionModule_getEmoteBehaviorFromEmoteId)
1810 return _Emotes->get(emoteId);
1816 void CClientEditionModule::resetDisplayInfo()
1818 //H_AUTO(R2_CClientEditionModule_resetDisplayInfo)
1819 this->_ClientEditorConfig->setDisplayInfo(0xFFFFFFFF);
1822 void CClientEditionModule::setDisplayInfo(const std::string& formName, bool displayInfo)
1824 //H_AUTO(R2_CClientEditionModule_setDisplayInfo)
1825 this->_ClientEditorConfig->setDisplayInfo(formName, displayInfo);
1826 //CShareServerEditionItfProxy proxy(_ServerEditionProxy);
1827 //uint32 newDisplayInfo = this->_ClientEditorConfig->getDisplayInfo();
1828 //proxy.setDisplayInfo(this, newDisplayInfo);
1832 bool CClientEditionModule::mustDisplayInfo(const std::string& formName) const
1834 //H_AUTO(R2_CClientEditionModule_mustDisplayInfo)
1835 bool ok = this->_ClientEditorConfig->mustDisplayInfo(formName);
1836 return ok;
1839 bool CClientEditionModule::hasDisplayInfo(const std::string& formName) const
1841 //H_AUTO(R2_CClientEditionModule_hasDisplayInfo)
1842 bool ok = this->_ClientEditorConfig->hasDisplayInfo(formName);
1843 return ok;
1846 void CClientEditionModule::onDisplayInfoUpdated(NLNET::IModuleProxy * /* senderModuleProxy */, uint32 displayInfo)
1848 //H_AUTO(R2_CClientEditionModule_onDisplayInfoUpdated)
1849 this->_ClientEditorConfig->setDisplayInfo(displayInfo);
1853 void CClientEditionModule::setStartingActIndex(uint32 startingActIndex)
1855 //H_AUTO(R2_CClientEditionModule_setStartingActIndex)
1856 _StartingActIndex = startingActIndex;
1859 void CClientEditionModule::onTpPositionSimulated(NLNET::IModuleProxy * /* sender */, TSessionId /* sessionId */, uint64 /* characterId64 */, sint32 x, sint32 y, sint32 z, uint8 /* scenarioSeason */)
1861 //H_AUTO(R2_CClientEditionModule_onTpPositionSimulated)
1863 CVector dest((float)x, (float)y, (float) z);
1864 //Season ?
1866 UserEntity->pos(dest); // change position in pacs
1867 // Select the closest continent from the new position.
1868 beginLoading (LoadingBackground);
1869 #define BAR_STEP_TP 2 // fixme : this define is duplicated....
1870 ProgressBar.reset (BAR_STEP_TP);
1871 string nmsg("Loading...");
1872 ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) );
1873 ProgressBar.progress(0);
1874 ContinentMngr.select(dest, ProgressBar);
1875 endLoading();
1876 // Teleport the User.
1877 UserEntity->tp(dest);
1878 ProgressBar.finish();
1882 void CClientEditionModule::onDisconnected(NLNET::IModuleProxy * /* sender */)
1884 //H_AUTO(R2_CClientEditionModule_onDisconnected)
1885 R2::getEditor().getLua().executeScriptNoThrow(NLMISC::toString("r2.onDisconnected()"));
1888 void CClientEditionModule::onKicked(NLNET::IModuleProxy * /* sender */, uint32 timeBeforeDisconnection, bool mustKick)
1890 //H_AUTO(R2_CClientEditionModule_onKicked)
1892 R2::getEditor().getLua().push(timeBeforeDisconnection);
1893 R2::getEditor().getLua().push(mustKick);
1894 R2::getEditor().callEnvFunc( "onKicked", 2, 0);
1899 // Target : Animation Module
1901 void CClientEditionModule::requestTalkAs(const std::string& npcname)
1903 //H_AUTO(R2_CClientEditionModule_requestTalkAs)
1904 CMessage msg("talk_as");
1905 msg.serial(const_cast<std::string&>(npcname));
1906 _ServerAnimationProxy->sendModuleMessage(this, msg );
1909 void CClientEditionModule::requestStringTable()
1911 //H_AUTO(R2_CClientEditionModule_requestStringTable)
1912 CMessage msg("requestStringTable");
1913 _ServerAnimationProxy->sendModuleMessage(this, msg );
1916 void CClientEditionModule::requestSetStringValue(std::string& id,std::string& value )
1918 //H_AUTO(R2_CClientEditionModule_requestSetStringValue)
1919 CMessage msg("requestSetValue");
1920 msg.serial(id);
1921 msg.serial(value);
1922 _ServerAnimationProxy->sendModuleMessage(this,msg);
1925 void CClientEditionModule::requestStartAct(uint32 actId)
1927 //H_AUTO(R2_CClientEditionModule_requestStartAct)
1928 CMessage message ("requestStartAct");
1929 message.serial(actId);
1930 DROP_IF(_ServerAnimationProxy == NULL, "Server Animation Module not connected", return);
1931 _ServerAnimationProxy->sendModuleMessage(this, message );
1934 void CClientEditionModule::requestSetWeather(uint16 weatherValue)
1936 //H_AUTO(R2_CClientEditionModule_requestSetWeather)
1937 CMessage message ("requestSetWeather");
1938 message.serial(weatherValue);
1939 DROP_IF(_ServerAnimationProxy == NULL, "Server Animation Module not connected", return);
1940 _ServerAnimationProxy->sendModuleMessage(this, message );
1943 void CClientEditionModule::requestSetSeason(uint8 seasonValue)
1945 //H_AUTO(R2_CClientEditionModule_requestSetSeason)
1946 CMessage message ("requestSetSeason");
1947 message.serial(seasonValue);
1948 DROP_IF(_ServerAnimationProxy == NULL, "Server Animation Module not connected", return);
1949 _ServerAnimationProxy->sendModuleMessage(this, message );
1952 void CClientEditionModule::requestStopAct()
1954 //H_AUTO(R2_CClientEditionModule_requestStopAct)
1955 CMessage message ("requestStopAct");
1956 DROP_IF(_ServerAnimationProxy == NULL, "Server Animation Module not connected", return);
1957 _ServerAnimationProxy->sendModuleMessage(this, message );
1960 void CClientEditionModule::requestStopTalkAs()
1962 //H_AUTO(R2_CClientEditionModule_requestStopTalkAs)
1963 DROP_IF(_ServerAnimationProxy == NULL, "Server Animation Module not connected", return);
1965 CMessage msg("stopTalk");
1966 _ServerAnimationProxy->sendModuleMessage(this, msg );
1969 void CClientEditionModule::requestStringValue(std::string& localId )
1971 //H_AUTO(R2_CClientEditionModule_requestStringValue)
1972 DROP_IF(_ServerAnimationProxy == NULL, "Server Animation Module not connected", return);
1973 CMessage msg("requestStringValue");
1974 msg.serial(localId);
1975 _ServerAnimationProxy->sendModuleMessage(this, msg );
1977 void CClientEditionModule::requestTpPosition(float x, float y, float z)
1979 //H_AUTO(R2_CClientEditionModule_requestTpPosition)
1980 DROP_IF(_ServerEditionProxy == NULL, "Server Edition Module not connected", return);
1981 CShareServerEditionItfProxy serverEditionModule(_ServerEditionProxy);
1982 serverEditionModule.onTpPositionAsked(this, x, y, z);
1983 return ;
1987 void CClientEditionModule::requestIdList()
1989 //H_AUTO(R2_CClientEditionModule_requestIdList)
1990 DROP_IF(_ServerAnimationProxy == NULL, "Server Animation Module not connected", return);
1991 CMessage msg("requestIdList");
1992 _ServerAnimationProxy->sendModuleMessage(this, msg );
1997 bool CClientEditionModule::requestTpToEntryPoint(uint32 actIndex)
1999 //H_AUTO(R2_CClientEditionModule_requestTpToEntryPoint)
2000 DROP_IF(_ServerEditionProxy == NULL, "Server Edition Module not connected", return false);
2001 if (R2::getEditor().isClearingContent()) { return true;}
2003 CShareServerEditionItfProxy serverEditionModule(_ServerEditionProxy);
2004 serverEditionModule.tpToEntryPoint(this, actIndex);
2005 return true;
2009 bool CClientEditionModule::requestSetStartingAct(uint32 actIndex)
2011 //H_AUTO(R2_CClientEditionModule_requestSetStartingAct)
2012 DROP_IF(_ServerEditionProxy == NULL, "Server Edition Module not connected", return false);
2014 CShareServerEditionItfProxy serverEditionModule(_ServerEditionProxy);
2015 serverEditionModule.setStartingAct(this, actIndex);
2016 return true;
2021 bool CClientEditionModule::connectAnimationModePlay()
2023 //H_AUTO(R2_CClientEditionModule_connectAnimationModePlay)
2024 DROP_IF(_ServerAnimationProxy == NULL, "Server Animation Module not connected", return false);
2026 CShareServerAnimationItfProxy serverAnimationModule(_ServerAnimationProxy);
2027 serverAnimationModule.connectAnimationModePlay(this);
2028 return true;
2032 void CClientEditionModule::onAnimationModePlayConnected(NLNET::IModuleProxy * /* senderModuleProxy */)
2034 //H_AUTO(R2_CClientEditionModule_onAnimationModePlayConnected)
2035 _Client->onAnimationModePlayConnected();
2039 void CClientEditionModule::scheduleStartAct(NLNET::IModuleProxy * /* sender */, uint32 errorId, uint32 actId, uint32 nbSeconds)
2041 //H_AUTO(R2_CClientEditionModule_scheduleStartAct)
2042 R2::getEditor().getLua().push(errorId);
2043 R2::getEditor().getLua().push(actId);
2044 R2::getEditor().getLua().push(nbSeconds);
2045 R2::getEditor().callEnvFunc( "onScheduleStartAct", 3, 0);
2050 void CClientEditionModule::updateScenarioHeader(NLNET::IModuleProxy * /* sender */, const TScenarioHeaderSerializer& header)
2052 //H_AUTO(R2_CClientEditionModule_updateScenarioHeader)
2053 _ScenarioHeader = header.Value;
2054 R2::getEditor().getLua().executeScriptNoThrow( "r2.onScenarioHeaderUpdated(r2.getScenarioHeader())" );
2057 void CClientEditionModule::updateMissionItemsDescription(NLNET::IModuleProxy * /* sender */, TSessionId /* sessionId */, const std::vector<R2::TMissionItem> &missionItem)
2059 //H_AUTO(R2_CClientEditionModule_updateMissionItemsDescription)
2060 uint i;
2061 uint maxNumPlotItems = CEditor::getMaxNumPlotItems();
2062 for(i = 0; i < std::min((uint) missionItem.size(), maxNumPlotItems); ++i)
2064 CCDBNodeLeaf *leaf = CEditor::getPlotItemSheetDBLeaf(i);
2065 if (leaf)
2067 uint32 sheetId = (uint32) missionItem[i].SheetId.asInt();
2068 leaf->setValue32(sheetId);
2069 getEditor().setPlotItemInfos(missionItem[i]);
2072 for(; i < maxNumPlotItems; ++i)
2074 CCDBNodeLeaf *leaf = CEditor::getPlotItemSheetDBLeaf(i);
2075 if (leaf)
2077 leaf->setValue32(0);
2082 void CClientEditionModule::updateActPositionDescriptions(NLNET::IModuleProxy * /* sender */, const TActPositionDescriptions &actPositionDescriptions)
2084 //H_AUTO(R2_CClientEditionModule_updateActPositionDescriptions)
2085 this->_ActPositionDescriptions = actPositionDescriptions;
2086 R2::getEditor().getLua().executeScriptNoThrow( "r2.onRuntimeActUpdated(r2.getRuntimeActs())" );
2090 void CClientEditionModule::updateUserTriggerDescriptions(NLNET::IModuleProxy * /* sender */, const TUserTriggerDescriptions &userTriggerDescriptions)
2092 //H_AUTO(R2_CClientEditionModule_updateUserTriggerDescriptions)
2093 this->_UserTriggerDescriptions = userTriggerDescriptions;
2094 R2::getEditor().getLua().executeScriptNoThrow( "r2.onUserTriggerDescriptionUpdated(r2.getUserTriggers())" );
2098 bool CClientEditionModule::askMissionItemsDescription()
2100 //H_AUTO(R2_CClientEditionModule_askMissionItemsDescription)
2101 DROP_IF(_ServerAnimationProxy == NULL, "Server Animation Module not connected", return false);
2102 CShareServerAnimationItfProxy serverAnimationModule(_ServerAnimationProxy);
2103 serverAnimationModule.askMissionItemsDescription(this);
2104 return true;
2107 bool CClientEditionModule::requestTriggerUserTrigger(uint32 actId, uint triggerId)
2109 //H_AUTO(R2_CClientEditionModule_requestTriggerUserTrigger)
2110 DROP_IF(_ServerAnimationProxy == NULL, "Server Animation Module not connected", return false);
2111 CShareServerAnimationItfProxy serverAnimationModule(_ServerAnimationProxy);
2112 serverAnimationModule.onUserTriggerTriggered(this, actId, triggerId);
2113 return true;
2115 void CClientEditionModule::onCurrentActIndexUpdated(NLNET::IModuleProxy * /* sender */, uint32 actId)
2117 //H_AUTO(R2_CClientEditionModule_onCurrentActIndexUpdated)
2118 this->_CurrentActIndex = actId;
2119 R2::getEditor().getLua().executeScriptNoThrow( "r2.onCurrentActIndexUpdated(r2.getCurrentActIndex())" );
2123 void CClientEditionModule::dssTarget( std::vector<std::string>& args)
2125 //H_AUTO(R2_CClientEditionModule_dssTarget)
2126 DROP_IF(_ServerAnimationProxy == NULL, "Server Animation Module not connected", return);
2128 CShareServerAnimationItfProxy serverAnimationModule(_ServerAnimationProxy);
2129 serverAnimationModule.onDssTarget(this, args);
2133 void CClientEditionModule::updateIncarningList(NLNET::IModuleProxy * /* sender */, const std::vector<uint32> & botId)
2135 //H_AUTO(R2_CClientEditionModule_updateIncarningList)
2136 this->_IncarnatingList = botId;
2137 R2::getEditor().getLua().executeScriptNoThrow( "r2.onIncarnatingListUpdated()" );
2140 void CClientEditionModule::updateTalkingAsList(NLNET::IModuleProxy * /* sender */, const std::vector<uint32> & botId)
2142 //H_AUTO(R2_CClientEditionModule_updateTalkingAsList)
2143 this->_TalkingAsList = botId;
2144 R2::getEditor().getLua().executeScriptNoThrow( "r2.onTalkingAsListUpdated()" );
2147 std::vector<uint32> CClientEditionModule::getIncarnatingList() const
2149 //H_AUTO(R2_CClientEditionModule_getIncarnatingList)
2150 return this->_IncarnatingList;
2153 std::vector<uint32> CClientEditionModule::getTalkingAsList() const
2155 //H_AUTO(R2_CClientEditionModule_getTalkingAsList)
2156 return this->_TalkingAsList;
2160 void CClientEditionModule::systemMsg(NLNET::IModuleProxy * /* sender */, const std::string& msgType, const std::string& who, const std::string& msg)
2162 //H_AUTO(R2_CClientEditionModule_systemMsg)
2163 R2::getEditor().getLua().push(msgType);
2164 R2::getEditor().getLua().push(who);
2165 R2::getEditor().getLua().push(msg);
2166 R2::getEditor().callEnvFunc("onSystemMessageReceived", 3 , 0);
2170 void CClientEditionModule::updateScenarioRingAccess(bool ok, const std::string& ringAccess, const std::string& errMsg)
2172 //H_AUTO(R2_CClientEditionModule_updateScenarioRingAccess)
2174 DROP_IF(_ServerEditionProxy == NULL, "Server Edition Module not connected", return);
2176 CShareServerEditionItfProxy serverEditionModule(_ServerEditionProxy);
2177 serverEditionModule.onScenarioRingAccessUpdated(this, ok, ringAccess, errMsg);
2180 std::string CClientEditionModule::getCharacterRingAccess() const
2182 //H_AUTO(R2_CClientEditionModule_getCharacterRingAccess)
2183 return _RingAccess;
2186 void CClientEditionModule::onRingAccessUpdated(NLNET::IModuleProxy * /* moduleSocket */, const std::string& ringAccess)
2188 //H_AUTO(R2_CClientEditionModule_onRingAccessUpdated)
2190 _RingAccess = ringAccess;
2191 //Remove first and last char
2192 if (!_RingAccess.empty())
2194 if (_RingAccess[0] == '\'' || _RingAccess[0] == '"')
2196 _RingAccess = _RingAccess.substr(1);
2199 if (!_RingAccess.empty())
2201 if (_RingAccess[_RingAccess.size()-1] == '\''
2202 || _RingAccess[_RingAccess.size()-1] == '"')
2204 _RingAccess = _RingAccess.substr(0, _RingAccess.size()-1);
2207 R2::getEditor().getLua().push(_RingAccess);
2208 R2::getEditor().callEnvFunc( "onRingAccessUpdated",1 ,0);
2214 void CClientEditionModule::addToSaveList(const std::string& filename, const std::vector< std::pair < std::string, std::string> >& values)
2216 //H_AUTO(R2_CClientEditionModule_addToSaveList)
2219 std::string name = filename; // Must use prefix or suffix?
2221 NLMISC::COFile out;
2223 CObject* scenario = getCurrentScenario()->getHighLevel();
2225 if (!scenario)
2227 nlwarning("Can't save: no scenario yet");
2228 return;
2231 CScenarioValidator* sv = new CScenarioValidator();
2232 CScenarioValidator::TValues v1(values);
2233 std::string md5;
2234 bool ok = true;
2235 ok = sv->setScenarioToSave(filename, scenario, v1, md5);
2236 if (!ok)
2238 delete sv;
2239 return;
2241 else
2243 if ( !_ScenarioToSave.insert( std::make_pair(md5, sv)).second )
2245 nlwarning("Ask 2 time the save of the same scenario?");
2246 delete sv;
2247 return;
2249 DROP_IF(_ServerEditionProxy == NULL, "Server Edition Module not connected", return);
2251 CShareServerEditionItfProxy serverEditionModule(_ServerEditionProxy);
2252 serverEditionModule.saveScenarioFile(this, md5 ,R2::TScenarioHeaderSerializer (v1) );
2256 // :TODO: VIANNEY add all
2257 _LastReadHeader.clear();
2258 _LastReadHeader.push_back( std::pair<std::string, std::string>("BodyMD5", sv->getBodyMd5() ));
2259 _LastReadHeader.insert(_LastReadHeader.end(), values.begin(), values.end());
2263 // sv.openHeader(filename, v2, true);
2264 return;
2267 /**********************************************************/
2268 /****** ADD TO USER COMPONENT SAVE LIST *******************/
2269 /**********************************************************/
2270 void CClientEditionModule::addToUserComponentSaveList(const std::string& filename, const std::vector< std::pair < std::string, std::string> >& values, std::string &body)
2272 //H_AUTO(R2_CClientEditionModule_addToSaveList)
2275 std::string name = filename; // Must use prefix or suffix?
2277 NLMISC::COFile out;
2279 CUserComponentValidator* ucv = new CUserComponentValidator();
2280 CUserComponentValidator::TValues v1(values);
2281 std::string md5;
2282 bool ok = true;
2283 ok = ucv->setUserComponentToSave(filename, v1, md5, body);
2284 if (!ok)
2286 delete ucv;
2288 else
2290 if ( !_UserComponentToSave.insert( std::make_pair(md5, ucv)).second )
2292 nlwarning("Ask 2 time the save of the same user component?");
2293 delete ucv;
2294 return;
2296 DROP_IF(_ServerEditionProxy == NULL, "Server Edition Module not connected", return);
2298 CShareServerEditionItfProxy serverEditionModule(_ServerEditionProxy);
2299 serverEditionModule.saveUserComponentFile(this, md5 ,R2::TScenarioHeaderSerializer (v1) );
2303 return;
2306 void CClientEditionModule::saveUserComponentFileAccepted(NLNET::IModuleProxy *senderModuleProxy, const std::string& md5, const std::string& signature, bool ok)
2308 //H_AUTO(R2_CClientEditionModule_saveScenarioFileAccepted)
2310 TUserComponentToSave::iterator found(_UserComponentToSave.find(md5));
2311 if (found == _UserComponentToSave.end())
2313 nlwarning("The client has ask more than one time to save the same file");
2314 return;
2317 CUserComponentValidator* userComponentToSave = found->second;
2318 _UserComponentToSave.erase(found);
2320 if (ok)
2322 userComponentToSave->applySave(signature);
2323 addToUserComponentLoadList(userComponentToSave->getFilename(), new CLoadUserComponentSucceeded(this));
2325 else
2327 systemMsg(senderModuleProxy, "ERR", "", "uiR2EDServerRefuseToSave");
2333 bool CClientEditionModule::addToUserComponentLoadList( const std::string& filename, CUserComponentValidatorLoadSuccededCallback* cb)
2335 //H_AUTO(R2_CClientEditionModule_addToLoadList)
2336 CUserComponentValidator* ucv = new CUserComponentValidator(cb);
2337 CUserComponentValidator::TValues values;
2338 std::string md5;
2339 std::string signature;
2340 bool ok = true;
2341 nlinfo("Adding user component '%s' to load list", filename.c_str());
2342 ok = ucv->setUserComponentToLoad(filename, values, md5, signature, ClientCfg.CheckR2ScenarioMD5);
2343 if (!ok)
2345 R2::getEditor().callEnvFunc( "displayModifiedUserComponentFileError", 0, 0);
2346 nlwarning("setUserComponentToLoad failed");
2347 return false;
2350 if ( !_UserComponentToLoad.insert( std::make_pair(md5, ucv)).second )
2352 nlwarning("Ask 2 time the load of the same user component?"); //or the same empty uc file
2353 delete ucv;
2354 return false;
2356 DROP_IF(_ServerEditionProxy == NULL, "Server Edition Module not connected", return false);
2358 CShareServerEditionItfProxy serverEditionModule(_ServerEditionProxy);
2359 serverEditionModule.loadUserComponentFile(this, md5, signature);
2360 return true;
2364 void CClientEditionModule::loadUserComponentFileAccepted(NLNET::IModuleProxy * /* senderModuleProxy */, const std::string& md5, bool ok)
2366 //H_AUTO(R2_CClientEditionModule_loadScenarioFileAccepted)
2368 TUserComponentToLoad::iterator found(_UserComponentToLoad.find(md5));
2369 if (found == _UserComponentToLoad.end())
2371 nlwarning("The client has ask more than one time to save the same file");
2372 return;
2375 CUniquePtr<CUserComponentValidator> userComponentToLoad(found->second);
2376 _UserComponentToLoad.erase(found);
2378 if (!ok)
2380 nlwarning("The server has refuse the client to load the a file"); //should (can) not happen
2381 this->systemMsg(0, "ERR", "", "The server has refuse the client to load the a file");
2382 return;
2385 std::string filename;
2386 std::string body;
2387 CUserComponentValidator::TValues values;
2388 userComponentToLoad->applyLoad(filename, body, values);
2389 _LastReadHeader = values;
2390 //return body;
2394 /**************************************************************************************/
2396 void CClientEditionModule::saveScenarioFileAccepted(NLNET::IModuleProxy *senderModuleProxy, const std::string& md5, const std::string& signature, bool ok)
2398 //H_AUTO(R2_CClientEditionModule_saveScenarioFileAccepted)
2400 TScenarioToSave::iterator found(_ScenarioToSave.find(md5));
2401 if (found == _ScenarioToSave.end())
2403 nlwarning("The client has ask more than one time to save the same file");
2404 return;
2407 CUniquePtr<CScenarioValidator> scenarioToSave(found->second);
2408 _ScenarioToSave.erase(found);
2410 if (ok)
2412 scenarioToSave->applySave(signature);
2414 else
2416 systemMsg(senderModuleProxy, "ERR", "", "uiR2EDServerRefuseToSave");
2421 bool CClientEditionModule::addToLoadList( const std::string& filename, CScenarioValidatorLoadSuccededCallback* cb)
2423 //H_AUTO(R2_CClientEditionModule_addToLoadList)
2424 CScenarioValidator* sv = new CScenarioValidator(cb);
2425 CScenarioValidator::TValues values;
2426 std::string md5;
2427 std::string signature;
2428 bool ok = true;
2429 ok = sv->setScenarioToLoad(filename, values, md5, signature, ClientCfg.CheckR2ScenarioMD5);
2430 if (!ok){ return false; }
2432 if ( !_ScenarioToLoad.insert( std::make_pair(md5, sv)).second )
2434 nlwarning("Ask 2 time the load of the same scenario?"); //or the same empty scenario
2435 delete sv;
2436 return false;
2438 DROP_IF(_ServerEditionProxy == NULL, "Server Edition Module not connected", return false);
2440 CShareServerEditionItfProxy serverEditionModule(_ServerEditionProxy);
2441 serverEditionModule.loadScenarioFile(this, md5, signature);
2442 return true;
2446 void CClientEditionModule::loadScenarioSucceded(const std::string& filename, const std::string& body, const CScenarioValidator::TValues& values)
2448 //H_AUTO(R2_CClientEditionModule_loadScenarioSucceded)
2449 string initialIsland, initialEntryPoint, initialSeason;
2450 string creatorMD5, modifiedByMD5;
2451 string name;
2452 string locked;
2453 for(uint i=0; i<values.size(); i++)
2455 const std::pair<std::string, std::string>& pair = values[i];
2456 if(pair.first == "InitialIsland") initialIsland = pair.second;
2457 else if(pair.first == "InitialEntryPoint") initialEntryPoint = pair.second;
2458 else if(pair.first == "InitialSeason") initialSeason = pair.second;
2459 else if(pair.first == "OwnerMd5") initialSeason = pair.second;
2460 else if(pair.first == "CreatorMD5") creatorMD5 = pair.second;
2461 else if(pair.first == "OtherCharAccess") locked = pair.second;
2462 else if(pair.first == "ModifierMD5") modifiedByMD5 = pair.second;
2463 else if(pair.first == "Name") name = pair.second;
2468 if (!modifiedByMD5.empty() && !locked.empty() && locked == "RunOnly")
2470 bool ok = hasCharacterSameCharacterIdMd5(modifiedByMD5);
2471 if (!ok)
2473 this->systemMsg(0, "ERR", "", "uiR2EDLoadingLockedScenario");
2474 return;
2478 R2::getEditor().getUI().displaySystemInfo(CI18N::get("uiR2EDLoadingScenario"), "BC");
2479 CObject* object = _Client->getComLuaModule().loadFromBuffer(body, filename, values);
2480 _LastReadHeader = values;
2481 if (object)
2483 if (!initialIsland.empty() && !initialEntryPoint.empty() && !initialSeason.empty())
2485 // CShareServerEditionItfProxy serverEditionModule(_ServerEditionProxy);
2486 // serverEditionModule.teleportWhileUploadingScenario(this, initialIsland, initialEntryPoint, initialSeason);
2487 R2::getEditor().clearContent();
2489 _Client->requestUploadScenario(object);
2490 if (!name.empty() && object && object->isTable() && object->isString("InstanceId"))
2492 CObjectString objectName(name);
2493 _Client->requestSetNode(object->toString("InstanceId"), "Ghost_Name", &objectName);
2497 if (CFile::fileExists(filename))
2499 CFile::copyFile("save/r2_buffer.dat", filename);
2504 void CClientEditionModule::loadAnimationSucceded(const std::string& filename, const std::string& body, const CScenarioValidator::TValues& values)
2506 //H_AUTO(R2_CClientEditionModule_loadAnimationSucceded)
2507 std::string errMsg;
2508 _Client->loadAnimationFromBuffer(body, filename, errMsg, values);
2511 void CClientEditionModule::loadScenarioFileAccepted(NLNET::IModuleProxy * /* senderModuleProxy */, const std::string& md5, bool ok)
2513 //H_AUTO(R2_CClientEditionModule_loadScenarioFileAccepted)
2515 TScenarioToLoad::iterator found(_ScenarioToLoad.find(md5));
2516 if (found == _ScenarioToLoad.end())
2518 nlwarning("The client has ask more than one time to save the same file");
2519 return;
2522 CUniquePtr<CScenarioValidator> scenarioToLoad(found->second);
2523 _ScenarioToLoad.erase(found);
2525 if (!ok)
2527 nlwarning("The server has refuse the client to load the a file"); //should (can) not append
2528 this->systemMsg(0, "ERR", "", "The server has refuse the client to load the a file");
2529 return;
2532 std::string filename;
2533 std::string body;
2534 CScenarioValidator::TValues values;
2535 scenarioToLoad->applyLoad(filename, body, values);
2536 _LastReadHeader = values;
2540 void CClientEditionModule::setMute(bool mute)
2542 //H_AUTO(R2_CClientEditionModule_setMute)
2543 _Mute = mute;
2546 void CLoadUserComponentSucceeded::doOperation(const std::string& filename,const std::string& body,const CScenarioValidator::TValues& header)
2548 CLuaState& state = R2::getEditor().getLua();
2549 state.push((std::string)filename);
2550 state.push((std::string)body);
2552 state.newTable();
2553 CClientEditionModule::TScenarioHeader::const_iterator first(header.begin()), last(header.end());
2555 for ( ; first != last; ++first)
2558 state.push(first->first);
2559 state.push(first->second);
2561 state.setTable(-3);
2563 //R2::getEditor().getLua().push((bool)mustKick);
2564 R2::getEditor().callEnvFunc( "loadUserComponentCallback", 3, 0);
2569 void CLoadAnimationSucceded::doOperation(const std::string& filename,const std::string& body,const CScenarioValidator::TValues& values)
2571 //H_AUTO(R2_CLoadAnimationSucceded_doOperation)
2572 _Module->loadAnimationSucceded(filename, body, values);
2575 void CLoadScenarioSucceded::doOperation(const std::string& filename,const std::string& body,const CScenarioValidator::TValues& values)
2577 //H_AUTO(R2_CLoadScenarioSucceded_doOperation)
2578 _Module->loadScenarioSucceded(filename, body, values);
2582 void CClientEditionModule::resetNameGiver()
2584 //H_AUTO(R2_CClientEditionModule_resetNameGiver)
2585 _Factory->clear();
2588 bool CClientEditionModule::hasCharacterSameCharacterIdMd5(const std::string & charIdMd5) const
2590 if (ClientCfg.Local == 1 )
2592 return true;
2595 uint32 val = 0;
2596 uint32 first=0,last=(uint32)charIdMd5.size();
2597 for (;first != last; ++first)
2600 val *= 16;
2601 char c = charIdMd5[first];
2602 if ('0' <= c && c <= '9')
2604 val += (c-'0');
2606 else if ('A' <= c && c <= 'F')
2608 val += 10+(c-'A');
2611 uint32 charId = CRingAccess::uncypherCharId(val);
2613 uint32 myUserId = NetMngr.getUserId();
2614 if ((charId>>4) != myUserId)
2617 return false;
2619 return true;
2622 class CModuleMessageSender : public R2::IMessageSender
2624 public:
2625 CModuleMessageSender(const NLNET::TModuleProxyPtr& proxy, NLNET::IModule* senderModule):_Proxy(proxy), _Sender(senderModule){}
2627 void operator()(const NLNET::CMessage & msg)
2629 if (!_Proxy)
2631 nlwarning("Can not send Message %s to destination", msg.getName().c_str());
2632 return;
2635 // Send msg to DSS (after cuting msg)
2636 if (ClientCfg.R2EDDssNetwork == 1)
2638 _Proxy->sendModuleMessage(_Sender, msg);
2639 return;
2642 TCharId charId = 0;
2643 if (ClientCfg.Local )
2645 charId = 999 << 4;
2647 else
2649 charId = CSessionBrowserImpl::getCharId();
2653 // Send msg to DSS (Simulate forward system)
2654 if (ClientCfg.R2EDDssNetwork == 2)
2657 NLNET::CMessage handle;
2658 R2::CShareServerEditionItfProxy::buildMessageFor_forwardToDss(handle, charId, msg);
2659 _Proxy->sendModuleMessage(_Sender, handle);
2660 return;
2664 // Send msg to DSS (Simulate forward system)
2665 if (ClientCfg.R2EDDssNetwork == 3)
2668 NLNET::CMessage handle;
2669 R2::CShareServerEditionItfProxy::buildMessageFor_forwardToDss(handle, charId, msg);
2670 CSessionBrowserImpl::getInstance().send(handle);
2671 return;
2673 // wrong value
2674 nlwarning("Error Msg lost");
2675 return;
2677 protected:
2678 NLNET::TModuleProxyPtr _Proxy;
2679 NLNET::IModule* _Sender;
2683 void CClientEditionModule::sendMsgToDss(const NLNET::CMessage& msg)
2686 TCharId charId = 0;
2687 if (ClientCfg.Local )
2689 charId = 999 << 4;
2691 else
2693 charId = CSessionBrowserImpl::getCharId();
2695 // Direct send msg to DSS (not cut)
2696 if (ClientCfg.R2EDDssNetwork == 0)
2698 _ServerEditionProxy->sendModuleMessage(this, msg);
2699 return;
2702 CModuleMessageSender sender(_ServerEditionProxy, this);
2703 CMessageSpliter::sendSplitedMsg(charId, msg, sender);
2707 //----------------------------------------------------------------------------------------------------------------
2713 void CMessageSpliter::sendSplitedMsg(uint32 charId, const NLNET::CMessage& msg, IMessageSender& sender)
2716 static const uint32 packetSize = 512; // 16K by packet
2717 uint32 size = msg.length();
2718 uint32 nbPacket = 1 + (size-1) / packetSize;
2720 // :TODO: use the brodcast form of the message instead of manual message
2723 nldebug("Sending DSS message");
2727 NLNET::CMessage subMsg;
2728 R2::CShareServerEditionItfProxy::buildMessageFor_multiPartMsgHead(subMsg, charId, msg.getName(), nbPacket, size);
2730 // dssMsgForward
2731 sender(subMsg);
2736 const uint8* buffer = msg.buffer();
2739 uint32 i=0;
2740 for (; i != nbPacket; ++i)
2744 // send packetSize octet except for the last packet that just send the remainings data
2745 uint32 dataSend = (i+1)*packetSize > size ? size - packetSize*i:packetSize;
2747 std::vector<uint8> data(const_cast<uint8*>(&buffer[i*packetSize]), const_cast<uint8*>(&buffer[i*packetSize + dataSend]) );
2748 NLNET::CMessage subMsg;
2749 R2::CShareServerEditionItfProxy::buildMessageFor_multiPartMsgBody(subMsg, charId, i, data);
2752 sender(subMsg);
2754 // TODO -> add callback send( (size - packetSize*i) / size)
2759 NLNET::CMessage subMsg;
2760 R2::CShareServerEditionItfProxy::buildMessageFor_multiPartMsgFoot(subMsg, charId);
2762 sender(subMsg);
2767 // Messages from dss that notify that he has received data
2768 // We received first a multiPartMsgHead, then X multiPartMsgBody, then one multiPartMsgFoot
2769 void CClientEditionModule::multiPartMsgHead(NLNET::IModuleProxy * /* sender */, const std::string& msgName, uint32 nbPacket, uint32 size)
2771 R2::getEditor().getLua().executeScriptNoThrow( NLMISC::toString("r2:onMessageSendingStart('%s', %u, %u)",msgName.c_str(), nbPacket, size ) );
2774 void CClientEditionModule::multiPartMsgBody(NLNET::IModuleProxy * /* sender */, uint32 packetId, uint32 packetSize)
2776 R2::getEditor().getLua().executeScriptNoThrow( NLMISC::toString("r2:onMessageSendingUpdate(%u, %u)", packetId, packetSize));
2779 void CClientEditionModule::multiPartMsgFoot(NLNET::IModuleProxy * /* sender */)
2781 R2::getEditor().getLua().executeScriptNoThrow( NLMISC::toString("r2:onMessageSendingFinish()"));