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
