Thread: Say Links
View Single Post
  #2  
Old 05-20-2009, 07:56 AM
trevius's Avatar
trevius
Developer
 
Join Date: Aug 2006
Location: USA
Posts: 5,946
Default

Ok, I think I have this almost working. So far, I have it able to create the link properly. It will update the table with a new phrase and ID automatically if one doesn't exist. The only problem left is that I don't know how to pull a string out of a query result to use for when you click the actual link.

Here is what I have so far. Feel free to make fixes, comments, or suggestions. Also note that I have a few extra messages being sent to the client for testing purposes. Those can be removed when this is finished.

Here is the part that is not working:
client_packet.cpp
Code:
void Client::Handle_OP_ItemLinkClick(const EQApplicationPacket *app)
{
	if(app->size != sizeof(ItemViewRequest_Struct)){
		LogFile->write(EQEMuLog::Error, "Wrong size on OP_ItemLinkClick.  Got: %i, Expected: %i", app->size, sizeof(ItemViewRequest_Struct));
		DumpPacket(app);
		return;
	}
	DumpPacket(app);
	ItemViewRequest_Struct* ivrs = (ItemViewRequest_Struct*)app->pBuffer;

	//todo: verify ivrs->link_hash based on a rule, in case we don't care about people being able to sniff data from the item DB

	const Item_Struct* item = database.GetItem(ivrs->item_id);
	if (!item) {
		if (ivrs->item_id > 500000)
		{
			char* response;
			int sayid = ivrs->item_id - 500000;

			if (sayid && sayid > 0) 
			{
				const char *ERR_MYSQLERROR = "Error in saylink phrase queries after clicking the link";
				char errbuf[MYSQL_ERRMSG_SIZE];
				char *query = 0;
				MYSQL_RES *result;
				MYSQL_ROW row;
				

				if(database.RunQuery(query,MakeAnyLenString(&query,"SELECT `phrase` FROM saylink WHERE `id` = '%i'", response),errbuf,&result))
				{

					if (mysql_num_rows(result) >= 1)
					{
						while((row = mysql_fetch_row(result)))
						{
							response = new char[strlen(row[0]) + 1];
							strcpy(response, row[0]);
						}
						mysql_free_result(result);
					}
						
					mysql_free_result(result);
					safe_delete_array(query);
				}
				else 
				{
					Message(13, "Error: The saylink (%s) was not found in the database.",response);
					safe_delete_array(query);
					return;
				}
			}
			Message(13, "The Respone is %s.",response);
			this->ChannelMessageReceived(8, 1, 100, response);
			return;
		}
		else {
			Message(13, "Error: The item for the link you have clicked on does not exist!");
			return;
		}

	}

	ItemInst* inst = database.CreateItem(item, item->MaxCharges, ivrs->augments[0], ivrs->augments[1], ivrs->augments[2], ivrs->augments[3], ivrs->augments[4]);
	if (inst) {
		SendItemPacket(0, inst, ItemPacketViewLink);
		safe_delete(inst);
	}
	return;
}
Here is the rest that seems to work just fine, but could probably use some looking over by a more experienced coder:
questmgr.cpp
Code:
const char* QuestManager::saylink(char* Phrase) {

	const char *ERR_MYSQLERROR = "Error in saylink phrase queries";
	char errbuf[MYSQL_ERRMSG_SIZE];
	char *query = 0;
	MYSQL_RES *result;
	MYSQL_ROW row;
	int sayid = 0;

	// Search for existing saylink table entry for this phrase
	if(database.RunQuery(query,MakeAnyLenString(&query,"SELECT `id` FROM `saylink` WHERE `phrase` = '%s'", Phrase),errbuf,&result))
	{
		if (mysql_num_rows(result) >= 1)
		{
			while((row = mysql_fetch_row(result)))
			{
				sayid = atoi(row[0]);
			}
			mysql_free_result(result);
		}
		else   // Add a new saylink entry to the database and query it again for the new sayid number
		{
			mysql_free_result(result);
			safe_delete_array(query);

			database.RunQuery(query,MakeAnyLenString(&query,"INSERT INTO `saylink` (`phrase`) VALUES ('%s')", Phrase),errbuf);
			safe_delete_array(query);

			if(database.RunQuery(query,MakeAnyLenString(&query,"SELECT `id` FROM saylink WHERE `phrase` = '%s'", Phrase),errbuf,&result))
			{
				if (mysql_num_rows(result) >= 1)
				{
					while((row = mysql_fetch_row(result)))
					{
						sayid = atoi(row[0]);
					}
				}
				mysql_free_result(result);
				safe_delete_array(query);
			}
			else 
			{
				LogFile->write(EQEMuLog::Error, ERR_MYSQLERROR, errbuf);
				safe_delete_array(query);
			}
			safe_delete_array(query);
		}
		safe_delete_array(query);
	}

	char linktext[250];
	if (initiator->GetClientVersion() == EQClientSoF)
	{
		sprintf(linktext,"%c%06X%s%s%c",0x12,500000+sayid,"00000000000000000000000000000000000000000000",Phrase,0x12);
	}
	else
	{
		sprintf(linktext,"%c%06X%s%s%c",0x12,500000+sayid,"000000000000000000000000000000000000000",Phrase,0x12);
	}
	strcpy(Phrase,linktext);
	return Phrase;
}
questmgr.h
Code:
const char* saylink(char* Phrase);
perlparser.cpp
Code:
XS(XS__saylink);
XS(XS__saylink) {
	dXSARGS;
	if (items != 1)
		Perl_croak(aTHX_ "Usage: saylink(phrase)");
	dXSTARG;

	Const_char * RETVAL;
	char text[250];
	strcpy(text,(char *)SvPV_nolen(ST(0)));

	RETVAL = quest_manager.saylink(text);

	sv_setpv(TARG, RETVAL); XSprePUSH; PUSHTARG;
	XSRETURN(1);
}
And here is the SQL for the table:
Code:
DROP TABLE IF EXISTS `saylink`;
CREATE TABLE `saylink` (
  `id` int(10) NOT NULL auto_increment,
  `phrase` varchar(64) NOT NULL default '',
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=10 DEFAULT CHARSET=latin1;
This won't be a required table unless you want to use saylinks.

I think saylink is pretty close to done now. Once this is working and hopefully gets reviewed by a decent coder here, I will get it added to the SVN unless someone else wants to beat me to it. I can't wait to try this out
__________________
Trevazar/Trevius Owner of: Storm Haven
Everquest Emulator FAQ (Frequently Asked Questions) - Read It!
Reply With Quote