Exemple #1
0
void CClient::EchoMessage(const CMessage& Message)
{
	for (CClient* pClient : GetClients()) {
		if (pClient->HasEchoMessage() || (pClient != this && (m_pNetwork->IsChan(Message.GetParam(0)) || pClient->HasSelfMessage()))) {
			pClient->PutClient(":" + GetNickMask() + " " + Message.ToString(CMessage::ExcludePrefix));
		}
	}
}
Exemple #2
0
void CConnect::Handle_Connect()
{
	CMessage *Msg = CMessageAlloctor::AllocMSG(100, 4);
	Msg->fd_ = GetFd();
	Msg->Write(EventLoop_->GetIndex());
	Msg->SetSendFlag();
	EventLoop_->PushMsg(Msg);
}
Exemple #3
0
int mesage_SaveFieldBinary(lua_State* L) {
	int err = 0;
	char *b = NULL;
	CMessage* msg = cmessage_arg(L, "mesage_AddFieldBinary");
	CString fldName = luaL_checkstring(L, 2);
	CString path = luaL_checkstring(L, 3);
	char *description;
	DWORD l;

	CDatum *d = msg->GetDatum(fldName);
	if (d->GetVarType() != (VT_ARRAY | VT_UI1) ) {
		err = -1;
		description = "Not Binary Data";
		goto err;
	}
	{
		l = d->GetDataSize();
		b = new char[l];


		SAFEARRAY* pArray = d->value().parray;
		ASSERT(pArray->cDims == 1); // check we have 1 dimension array
		ASSERT(l == pArray->rgsabound[0].cElements * pArray->cbElements); // get size of array
		memcpy(b, (BYTE*)pArray->pvData, l);

		int charsLen = ::MultiByteToWideChar(CP_UTF8, 0, path, lstrlen(path), NULL, 0);
		std::wstring characters(charsLen, '\0');
		::MultiByteToWideChar(CP_UTF8, 0, path, lstrlen(path), &characters[0], charsLen);

		int pf;

		err = _wsopen_s(&pf, characters.c_str(), _O_BINARY | _O_CREAT | _O_TRUNC | _O_WRONLY, _SH_DENYRW, _S_IWRITE);
		if (err) {
			description = "Open File Error";
			goto err;
		}
		if (l != _write(pf, (b), l)) {
			err = -2;
			description = "Write File Error";
			goto err;
		}

		err = _close(pf);
		if (err){
			description = "Close File Error";
			goto err;
		}
	}
err:
	if (b)
		delete[]b;
	lua_pushinteger(L, err);
	if (err)
		lua_pushstring(L, description);
	else
		lua_pushinteger(L, l);
	return 2;
}
void CBunny::receiveMessage( CMessage theMessage, unsigned int senderID )
{
	// Do stuff that's specific to this type of object...
	
	CNameValuePair firstNVPair;

	if ( theMessage.findNVPairByName( "FollowClosest", firstNVPair ) )
	{	
		// ___      _  _                ___  _                    _   
		//| __|___ | || | ___ __ __ __ / __|| | ___  ___ ___  ___| |_ 
		//| _|/ _ \| || |/ _ \\ V  V /| (__ | |/ _ \(_-</ -_)(_-<|  _|
		//|_| \___/|_||_|\___/ \_/\_/  \___||_|\___//__/\___|/__/ \__|
		//                                                            
		//vec[0].name = "FollowClosest"   
		//vec[1].fValue = 0.1f  			<-- closest distance
		//vec[2].fValue = 0.1f				<-- speed we'll go

		// We'll save this inforamtion, and also query the mediator about stuff...
		this->m_followClosestDistance = theMessage.vecNVPairs[1].fValue;
		this->m_followSpeed = theMessage.vecNVPairs[2].fValue;
		// Find the closest object
		std::vector< unsigned int > vecIDs;
		vecIDs = this->m_pMediator->GetIDOfNearestObjects( this->position, 20.0f ); 
		// Did we find anything close? 
		if ( !vecIDs.empty() )
		{	// Yup, we did, so pick the first
			// (m_closestObject is a CVector3f)
			this->m_pMediator->GetPositionByID( vecIDs[0], this->m_closestObject );
			// Update the state of this object
			this->m_CurrentState = CBunny::IS_FOLLOWING_CLOSEST_OBJECT;
		}
	}
	else if ( theMessage.findNVPairByName( "FollowObject", firstNVPair ) )
	{
		// ___      _  _                ___   _      _           _   
		//| __|___ | || | ___ __ __ __ / _ \ | |__  (_) ___  __ | |_ 
		//| _|/ _ \| || |/ _ \\ V  V /| (_) || '_ \ | |/ -_)/ _||  _|
		//|_| \___/|_||_|\___/ \_/\_/  \___/ |_.__/_/ |\___|\__| \__|
		//                                        |__/               
		//vec[0].name = "FollowClosest"   
		//vec[0].iValue = ID of object to follow
		//vec[1].fValue = 0.1f  			<-- closest distance
		//vec[2].fValue = 0.1f				<-- speed we'll go
		// We'll save this inforamtion, and also query the mediator about stuff...
		this->m_followClosestDistance = theMessage.vecNVPairs[1].fValue;
		this->m_followSpeed = theMessage.vecNVPairs[2].fValue;
		this->m_ID_of_ObjectToFollow = static_cast<unsigned int>( theMessage.vecNVPairs[0].iValue );
		this->m_CurrentState = CBunny::IS_FOLLOWING_SPECIFIC_OBJECT;
		// We'll wait for the next update to start following this object		
	}



	// Calls the base class (or in Java, the super class)
	CGameObject::receiveMessage( theMessage, senderID );

	return;
}
// a front end closes the connection, deconnect him
void cbFESDisconnection (const std::string &serviceName, TServiceId  sid, void *arg)
{
	nldebug("new FES disconnection: sid %u", sid.get());

	for (list<CFES>::iterator it = FESList.begin(); it != FESList.end(); it++)
	{
		if ((*it).SId == sid)
		{
			// send a message to the LS to say that all players from this FES are offline
			map<uint32, TServiceId>::iterator itc = UserIdSockAssociations.begin();
			map<uint32, TServiceId>::iterator nitc = itc;
			while (itc != UserIdSockAssociations.end())
			{
				nitc++;
				if ((*itc).second == sid)
				{
					// bye bye little player
					uint32 userid = (*itc).first;
					nlinfo ("Due to a frontend crash, removed the player %d", userid);
					if (!DontUseLS)
					{
						CMessage msgout ("CC");
						msgout.serial (userid);
						uint8 con = 0;
						msgout.serial (con);
						CUnifiedNetwork::getInstance()->send ("LS", msgout);
					}
					UserIdSockAssociations.erase (itc);
				}
				itc = nitc;
			}

			bool	dummy;
			(*it).reportStateToLS(dummy, false);

			// remove the FES
			FESList.erase (it);

			break;
		}
	}

	// Update the welcome service client with the new count of connection

	uint32 totalNbOnlineUsers =0, totalNbPendingUsers = 0;
	for (list<CFES>::iterator it = FESList.begin(); it != FESList.end(); it++)
	{
		const CFES &fes = *it;
		totalNbOnlineUsers += fes.NbUser;
		totalNbPendingUsers += fes.NbPendingUsers;
	}

	if (CWelcomeServiceMod::isInitialized())
		CWelcomeServiceMod::getInstance()->updateConnectedPlayerCount(totalNbOnlineUsers, totalNbPendingUsers);

	displayFES ();
}
Exemple #6
0
void	sendSelectedInInventory (uint32 did)
{
if (!isOnline ()) return;

	CMessage msgout (Connection->getSIDA(), "INV_SELECT");
	msgout.serial( did );
	Connection->send (msgout);
//	nlinfo("Sending snowball to network (%f,%f,%f) to (%f,%f,%f) with %f %f", position.x, position.y, position.z, target.x, target.y, target.z, speed, deflagRadius);
}
Exemple #7
0
bool CClient::OnPingMessage(CMessage& Message) {
    // All PONGs are generated by ZNC. We will still forward this to
    // the ircd, but all PONGs from irc will be blocked.
    if (!Message.GetParams().empty())
        PutClient(":irc.znc.in PONG irc.znc.in " + Message.GetParams(0));
    else
        PutClient(":irc.znc.in PONG irc.znc.in");
    return false;
}
void CCallbackClient::connect( const CInetAddress& addr )
{
#ifdef USE_MESSAGE_RECORDER
	if ( _MR_RecordingState != Replay )
	{
		try
		{
#endif

			// Connect
			CBufClient::connect( addr );

#ifdef USE_MESSAGE_RECORDER
			if ( _MR_RecordingState == Record )
			{
				// Record connection
				CMessage addrmsg;
				addrmsg.serial( const_cast<CInetAddress&>(addr) );
				_MR_Recorder.recordNext( _MR_UpdateCounter, Connecting, _BufSock, addrmsg );
			}
		}
		catch ( ESocketConnectionFailed& )
		{
			if ( _MR_RecordingState == Record )
			{
				// Record connection
				CMessage addrmsg;
				addrmsg.serial( const_cast<CInetAddress&>(addr) );
				_MR_Recorder.recordNext( _MR_UpdateCounter, ConnFailing, _BufSock, addrmsg );
			}
			throw;
		}
	}
	else
	{
		// Check the connection : failure or not
		TNetworkEvent event = _MR_Recorder.replayConnectionAttempt( addr );
		switch ( event )
		{
		case Connecting :
			// Set the remote address
			nlassert( ! _BufSock->Sock->connected() );
			_BufSock->connect( addr, _NoDelay, true );
			_PrevBytesDownloaded = 0;
			_PrevBytesUploaded = 0;
			/*_PrevBytesReceived = 0;
			_PrevBytesSent = 0;*/
			break;
		case ConnFailing :
			throw ESocketConnectionFailed( addr );
			//break;
		default :
			nlwarning( "LNETL3C: No connection event in replay data, at update #%"NL_I64"u", _MR_UpdateCounter );
		}
	}
#endif
}
Exemple #9
0
void	sendSummonMammoth (uint32 mammothId)
{
	if (!isOnline ()) return;

	CMessage msgout (Connection->getSIDA(), "SUMMON_MAMMOTH");
	msgout.serial(mammothId);
	Connection->send (msgout);
//	nlinfo("Sending snowball to network (%f,%f,%f) to (%f,%f,%f) with %f %f", position.x, position.y, position.z, target.x, target.y, target.z, speed, deflagRadius);
}
Exemple #10
0
    EModRet OnUserRawMessage(CMessage& msg) override {
        if (!msg.GetCommand().Equals("AWAY")) return CONTINUE;

        // If a client set us away, we don't touch that away message
        m_bClientSetAway = !msg.GetParam(0).Trim_n(" ").empty();
        m_bWeSetAway = false;

        return CONTINUE;
    }
