Пример #1
0
int PrepExt_GenericChatMessage(char *buffer, int creatureID, const char *name, const char *channel, const char *message)
{
	//Handles a "communicate" (0x04) message containing a channel and string
	//Sends back a "_handleCommunicationMsg" (50 = 0x32) to the client
	//Ideally this function should broadcast the message to all active player threads
	//in the future so that all players can receive the communication message.

	int wpos = 0;
	wpos += PutByte(&buffer[wpos], 0x32);       //_handleCommunicationMsg
	wpos += PutShort(&buffer[wpos], 0);         //Placeholder for size

	wpos += PutInteger(&buffer[wpos], creatureID);    //Character ID who's sending the message
	wpos += PutStringUTF(&buffer[wpos], name);     //Character name
	wpos += PutStringUTF(&buffer[wpos], channel);  //channel type
	wpos += PutStringUTF(&buffer[wpos], message);  //message body

	PutShort(&buffer[1], wpos - 3);     //Set size
	return wpos;
}
Пример #2
0
/*-------------------------------------------------------------------------*/
long _CALLSTYLE_ SM32Post( tSM32Motor* M, long Cmd, long Data )
{
WORD16 MyOffset;

  if( M_BASEPORT==mhSoftwareTest ) return mcrOk;

  /* M valid ? */
  if(    (M_BASEPORT < 0x100)
      || (M_BASEPORT & 3    )
      || (((BYTE8)(M_NUMBER-1)) >2) )                 return mcrNotInitialised;

  /* Calc channel offset  */
  MyOffset = oChannel[ M_NUMBER-1 ];

  /* Previous command not processed yet? */
  if( GetByte(M_BASEPORT, MyOffset+oFlags) & cWFlag ) return mcrBusy;

  /* Put Data and Command. */
  PutLong( M_BASEPORT, MyOffset+oData, Data );
  PutByte( M_BASEPORT, MyOffset+oWCmd, Cmd  );        return mcrOk;
}
Пример #3
0
int ChatManager :: handleCommunicationMsg(char *channel, char *message, char *name)
{
	//Returns the number of bytes composing the message data.

	//Mostly copied from the Simulator function with the same name, but without permissions
	//checks.  To be used internally by the server when it needs to send arbitrary messages
	//to clients.  Should not be used for /tell messages.

	//Handles a "communicate" (0x04) message containing a channel and string
	//Sends back a "_handleCommunicationMsg" (50 = 0x32) to the client
	//Ideally this function should broadcast the message to all active player threads
	//in the future so that all players can receive the communication message.
	
	char ComBuf[1024];
	char LogBuffer[1024];
	
	if(strlen(channel) == 0 || strlen(message) == 0)
		return 0;

	//LogMessageL("[%s]:[%s]", channel, message);

	/*
	bool log = false;
	char *prefix = NULL;
	if(strcmp(channel, "s") == 0)
	{
		log = true;
		prefix = ChatPrefix_Say;
	}
	else if(strcmp(channel, "gm/earthsages") == 0)
	{
		log = true;
		prefix = ChatPrefix_GM;
	}
	else if(strcmp(channel, "*SysChat") == 0)
	{
		log = true;
		prefix = ChatPrefix_SysChat;
	}
	else if(strcmp(channel, "rc/") == 0)
	{
		log = true;
		prefix = ChatPrefix_Region;
	}

	if(log == true)
	{
		if(prefix != NULL)
			sprintf(LogBuffer, "%s %s: %s", prefix, name, message);
		else
			sprintf(LogBuffer, "%s: %s", name, message);
		LogChatMessage(LogBuffer);
	}
	else
	{
		sprintf(LogBuffer, "%s: %s", name, message);
		LogChatMessage(LogBuffer);
	}*/

	int found = 0;
	int a;
	for(a = 1; a < NumValidChatChannel; a++)
	{
		if(strcmp(ValidChatChannel[a].channel, channel) == 0)
		{
			found = a;
			break;
		}
	}

	int wpos = 0;
	if(ValidChatChannel[found].prefix != NULL)
		wpos += sprintf(&LogBuffer[wpos], "%s ", ValidChatChannel[found].prefix);
	if(ValidChatChannel[found].name == true)
		wpos += sprintf(&LogBuffer[wpos], "%s: ", name);
	else
		name[0] = 0;   //Disable name from showing in the data buffer

	wpos += sprintf(&LogBuffer[wpos], "%s", message);
	ChatMessage cm(message);
	LogChatMessage(cm);

	wpos = 0;
	wpos += PutByte(&ComBuf[wpos], 0x32);       //_handleCommunicationMsg
	wpos += PutShort(&ComBuf[wpos], 0);         //Placeholder for size

	wpos += PutInteger(&ComBuf[wpos], 0);    //Character ID who's sending the message
	wpos += PutStringUTF(&ComBuf[wpos], name);  //Character name
	wpos += PutStringUTF(&ComBuf[wpos], channel);  //return the channel type
	wpos += PutStringUTF(&ComBuf[wpos], message);  //return the message

	PutShort(&ComBuf[1], wpos - 3);     //Set size

	SIMULATOR_IT it;
	for(it = Simulator.begin(); it != Simulator.end(); ++it)
	{
		if(it->isConnected == true)
			it->AttemptSend(ComBuf, wpos);
	}
	return wpos;
}
Пример #4
0
void CJpegEncoder::WriteSOF0()
{
	PutByte(0xff);
	PutByte(0xc0);

	WORD size = 8 + 3*ColorComponents;
	PutByte(size>>8);
	PutByte(size&0xff);

	PutByte(8); // precision

	PutByte(m_h>>8);
	PutByte(m_h&0xff);
	PutByte(m_w>>8);
	PutByte(m_w&0xff);

	PutByte(ColorComponents); // color components

	PutByte(1); // component id
	PutByte(0x11); // hor | ver sampling factor
	PutByte(0); // quant. tbl. id

	PutByte(2); // component id
	PutByte(0x11); // hor | ver sampling factor
	PutByte(1); // quant. tbl. id

	PutByte(3); // component id
	PutByte(0x11); // hor | ver sampling factor
	PutByte(1); // quant. tbl. id
}
Пример #5
0
void CJpegEncoder::WriteSOI()
{
	PutByte(0xff);
	PutByte(0xd8);
}
Пример #6
0
void CJpegEncoder::WriteEOI()
{
	PutByte(0xff);
	PutByte(0xd9);
}
Пример #7
0
void CJpegEncoder::WriteSOS()
{
	PutByte(0xff);
	PutByte(0xda);

	WORD size = 6 + 2*ColorComponents;
	PutByte(size>>8);
	PutByte(size&0xff);

	PutByte(ColorComponents); // color components: 3

	PutByte(1); // component id
	PutByte(0x00); // DC | AC huff tbl

	PutByte(2); // component id
	PutByte(0x11); // DC | AC huff tbl

	PutByte(3); // component id
	PutByte(0x11); // DC | AC huff tbl

	PutByte(0); // ss, first AC
	PutByte(63); // se, last AC

	PutByte(0); // ah | al

	static float cosuv[8][8][8][8];

	// oh yeah, we don't need no fast dct :)
	for(int v = 0; v < 8; v++) 
		for(int u = 0; u < 8; u++)
			for(int j = 0; j < 8; j++) 
				for(int i = 0; i < 8; i++)
					cosuv[v][u][j][i] = (float)(cos((2*i+1)*u*PI/16) * cos((2*j+1)*v*PI/16));

	int prevDC[3] = {0, 0, 0};

	for(int y = 0; y < m_h; y += 8)
	{
		int jj = min(m_h - y, 8);

		for(int x = 0; x < m_w; x += 8)
		{
			int ii = min(m_w - x, 8);

			for(int c = 0; c < ColorComponents; c++)
			{
				int cc = !!c;

				int ACs = 0;

				static short block[64];

				for(int zigzag = 0; zigzag < 64; zigzag++) 
				{
					BYTE u = zigzagU[zigzag];
					BYTE v = zigzagV[zigzag];

					float F = 0;
/*
					for(int j = 0; j < jj; j++)
						for(int i = 0; i < ii; i++) 
							F += (signed char)m_p[((y+j)*m_w + (x+i))*4 + c] * cosuv[v][u][j][i];
*/
					for(int j = 0; j < jj; j++)
					{
						signed char* p = (signed char*)&m_p[((y+j)*m_w + x)*4 + c];
						for(int i = 0; i < ii; i++, p += 4) 
							F += *p * cosuv[v][u][j][i];
					}

					float cu = !u ? invsq2 : 1.0f;
					float cv = !v ? invsq2 : 1.0f;

					block[zigzag] = short(2.0 / 8.0 * cu * cv * F) / quanttbl[cc][zigzag];
				}

				short DC = block[0] - prevDC[c];
				prevDC[c] = block[0];

				int size = GetBitWidth(DC);
				PutBit(DCVLC[cc][size], DCVLC_Size[cc][size]);

				if(DC < 0) DC = DC - 1;
				PutBit(DC, size);

				int j;
				for(j = 64; j > 1 && !block[j-1]; j--);

				for(int i = 1; i < j; i++)
				{
					short AC = block[i];

					if(AC == 0)
					{
						if(++ACs == 16)
						{
							PutBit(ACVLC[cc][15][0], ACVLC_Size[cc][15][0]);
							ACs = 0;
						}
					}
					else
					{
						int size = GetBitWidth(AC);
						PutBit(ACVLC[cc][ACs][size], ACVLC_Size[cc][ACs][size]);
						
						if(AC < 0) AC--;
						PutBit(AC, size);

						ACs = 0;
					}
				}

				if(j < 64) PutBit(ACVLC[cc][0][0], ACVLC_Size[cc][0][0]);
			}
		}
	}

	Flush();
}
Пример #8
0
void ScreenShot()
{
	int i;
	char Name[40];
	
	int width, height;
	unsigned char *buf = GetScreenShot24(&width, &height);
	if (buf == NULL)
		return;
	
	strcpy(Name,"avp");
	int length=strlen(Name);
	strncpy(&Name[length],"00.bmp",8);
	for(i=0;i<100;i++)
	{
		Name[length]=i/10+'0';
		Name[length+1]=(i%10)+'0';
		FILE* tempfp = OpenGameFile(Name, FILEMODE_READONLY, FILETYPE_CONFIG);
		if(!tempfp)break;
		else
 		{
			fclose(tempfp);
		}
	}
	if(i==100) return;
	
	FILE *fp = OpenGameFile(Name, FILEMODE_WRITEONLY, FILETYPE_CONFIG);
	if (!fp)
	{
		return;
	}
	
	BMPHEADER2 h;

	// fill out header
	
	h.Header.Type      = 'B'+'M'*256;
	h.Header.Reserved1 = 0;
	h.Header.Reserved2 = 0;
	h.Header.Offset    = 14+40+0;

	/*
	** The type of information found in a BMP structure is indicated by
	** the Size (Information Headere Size) field with a non-zero value.
	*/
	h.PmInfo.Size   = 0;
	h.Pm2Info.Size  = 0;

	h.WinInfo.Size          = 40;
	h.WinInfo.Width         = width;
	h.WinInfo.Height        = height;
	h.WinInfo.Planes        = 1;
	h.WinInfo.BitCount      = 24;
	h.WinInfo.Compression   = 0;
	h.WinInfo.SizeImage     = h.WinInfo.Width*h.WinInfo.Height*3;
	h.WinInfo.XPelsPerMeter = h.WinInfo.Width;
	h.WinInfo.YPelsPerMeter = h.WinInfo.Height;
	h.WinInfo.ClrUsed       = 0;
	h.WinInfo.ClrImportant  = 0;

	h.Header.FileSize  = h.WinInfo.SizeImage + h.Header.Offset + 8;

	// write header

	PutWord_F PutWord = PutLittleWord;
	PutDword_F PutDword = PutLittleDword;

    PutWord(h.Header.Type, fp);
    PutDword(h.Header.FileSize, fp);
    PutWord(h.Header.Reserved1, fp);
    PutWord(h.Header.Reserved2, fp);
    PutDword(h.Header.Offset, fp);

	PutDword(h.WinInfo.Size, fp);

    PutDword(h.WinInfo.Width, fp);
    PutDword(h.WinInfo.Height, fp);
    PutWord(h.WinInfo.Planes, fp);
    PutWord(h.WinInfo.BitCount, fp);
    PutDword(h.WinInfo.Compression, fp);
    PutDword(h.WinInfo.SizeImage, fp);
    PutDword(h.WinInfo.XPelsPerMeter, fp);
    PutDword(h.WinInfo.YPelsPerMeter, fp);
    PutDword(h.WinInfo.ClrUsed, fp);
    PutDword(h.WinInfo.ClrImportant, fp);

	// write 24 bit image

//	unsigned char *BufferPtr = &buf[(width * 3) * (height - 1)];
	unsigned char *BufferPtr = &buf[0];
	for (i=h.WinInfo.Height-1; i>=0; --i)
	{
		unsigned int j;
		for (j=0; j<h.WinInfo.Width; ++j)
		{
			PutByte((BYTE)BufferPtr[j*3+2],fp);  //b
			PutByte((BYTE)BufferPtr[j*3+1],fp);  //g
			PutByte((BYTE)BufferPtr[j*3],fp);  //r
		}
			
		// pad to 4 byte boundary
		for (j=~(h.WinInfo.Width*3-1) & 3; j; --j) PutByte(0,fp);
//		BufferPtr -= width * 3;
		BufferPtr += width * 3;
	}

	free(buf);
	fclose(fp);	
}
Пример #9
0
int TradeStartHandler::protected_helper_query_trade_start(SimulatorThread *sim,
		CharacterServerData *pld, SimulatorQuery *query,
		CreatureInstance *creatureInstance) {
	// Note: query errors don't seem to do anything in the client.

	// Note: The trade starter has an argument for the target player.
	//       When the target player accepts, there is no argument to this
	//       query.

	int selfPlayerID = creatureInstance->CreatureID;
	int otherPlayerID = 0;
	if (query->argCount > 0)
		otherPlayerID = query->GetInteger(0);

	ActiveInstance *actInst = creatureInstance->actInst;
	if (actInst == NULL) {
		g_Logs.simulator->error(
				"[%v] trade.start active instance is NULL", sim->InternalID);
		return QueryErrorMsg::INVALIDOBJ;
	}

	CreatureInstance *target = NULL;
	if (otherPlayerID != 0) {
		//Make sure we're not busy.
		if (sim->CanMoveItems() == false)
			return QueryErrorMsg::SELFBUSYSKILL;

		//Make sure the other player exists
		target = actInst->GetPlayerByID(otherPlayerID);
		if (target == NULL)
			return QueryErrorMsg::INVALIDOBJ;

		//Make sure the other player isn't busy
		if (actInst->tradesys.GetExistingTradeForPlayer(otherPlayerID) != NULL)
			return QueryErrorMsg::TRADEBUSY;

		if (target->simulatorPtr->CanMoveItems() == false)
			return QueryErrorMsg::OTHERBUSYSKILL;
	}

	//It only takes one player to start the trade for both, so initialize a
	//transaction for both players.
	int CheckID = creatureInstance->activeLootID;
	if (CheckID == 0)
		CheckID = selfPlayerID;
	TradeTransaction *tradeData = actInst->tradesys.GetNewTransaction(CheckID);
	//tradeData->Clear();
	bool initiator = false;
	if (otherPlayerID != 0) {
		initiator = true;
		tradeData->SetPlayers(creatureInstance, target);
		creatureInstance->activeLootID = CheckID;
		target->activeLootID = CheckID;
		tradeData->init = true;
	} else {
		//This is the accepting player, so the target must be the origin.
		otherPlayerID = tradeData->player[0].selfPlayerID;
		target = tradeData->player[0].cInst;
	}

	if (target == NULL || otherPlayerID == 0)
		return QueryErrorMsg::INVALIDOBJ;

	tradeData->GetPlayerData(selfPlayerID)->tradeWindowOpen = true;

	if (initiator == true) {
		// Send trade request message to the other player.
		int wpos = 0;
		wpos += PutByte(&sim->SendBuf[wpos], 51);    //_handleTradeMsg
		wpos += PutShort(&sim->SendBuf[wpos], 0);
		wpos += PutInteger(&sim->SendBuf[wpos], selfPlayerID);   //traderID
		wpos += PutByte(&sim->SendBuf[wpos], TradeEventTypes::REQUEST); //eventType
		PutShort(&sim->SendBuf[1], wpos - 3);
		SendToOneSimulator(sim->SendBuf, wpos, target->simulatorPtr);
	} else {
		int wpos = 0;
		wpos += PutByte(&sim->SendBuf[wpos], 51);    //_handleTradeMsg
		wpos += PutShort(&sim->SendBuf[wpos], 0);
		wpos += PutInteger(&sim->SendBuf[wpos], selfPlayerID);   //traderID
		wpos += PutByte(&sim->SendBuf[wpos], TradeEventTypes::REQUEST_ACCEPTED); //eventType
		PutShort(&sim->SendBuf[1], wpos - 3);
		SendToOneSimulator(sim->SendBuf, wpos, target->simulatorPtr);
	}

	return PrepExt_QueryResponseString(sim->SendBuf, query->ID, "OK");
}
Пример #10
0
void SceneryManager::SendPageRequest(const SceneryPageRequest& request, std::list<PacketManager::PACKET_PAIR>& outgoingPackets)
{
	TimeObject to("SceneryManager::SendPageRequest");

	STRINGLIST queryRows;
	Packet data;
	int wpos = 0;
	char idBuf[32];

	GetThread("SceneryManager::HandlePageRequests[page]");

	SceneryPage *page = GetOrCreatePage(request.zone, request.x, request.y);

	if(page == NULL)
	{
		g_Log.AddMessageFormat("[ERROR] SendPageRequest retrieved NULL page");
		
		wpos = PrepExt_QueryResponseNull(prepBuf, request.queryID);
		data.Assign(prepBuf, wpos);
		outgoingPackets.push_back(PacketManager::PACKET_PAIR(request.socket, data));

		ReleaseThread();
		return;
	}

	SceneryPage::SCENERY_IT it;
	for(it = page->mSceneryList.begin(); it != page->mSceneryList.end(); ++it)
	{
		//Build the list of scenery ID strings to form the response to the scenery.list query.
		//No need to save row data unless the query is required.
		if(request.skipQuery == false)
		{
			sprintf(idBuf, "%d", it->second.ID);
			queryRows.push_back(idBuf);
		}
		
		wpos += PrepExt_UpdateScenery(&prepBuf[wpos], &it->second);
		if(wpos > Global::MAX_SEND_CHUNK_SIZE)
		{
			data.Assign(prepBuf, wpos);
			outgoingPackets.push_back(PacketManager::PACKET_PAIR(request.socket, data));
			wpos = 0;
		}
	}
	if(wpos > 0)
	{
		data.Assign(prepBuf, wpos);
		outgoingPackets.push_back(PacketManager::PACKET_PAIR(request.socket, data));
	}

	//Done accessing the scenery data itself, no need to hold the thread any longer.
	//All the remaining stuff is using a resident list of query IDs to form into a response
	//packet.
	ReleaseThread();

	//Now build the query response if the client has requested it.
	if(request.skipQuery == true)
		return;

	//Reset the packet buffer and data.
	wpos = 0;
	data.Clear();

	//Get the size of the response
	int sizeReq = 6;  //Query ID (4 bytes) + row count (2 bytes)
	for(size_t s = 0; s < queryRows.size(); s++)
	{
		sizeReq++;  //1 string per row
		sizeReq += PutStringReq(queryRows[s].c_str());
	}

	wpos += PutByte(&prepBuf[wpos], 1);         //_handleQueryResultMsg
	wpos += PutShort(&prepBuf[wpos], sizeReq);  //Message size

	wpos += PutInteger(&prepBuf[wpos], request.queryID);
	wpos += PutShort(&prepBuf[wpos], queryRows.size());
	for(size_t s = 0; s < queryRows.size(); s++)
	{
		wpos += PutByte(&prepBuf[wpos], 1);
		wpos += PutStringUTF(&prepBuf[wpos], queryRows[s].c_str());
		if(wpos > Global::MAX_SEND_CHUNK_SIZE)
		{
			data.Append(prepBuf, wpos);
			wpos = 0;
		}
	}
	if(wpos > 0)
		data.Append(prepBuf, wpos);

	outgoingPackets.push_back(PacketManager::PACKET_PAIR(request.socket, data));
}
Пример #11
0
int LobbyAuthenticateMessage::handleMessage(SimulatorThread *sim, CharacterServerData *pld,
		SimulatorQuery *query, CreatureInstance *creatureInstance) {

	if(g_AccountManager.AcceptingLogins() == false) {
		sim->ForceErrorMessage("Not accepting more logins.", INFOMSG_ERROR);
		sim->Disconnect("SimulatorThread::handle_lobby_authenticate");
		return 0;
	}

	char authType = GetByte(&sim->readPtr[sim->ReadPos], sim->ReadPos);
	AuthHandler *authHandler = g_AuthManager.GetAuthenticator(authType);
	if (authHandler == NULL) {
		g_Logs.simulator->error("[%v] Could not find authentication handler [%v]",
				sim->InternalID, authType);
		sim->ForceErrorMessage(g_Config.InvalidLoginMessage.c_str(), INFOMSG_ERROR);
		sim->Disconnect("SimulatorThread::handle_lobby_authenticate");
		return 0;
	}

	int simID = sim->InternalID;

	char loginName[128];
	char authHash[128];
	GetStringUTF(&sim->readPtr[sim->ReadPos], loginName, sizeof(loginName), sim->ReadPos);  //login name
	GetStringUTF(&sim->readPtr[sim->ReadPos], authHash, sizeof(authHash), sim->ReadPos);  //authorization hash or or X-CSRF-Token:sess_id:session_name:uid


	/* Authentication can take a long time as it might now be going off to an external service.
	 * So we put the time consuming bit into a pool thread, then return to the server thread
	 * once that is done.
	 */
	g_Scheduler.Pool([this, simID, authHandler, loginName, authHash](){

		SimulatorThread *sim = g_SimulatorManager.GetPtrByID(simID);
		if(sim == NULL) {
			g_Logs.server->error("Lost simulator %v whilst initializing authentication. Aborting.", simID);
			return;
		}
		std::string errorMessage;
		AccountData *accPtr = authHandler->authenticate(loginName, authHash, &errorMessage);
		g_Logs.simulator->info("Completed first phase of authentiation for %v (%v)", loginName, simID);

		if (accPtr == NULL) {
			g_Logs.simulator->error("[%v] Could not find account: %v", sim->InternalID, loginName);
			sim->ForceErrorMessage(g_Config.InvalidLoginMessage.c_str(), INFOMSG_ERROR);
			sim->Disconnect("SimulatorThread::handle_lobby_authenticate");
		}
		else {

			if(errorMessage.length() > 0) {
				g_Logs.simulator->error("[%v] Authentication failed for %v. %v", sim->InternalID, loginName, errorMessage);
				sim->ForceErrorMessage(errorMessage.c_str(), INFOMSG_ERROR);
				sim->Disconnect("SimulatorThread::handle_lobby_authenticate");
				return;
			}

			/* Now the lengthy operation is over, complete authentication on the main server thread */

			g_Logs.simulator->info("Submitting authentication on main thread for %v (%v)", accPtr->Name, simID);
			g_Scheduler.Submit([this, accPtr, simID](){
				g_Logs.server->info("Completing authentication on main thread for %v (%v)", accPtr->Name, simID);

				SimulatorThread *sim = g_SimulatorManager.GetPtrByID(simID);
				if(sim == NULL) {
					g_Logs.server->error("Lost simulator %v whilst authenticating. Aborting.", simID);
					return;
				}

				if(g_Config.MaintenanceMessage.length() > 0 && accPtr->HasPermission(Perm_Account, Permission_Admin) == false && accPtr->HasPermission(Perm_Account, Permission_Sage) == false)	{
					Util::SafeFormat(sim->Aux1, sizeof(sim->Aux1), "The server is currently unavailable due to mainenance. The reason given was '%s'", g_Config.MaintenanceMessage.c_str());
					sim->ForceErrorMessage(sim->Aux1, INFOMSG_ERROR);
					sim->Disconnect("SimulatorThread::handle_lobby_authenticate");
					return;
				}

				//Check for ban.
				if (accPtr->SuspendTimeSec >= 0) {
					unsigned long timePassed = g_PlatformTime.getAbsoluteSeconds()
							- accPtr->SuspendTimeSec;
					if (timePassed < accPtr->SuspendDurationSec) {
						unsigned long remain = accPtr->SuspendDurationSec - timePassed;
						Util::FormatTime(sim->Aux3, sizeof(sim->Aux3), remain);
						Util::SafeFormat(sim->Aux1, sizeof(sim->Aux1),
								"Your account has been suspended. Time remaining: %s",
								sim->Aux3);
						sim->ForceErrorMessage(sim->Aux1, INFOMSG_ERROR);
						sim->Disconnect("SimulatorThread::handle_lobby_authenticate");
						return;
					} else
						accPtr->ClearBan();
				}

				//Check for multiple logins.
				if (g_ClusterManager.CountAccountSessions(accPtr->ID) > 0) {
					if (accPtr->HasPermission(Perm_Account, Permission_Admin) == false) {
						g_SimulatorManager.CheckIdleSimulatorBoot(accPtr);
						sim->ForceErrorMessage("That account is already logged in.",
								INFOMSG_ERROR);
						sim->Disconnect("SimulatorThread::handle_lobby_authenticate");
						return;
					}
				}

				g_Logs.event->info("[ACCOUNT] Account '%v' logged in", accPtr->Name);

				//If we get here, we can successfully log into the account.
				accPtr->AdjustSessionLoginCount(1);
				g_Logs.simulator->info("[%v] Logging in as: %v [Socket:%v]", sim->InternalID,
						accPtr->Name, sim->sc.ClientSocket);
				unsigned long startTime = g_PlatformTime.getMilliseconds();
				sim->LoadAccountCharacters(accPtr);
				g_Logs.simulator->debug("[%v] TIME PASS loading account chars: %v ms",
						sim->InternalID, g_PlatformTime.getMilliseconds() - startTime);

				int wpos = 0;
				wpos += PutByte(&sim->SendBuf[wpos], 50);       //_handleLoginQueueMessage
				wpos += PutShort(&sim->SendBuf[wpos], 0);       //Placeholder for message size
				wpos += PutInteger(&sim->SendBuf[wpos], 0);     //Queue position
				PutShort(&sim->SendBuf[1], wpos - 3);
				sim->AttemptSend(sim->SendBuf, wpos);

			});
		}


	});
	return 0;
}
Пример #12
0
int PrepExt_ItemDef(char *SendBuf, ItemDef *item, int ProtocolState)
{
	int WritePos = 0;

	//_handleItemDefUpdateMsg is [4] for lobby, [71] for play (most common) protocol
	char message = 71;
	if(ProtocolState == 0)
		message = 4;

	WritePos += PutByte(&SendBuf[WritePos], message);
	WritePos += PutShort(&SendBuf[WritePos], 0);      //Message size

	WritePos += PutInteger(&SendBuf[WritePos], item->mID);

	//Fill the item properties
	WritePos += PutByte(&SendBuf[WritePos], item->mType);
	WritePos += PutStringUTF(&SendBuf[WritePos], item->mDisplayName.c_str());
	WritePos += PutStringUTF(&SendBuf[WritePos], item->mAppearance.c_str());
	WritePos += PutStringUTF(&SendBuf[WritePos], item->mIcon.c_str());

	WritePos += PutByte(&SendBuf[WritePos], item->mIvType1);
	WritePos += PutShort(&SendBuf[WritePos], item->mIvMax1);
	WritePos += PutByte(&SendBuf[WritePos], item->mIvType2);
	WritePos += PutShort(&SendBuf[WritePos], item->mIvMax2);
	WritePos += PutStringUTF(&SendBuf[WritePos], item->mSv1.c_str());

	if(g_ProtocolVersion < 5)
		WritePos += PutInteger(&SendBuf[WritePos], item->_mCopper);

	WritePos += PutShort(&SendBuf[WritePos], item->mContainerSlots);
	WritePos += PutByte(&SendBuf[WritePos], item->mAutoTitleType);
	WritePos += PutShort(&SendBuf[WritePos], item->mLevel);
	WritePos += PutByte(&SendBuf[WritePos], item->mBindingType);
	WritePos += PutByte(&SendBuf[WritePos], item->mEquipType);

	WritePos += PutByte(&SendBuf[WritePos], item->mWeaponType);
	if(item->mWeaponType != 0)
	{
		if(g_ProtocolVersion == 7)
		{
			WritePos += PutByte(&SendBuf[WritePos], item->mWeaponDamageMin);
			WritePos += PutByte(&SendBuf[WritePos], item->mWeaponDamageMax);
			WritePos += PutByte(&SendBuf[WritePos], item->_mSpeed);
			WritePos += PutByte(&SendBuf[WritePos], item->mWeaponExtraDamangeRating);
			WritePos += PutByte(&SendBuf[WritePos], item->mWeaponExtraDamageType);
		}
		else
		{
			WritePos += PutInteger(&SendBuf[WritePos], item->mWeaponDamageMin);
			WritePos += PutInteger(&SendBuf[WritePos], item->mWeaponDamageMax);
			WritePos += PutByte(&SendBuf[WritePos], item->mWeaponExtraDamangeRating);
			WritePos += PutByte(&SendBuf[WritePos], item->mWeaponExtraDamageType);
		}
	}

	WritePos += PutInteger(&SendBuf[WritePos], item->mEquipEffectId);
	WritePos += PutInteger(&SendBuf[WritePos], item->mUseAbilityId);
	WritePos += PutInteger(&SendBuf[WritePos], item->mActionAbilityId);
	WritePos += PutByte(&SendBuf[WritePos], item->mArmorType);
	if(item->mArmorType != 0)
	{
		if(g_ProtocolVersion == 7)
		{
			WritePos += PutByte(&SendBuf[WritePos], item->mArmorResistMelee);
			WritePos += PutByte(&SendBuf[WritePos], item->mArmorResistFire);
			WritePos += PutByte(&SendBuf[WritePos], item->mArmorResistFrost);
			WritePos += PutByte(&SendBuf[WritePos], item->mArmorResistMystic);
			WritePos += PutByte(&SendBuf[WritePos], item->mArmorResistDeath);
		}
		else
		{
			WritePos += PutInteger(&SendBuf[WritePos], item->mArmorResistMelee);
			WritePos += PutInteger(&SendBuf[WritePos], item->mArmorResistFire);
			WritePos += PutInteger(&SendBuf[WritePos], item->mArmorResistFrost);
			WritePos += PutInteger(&SendBuf[WritePos], item->mArmorResistMystic);
			WritePos += PutInteger(&SendBuf[WritePos], item->mArmorResistDeath);
		}
	}
	if(g_ProtocolVersion == 7)
	{
		WritePos += PutByte(&SendBuf[WritePos], item->mBonusStrength);
		WritePos += PutByte(&SendBuf[WritePos], item->mBonusDexterity);
		WritePos += PutByte(&SendBuf[WritePos], item->mBonusConstitution);
		WritePos += PutByte(&SendBuf[WritePos], item->mBonusPsyche);
		WritePos += PutByte(&SendBuf[WritePos], item->mBonusSpirit);
		WritePos += PutByte(&SendBuf[WritePos], item->_mBonusHealth);
		WritePos += PutByte(&SendBuf[WritePos], item->mBonusWill);
	}
	else
	{
		WritePos += PutInteger(&SendBuf[WritePos], item->mBonusStrength);
		WritePos += PutInteger(&SendBuf[WritePos], item->mBonusDexterity);
		WritePos += PutInteger(&SendBuf[WritePos], item->mBonusConstitution);
		WritePos += PutInteger(&SendBuf[WritePos], item->mBonusPsyche);
		WritePos += PutInteger(&SendBuf[WritePos], item->mBonusSpirit);

		if(g_ProtocolVersion < 32)
			WritePos += PutInteger(&SendBuf[WritePos], item->_mBonusHealth);
		WritePos += PutInteger(&SendBuf[WritePos], item->mBonusWill);
	}

	if(g_ProtocolVersion >= 4)
	{
		WritePos += PutByte(&SendBuf[WritePos], item->isCharm);
		if(item->isCharm != 0)
		{
			WritePos += PutFloat(&SendBuf[WritePos], item->mMeleeHitMod);
			WritePos += PutFloat(&SendBuf[WritePos], item->mMeleeCritMod);
			WritePos += PutFloat(&SendBuf[WritePos], item->mMagicHitMod);
			WritePos += PutFloat(&SendBuf[WritePos], item->mMagicCritMod);
			WritePos += PutFloat(&SendBuf[WritePos], item->mParryMod);
			WritePos += PutFloat(&SendBuf[WritePos], item->mBlockMod);
			WritePos += PutFloat(&SendBuf[WritePos], item->mRunSpeedMod);
			WritePos += PutFloat(&SendBuf[WritePos], item->mRegenHealthMod);
			WritePos += PutFloat(&SendBuf[WritePos], item->mAttackSpeedMod);
			WritePos += PutFloat(&SendBuf[WritePos], item->mCastSpeedMod);
			WritePos += PutFloat(&SendBuf[WritePos], item->mHealingMod);
		}
	}

	if(g_ProtocolVersion >= 5)
	{
		WritePos += PutInteger(&SendBuf[WritePos], item->mValue);
		WritePos += PutByte(&SendBuf[WritePos], item->mValueType);
	}

	bool ItemUpdateDefMsgCraft = false;
	if(g_ProtocolVersion >= 7)
		ItemUpdateDefMsgCraft = true;
	if(ItemUpdateDefMsgCraft == true)
	{
		WritePos += PutInteger(&SendBuf[WritePos], item->resultItemId);
		WritePos += PutInteger(&SendBuf[WritePos], item->keyComponentId);
		WritePos += PutInteger(&SendBuf[WritePos], item->numberOfItems);
		for(size_t i = 0; i < item->craftItemDefId.size(); i++)
			WritePos += PutInteger(&SendBuf[WritePos], item->craftItemDefId[i]);

		if(item->numberOfItems != item->craftItemDefId.size())
			g_Logs.server->error("Crafting material item count mismatch for ID: %v", item->mID);
	}

	if(g_ProtocolVersion >= 9)
		WritePos += PutStringUTF(&SendBuf[WritePos], item->mFlavorText.c_str());

	if(g_ProtocolVersion >= 18)
		WritePos += PutByte(&SendBuf[WritePos], item->mSpecialItemType);

	if(g_ProtocolVersion >= 30)
		WritePos += PutByte(&SendBuf[WritePos], item->mOwnershipRestriction);

	if(g_ProtocolVersion >= 31)
	{
		WritePos += PutByte(&SendBuf[WritePos], item->mQualityLevel);
		WritePos += PutShort(&SendBuf[WritePos], item->mMinUseLevel);
	}

	PutShort(&SendBuf[1], WritePos - 3);
	return WritePos;
}
Пример #13
0
bufPtr CompressStandard(bufPtr srcBuf, int flag)
{
    if(!srcBuf)
        return NULL;

    // allocate a 2^12 sized buffer
    bufPtr destBuf = CreateBuffer(0x1000);

    if(!destBuf)
        return NULL;

    destBuf->wOffset = 0;

    int i = 0, j = 0, k = 0;

    int byte      = 0;
    int highByte  = 0;
    int remainder = 0;
    int word      = 0;
    int identical = 0;
    int oldSize = srcBuf->length;

    comp_mode p = mode_no_compress;

    int n = 0;
    int x = 0, q = 0, r;

    // flag is an endianness flag as follows
    // flag ?  bigEndian() : littleEndian();
    // hence default behavior is littleEndian

    // int *size; this is the return size of the compressed data
    // after the routine has finished

    for(i = 0; i < oldSize; )
    {
        byte = GetByte(srcBuf, i); // grab a char from the buffer.

        k = 0;

        // r = the same logical value (0 or 1) as q, but not the same value necesarily.
        r = !!q;

        // looking at the bytes from the start of the array up until the byte at i for some reason...
        for(j = 0; j < i - 1; j++)
        {
            //
            if( GetByte(srcBuf, j) == byte)
            {
                for(n = j; n < oldSize; n++)
                {
                    if( GetByte(srcBuf, n) != GetByte(srcBuf, n + i) )
                        break;
                }

                if(n > k)
                    k = n, word = j;
            }
        }

        identical = 0;

        // get the number of bytes starting at i that are identical to
        // the byte at i
        for( j = (i + 1); j < oldSize; j++ )
        {
            if( GetByte(srcBuf, j) != byte )
                break;

            identical++;
        }

        if( identical > (1 + r) )
            p = mode_byte_repeat;
        else
        {
            // if looking for repeating bytes failed, we're going to try
            // to find a sequence of repeating words (16-bit) instead

            word = Get2Bytes(srcBuf, i);
            identical = 0;

            for(j = i + 2; j < oldSize; j++)
            {
                // while words are matched, the total number of actual bytes
                // matched is recorded, not the number of words
                if(Get2Bytes(srcBuf, j) != word)
                {
                    if(GetByte(srcBuf, j) == byte)
                        identical++;

                    break;
                }
                else
                    identical += 2;
            }

            if( identical > (2 + r) )
                p = mode_word_repeat;
            else
            {
                // well that didn't work so we're going to try to
                // find an incrementing byte series

                // MON is iffy on how well this will actually work...
                // due to how the actual algorithm decompresses stuff...

                identical = 0;

                for(j = (i + 1); j < oldSize; j++)
                {
                    if(GetByte(srcBuf, j) != (byte + j) )
                        break;

                    identical++;
                }

                if( identical > (1 + r) )
                    p = mode_increment;
                else
                    p = mode_no_compress;
            }
        }

        // what the f**k is this
        if( (k > r + 3) && (k > n + (p % 2)) )
        {
            p = mode_copy;
            n = k;
        }

        if(!p)
            q++, i++;
        else
        {
            if(q)
            {
                q--;

                if(q > 0x1F)
                    PutByte(destBuf, 0xE0 + (q >> 8) );

                PutByte(destBuf, q);
                q++;

                CopyBuffer(destBuf, srcBuf,
                           destBuf->wOffset,      i - q,
                           q);

                destBuf->wOffset += q;
                q = 0;
            }

            i += identical;
            identical--;

            if(identical > 0x1F)
            {
                PutByte(destBuf, 0xE0 + (identical >> 8) + (p << 2));
                PutByte(destBuf, identical);
            }
            else
                PutByte(destBuf, ((p << 5)+ identical));

            switch(p)
            {
            case mode_byte_repeat:
            case mode_increment:

                PutByte(destBuf, byte);
                break;

            case mode_word_repeat:

                Put2Bytes(destBuf, word);
                break;

            case mode_copy:
                if(flag)
                {
                    PutByte(destBuf, word >> 8);
                    PutByte(destBuf, word);
                }
                else
                {
                    Put2Bytes(destBuf, word);
                }

                break;

            case mode_no_compress:
            default:

                break;
            }
Пример #14
0
/*
 * These have no purpose but to wrapper the Byte, Short & Long 
 * functions.
 */
static void 
writeU1 (u1 const v) {
   file_offset++;
   PutByte(v);
}
Пример #15
0
bool ChatManager::DeliverChatMessage(ChatMessage &message, CreatureInstance *sendingCreatureInstance) {

	message.mTime =  time(NULL);

	int wpos = 0;
	wpos += PutByte(&SendBuf[wpos], 50);       //_handleCommunicationMsg
	wpos += PutShort(&SendBuf[wpos], 0);         //Placeholder for size
	wpos += PutInteger(&SendBuf[wpos], message.mSenderCreatureID);    //Character ID who's sending the message
	wpos += PutStringUTF(&SendBuf[wpos], message.mSender.c_str()); //pld.charPtr->cdef.css.display_name);  //Character name
	wpos += PutStringUTF(&SendBuf[wpos], message.mTell ? "t/" : message.mChannel->channel);
	wpos += PutStringUTF(&SendBuf[wpos], message.mMessage.c_str());
	PutShort(&SendBuf[1], wpos - 3);     //Set size

	bool found = false;
	bool log = !message.mTell && ( message.mChannel->chatScope == CHAT_SCOPE_REGION || message.mChannel->chatScope == CHAT_SCOPE_SERVER );

	bool breakLoop = false;
	SIMULATOR_IT it;
	for(it = Simulator.begin(); it != Simulator.end(); ++it)
	{
		if(breakLoop == true)
			break;

		if(it->ProtocolState == 0)
		{
			//LogMessageL(MSG_ERROR, "[WARNING] Cannot not send chat to lobby protocol simulator");
			continue;
		}

		if(it->isConnected == false)
			continue;

		if(it->pld.charPtr == NULL)
			continue;

		bool send = false;
		if(message.mTell == true)
		{
			if(strcmp(it->pld.charPtr->cdef.css.display_name, message.mRecipient.c_str()) == 0)
			{
				send = true;
				found = true;
			}
		}
		else
		{
			switch(message.mChannel->chatScope)
			{
			case CHAT_SCOPE_LOCAL:
				if(sendingCreatureInstance == NULL || it->pld.CurrentInstanceID != message.mSendingInstance)
					break;
				if(ActiveInstance::GetPlaneRange(it->creatureInst, sendingCreatureInstance, LOCAL_CHAT_RANGE) > LOCAL_CHAT_RANGE)
					break;

				send = true;
				break;

			case CHAT_SCOPE_REGION:
				if(it->pld.CurrentInstanceID != message.mSendingInstance)
					break;
				send = true;
				break;
			case CHAT_SCOPE_SERVER:
				send = true;

				if(message.mChannelName.compare("gm/earthsages") == 0 && !it->pld.accPtr->HasPermission(Perm_Account, Permission_GMChat) && !it->pld.accPtr->HasPermission(Perm_Account, Permission_Admin)) {
					send = false;
				}

				break;
			case CHAT_SCOPE_FRIEND:
				if(it->pld.CreatureDefID == message.mSenderCreatureDefID)  //Send to self
					send = true;
				else if(g_FriendListManager.IsMutualFriendship(it->pld.CreatureDefID, message.mSenderCreatureDefID) ==true)
					send = true;
				break;
			case CHAT_SCOPE_CHANNEL:
			{
				PrivateChannel *privateChannelData = g_ChatChannelManager.GetChannelForMessage(message.mSimulatorID, message.mChannelName.c_str() + 3);
				if(privateChannelData != NULL) {
					for(size_t i = 0; i < privateChannelData->mMemberList.size(); i++)
						if(it->InternalID == privateChannelData->mMemberList[i].mSimulatorID)
							send = true;
				}
				break;
			}
			case CHAT_SCOPE_PARTY:
				if(sendingCreatureInstance == NULL)
					break;
				g_PartyManager.BroadCastPacket(sendingCreatureInstance->PartyID, sendingCreatureInstance->CreatureDefID, SendBuf, wpos);
				breakLoop = true;
				break;
			case CHAT_SCOPE_CLAN:
			{

				Clans::Clan c = g_ClanManager.GetClan(message.mSenderClanID);
				if(it->pld.CreatureDefID == message.mSenderCreatureDefID)  //Send to self
					send = true;
				else {
					if(c.mId > 0 && it->pld.charPtr->clan == c.mId)
						send = true;
					else if(g_GuildManager.IsMutualGuild(it->pld.CreatureDefID, message.mSenderCreatureDefID) ==true)
						send = true;
				}
				break;
			}
			default:
				break;
			}
		}

		if(send == true) {
			found = true;
			it->AttemptSend(SendBuf, wpos);
		}
	}

	if(log == true)
		LogChatMessage(message);

	return found;
}
Пример #16
0
int TradeAcceptHandler::protected_helper_query_trade_accept(SimulatorThread *sim,
		CharacterServerData *pld, SimulatorQuery *query,
		CreatureInstance *creatureInstance) {
	int selfID = creatureInstance->CreatureID;
	int tradeID = creatureInstance->activeLootID;
	ActiveInstance *actInst = creatureInstance->actInst;
	TradeTransaction *tradeData = actInst->tradesys.GetExistingTransaction(
			tradeID);
	if (tradeData == NULL)
		return QueryErrorMsg::TRADENOTFOUND;

	TradePlayerData *pData = tradeData->GetPlayerData(selfID);
	if (pData == NULL)
		return actInst->tradesys.CancelTransaction(selfID, tradeID, sim->SendBuf);

	CreatureInstance *cInst = pData->otherPlayerData->cInst;

	pData->SetAccepted(true);

	int wpos = 0;
	wpos += PutByte(&sim->SendBuf[wpos], 51);     //_handleTradeMsg
	wpos += PutShort(&sim->SendBuf[wpos], 0);    //Placeholder for size
	wpos += PutInteger(&sim->SendBuf[wpos], creatureInstance->CreatureID);   //traderID
	wpos += PutByte(&sim->SendBuf[wpos], TradeEventTypes::OFFER_ACCEPTED); //eventType
	PutShort(&sim->SendBuf[1], wpos - 3);       //Set message size
	SendToOneSimulator(sim->SendBuf, wpos, cInst->simulatorPtr);
	//actInst->LSendToOneSimulator(SendBuf, wpos, cInst->SimulatorIndex);

	CreatureInstance *origin = tradeData->player[0].cInst;
	CreatureInstance *target = tradeData->player[1].cInst;
	if (origin == NULL || target == NULL)
		return QueryErrorMsg::INVALIDOBJ;

	if (tradeData->MutualAccept() == true) {
		//Process the trade.
		int wpos = 0;

		//When counting slots, get the currently free slots.
		//Then add the number of items that would be traded (given away).
		//This allows a currently full inventory to potentially receive items
		//after the transaction is processed.

		int oslots = origin->charPtr->inventory.CountFreeSlots(INV_CONTAINER);
		oslots += tradeData->player[0].itemList.size();

		int tslots = target->charPtr->inventory.CountFreeSlots(INV_CONTAINER);
		tslots += tradeData->player[1].itemList.size();

		if (oslots < (int) tradeData->player[1].itemList.size()) {
			//Origin player does not have enough space to receive items.
			wpos = 0;
			wpos += PutByte(&sim->SendBuf[wpos], 51);    //_handleTradeMsg
			wpos += PutShort(&sim->SendBuf[wpos], 0);    //Placeholder for size
			wpos += PutInteger(&sim->SendBuf[wpos], origin->CreatureID);   //traderID
			wpos += PutByte(&sim->SendBuf[wpos], TradeEventTypes::REQUEST_CLOSED); //eventType
			wpos += PutByte(&sim->SendBuf[wpos], CloseReasons::INSUFFICIENT_SPACE); //eventType
			PutShort(&sim->SendBuf[1], wpos - 3);       //Set message size
			SendToOneSimulator(sim->SendBuf, wpos, origin->simulatorPtr);
			SendToOneSimulator(sim->SendBuf, wpos, target->simulatorPtr);
			//origin->actInst->LSendToOneSimulator(SendBuf, wpos, origin->SimulatorIndex);
			//target->actInst->LSendToOneSimulator(SendBuf, wpos, target->SimulatorIndex);
			g_Logs.simulator->debug("[%v] Origin lacks space", sim->InternalID);
			goto exit;
		}
		if (tslots < (int) tradeData->player[0].itemList.size()) {
			//Target player does not have enough space to receive items.
			wpos = 0;
			wpos += PutByte(&sim->SendBuf[wpos], 51);    //_handleTradeMsg
			wpos += PutShort(&sim->SendBuf[wpos], 0);    //Placeholder for size
			wpos += PutInteger(&sim->SendBuf[wpos], target->CreatureID);   //traderID
			wpos += PutByte(&sim->SendBuf[wpos], TradeEventTypes::REQUEST_CLOSED); //eventType
			wpos += PutByte(&sim->SendBuf[wpos], CloseReasons::INSUFFICIENT_SPACE); //eventType
			PutShort(&sim->SendBuf[1], wpos - 3);       //Set message size
			SendToOneSimulator(sim->SendBuf, wpos, origin->simulatorPtr);
			SendToOneSimulator(sim->SendBuf, wpos, target->simulatorPtr);
			//origin->actInst->LSendToOneSimulator(SendBuf, wpos, origin->SimulatorIndex);
			//target->actInst->LSendToOneSimulator(SendBuf, wpos, target->SimulatorIndex);
			g_Logs.simulator->debug("[%v] Target lacks space", sim->InternalID);
			goto exit;
		}

		//Check that each player has the required currencies.
		if (tradeData->player[0].coin > origin->css.copper) {
			wpos = 0;
			wpos += PutByte(&sim->SendBuf[wpos], 51);    //_handleTradeMsg
			wpos += PutShort(&sim->SendBuf[wpos], 0);    //Placeholder for size
			wpos += PutInteger(&sim->SendBuf[wpos], origin->CreatureID);   //traderID
			wpos += PutByte(&sim->SendBuf[wpos], TradeEventTypes::REQUEST_CLOSED); //eventType
			wpos += PutByte(&sim->SendBuf[wpos], CloseReasons::INSUFFICIENT_FUNDS); //eventType
			PutShort(&sim->SendBuf[1], wpos - 3);       //Set message size
			SendToOneSimulator(sim->SendBuf, wpos, origin->simulatorPtr);
			SendToOneSimulator(sim->SendBuf, wpos, target->simulatorPtr);
			//origin->actInst->LSendToOneSimulator(SendBuf, wpos, origin->SimulatorIndex);
			//target->actInst->LSendToOneSimulator(SendBuf, wpos, target->SimulatorIndex);
			g_Logs.simulator->debug("[%v] Origin lacks copper", sim->InternalID);
			goto exit;
		}
		if (tradeData->player[1].coin > target->css.copper) {
			wpos = 0;
			wpos += PutByte(&sim->SendBuf[wpos], 51);    //_handleTradeMsg
			wpos += PutShort(&sim->SendBuf[wpos], 0);    //Placeholder for size
			wpos += PutInteger(&sim->SendBuf[wpos], target->CreatureID);   //traderID
			wpos += PutByte(&sim->SendBuf[wpos], TradeEventTypes::REQUEST_CLOSED); //eventType
			wpos += PutByte(&sim->SendBuf[wpos], CloseReasons::INSUFFICIENT_FUNDS); //eventType
			PutShort(&sim->SendBuf[1], wpos - 3);       //Set message size
			SendToOneSimulator(sim->SendBuf, wpos, origin->simulatorPtr);
			SendToOneSimulator(sim->SendBuf, wpos, target->simulatorPtr);
			//origin->actInst->LSendToOneSimulator(SendBuf, wpos, origin->SimulatorIndex);
			//target->actInst->LSendToOneSimulator(SendBuf, wpos, target->SimulatorIndex);
			g_Logs.simulator->debug("[%v] Target lacks copper", sim->InternalID);
			goto exit;
		}

		//Ready to trade.
		g_Logs.simulator->debug("[%v] Trade requirements passed", sim->InternalID);

		//Adjust and send coin transfer to both players.
		origin->css.copper -= tradeData->player[0].coin;
		target->css.copper -= tradeData->player[1].coin;

		origin->css.copper += tradeData->player[1].coin;
		target->css.copper += tradeData->player[0].coin;

		static const short statSend = STAT::COPPER;
		wpos = PrepExt_SendSpecificStats(sim->SendBuf, origin, &statSend, 1);
		SendToOneSimulator(sim->SendBuf, wpos, origin->simulatorPtr);
		//origin->actInst->LSendToOneSimulator(SendBuf, wpos, origin->SimulatorIndex);

		wpos = PrepExt_SendSpecificStats(sim->SendBuf, target, &statSend, 1);
		SendToOneSimulator(sim->SendBuf, wpos, target->simulatorPtr);
		//origin->actInst->LSendToOneSimulator(SendBuf, wpos, target->SimulatorIndex);

		//Adjust and send items for first player.

		//Remove items from first player.
		wpos = 0;
		CharacterData *p1 = origin->charPtr;
		CharacterData *p2 = target->charPtr;
		g_Logs.simulator->debug("[%v] Trade betweeen [%v] and [%v]",
				sim->InternalID, p1->cdef.css.display_name, p2->cdef.css.display_name);
		for (size_t a = 0; a < tradeData->player[0].itemList.size(); a++) {
			unsigned long CCSID = tradeData->player[0].itemList[a].CCSID;
			InventorySlot *item = p1->inventory.GetItemPtrByCCSID(CCSID);
			if (item == NULL) {
				g_Logs.simulator->error(
						"[%v] Failed to remove item from first player.", sim->InternalID);
			} else {
				wpos += p1->inventory.RemoveItemUpdate(&sim->SendBuf[wpos], sim->Aux3,
						item);
				p1->inventory.RemItem(CCSID);
				p1->pendingChanges++;
			}
		}
		SendToOneSimulator(sim->SendBuf, wpos, origin->simulatorPtr);
		//origin->actInst->LSendToOneSimulator(SendBuf, wpos, origin->SimulatorIndex);
		g_Logs.simulator->debug("[%v] Removed %v items from first player.", sim->InternalID,
				tradeData->player[0].itemList.size());

		//Remove items from second player.
		wpos = 0;
		for (size_t a = 0; a < tradeData->player[1].itemList.size(); a++) {
			unsigned long CCSID = tradeData->player[1].itemList[a].CCSID;
			InventorySlot *item = p2->inventory.GetItemPtrByCCSID(CCSID);
			if (item == NULL) {
				g_Logs.simulator->error(
						"[%v] Failed to remove item from first player.", sim->InternalID);
			} else {
				wpos += p2->inventory.RemoveItemUpdate(&sim->SendBuf[wpos], sim->Aux3,
						item);
				p2->inventory.RemItem(CCSID);
				p2->pendingChanges++;
			}
		}
		SendToOneSimulator(sim->SendBuf, wpos, target->simulatorPtr);
		//target->actInst->LSendToOneSimulator(SendBuf, wpos, target->SimulatorIndex);
		g_Logs.simulator->debug("[%v] Removed %v items from second player.", sim->InternalID,
				tradeData->player[1].itemList.size());

		//Give items to first player
		wpos = 0;
		for (size_t a = 0; a < tradeData->player[1].itemList.size(); a++) {
			int itemID = tradeData->player[1].itemList[a].IID;
			int count = tradeData->player[1].itemList[a].count + 1;
			InventorySlot *item = p1->inventory.AddItem_Ex(INV_CONTAINER,
					itemID, count);
			if (item == NULL)
				g_Logs.simulator->error("[%v] Failed to add item to first player.", sim->InternalID);
			else {
				p1->pendingChanges++;
				g_Logs.event->info("[TRADE] From %v to %v (%v)",
						tradeData->player[1].cInst->css.display_name,
						tradeData->player[0].cInst->css.display_name,
						item->IID);
				item->CopyWithoutCount(tradeData->player[1].itemList[a], false);
				sim->ActivateActionAbilities(item);
				wpos += AddItemUpdate(&sim->SendBuf[wpos], sim->Aux3, item);
			}
		}
		SendToOneSimulator(sim->SendBuf, wpos, origin->simulatorPtr);
		//origin->actInst->LSendToOneSimulator(SendBuf, wpos, origin->SimulatorIndex);
		g_Logs.simulator->debug("[%v] Gave %v items to first player.", sim->InternalID,
				tradeData->player[1].itemList.size());

		//Give items to second player
		wpos = 0;
		for (size_t a = 0; a < tradeData->player[0].itemList.size(); a++) {
			int itemID = tradeData->player[0].itemList[a].IID;
			int count = tradeData->player[0].itemList[a].count + 1;
			InventorySlot *item = p2->inventory.AddItem_Ex(INV_CONTAINER,
					itemID, count);
			if (item == NULL)
				g_Logs.simulator->error("[%v] Failed to add item to second player.", sim->InternalID);
			else {
				p2->pendingChanges++;
				g_Logs.event->info("[TRADE] From %v to %v (%v)",
						tradeData->player[0].cInst->css.display_name,
						tradeData->player[1].cInst->css.display_name,
						item->IID);
				item->CopyWithoutCount(tradeData->player[0].itemList[a], false);
				sim->ActivateActionAbilities(item);
				wpos += AddItemUpdate(&sim->SendBuf[wpos], sim->Aux3, item);
			}
		}
		SendToOneSimulator(sim->SendBuf, wpos, target->simulatorPtr);
		//target->actInst->LSendToOneSimulator(SendBuf, wpos, target->SimulatorIndex);
		g_Logs.simulator->debug("[%v] Gave %v items to second player.", sim->InternalID,
				tradeData->player[0].itemList.size());

		//Send trade completion message.
		wpos = 0;
		wpos += PutByte(&sim->SendBuf[wpos], 51);    //_handleTradeMsg
		wpos += PutShort(&sim->SendBuf[wpos], 0);    //Placeholder for size
		wpos += PutInteger(&sim->SendBuf[wpos], origin->CreatureID);     //traderID
		wpos += PutByte(&sim->SendBuf[wpos], TradeEventTypes::REQUEST_CLOSED); //eventType
		wpos += PutByte(&sim->SendBuf[wpos], CloseReasons::COMPLETE);     //eventType
		PutShort(&sim->SendBuf[1], wpos - 3);       //Set message size

		SendToOneSimulator(sim->SendBuf, wpos, origin->simulatorPtr);
		//origin->actInst->LSendToOneSimulator(SendBuf, wpos, origin->SimulatorIndex);

		PutInteger(&sim->SendBuf[3], target->CreatureID);     //traderID
		SendToOneSimulator(sim->SendBuf, wpos, target->simulatorPtr);
		//target->actInst->LSendToOneSimulator(SendBuf, wpos, target->SimulatorIndex);

		//Clear trade IDs.
		origin->activeLootID = 0;
		target->activeLootID = 0;

		g_Logs.simulator->debug("[%v] Trade complete", sim->InternalID);
		actInst->tradesys.RemoveTransaction(tradeID);
	}

	//Yes, I'm using goto.
	//Yes, I know this whole thing is badly programmed.
	//Deal with it.

	exit: return PrepExt_QueryResponseString(sim->SendBuf, query->ID, "OK");
}
Пример #17
0
void Encode()
{
     int i,c,len,r,s,lml,cbp;
     unsigned char codebuf[17],mask;
     InitTree();
     codebuf[0]=0;
     cbp=mask=1;
     s=0;
     r=N-F;
     memset(buffer,' ',r);
     for( len=0; len<F && (c = GetByte()) != EOF; len++ )
         buffer[r+len]=c;
     if(len==0)  return;
     for(i=1;i<=F;i++)
         InsertNode(r-i);
     InsertNode(r);
     do
     {
         if(mlen>len)
             mlen=len;
         if(mlen<=THRESHOLD)
         {
             mlen=1;
             codebuf[0]|=mask;
             codebuf[cbp++]=buffer[r];
         }
         else
         {
             codebuf[cbp++]=(unsigned char)mpos;
             codebuf[cbp++]=(unsigned char)(((mpos>>4)&0xF0)|(mlen-(THRESHOLD+1)));
         }
         if((mask<<=1)==0)
         {
             for(i=0;i<cbp;i++)
                 PutByte(codebuf[i]);
             codebuf[0]=0;
             cbp=mask=1;
         }
         lml=mlen;
         for(i=0;i<lml&&(c=GetByte())!=EOF;i++)
         {
             DeleteNode(s);
             buffer[s]=c;
             if(s<F-1)
                 buffer[s+N]=c;
             s=(s+1)&(N-1);
             r=(r+1)&(N-1);
             InsertNode(r);
         }
         while(i++<lml)
         {
             DeleteNode(s);
             s=(s+1)&(N-1);
             r=(r+1)&(N-1);
             if(--len)
                 InsertNode(r);
         }
     }while(len>0);

     if(cbp>1)
         for(i=0;i<cbp;i++)
             PutByte(codebuf[i]);
}
Пример #18
0
int PersonaListHandler::handleQuery(SimulatorThread *sim,
		CharacterServerData *pld, SimulatorQuery *query,
		CreatureInstance *creatureInstance) {
	/* Query: persona.list
	 Args : [none]
	 Notes: First query sent to the server.
	 Response: Send back the list of characters available on this account.
	 */

	//Seems to be a rare condition when the account can indeed be NULL at this point.  Possibly
	//disconnecting after the query is sent, but before it's processed?
	if (pld->accPtr == NULL) {
		g_Logs.simulator->error("[%v] persona.list null account", sim->InternalID);
		return 0;
	}

	g_Logs.simulator->info("Retrieving persona list for account:%v",
			pld->accPtr->ID);
	//TODO: Fix a potential buffer overflow.

	int WritePos = 0;
	WritePos += PutByte(&sim->SendBuf[WritePos], 1);     //_handleQueryResultMsg
	WritePos += PutShort(&sim->SendBuf[WritePos], 0);           //Message size
	WritePos += PutInteger(&sim->SendBuf[WritePos], query->ID);  //Query ID

	//Character row count
	int charCount = pld->accPtr->GetCharacterCount();
	if (g_ProtocolVersion >= 38) {
		//Version 0.8.9 has a an extra row in the beginning
		//with one string, the number of characters following.
		WritePos += PutShort(&sim->SendBuf[WritePos], charCount + 1);

		WritePos += PutByte(&sim->SendBuf[WritePos], 1);
		sprintf(sim->Aux3, "%d", charCount + 1);
		WritePos += PutStringUTF(&sim->SendBuf[WritePos], sim->Aux3);
	} else {
		WritePos += PutShort(&sim->SendBuf[WritePos], charCount);
	}

	g_CharacterManager.GetThread("SimulatorThread::handle_query_persona_list");

	int b;
	for (b = 0; b < AccountData::MAX_CHARACTER_SLOTS; b++) {
		if (pld->accPtr->CharacterSet[b] != 0) {
			int cdefid = pld->accPtr->CharacterSet[b];
			CharacterCacheEntry *cce =
					pld->accPtr->characterCache.ForceGetCharacter(cdefid);
			if (cce == NULL) {
				g_Logs.simulator->error("[%v] Could not request character: %v", sim->InternalID, cdefid);
				sim->ForceErrorMessage("Critical: could not load a character.",
						INFOMSG_ERROR);
				sim->Disconnect("SimulatorThread::handle_query_persona_list");
				return 0;
			}

			if (g_Config.AprilFools != 0) {
				WritePos += PutByte(&sim->SendBuf[WritePos], 6); //6 character data strings
				WritePos += PutStringUTF(&sim->SendBuf[WritePos],
						cce->display_name.c_str()); //Seems to be sent twice in 0.8.9.  Unknown purpose.
				WritePos += PutStringUTF(&sim->SendBuf[WritePos],
						cce->display_name.c_str());
				WritePos += PutStringUTF(&sim->SendBuf[WritePos],
						cce->appearance.c_str());

				const char *eqApp = cce->eq_appearance.c_str();
				switch (cce->profession) {
				case 1:
					eqApp =
							"{[1]=3163,[0]=141760,[6]=3019,[10]=3008,[11]=2831}";
					break;
				case 2:
					eqApp =
							"{[0]=141763,[1]=141764,[6]=2107,[10]=2442,[11]=2898}";
					break;
				case 3:
					eqApp = "{[6]=2810,[10]=1980,[11]=2108,[2]=141765}";
					break;
				case 4:
					eqApp = "{[2]=143609,[6]=3160,[10]=3161,[11]=3162}";
					break;
				}
				WritePos += PutStringUTF(&sim->SendBuf[WritePos], eqApp);

				//sprintf(Aux3, "%d", cce->level);
				WritePos += PutStringUTF(&sim->SendBuf[WritePos], "1");

				sprintf(sim->Aux3, "%d", cce->profession);
				WritePos += PutStringUTF(&sim->SendBuf[WritePos], sim->Aux3);
				if (WritePos >= (int) sizeof(sim->SendBuf))
					g_Logs.server->error("Buffer overflow in persona.list");
			} else {
				//Normal stuff.
				WritePos += PutByte(&sim->SendBuf[WritePos], 6); //6 character data strings
				WritePos += PutStringUTF(&sim->SendBuf[WritePos],
						cce->display_name.c_str()); //Seems to be sent twice in 0.8.9.  Unknown purpose.
				WritePos += PutStringUTF(&sim->SendBuf[WritePos],
						cce->display_name.c_str());
				WritePos += PutStringUTF(&sim->SendBuf[WritePos],
						cce->appearance.c_str());
				WritePos += PutStringUTF(&sim->SendBuf[WritePos],
						cce->eq_appearance.c_str());

				sprintf(sim->Aux3, "%d", cce->level);
				WritePos += PutStringUTF(&sim->SendBuf[WritePos], sim->Aux3);

				sprintf(sim->Aux3, "%d", cce->profession);
				WritePos += PutStringUTF(&sim->SendBuf[WritePos], sim->Aux3);
				if (WritePos >= (int) sizeof(sim->SendBuf))
					g_Logs.server->error("Buffer overflow in persona.list");
			}
		}
	}
	PutShort(&sim->SendBuf[1], WritePos - 3);       //Set message size
	g_CharacterManager.ReleaseThread();

	return WritePos;
}
Пример #19
0
void OpcodesTest() {
    printf(">>> OpcodesTest \n");
    
    struct State state;
    struct CompilationState compilationState;
    Mem memory[512];

    InitState(&state, memory, sizeof(memory));
    InitCompilationState(&compilationState, memory, sizeof(memory));
    
    int opcodeTestOffset = 127;
    char* string = "OpcodeTest #1";
    long len = strlen(string);
    memcpy(memory+opcodeTestOffset, string, len);
    
    int argNum = 0;
    

    
    PutCall(&compilationState, "MethodEnter");
    PutByte(&compilationState, (argNum+1) * sizeof(Short));
    NextInstruction(&state);
    
    PutCall(&compilationState, "PushShortToStack");
    PutShort(&compilationState, opcodeTestOffset);
    NextInstruction(&state);

    AssertStackTopShort(&state, opcodeTestOffset);
    
    PutCall(&compilationState, "StoreShort");
    PutByte(&compilationState, argNum);
    NextInstruction(&state);
    
    PutCall(&compilationState, "LoadByte");
    PutByte(&compilationState, argNum);
    NextInstruction(&state);
    
    AssertStackTopByte(&state, (Byte)opcodeTestOffset);
    
    PutCall(&compilationState, "StoreByte");
    PutByte(&compilationState, argNum);
    NextInstruction(&state);
    
    PutCall(&compilationState, "LoadShort");
    PutByte(&compilationState, argNum);
    NextInstruction(&state);
    
    AssertStackTopShort(&state, opcodeTestOffset);
    
    PutCall(&compilationState, "PushByteToStack");
    PutByte(&compilationState, 1);
    NextInstruction(&state);
    
    PutCall(&compilationState, "JumpIf");
    PutShort(&compilationState, CodeSizeForInstruction("ZeroOpcodeFail") + CodeSizeForInstruction("Jump"));
    
    PutCall(&compilationState, "ZeroOpcodeFail");
    
    PutCall(&compilationState, "Jump");
    PutShort(&compilationState, CodeSizeForInstruction("Jump") + CodeSizeForInstruction("ZeroOpcodeFail"));
    
    PutCall(&compilationState, "Jump");
    PutShort(&compilationState, -CodeSizeForInstruction("Jump")*2);
    
    PutCall(&compilationState, "ZeroOpcodeFail");
    
    PutCall(&compilationState, "PassToPutS");
    
    NextInstruction(&state);
    NextInstruction(&state);
    NextInstruction(&state);

    AssertStackTopShort(&state, opcodeTestOffset);
    NextInstruction(&state);
    
    PutCall(&compilationState, "PushByteToStack");
    PutByte(&compilationState, 0);
    NextInstruction(&state);
    
    PutCall(&compilationState, "JumpIf");
    PutShort(&compilationState, -CodeSizeForInstruction("JumpIf") );
    NextInstruction(&state);
    
    PutCall(&compilationState, "PushByteToStack");
    PutByte(&compilationState, 2);
    NextInstruction(&state);
    
    PutCall(&compilationState, "PushByteToStack");
    PutByte(&compilationState, 2);
    NextInstruction(&state);
    
    PutCall(&compilationState, "CompareBytes");
    NextInstruction(&state);
    
    PutCall(&compilationState, "JumpIf");
    PutShort(&compilationState, CodeSizeForInstruction("ZeroOpcodeFail"));
    
    PutCall(&compilationState, "ZeroOpcodeFail");
    
    NextInstruction(&state);
    
    PutCall(&compilationState, "PushShortToStack");
    PutShort(&compilationState, 2000);
    NextInstruction(&state);
    
    PutCall(&compilationState, "PushShortToStack");
    PutShort(&compilationState, 2000);
    NextInstruction(&state);
    
    PutCall(&compilationState, "CompareShorts");
    NextInstruction(&state);
    
    PutCall(&compilationState, "JumpIf");
    PutShort(&compilationState, CodeSizeForInstruction("ZeroOpcodeFail"));
    
    PutCall(&compilationState, "ZeroOpcodeFail");
    
    NextInstruction(&state);
    
    PutCall(&compilationState, "PushShortToStack");
    PutShort(&compilationState, 100);
    NextInstruction(&state);
    
    PutCall(&compilationState, "StoreByte");
    PutByte(&compilationState, 1);
    NextInstruction(&state);
    
    PutCall(&compilationState, "LoadShort");
    PutByte(&compilationState, 1);
    NextInstruction(&state);
    
    PutCall(&compilationState, "Inc");
    NextInstruction(&state);
    
    PutCall(&compilationState, "Dec");
    NextInstruction(&state);
    
    PutCall(&compilationState, "LoadShort");
    PutByte(&compilationState, 1);
    NextInstruction(&state);
    
    PutCall(&compilationState, "CompareShorts");
    NextInstruction(&state);
    
    PutCall(&compilationState, "JumpIf");
    PutShort(&compilationState, CodeSizeForInstruction("ZeroOpcodeFail"));
    PutCall(&compilationState, "ZeroOpcodeFail");
    NextInstruction(&state);
    
    PutCall(&compilationState, "LoadShort");
    PutByte(&compilationState, 1);
    NextInstruction(&state);
    
    PutCall(&compilationState, "DupShort");
    NextInstruction(&state);
    
    PutCall(&compilationState, "CompareShorts");
    NextInstruction(&state);
    PutCall(&compilationState, "JumpIf");
    PutShort(&compilationState, CodeSizeForInstruction("ZeroOpcodeFail"));
    PutCall(&compilationState, "ZeroOpcodeFail");
    NextInstruction(&state);
    
    PutCall(&compilationState, "LoadByte");
    PutByte(&compilationState, 1);
    NextInstruction(&state);
    
    PutCall(&compilationState, "DupByte");
    NextInstruction(&state);
    
    PutCall(&compilationState, "CompareBytes");
    NextInstruction(&state);
    PutCall(&compilationState, "JumpIf");
    PutShort(&compilationState, CodeSizeForInstruction("ZeroOpcodeFail"));
    PutCall(&compilationState, "ZeroOpcodeFail");
    NextInstruction(&state);
    
    PutCall(&compilationState, "LoadShort");
    PutByte(&compilationState, 1);
    NextInstruction(&state);
    
    PutCall(&compilationState, "DupShort");
    NextInstruction(&state);
    
    PutCall(&compilationState, "Add");
    NextInstruction(&state);
    
    AssertStackTopShort(&state, 200);
    
    PutCall(&compilationState, "PushShortToStack");
    PutShort(&compilationState, -2);
    NextInstruction(&state);
    
    AssertStackTopShort(&state, -2);
    
    PutCall(&compilationState, "Mul");
    NextInstruction(&state);
    
    AssertStackTopShort(&state, -400);
    
    PutCall(&compilationState, "PushShortToStack");
    PutShort(&compilationState, -4);
    NextInstruction(&state);
    
    PutCall(&compilationState, "Div");
    NextInstruction(&state);
    
    AssertStackTopShort(&state, 100);
    
    PutCall(&compilationState, "PushShortToStack");
    PutShort(&compilationState, 99);
    NextInstruction(&state);
    
    PutCall(&compilationState, "Sub");
    NextInstruction(&state);
    
    AssertStackTopShort(&state, 1);
    
    int methodOffset = 200;
    
    MemPtr mainPC = compilationState.PC;
    {
        compilationState.PC = compilationState.memory + methodOffset;
        
        PutCall(&compilationState, "MethodEnter");
        PutByte(&compilationState, 0);
        
        PutCall(&compilationState, "PushShortToStack");
        PutShort(&compilationState, opcodeTestOffset);
        
        PutCall(&compilationState, "PassToPutS");
        
        PutCall(&compilationState, "MethodExit");
    }
    compilationState.PC = mainPC;
    
    
    PutCall(&compilationState, "PushShortToStack");
    PutShort(&compilationState, methodOffset);
    NextInstruction(&state);
    
    PutCall(&compilationState, "CallStackPtr");
    NextInstruction(&state);
    
    NextInstruction(&state);
    NextInstruction(&state);
    NextInstruction(&state);
    NextInstruction(&state);
    
    methodOffset = 200;
    int argValue = 0x40;
    
    PutCall(&compilationState, "PushByteToStack");
    PutByte(&compilationState, argValue);
    
    PutCall(&compilationState, "Call");
    PutShort(&compilationState, methodOffset);
    
    mainPC = compilationState.PC;
    {
        compilationState.PC = compilationState.memory + methodOffset;
        
        PutCall(&compilationState, "MethodEnter");
        PutByte(&compilationState, 1*sizeof(Short));
        
        PutCall(&compilationState, "SetupArgsStack");
        
        PutCall(&compilationState, "StoreByte");
        PutByte(&compilationState, 0);
        
        PutCall(&compilationState, "SetupFrameStack");
        
        PutCall(&compilationState, "LoadShort");
        PutByte(&compilationState, 0);
        
        PutCall(&compilationState, "MethodReturn");
        PutByte(&compilationState, sizeof(Short));
    }
    compilationState.PC = mainPC;
    
    NextInstruction(&state);
    NextInstruction(&state);
    NextInstruction(&state);
    NextInstruction(&state);
    
    AssertStackTopByte(&state, argValue);
    NextInstruction(&state);
    
    NextInstruction(&state);
    NextInstruction(&state);
    
    AssertStackTopShort(&state, argValue);
    NextInstruction(&state);
    
    AssertStackTopShort(&state, argValue);
    
    PutCall(&compilationState, "MethodExit");
    NextInstruction(&state);
    

}
Пример #20
0
void done_outputing_bits()
{   
	PutByte(buffer<<bits_to_go);
	buffer = 0;					/* Buffer is empty to start */
    bits_to_go= 8;				/* with.                    */
}