Page 1 of 1

FIX FOR MXI FFXI-BOOT DNS FOR IP ON AH SEARCH SUCCESS

Posted: Fri Mar 08, 2013 9:55 pm
by WiiStream
Have you ever tried to use a DNS domain name in the ffxi-boot.ini or the client.ini for mxi and you get a search failed in the Auction house??

This will fix that, so you can use the DNS domain name for your .ini files this is good for dynamic IP address that change, you can use a no-ip service to keep your IP and update your IP with out reconfigure your whole server, this also allows you to not have to use the zoneid field in the table zone_setting in mysql.

ADD TO MAP SERVER

Code: Select all

void CZone::LoadZoneSettings()
{
	in_addr inaddr;
	inaddr.S_un.S_addr = inet_addr(map_config.mysql_host);
	//ShowFatalError(CL_RED"CZone:GET HOST NAME2(%u)\n" CL_RESET, inaddr);
	
	if( inaddr.S_un.S_addr == INADDR_NONE)
	{
		hostent* phostent = gethostbyname(map_config.mysql_host);
		//ShowFatalError(CL_RED"CZone:GET HOST NAME3(%u)\n" CL_RESET, phostent);
		if( phostent == 0)
		{
			//ShowFatalError(CL_RED"CZone:GET HOST NAME4(%u)\n" CL_RESET, phostent);
			return;
		}

		if( sizeof(inaddr) != phostent->h_length)
		{
			//ShowFatalError(CL_RED"CZone:GET HOST NAME5(%u)\n" CL_RESET, phostent);
			return; 
		}

		inaddr.S_un.S_addr = *((unsigned long*) phostent->h_addr);
		

		
	}
	
	//GetHostNameOrIP ("ffxi-a.com");
    const int8* Query =
        "SELECT "
          "zone.name,"
          "zone.zoneip,"
          "zone.zoneport,"
          "zone.music,"
          "zone.battlesolo,"
          "zone.battlemulti,"
          "zone.tax,"
          "zone.misc,"
          "bcnm.name "
        "FROM zone_settings AS zone "
        "LEFT JOIN bcnm_info AS bcnm "
        "USING (zoneid) "
        "WHERE zoneid = %u "
        "LIMIT 1";

    if (Sql_Query(SqlHandle, Query, m_zoneID) != SQL_ERROR && Sql_NumRows(SqlHandle) != 0 && Sql_NextRow(SqlHandle) == SQL_SUCCESS)
    {
        m_zoneName.insert(0, Sql_GetData(SqlHandle,0));
		string_t zonename = Sql_GetData(SqlHandle,0);
		m_zoneIP   = inaddr.S_un.S_addr; 
		//TODO ADD TO THE  CONFIG FILE FOR THIS SO ALSO USE MAP SERVER THE NORMAL WAY BUT SHOULD NOT BE NEEDED.
		//(uint32)Sql_GetUIntData(SqlHandle,1);
		m_zonePort = (uint16)Sql_GetUIntData(SqlHandle,2);
		m_zoneMusic.m_song   = (uint8)Sql_GetUIntData(SqlHandle,3);		// background music
		m_zoneMusic.m_bSongS = (uint8)Sql_GetUIntData(SqlHandle,4);		// solo battle music
		m_zoneMusic.m_bSongM = (uint8)Sql_GetUIntData(SqlHandle,5);		// party battle music
		m_tax = (uint16)(Sql_GetFloatData(SqlHandle,6) * 100);			// tax for bazaar
		m_miscMask = (uint16)Sql_GetUIntData(SqlHandle,7);

        if (Sql_GetData(SqlHandle,8) != NULL) // сейчас нельзя использовать bcnmid, т.к. они начинаются с нуля
        {
            m_InstanceHandler = new CInstanceHandler(m_zoneID);
	    }
        if (m_miscMask & MISC_TREASURE)
		{
            m_TreasurePool = new CTreasurePool(TREASUREPOOL_ZONE);
		}
		
		ShowNotice(CL_GREEN"TRACER: Resolveing Zonename %s\n" CL_RESET, zonename.c_str() );
		ShowNotice(CL_GREEN"TRACER: Resolveing IP %u\n" CL_RESET, inaddr.S_un.S_addr );
    }
    else
    {
        ShowFatalError(CL_RED"CZone::LoadZoneSettings: Cannot load zone settings (%u)\n" CL_RESET, m_zoneID);
    }
}