void CSimClientEditionModule::requestUploadScenario(CObject* scenario)
{
	nlinfo( "SimCEM%d: requestUploadScenario: %x", _Id, scenario );
	CSerialFactoryBackup fb;
	CMessage message ("requestUploadScenario");
	BOMB_IF(_ServerEditionProxy == NULL, "Server Edition Module not connected", return);	
	message.serial(CObjectSerializer(scenario));
	_ServerEditionProxy->sendModuleMessage(this, message );
}
Exemple #12
0
int mesage_AttachMessage(lua_State* L)
{	
	CMessage* msg = cmessage_arg(L,"mesage_AttachMessage");
	CString subName = luaL_checkstring(L,2);
	CMessage* subMsg = cmessage_arg(L,"mesage_AttachMessage",3);
	subMsg->id(subName);
	msg->AttachMsg(subMsg);
	return 0;
}
Exemple #13
0
int mesage_AddFieldBinary(lua_State* L) {
	CMessage* msg = cmessage_arg(L, "mesage_AddFieldBinary");
	CString fldName = luaL_checkstring(L, 2);
	CString path = luaL_checkstring(L, 3); 
	int err;
	char *description;

	int charsLen = ::MultiByteToWideChar(CP_UTF8, 0, path, lstrlen(path), NULL, 0);
	std::wstring characters(charsLen, '\0');
	::MultiByteToWideChar(CP_UTF8, 0, path, lstrlen(path), &characters[0], charsLen);

	int pf;
	char *b = NULL;
	err = _wsopen_s(&pf, characters.c_str(), _O_BINARY | _O_RDONLY, _SH_DENYWR, _S_IREAD);
	if (err) {
		description = "Open File error";
		goto err;
	}

	DWORD l = _filelength(pf);

	b = new char[l];


	if (l != _read(pf, b, l)) {
		err = -1;
		description = "Read File error";
		goto err;
	}
	err = _close(pf);
	if (err) {
		description = "Close File error";
		goto err;
	}
	{
		COleSafeArray arr;
		arr.Create(VT_UI1, 1, &l);

		for (DWORD i = 0; i < l; i++) {

			arr.PutElement((long*)&i, &b[i]);
		}

		msg->AddDatum(fldName, arr);
	}

err:
	if (b)
		delete []b;
	lua_pushinteger(L, err);
	if (err)
		lua_pushstring(L, description);
	else
		lua_pushinteger(L, l);
	return 2;
}
Exemple #14
0
/****************************************************************************
 * Function:   cbAddEntity
 *             Callback function called when the Position Service receive a
 *             "ADD_ENTITY" message
 ****************************************************************************/
