// Ryzom - MMORPG Framework // Copyright (C) 2010 Winch Gate Property Limited // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . #include "stdpch.h" #include "id_impulsions.h" #include "uid_impulsions.h" #include "game_share/generic_xml_msg_mngr.h" #include "game_share/sphrase_com.h" #include "game_share/synchronised_message.h" #include "entity_container.h" #include "frontend_service.h" using namespace std; using namespace NLMISC; using namespace NLNET; extern CGenericXmlMsgHeaderManager GenericXmlMsgHeaderMngr; extern NLNET::TServiceId SelfServiceId; void cbImpulsionIdGatewayOpen( CEntityId& sender, CBitMemStream &bms, TGameCycle gamecycle, uint16 serviceId ); void cbImpulsionIdGatewayMessage( CEntityId& sender, CBitMemStream &bms, TGameCycle gamecycle, uint16 serviceId ); void cbImpulsionIdGatewayClose( CEntityId& sender, CBitMemStream &bms, TGameCycle gamecycle, uint16 serviceId ); /* * Callbacks of messages with special data handling */ //----------------------------------------------- // impulsionRdy : // //----------------------------------------------- void impulsionRdy( CEntityId& sender, CBitMemStream &bms, TGameCycle gamecycle, uint16 serviceId ) { // Tell EGS that the character is ready. When processing this message, the EGS will // add the entity into mirror. Thus the sending must be done using sendMessageViaMirror // for proper synchronization CMessage msgout("RDY"); msgout.serial( sender ); sendMessageViaMirror("EGS", msgout); /* // Forward message from client to IOS (for string info) CMessage msgout2("READY_STRING"); msgout2.serial( sender ); uint8 nbBitsToSkip = (uint8)bms.getPosInBit(); // instead of deleting the bits already read by the GenericXMLManager, tell how many there are msgout2.serial( nbBitsToSkip ); msgout2.serialMemStream( bms ); CUnifiedNetwork::getInstance()->send("IOS", msgout2 ); */ } //----------------------------------------------- // impulsionCmd : send a command to be executed on the destination // //----------------------------------------------- void impulsionCmd( CEntityId& sender, CBitMemStream &bms, TGameCycle gamecycle, uint16 serviceId ) { bool addentity; string dest, cmd, arg; try { bms.serial(addentity); bms.serial(dest); bms.serial(cmd); bms.serial(arg); } catch( Exception& e ) { nlwarning(" %s",e.what()); return; } nlinfo(" CMD received : %s %s to %s",cmd.c_str(), arg.c_str(), dest.c_str()); CMessage msgout("EXEC_COMMAND"); string res; res = cmd + " "; if (addentity) { res += sender.toString() + " "; } res += arg; msgout.serial (res); nlinfo(" CMD forwarded : '%s'",res.c_str()); CUnifiedNetwork::getInstance()->send(dest, msgout); } //----------------------------------------------- // impulsionAdmin OUTOFDATE // //----------------------------------------------- /*void impulsionAdmin( CEntityId& sender, CBitMemStream &bms, TGameCycle gamecycle, uint16 serviceId ) { string cmd, arg; bool onTarget; try { bms.serial(onTarget); bms.serial(cmd); bms.serial(arg); } catch( Exception& e ) { nlwarning(" %s",e.what()); return; } nlinfo ("User %s wants to execute '%s' '%s' from the client, forward it to the EGS", sender.toString().c_str(), cmd.c_str(), arg.c_str()); CMessage msgout("CLIENT:COMMAND:ADMIN"); msgout.serial (sender); msgout.serial (onTarget); msgout.serial (cmd); msgout.serial (arg); CUnifiedNetwork::getInstance()->send("EGS", msgout); }*/ //----------------------------------------------- // impulsionStringRequestId // //----------------------------------------------- //void impulsionStringRequestId( CEntityId& sender, CBitMemStream &bms, TGameCycle gamecycle, uint16 serviceId ) //{ // uint32 stringId; // try // { // bms.serial(stringId); // } // catch( Exception& e ) // { // nlwarning(" %s", e.what()); // return; // } // // CMessage msgout( "STRING_RQ_ID" ); // msgout.serial( sender ); // msgout.serial( stringId ); // CUnifiedNetwork::getInstance()->send("IOS", msgout); // //} //----------------------------------------------- // impulsionPhraseLearn : learn a phrase //----------------------------------------------- void impulsionPhraseLearn( CEntityId& sender, CBitMemStream &bms, TGameCycle gamecycle, uint16 serviceId ) { uint16 phraseId; CSPhraseCom phraseDesc; try { bms.serial( phraseId ); bms.serial( phraseDesc ); } catch( Exception& e ) { nlwarning(" %s",e.what()); return; } CMessage msgout("CLIENT:PHRASE:LEARN"); msgout.serial( sender ); msgout.serial( phraseId ); msgout.serial( phraseDesc ); CUnifiedNetwork::getInstance()->send("EGS", msgout); } //----------------------------------------------- // impulsionPhraseMemorize : memorize a phrase //----------------------------------------------- void impulsionPhraseMemorize( CEntityId& sender, CBitMemStream &bms, TGameCycle gamecycle, uint16 serviceId ) { uint8 set,slot; uint16 phraseId; CSPhraseCom phraseDesc; try { bms.serial( set ); bms.serial( slot ); bms.serial( phraseId ); bms.serial( phraseDesc ); } catch( Exception& e ) { nlwarning(" %s",e.what()); return; } CMessage msgout("CLIENT:PHRASE:MEMORIZE"); msgout.serial( sender ); msgout.serial( set ); msgout.serial( slot ); msgout.serial( phraseId ); msgout.serial( phraseDesc ); CUnifiedNetwork::getInstance()->send("EGS", msgout); } //----------------------------------------------- // impulsionExecuteFaber : client execute faber phrase //----------------------------------------------- void impulsionExecuteFaber( CEntityId& sender, CBitMemStream &bms, TGameCycle gamecycle, uint16 serviceId ) { NLMISC::CSheetId craftPlan; uint8 memory, slot; std::vector< CFaberMsgItem > rmSelected; std::vector< CFaberMsgItem > rmFormulaSelected; try { bms.serial( craftPlan ); bms.serial( memory ); bms.serial( slot ); bms.serialCont( rmSelected ); bms.serialCont( rmFormulaSelected ); } catch( Exception& e ) { nlwarning(" %s",e.what()); return; } CMessage msgout("CLIENT:PHRASE:EXECUTE_FABER"); msgout.serial( sender ); msgout.serial( craftPlan ); msgout.serial( memory ); msgout.serial( slot ); msgout.serialCont( rmSelected ); msgout.serialCont( rmFormulaSelected ); CUnifiedNetwork::getInstance()->send("EGS", msgout); } //----------------------------------------------- // cbImpulsionGetNpcIconDesc //----------------------------------------------- void cbImpulsionGetNpcIconDesc( CEntityId& sender, CBitMemStream &bms, TGameCycle gamecycle, uint16 serviceId ) { try { vector npcKeys; uint8 nb8; bms.serial( nb8 ); npcKeys.resize( nb8 ); for (uint i=0; i!=(uint)nb8; ++i) { bms.serial( npcKeys[i] ); } CMessage msgout("CLIENT:NPC_ICON:GET_DESC"); msgout.serial( sender ); msgout.serialCont( npcKeys ); CUnifiedNetwork::getInstance()->send("EGS", msgout); //nldebug("Forwarding GET_DESC to EGS (%hu NPCs)", nb8 ); } catch ( Exception& e ) { nlwarning(" %s", e.what()); return; } } /* * General receiving function for impulsions by CEntityId from client to server */ void routeImpulsionIdFromClient( NLMISC::CBitMemStream& bms, const NLMISC::CEntityId& sender, const NLMISC::TGameCycle& gamecycle ) { string msgName; try { /* // Check player behaviour in case the player is stunned const TDataSetRow& dataSetRow = TheDataset.getDataSetRow( sender ); if ( dataSetRow.isValid() ) { CMirrorPropValueRO stunned( TheDataset, dataSetRow, DSPropertyStunned ); if ( stunned() ) { nldebug("Entity %s is stunned, reject impulsion", sender.toString().c_str()); return; } } */ // Decode XML header CGenericXmlMsgHeaderManager::CNodeId msgNodeId = GenericXmlMsgHeaderMngr.getNodeId(bms, msgName); // check if message decoded safely if (!msgNodeId.isValid()) { nlwarning("Unable to decode message from sender %s", sender.toString().c_str()); } else { // get format and sendto of message const CGenericXmlMsgHeaderManager::TMessageFormat &format = GenericXmlMsgHeaderMngr.getNodeFormat(msgNodeId); const string &sendto = GenericXmlMsgHeaderMngr.getNodeSendTo(msgNodeId); // check sendto if (sendto == "") { TImpulsionIdCb cb = (TImpulsionIdCb)(GenericXmlMsgHeaderMngr.getNodeUserData(msgNodeId, 0)); if (cb != NULL) { cb(sender, bms, gamecycle, SelfServiceId); //nldebug( "RTG: Routed impulsion %s via user callback [%s]", msgName.c_str(), sender.toString().c_str() ); } else { // Try with the "impulsions uid" callbacks. // After a CEntityId has been stored for a user, the FS routes all by id. The client // may want to send a message that has a uid callback. // Warning: the message should contain the character index, as the FS callback knows only the userId TImpulsionUidCb ucb = (TImpulsionUidCb)(GenericXmlMsgHeaderMngr.getNodeUserData(msgNodeId, 1)); if (ucb != NULL) { ucb((uint32)(sender.getShortId() >> 4), bms, gamecycle); nldebug( "RTG: Routed impulsion %s (redir uid) via user callback [%s]", msgName.c_str(), sender.toString().c_str() ); } else { nlwarning( "RTG: Can't route impulsion %s [%s], no 'sendto' nor user callback", msgName.c_str(), sender.toString().c_str() ); return; } } } else { // create forward message CMessage msgout("CLIENT:"+msgName); msgout.serial(const_cast(sender)); if (GenericXmlMsgHeaderMngr.nodeUsesCycle(msgNodeId)) msgout.serial(const_cast(gamecycle)); union { bool b; uint8 u8; uint16 u16; uint32 u32; uint64 u64; sint8 s8; sint16 s16; sint32 s32; sint64 s64; float f; double d; } store; CEntityId e; string s; ucstring ucs; uint i; // for each message field, serial in and serial out for (i=0; isend(sendto, msgout ); sendMessageViaMirror( sendto, msgout ); // because of guild management //nldebug( "RTG: Routed impulsion %s to %s [%s]", msgName.c_str(), sendto.c_str(), sender.toString().c_str() ); } } // transfer the message to the BBS /*if( BBSUp ) { CMessage msgout("IMPULSION_ID"); msgout.serial( sender ); msgout.serialCont( v ); msgout.serial( gamecycle ); CUnifiedNetwork::getInstance()->send("BBS", msgout); }*/ } catch( Exception& e ) { nlwarning(" %s %s", msgName.c_str(), e.what() ); return; } } // cbImpulsionId // /* * Receiving function for impulsions by CEntityId, with slot translation, from client to server */ void routeImpulsionIdSlotFromClient( const uint32& targetLootHarvest, const TDataSetRow& targetIndex, const TDataSetRow& senderIndex, const NLMISC::TGameCycle& ) { if ( targetLootHarvest == 0 ) { // TARGET CMessage msgout( "TARGET" ); msgout.serial( const_cast(senderIndex), const_cast(targetIndex) ); // the gamecycle is not used by EGS CUnifiedNetwork::getInstance()->send( "EGS", msgout ); } else { // PICKUP (loot/harvest) CMessage msgout( "ITEM_PICK_UP" ); const CEntityId& senderId = TheDataset.getEntityId( senderIndex ); const CEntityId& pickedId = TheDataset.getEntityId( targetIndex ); msgout.serial( const_cast(senderId), const_cast(pickedId) ); uint8 lootHarvestState = (uint8)targetLootHarvest; // targetLootHarvest is one from LHSTATE::TLHState msgout.serial( lootHarvestState ); CUnifiedNetwork::getInstance()->send( "EGS", msgout ); } } /* * Map the callbacks for messages with special data handling */ void initImpulsionId() { GenericXmlMsgHeaderMngr.setUserData("CONNECTION:READY", (uint64)impulsionRdy, 0); GenericXmlMsgHeaderMngr.setUserData("DEBUG:CMD", (uint64)impulsionCmd, 0); // GenericXmlMsgHeaderMngr.setUserData("COMMAND:ADMIN", (uint64)impulsionAdmin, 0); // GenericXmlMsgHeaderMngr.setUserData("STRING_MANAGER:STRING_RQ", (uint64)impulsionStringRequestId, 0); GenericXmlMsgHeaderMngr.setUserData("PHRASE:LEARN", (uint64)impulsionPhraseLearn, 0); GenericXmlMsgHeaderMngr.setUserData("PHRASE:MEMORIZE", (uint64)impulsionPhraseMemorize, 0); GenericXmlMsgHeaderMngr.setUserData("PHRASE:EXECUTE_FABER", (uint64)impulsionExecuteFaber, 0); GenericXmlMsgHeaderMngr.setUserData("MODULE_GATEWAY:FEOPEN", (uint64)cbImpulsionIdGatewayOpen, 0); GenericXmlMsgHeaderMngr.setUserData("MODULE_GATEWAY:GATEWAY_MSG", (uint64)cbImpulsionIdGatewayMessage, 0); GenericXmlMsgHeaderMngr.setUserData("MODULE_GATEWAY:FECLOSE", (uint64)cbImpulsionIdGatewayClose, 0); GenericXmlMsgHeaderMngr.setUserData("NPC_ICON:GET_DESC", (uint64)cbImpulsionGetNpcIconDesc, 0); }