ADD TO LOGIN SERVER

Code: Select all

int32 lobbydata_parse(int32 fd)
{
	login_session_data_t* sd = (login_session_data_t*)session[fd]->session_data;

	if( sd == NULL )
	{
		if( RFIFOREST(fd) >= 5 &&
			RBUFB(session[fd]->rdata,0) == 0xA1 )
		{
			unsigned char *buff = session[fd]->rdata;

			int32 accid = RBUFL(buff,1);

			sd = find_loginsd_byaccid(accid);
			if( sd == NULL )
			{
				do_close_tcp(fd);
				return -1;
			}

			sd->login_lobbydata_fd    = fd;
			session[fd]->session_data = sd;
			return 0;
		}

	}

	
	if( session[fd]->flag.eof )
	{
		do_close_lobbydata(sd,fd);
		return 0;
	}

	if( RFIFOREST(fd) >= 1 )
	{
		unsigned char *buff = session[fd]->rdata;
		ShowDebug("lobbydata_parse:Incoming Packet:" CL_WHITE"<%x>" CL_RESET" from ip:<%s>\n",RBUFB(buff,0),ip2str(sd->client_addr,NULL));

		int32 code = RBUFB(buff,0);
		switch(code)
		{
			case 0xA1:
			{
				if( RFIFOREST(fd) < 9 )
				{
					ShowError("lobbydata_parse:" CL_WHITE"<%s>" CL_RESET" sent less then 9 bytes\n",ip2str(session[fd]->client_addr,NULL));
					do_close_lobbydata(sd,fd);
					return -1;
				}
				char uList[300];
				memset(uList,0,sizeof(uList));

				sd->servip = RBUFL(buff,5);

				unsigned char CharList[2500];
				memset(CharList,0,sizeof(CharList));
				//запись зарезервированных чисел
				CharList[0] = 0xE0;CharList[1] = 0x08;
				CharList[4] = 0x49;CharList[5] = 0x58;CharList[6] = 0x46;CharList[7] = 0x46;CharList[8] = 0x20;

				CharList[28] = 16; // количество ячеек, доступных для создания персонажей (0-16)

				const char *Query =  "SELECT charid, charname, pos_zone, pos_prevzone, mjob,\
												 race, face, head, body, hands, legs, feet, main, sub,\
												 war, mnk, whm, blm, rdm, thf, pld, drk, bst, brd, rng,\
												 sam, nin, drg, smn, blu, cor, pup, dnc, sch \
										  FROM chars \
											INNER JOIN char_stats USING(charid)\
											INNER JOIN char_look  USING(charid) \
											INNER JOIN char_jobs  USING(charid) \
										  WHERE accid = %i \
										  LIMIT 16;";

				int32 ret =  Sql_Query(SqlHandle,Query,sd->accid);
				if( ret == SQL_ERROR )
				{
					do_close_lobbydata(sd,fd);
					return -1;
				}
				/*int32 Content_ID = 1; //DEFAULT TO SEE IF THEY ARE NEW CREATED CHAR OR A RETURNING CHAR
                 Query = "SELECT content_ids FROM accounts WHERE id = '%u';";
	             ret = Sql_Query(SqlHandle,Query,sd->accid);

	             if (ret != SQL_ERROR && Sql_NumRows(SqlHandle) != 0 && Sql_NextRow(SqlHandle) == SQL_SUCCESS)
	                {
						Content_ID =  Sql_GetIntData(SqlHandle,0);
						ShowDebug("GET CONTENT ID AMOUNT %u OF PLAYER %u \n" CL_RESET,Content_ID,sd->accid);
				    }
				 else
				 {
                   ShowDebug("SHOULD NEVER SEE THIS PLAYER IS NOT IN DATABASE \n" CL_RESET);
				 }*/

				LOBBY_A1_RESERVEPACKET(ReservePacket);

				//server's name that shows in lobby menu
				

                memcpy(ReservePacket+60, login_config.servername, dsp_cap(strlen(login_config.servername), 0, 15));


				//Подготовка пространства в пакете для информации о 16 игровых персонажах
				for(int j = 0; j<1; ++j) 
				{
					memcpy(CharList+32+140*j, ReservePacket+32, 140);
					char ContentID[3];
					memcpy(ContentID, CharList+32, sizeof(ContentID));
					ContentID[2] += j;

					memcpy(CharList+32+140*j, &ContentID, 3);
					memcpy(uList+16*(j+1),&ContentID, 3);
				}

				uList[0] = 0x03;


				int i = 0;
				//Считывание информации о конкректном персонаже
				//Загрузка всей необходимой информации о персонаже из базы
				while(Sql_NextRow(SqlHandle) != SQL_NO_DATA) 
				{
					char* strCharName = NULL;
					
					Sql_GetData(SqlHandle,1,&strCharName,NULL);

					uint32 CharID    = Sql_GetIntData(SqlHandle,0);
					
					uint8 zone		 = (uint8)Sql_GetIntData(SqlHandle,2);
					uint8 prevzone	 = (uint8)Sql_GetIntData(SqlHandle,3);

					uint8 MainJob	 = (uint8)Sql_GetIntData(SqlHandle,4);
					uint8 lvlMainJob = (uint8)Sql_GetIntData(SqlHandle,13+MainJob);

					WBUFL(uList,20*(i+1)) = CharID;

					////////////////////////////////////////////////////
					WBUFL(CharList,4+32+i*140) = CharID;

					memcpy(CharList+12+32+i*140,strCharName, 15);

					WBUFB(CharList,46+32+i*140) = MainJob;
					WBUFB(CharList,73+32+i*140) = lvlMainJob; 

					WBUFB(CharList,44+32+i*140) = (uint8) Sql_GetIntData(SqlHandle, 5); // race;
					WBUFB(CharList,56+32+i*140) = (uint8) Sql_GetIntData(SqlHandle, 6); // face;
					WBUFW(CharList,58+32+i*140) = (uint16)Sql_GetIntData(SqlHandle, 7); // head;
					WBUFW(CharList,60+32+i*140) = (uint16)Sql_GetIntData(SqlHandle, 8); // body;
					WBUFW(CharList,62+32+i*140) = (uint16)Sql_GetIntData(SqlHandle, 9); // hands;
					WBUFW(CharList,64+32+i*140) = (uint16)Sql_GetIntData(SqlHandle,10); // legs;
					WBUFW(CharList,66+32+i*140) = (uint16)Sql_GetIntData(SqlHandle,11); // feet;
					WBUFW(CharList,68+32+i*140) = (uint16)Sql_GetIntData(SqlHandle,12); // main;
					WBUFW(CharList,70+32+i*140) = (uint16)Sql_GetIntData(SqlHandle,13); // sub;

					WBUFB(CharList,72+32+i*140) = (zone == 0 ? prevzone : zone);		// если персонаж в MogHouse
					///////////////////////////////////////////////////
					++i;
				}

				if(session[sd->login_lobbyview_fd]!=NULL){
					// write into lobbydata
					uList[1] = 0x10;
					memcpy(session[fd]->wdata,uList,0x110);
					WFIFOSET(fd,0x110);
					RFIFOSKIP(fd,session[fd]->rdata_size);
					RFIFOFLUSH(fd);
					////////////////////////////////////////
				
					unsigned char hash[16];
					md5((unsigned char*)(CharList), hash, 2272);

					memcpy(CharList+12,hash,16);
					// write into lobbyview
					memcpy(session[sd->login_lobbyview_fd]->wdata,CharList,2272);
					WFIFOSET(sd->login_lobbyview_fd,2272);
					RFIFOSKIP(sd->login_lobbyview_fd,session[sd->login_lobbyview_fd]->rdata_size);
					RFIFOFLUSH(sd->login_lobbyview_fd);
				}
				else{ //cleanup
					ShowWarning("lobbydata_parse: char:(%i) login data corrupt (0xA1). Disconnecting client.\n",sd->accid);
					do_close_lobbydata(sd,fd);
					return -1;
				}
				/////////////////////////////////////////

				break;
			}
		case 0xA2:
			{
				LOBBY_A2_RESERVEPACKET(ReservePacket);
				uint8 key3[20];
				memset(key3,0,sizeof(key3));
				memcpy(key3,buff+1,sizeof(key3));
				key3[16] -= 2;
				uint8 MainReservePacket[0x48];
				
				RFIFOSKIP(fd,session[fd]->rdata_size);
				RFIFOFLUSH(fd);

				if(session[sd->login_lobbyview_fd]==NULL){
					ShowWarning("lobbydata_parse: char:(%i) login data corrupt (0xA2). Disconnecting client.\n",sd->accid);
					do_close_lobbydata(sd,fd);
					return -1;
				}

				uint32 charid = RBUFL(session[sd->login_lobbyview_fd]->rdata,32);

				in_addr inaddr;
	inaddr.S_un.S_addr = inet_addr(login_config.mysql_host);
	
	
	if( inaddr.S_un.S_addr == INADDR_NONE)
	{
		hostent* phostent = gethostbyname(login_config.mysql_host);
		
		if( phostent == 0)
		{
			
			return 0;
		}

		if( sizeof(inaddr) != phostent->h_length)
		{
			
			return 0;; 
		}

		inaddr.S_un.S_addr = *((unsigned long*) phostent->h_addr);
		

		
	}

				const char *fmtQuery = "SELECT zoneip, zoneport, zoneid, pos_prevzone \
									    FROM zone_settings, chars \
										WHERE zoneid = pos_zone AND charid = %u;";
				uint32 ZoneIP	= inaddr.S_un.S_addr;//sd->servip;
                uint16 ZonePort = 54230;

				if( Sql_Query(SqlHandle,fmtQuery,charid) != SQL_ERROR &&
					Sql_NumRows(SqlHandle) != 0 )
				{
					Sql_NextRow(SqlHandle);
					
					if (Sql_GetIntData(SqlHandle,3) == 0)  key3[16] += 6;

					ZoneIP = inaddr.S_un.S_addr;//Sql_GetUIntData(SqlHandle,0);
					ZonePort = (uint16)Sql_GetUIntData(SqlHandle,1);
					uint8  ZoneID = (uint8)Sql_GetUIntData(SqlHandle,2);
					WBUFL(ReservePacket,(0x38)) = ZoneIP;
					WBUFW(ReservePacket,(0x3C)) = ZonePort;
					ShowInfo("lobbydata_parse: zoneid:(%u),zoneip:(%s),zoneport:(%u) for char:(%u)\n",ZoneID,ip2str(ntohl(ZoneIP),NULL),ZonePort,charid);
				}else{
					ShowWarning("lobbydata_parse: zoneip:(%s) for char:(%u) is standard\n",ip2str(sd->servip,NULL),charid);
					WBUFL(ReservePacket,(0x38)) = ZoneIP;
					//WBUFL(ReservePacket,(0x38)) = //sd->servip;	// map-server ip
				  //WBUFW(ReservePacket,(0x3C)) = port;			// map-server port			
				}

				WBUFL(ReservePacket,(0x40)) = ZoneIP; //sd->servip;		// search-server ip
			  //WBUFW(ReservePacket,(0x44)) = port;				// search-server port

				memcpy(MainReservePacket,ReservePacket,RBUFB(ReservePacket,0));

				// необходиму одалять сессию, необработанную игровым сервером
				Sql_Query(SqlHandle,"DELETE FROM accounts_sessions WHERE accid = %u and client_port = 0", sd->accid);

				int8 session_key[sizeof(key3)*2+1];
				bin2hex(session_key,key3,sizeof(key3));

				fmtQuery = "INSERT INTO accounts_sessions(accid,charid,session_key,server_addr,server_port,client_addr) VALUES(%u,%u,x'%s',%u,%u,%u)";

				if( Sql_Query(SqlHandle, fmtQuery, sd->accid, charid, session_key, ZoneIP, ZonePort, sd->client_addr) == SQL_ERROR )
				{
					//отправляем клиенту сообщение об ошибке
					LOBBBY_ERROR_MESSAGE(ReservePacket);
					// устанавливаем код ошибки
					// Unable to connect to world server. Specified operation failed
					WBUFW(ReservePacket,32) = 305; 
					memcpy(MainReservePacket,ReservePacket,RBUFB(ReservePacket,0));
				}
			
				unsigned char Hash[16];
				uint8 SendBuffSize = RBUFB(MainReservePacket,0);

				memset(MainReservePacket+12,0,sizeof(Hash));
				md5(MainReservePacket, Hash, SendBuffSize);

				memcpy(MainReservePacket+12,Hash,sizeof(Hash));
				memcpy(session[sd->login_lobbyview_fd]->wdata,MainReservePacket,SendBuffSize);
				WFIFOSET(sd->login_lobbyview_fd,SendBuffSize);

				RFIFOSKIP(sd->login_lobbyview_fd,session[sd->login_lobbyview_fd]->rdata_size);
				RFIFOFLUSH(sd->login_lobbyview_fd);
				
				if (SendBuffSize == 0x24){
					// выходим в случае ошибки без разрыва соединения
					return -1;
				}

				do_close_tcp(sd->login_lobbyview_fd);
				ShowStatus("lobbydata_parse: client %s finished work with " CL_GREEN"lobbyview" CL_RESET"\n",ip2str(sd->client_addr,NULL));
				break;
			}
		default:

			break;
		}
	}
	return 0;
};
WHAT DOSE THIS DO???