void cbAddEntity (CMessage &msgin, const std::string &serviceName, TServiceId sid)
{
	bool    all;
	uint32  id;
	string  name;
	uint8   race;
	CVector startPoint;

	// Extract the incomming message content from the Frontend and print it
	msgin.serial( id );
	msgin.serial( name );
	msgin.serial( race );
	msgin.serial( startPoint );
	nldebug( "SB: Received ADD_ENTITY line." );

	// Prepare to send back the message.
	all = true;
	CMessage msgout( "ADD_ENTITY" );
	msgout.serial( all );
	msgout.serial( id );
	msgout.serial( id );
	msgout.serial( name );
	msgout.serial( race );
	msgout.serial( startPoint );

	/*
	 * Send the message to all the connected Frontend. If we decide to send
	 * it back to the sender, that last argument should be 'from' inteed of '0'
	 */
	CUnifiedNetwork::getInstance ()->send( "FS", msgout );

	CCLSClientPOS::addEntity(id, startPoint, /* 10.0f, */ 1.0f);

	nldebug( "SB: Send back ADD_ENTITY line." );

	// Send ADD_ENTITY message about all already connected client to the new one.
	all = false;
	_pmap::iterator ItPlayer;
	for (ItPlayer = playerList.begin(); ItPlayer != playerList.end(); ++ItPlayer)
	{
		CMessage msgout( "ADD_ENTITY" );
		msgout.serial( all );
		msgout.serial( id );
		msgout.serial( ((*ItPlayer).second).id );
		msgout.serial( ((*ItPlayer).second).name );
		msgout.serial( ((*ItPlayer).second).race );
		msgout.serial( ((*ItPlayer).second).position );

		CUnifiedNetwork::getInstance ()->send( sid, msgout);
	}

	nldebug( "SB: Send ADD_ENTITY line about all already connected clients to the new one." );

	// ADD the current added entity in the player list.
	playerList.insert( make_pair( id, _player( id, name, race, startPoint ) ));
}
Exemple #15
0
void CDummyWnd::RedirectClient(CMessage *pMsg)
{
	COMMON_PACKET cmnpck;
	unsigned short channelno;

	int nPacketLen = pMsg->GetData(&cmnpck, 0, sizeof(cmnpck));
	pMsg->GetData(&channelno, nPacketLen, sizeof(channelno));

	int nLen = m_ServerManager.GetLength();
	int nTotalChannel = 0;
	int serverid = 0;

	LPSERVER lpserver = NULL;
	//lpserver = new SERVER; 

	// Ŭ¶óÀ̾ðÆ®°¡ ÀÔÀåÇÒ Ã¤³ÎÀ» Æ÷ÇÔÇÏ´Â ¼­¹ö ¾ÆÀ̵𸦠±¸ÇÔ
	// ¼­¹ö¸¶´Ù ä³Î Å©±â°¡ °¢°¢ ´Ù¸¦ ¼ö ÀÖÀ½
	for(int i = 0 ; i < nLen ; i++)
	{
		lpserver = m_ServerManager.GetServer(i);
		// GetServer´Â lpserver¸¦ return....
		// ¿©±â¼­ ¸Þ¸ð¸® ÁÖ¼Ò ¹®Á¦ ¹ß»ý.....
		//

		if((nTotalChannel + lpserver->maxchannel) <= channelno)
		{
			serverid++;
			nTotalChannel += lpserver->maxchannel;
		}

		else
		{
			channelno -= nTotalChannel;
			break;
		}
	}

	if(lpserver != NULL)
	{
		CMessage Send;
		SERVERINFO si;

		si.cmnpck.header = CSM_DESTSVRINFO;
		si.cmnpck.length = sizeof(SERVERINFO);
		si.id = lpserver->id;
		strcpy((char *)si.ip, lpserver->ip.data());
		si.port = lpserver->portno;
		si.rooms = channelno; // rooms¿¡ ´ë½Å channelno°¡ µé¾î°¨ rooms´Â ³ªÁß¿¡ Game Server·ÎºÎÅÍ Á÷Á¢ ¹ÞÀ½
		
	//	LPCHANNEL temp = 

		Send.SetData(&si, 0, sizeof(SERVERINFO));

		m_ClientSocket.SendMsg((SOCKET)pMsg->GetSocket(), (char *)Send.GetDataPtr(), Send.GetLength());
	}
}
Exemple #16
0
void	sendDropDynamicObject (uint32 playerId, uint32 dynamicObjectId)
{
	if (!isOnline ()) return;
	if (dynamicObjectId<50000 || dynamicObjectId>90000) return;

	CMessage msgout (Connection->getSIDA(), "DROP_DO");
	msgout.serial ( playerId, dynamicObjectId);
	Connection->send (msgout);
	if (ShowDebugInChat) nlinfo("sent drop");
}
Exemple #17
0
static void cbChangeSkill (CMessage &msgin, TSockId from, CCallbackNetBase &netbase)
{
	if (ShowDebugInChat) nlinfo("CHSKILL");
	uint8 skillId;
	uint16 value;
	msgin.serial( skillId );
	msgin.serial( value );
	if (ShowDebugInChat) nlinfo("CHSKILL = %d id and %d value", skillId, value );
	CharacterSkills.update( skillId, value );
}
Exemple #18
0
static void cbChangeStat (CMessage &msgin, TSockId from, CCallbackNetBase &netbase)
{
	if (ShowDebugInChat) nlinfo("CHSTAT");
	uint8 statId;
	sint16 value;
	msgin.serial( statId );
	msgin.serial( value );
	if (ShowDebugInChat) nlinfo("CHSTAT = %d id and %d value", statId, value );
	CharacterStats.update( statId, value );
}
Exemple #19
0
void CMirrorService::serialToMessageFromLocalQueue( CMessage& msgout, const TMessageCarrier& srcMsgInQueue )
{
	//H_AUTO(serialToMessageFromLocalQueue);
	msgout.serial( const_cast<TServiceId&>(srcMsgInQueue.SenderId) );

	// Not using serialMemStream because the receiver will read the size and pass the entire message to the appropriate callback
	sint32 msgSize = (sint32)srcMsgInQueue.Msg.length();
	msgout.serial( msgSize );
	msgout.serialBuffer( const_cast<uint8*>(srcMsgInQueue.Msg.buffer()), srcMsgInQueue.Msg.length() );
}
void CSimClientEditionModule::requestMapConnection( uint32 scenarioId, bool mustTp)
{
	nlinfo( "CSimClientEditionModule: requestMapConnection: %d", scenarioId );
	CSerialFactoryBackup fb;
	CMessage message ("requestMapConnection");
	BOMB_IF(_ServerEditionProxy == NULL, "Server Edition Module not connected", return);	
	message.serial(scenarioId);
	message.serial(mustTp);
	_ServerEditionProxy->sendModuleMessage(this, message );
}
Exemple #21
0
void	sendEntityMissing ( uint32 id )
{
	if (!isOnline ()) return;

	CMessage msgout (Connection->getSIDA(), "ENTITY_MISSING");
	msgout.serial (id);

	Connection->send (msgout);

}
Exemple #22
0
int main(void)
{
	CMessage good_new("I pass the exam!");
	CMessage* pm =new CMessage("congratulation");
	good_new.ShowIt();
	pm->ShowIt();
	cout << endl;
	delete pm;
	return 0;
}
static void cbGetView(CMessage &msgin, const std::string &serviceName, TServiceId sid)
{
	uint32 rid;
	string rawvarpath;

	msgin.serial(rid);
	msgin.serial(rawvarpath);

	addRequest(rid, rawvarpath, sid);
}
Exemple #24
0
void	sendSummonShaman (uint32 shamanId)
{
	if (ShowDebugInChat) nlinfo("Summoning a Shaman");
	if (!isOnline ()) return;

	CMessage msgout (Connection->getSIDA(), "SUMMON_SHAMAN");
	msgout.serial(shamanId);
	Connection->send (msgout);
//	nlinfo("Sending snowball to network (%f,%f,%f) to (%f,%f,%f) with %f %f", position.x, position.y, position.z, target.x, target.y, target.z, speed, deflagRadius);
}
Exemple #25
0
//----------------------------------------------------------//
// CPacket::GetMessages
//----------------------------------------------------------//
CPacket::Error::Enum CPacket::GetMessages(TMessageList& tempList)
{
	//-- DataBuffer should have exactly m_HeaderV1.m_nMessages inside it.
	tempList.clear();

	u16 nProcessedMessages = 0;
	CPacketSerializer messageDeserializer(ISerializer::Mode::Deserializing, m_DataBuffer.Buffer(), m_DataBuffer.UsedSize());
	CPacketSerializer::Error::Enum eSerError = CPacketSerializer::Error::Ok;
	
	while ( (CPacketSerializer::Error::Ok == eSerError)
		&& (messageDeserializer.GetOffset() < messageDeserializer.GetSize()) )
	{
		CMessage::Type nMessageType = CMessage::kTypeUnknown;

		if (IS_ZERO(messageDeserializer.SerializeU32(nMessageType, 'type')))
		{
			return Error::Serializer;
		}

		CMessage* pMessage = CMessageFactory::CreateType(nMessageType);
		if (IS_NULL_PTR(pMessage))
		{
			return Error::ProtocolMismatch;
		}

		pMessage->Serialize(messageDeserializer);

		eSerError = messageDeserializer.GetError();
		if (CPacketSerializer::Error::Ok != eSerError)
		{
			return Error::Serializer;
		}

		SysSmartPtr<CMessage> pSmart(pMessage);
		tempList.push_back(pSmart);
		++nProcessedMessages;
	}

	//-- Sanity tests
	//-- messageSerializer should have consumed all its bytes.
	assert(messageDeserializer.GetOffset() == messageDeserializer.GetSize());
	if (messageDeserializer.GetOffset() != messageDeserializer.GetSize())
	{
		return Error::SanityFail;
	}

	//-- We should have processed exactly the right number of messages.
	assert(nProcessedMessages == GetMessageCount());
	if (nProcessedMessages != GetMessageCount())
	{
		return Error::SanityFail;
	}

	return Error::Ok;
}
Exemple #26
0
void	sendEndPathTrace (string pathName)
{
	if (ShowDebugInChat) nlinfo("Ending Path Trace");
	if (!isOnline ()) return;

	CMessage msgout (Connection->getSIDA(), "END_PATH_TRACE");
	
	msgout.serial( pathName );

	Connection->send (msgout);
}
Exemple #27
0
static void cbTracer(CMessage &msgin, TSockId from, CCallbackNetBase &netbase)
{
	CVector			position;
	std::string		tracerText;

	msgin.serial (position);
	msgin.serial (tracerText);
	if (ShowDebugInChat) nlinfo(" Text=%s", tracerText);
	if (ShowDebugInChat) nlinfo(" pos=%f %f %f", position.x, position.y, position.z);
	addTextTracer(tracerText, position);
}
Exemple #28
0
// Send a request for Environmental FX
void	sendAddEnviromentalFX(uint32 playerId, std::string name, std::string psName, std::string soundName)
{
	if (!isOnline ()) return;

	CMessage msgout (Connection->getSIDA(), "ADD_ENV_FX");
	msgout.serial(playerId);
	msgout.serial(name);
	msgout.serial(psName);
	msgout.serial(soundName);
	Connection->send (msgout);
}
Exemple #29
0
// Send a request for SpellFX
void	sendAddSpellFX(uint32 playerId, std::string psName, std::string soundName)
{
	if (!isOnline ()) return;

	if (ShowDebugInChat) nlinfo("Sending spell %s", psName);
	CMessage msgout (Connection->getSIDA(), "ADD_SPELL_FX");
	msgout.serial(playerId);
	msgout.serial(psName);
	msgout.serial(soundName);
	Connection->send (msgout);
}
Exemple #30
0
void	sendHoldDynamicObject (uint32 dynamicObjectId, bool leftHand)
{
	if (!isOnline ()) return;

	CMessage msgout (Connection->getSIDA(), "HOLD_DO");
	msgout.serial ( dynamicObjectId );
	msgout.serial ( leftHand );

	Connection->send (msgout);
	if (ShowDebugInChat) nlinfo("sent hold dynamic object %d", dynamicObjectId);
}