Amerio.Stephane Posted June 21, 2018 Share Posted June 21, 2018 Hello, I'm trying to exchange custom messages between the master and slaves. I've tried using the setTCPUserReceiveCallback on the slave, and sendTcpUser on the master, but when receiving a message, the slaves just freeze. Here is the code I used (I couldn't find an example in the samples/demo, so I just had to guess how to use it): class TcpUserReceive : public Unigine::CallbackBase1<const BlobPtr&> //< Is it the way to do it? { public: void run(const BlobPtr& blob) { String str = blob.get()->readString(); Log::warning("Received: %s\n", str.get()); } } tcpUserReceive; int AppWorldLogic::init() { int syncker_index = Engine::get()->findPlugin("Syncker"); if (syncker_index != -1) { Syncker::ManagerInterface* syncker_manager = (Syncker::ManagerInterface*)Engine::get()->getPluginData(syncker_index); if (!syncker_manager->isMasterInitialized()) //< do it only on slaves { syncker_manager->getSlave()->setTCPUserReceiveCallback(&tcpUserReceive); } } return 1; } int AppWorldLogic::update() { if (App::get()->clearKeyState('x') && !Console::get()->getActivity()) { int syncker_index = Engine::get()->findPlugin("Syncker"); if (syncker_index != -1) { Syncker::ManagerInterface* syncker_manager = (Syncker::ManagerInterface*)Engine::get()->getPluginData(syncker_index); if (syncker_manager->isMasterInitialized()) { BlobPtr blob = Unigine::Blob::create(100); //< what if I pass 0? Is the buffer resized auto? blob->writeString("custom message"); syncker_manager->getMaster()->sendTCPUser(~0, blob); } } } return 1; } Thanks for your help. Link to comment
alexander Posted June 21, 2018 Share Posted June 21, 2018 Hi again, I think you need to reset the current position of your Blob to the beginning before call sendTCPUser(). In future releases i will do it for you automatically. Is it the way to do it? There is a simple way to do it. There is no need to create a new class. what if I pass 0? Is the buffer resized auto? Yes. It is the same as: BlobPtr blob = Unigine::Blob::create(); blob->resize(100); So, try this code: void AppWorldLogic::tcp_user_receive(BlobPtr &blob) // ! { String str = blob->readString(); // ! don't need to use .get() ("->" and ".get()->" are the same things) Log::warning("Received: %s\n", str.get()); // ! but, with Log::warning/message you should use .get() for strings, yes } int AppWorldLogic::init() { int syncker_index = Engine::get()->findPlugin("Syncker"); if (syncker_index != -1) { Syncker::ManagerInterface* syncker_manager = (Syncker::ManagerInterface*)Engine::get()->getPluginData(syncker_index); if (!syncker_manager->isMasterInitialized()) { syncker_manager->getSlave()->setTCPUserReceiveCallback(MakeCallback(this, &AppWorldLogic::tcp_user_receive)); // ! } } return 1; } int AppWorldLogic::update() { if (App::get()->clearKeyState('x') && !Console::get()->getActivity()) { int syncker_index = Engine::get()->findPlugin("Syncker"); if (syncker_index != -1) { Syncker::ManagerInterface* syncker_manager = (Syncker::ManagerInterface*)Engine::get()->getPluginData(syncker_index); if (syncker_manager->isMasterInitialized()) { BlobPtr blob = Unigine::Blob::create(); // ! blob->writeString("custom message"); blob->seekSet(0); // ! reset current position to the beginning syncker_manager->getMaster()->sendTCPUser(~0, blob); } } } return 1; } Best regards, Alexander Link to comment
alexander Posted June 21, 2018 Share Posted June 21, 2018 "In future releases i will do it for you automatically." Sorry, it was a bug. Calling seekSet(0) will help you if you have only one slave. If you have more than one slave then the workaround is: auto master = syncker_manager->getMaster(); for (int i = 0; i < master->getNumSlaves(); i++) { int mask = 1 << i; blob->seekSet(0); master->sendTCPUser(mask, blob); } 1 Link to comment
Amerio.Stephane Posted June 21, 2018 Author Share Posted June 21, 2018 Thanks alex ! :) 33 minutes ago, alexander said: "In future releases i will do it for you automatically." Do you mean the seekSet(0) won't be needed in the future ? Or do you mean the for-loop won't be needed? Does this bug also exist for all other api using a mask to communicate with the slaves? Link to comment
alexander Posted June 21, 2018 Share Posted June 21, 2018 Do you mean the seekSet(0) won't be needed in the future? Yes! In SDK v2.7.2.Or do you mean the for-loop won't be needed? I mean you will be able to do it as you wrote before (without seekSet() and for-loop): syncker_manager->getMaster()->sendTCPUser(~0, blob); Does this bug also exist for all other api using a mask to communicate with the slaves? No. It was only inside the sendTCPUser() method of Master and Slave classes (hope so). Best regards, Alexander Link to comment
Amerio.Stephane Posted June 21, 2018 Author Share Posted June 21, 2018 Sorry to bother, but this line does not compile :( syncker_manager->getSlave()->setTCPUserReceiveCallback(MakeCallback(this, &AppWorldLogic::tcp_user_receive)); // ! 1>c:\tools\dev\unigine sdk browser\sdks\sim_per_channel_windows_2.7.1\include\UnigineCallback.h(451): error C2530: 'Unigine::CallbackObject1<Class,Ret (__cdecl AppWorldLogic::* )(A0),A0>::a0' : les références doivent être initialisées 1> with 1> [ 1> Class=AppWorldLogic, 1> Ret=void, 1> A0=Unigine::BlobPtr & 1> ] 1> c:\tools\dev\unigine sdk browser\sdks\sim_per_channel_windows_2.7.1\include\UnigineCallback.h(451): note: lors de la compilation de la fonction membre '<Inconnu>' de la classe <Inconnu> 1> c:\tools\dev\unigine sdk browser\sdks\sim_per_channel_windows_2.7.1\include\UnigineCallback.h(561): note: voir la référence à l'instanciation de la fonction modèle 'Unigine::CallbackObject1<Class,Ret (__cdecl AppWorldLogic::* )(A0),A0>::CallbackObject1(Class *,Func)' en cours de compilation 1> with 1> [ 1> Class=AppWorldLogic, 1> Ret=void, 1> A0=Unigine::BlobPtr &, 1> Func=void (__cdecl AppWorldLogic::* )(Unigine::Ptr<Unigine::Blob> &) 1> ] 1> c:\tools\dev\unigine sdk browser\sdks\sim_per_channel_windows_2.7.1\include\UnigineCallback.h(561): note: voir la référence à l'instanciation de la classe modèle 'Unigine::CallbackObject1<Class,Ret (__cdecl AppWorldLogic::* )(A0),A0>' en cours de compilation 1> with 1> [ 1> Class=AppWorldLogic, 1> Ret=void, 1> A0=Unigine::BlobPtr & 1> ] 1> AppWorldLogic.cpp(90): note: voir la référence à l'instanciation de la fonction modèle 'Unigine::CallbackBase1<Unigine::BlobPtr &> *Unigine::MakeCallback<AppWorldLogic,void,Unigine::BlobPtr&>(Class *,Ret (__cdecl AppWorldLogic::* )(A0))' en cours de compilation 1> with 1> [ 1> Class=AppWorldLogic, 1> Ret=void, 1> A0=Unigine::BlobPtr & 1> ] (I really don't understand this error, because I use successfully the MakeCallback macro elsewhere for Cigi callbacks). Link to comment
alexander Posted June 21, 2018 Share Posted June 21, 2018 Oops. Change this: void AppWorldLogic::tcp_user_receive(BlobPtr &blob) // ! to this: void AppWorldLogic::tcp_user_receive(BlobPtr blob) // remove '&' Link to comment
Amerio.Stephane Posted June 21, 2018 Author Share Posted June 21, 2018 Good catch :-) Thanks alex Link to comment
Recommended Posts