This allows you to skip the whole process with the config your ip with the handy tool its no longer needed.
Also in the database zone setting table the zoneID is not needed either, but if it is kept so you want to use map server on another dedicated server then some one needs to add extra code in the login.config as for my self i do not need it yet, server is to small.
need to make a config setting in the map and login server.config if you get a population that can not support one map server.
then you will also have to solve how you will communicate with different players in different map servers.
This also resolved the DNS so you do not have to use a Direct IP you can us DNS ffxi-a.com for IP or any domain name.

For ffxi-boot.exe mxi.exe config.ini or ffxi-boot.ini

THIS CODE HERE IS NOT NEEDED SHOULD CLEAN IT UP

Code: Select all

/*int32 Content_ID = 1; //DEFAULT TO SEE IF THEY ARE NEW CREATED CHAR OR A RETURNING CHAR
                 Query = "SELECT content_ids FROM accounts WHERE id = '%u';";
                ret = Sql_Query(SqlHandle,Query,sd->accid);

                if (ret != SQL_ERROR && Sql_NumRows(SqlHandle) != 0 && Sql_NextRow(SqlHandle) == SQL_SUCCESS)
                   {
                  Content_ID =  Sql_GetIntData(SqlHandle,0);
                  ShowDebug("GET CONTENT ID AMOUNT %u OF PLAYER %u \n" CL_RESET,Content_ID,sd->accid);
                }
             else
             {
                   ShowDebug("SHOULD NEVER SEE THIS PLAYER IS NOT IN DATABASE \n" CL_RESET);
             }*/
I was trying to load the contend IDs from the database account table into the login server and it was reading but not working correctly for some reason. unknown issue with this..