khanat-opennel-code/code/ryzom/client/src/r2/dmc/client_edition_module.cpp
2013-02-14 09:53:06 -06:00

2762 lines
81 KiB
C++

// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// 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 <http://www.gnu.org/licenses/>.
#include "stdpch.h"
#include <sstream>
#include <map>
#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 <zlib.h>
using namespace std;
using namespace NLMISC;
using namespace NLLIGO;
using namespace NLNET;
CVariable<std::string> UserComponentsExamplesDirectory ("DSS", "UserComponentsExampleDirectory", "", "examples/user_componts", 0, true );
CVariable<std::string> UserComponentsComponentsDirectory ("DSS", "UserComponentsComponentsDirectory", "", "examples/user_componts", 0, true );
CVariable<std::string> UserComponentsComponentExtension ("DSS", "UserComponentsComponentExtension", "", "gz", 0, true );
CVariable<std::string> 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<TMessageId, IServerAnswerMsg*> 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<R2::CObject> _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<R2::CObject> _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<R2::CObject> _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");
//----------------------------- <CServerAnswer> -------------------------------
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;
}
//------------------------------- <CEditorConfig> -------------------------------------------
std::map<std::string, uint32> 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<uint32>(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<sint32>(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<sint32>(displayInfo));
}
bool CEditorConfig::mustDisplayInfo(const std::string& formName) const
{
//H_AUTO(R2_CEditorConfig_mustDisplayInfo)
CInterfaceManager *IM = CInterfaceManager::getInstance ();
std::map<std::string, uint32>::const_iterator found = _NameToId.find(formName);
if (found == _NameToId.end())
return false;
uint32 index = (*found).second;
uint32 newValue = static_cast<uint32>(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<std::string, uint32>::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<uint32>(NLGUI::CDBManager::getInstance()->getDbProp("UI:SAVE:R2:DISPLAYINFO")->getValue32());
}
//----------------------------<CClientEditionModule>-------------------------------------------------------------
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<CUserComponent&>(*component));
component->serial( const_cast<CMessage&>(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<std::string> 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<CObject> 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<uLongf>(component->UncompressedDataLength);
sint32 decompressionState = uncompress (reinterpret_cast<Bytef*>(component->UncompressedData), &dataLength ,
reinterpret_cast<Bytef*>(component->CompressedData), component->CompressedDataLength);
component->UncompressedDataLength = static_cast<uint32>(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<sint32>(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<sint32>(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<uint8*>(dest);
compressedFileLength = static_cast<uint32>(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<std::string> result;
CPath::getPathContent (_ScriptDirectory, false, false, true, result, false, false);
CInterfaceManager *pIM= CInterfaceManager::getInstance();
std::vector<std::string> 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<uint32>(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<sint32>(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<std::string&>(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<R2::TMissionItem> &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<std::string>& 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<uint32> & botId)
{
//H_AUTO(R2_CClientEditionModule_updateIncarningList)
this->_IncarnatingList = botId;
R2::getEditor().getLua().executeScriptNoThrow( "r2.onIncarnatingListUpdated()" );
}
void CClientEditionModule::updateTalkingAsList(NLNET::IModuleProxy * /* sender */, const std::vector<uint32> & botId)
{
//H_AUTO(R2_CClientEditionModule_updateTalkingAsList)
this->_TalkingAsList = botId;
R2::getEditor().getLua().executeScriptNoThrow( "r2.onTalkingAsListUpdated()" );
}
std::vector<uint32> CClientEditionModule::getIncarnatingList() const
{
//H_AUTO(R2_CClientEditionModule_getIncarnatingList)
return this->_IncarnatingList;
}
std::vector<uint32> 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<std::string, std::string>("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<CUserComponentValidator> 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<CScenarioValidator> 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<values.size(); i++)
{
const std::pair<std::string, std::string>& 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<CScenarioValidator> 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<uint8> data(const_cast<uint8*>(&buffer[i*packetSize]), const_cast<uint8*>(&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()"));
}