mirror of
https://github.com/polserver/polserver
synced 2026-08-13 08:23:08 -04:00
461 lines
13 KiB
C++
461 lines
13 KiB
C++
/*
|
|
History
|
|
=======
|
|
2005/11/25 MuadDib: Added PKTBI_BF::TYPE_SESPAM: to do away with spam.
|
|
2005/11/23 MuadDib: Altered handle_mode_set for 0x72 Packet. Nows reads
|
|
from combat.cfg for warmode_wait object. Sends the
|
|
0x77 Packet and returns 0 when out of timer.
|
|
2005/12/09 MuadDib: Added TYPE_CLIENT_LANGUAGE for setting member uclang.
|
|
2006/05/24 Shinigami: Added PKTBI_BF::TYPE_CHARACTER_RACE_CHANGER to support Elfs
|
|
2006/05/30 Shinigami: Changed params of character_race_changer_handler()
|
|
2009/07/23 MuadDib: updates for new Enum::Packet IDs
|
|
2009/08/14 Turley: Added PKTBI_BF::TYPE_SCREEN_SIZE & TYPE_CLOSED_STATUS_GUMP (anti spam)
|
|
2009/09/03 MuadDib: Relocation of account related cpp/h
|
|
2009/09/03 MuadDib: Relocation of multi related cpp/h
|
|
|
|
Notes
|
|
=======
|
|
|
|
*/
|
|
|
|
#include "clib/stl_inc.h"
|
|
|
|
/* MISCMSG.CPP: Miscellaneous message handlers. Handlers shouldn't stay here long,
|
|
only until they find a better home - but this is better than putting them in POL.CPP. */
|
|
|
|
#include <stddef.h>
|
|
|
|
#include "clib/clib.h"
|
|
#include "clib/endian.h"
|
|
#include "clib/fdump.h"
|
|
#include "clib/logfile.h"
|
|
#include "clib/strutil.h"
|
|
|
|
#include "clib/stlutil.h"
|
|
|
|
#include "accounts/account.h"
|
|
#include "charactr.h"
|
|
#include "client.h"
|
|
#include "cmbtcfg.h"
|
|
#include "multi/customhouses.h"
|
|
#include "fnsearch.h"
|
|
#include "msghandl.h"
|
|
#include "multi/multi.h"
|
|
#include "pktboth.h"
|
|
#include "pktin.h"
|
|
#include "spells.h"
|
|
#include "tooltips.h"
|
|
#include "uvars.h"
|
|
#include "ufunc.h"
|
|
#include "sockio.h"
|
|
|
|
#include "ssopt.h"
|
|
#include "scrstore.h"
|
|
#include "polcfg.h"
|
|
|
|
void handle_unknown_packet( Client* client );
|
|
void character_race_changer_handler( Client* client, PKTBI_BF* msg );
|
|
void party_cmd_handler( Client* client, PKTBI_BF* msg );
|
|
|
|
void OnGuildButton( Client* client );
|
|
void OnQuestButton( Client* client );
|
|
void OnChatButton( Client* client );
|
|
|
|
void handle_bulletin_boards( Client* client, PKTBI_71* msg )
|
|
{
|
|
handle_unknown_packet( client );
|
|
}
|
|
MESSAGE_HANDLER_VARLEN( PKTBI_71, handle_bulletin_boards );
|
|
|
|
void handle_mode_set( Client *client, PKTBI_72 *msg )
|
|
{
|
|
if ( client->chr->warmode_wait > read_gameclock() )
|
|
{
|
|
send_move( client, client->chr );
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
client->chr->warmode_wait = read_gameclock() + combat_config.warmode_delay;
|
|
}
|
|
|
|
bool msg_warmode = msg->warmode ? true : false;
|
|
|
|
// FIXME: Should reply with 0x77 packet!? (so says various docs!) [TJ]
|
|
transmit( client, msg, sizeof *msg );
|
|
|
|
client->chr->set_warmode( msg_warmode );
|
|
}
|
|
MESSAGE_HANDLER( PKTBI_72, handle_mode_set );
|
|
|
|
void handle_rename_char( Client* client, PKTIN_75* msg )
|
|
{
|
|
Character* chr = find_character( cfBEu32( msg->serial ));
|
|
if (chr != NULL)
|
|
{
|
|
if (client->chr->can_rename( chr ))
|
|
{
|
|
msg->name[ sizeof msg->name-1 ] = '\0';
|
|
// check for legal characters
|
|
for( char* p = msg->name; *p; p++ )
|
|
{
|
|
// only allow: a-z, A-Z & spaces
|
|
if ( *p != ' ' && !isalpha(*p) )
|
|
{
|
|
char buffer[512];
|
|
sprintf(buffer, "Client #%lu (account %s) attempted an invalid rename (packet 0x%2.02x):",
|
|
client->instance_,
|
|
(client->acct != NULL) ? client->acct->name() : "unknown",
|
|
msg->msgtype);
|
|
cout << buffer << endl;
|
|
fdump( stdout, msg->name, static_cast<int>(strlen(msg->name)) );
|
|
|
|
if (logfile)
|
|
{
|
|
Log("%s\n", buffer);
|
|
fdump( logfile, msg->name, static_cast<int>(strlen(msg->name)) );
|
|
}
|
|
|
|
*p = '\0';
|
|
send_sysmessage( client, "Invalid name!" );
|
|
return; //dave 12/26 if invalid name, do not apply to chr!
|
|
}
|
|
}
|
|
chr->setname( msg->name );
|
|
}
|
|
else
|
|
{
|
|
send_sysmessage( client, "I can't rename that." );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
send_sysmessage( client, "I can't find that." );
|
|
}
|
|
}
|
|
MESSAGE_HANDLER( PKTIN_75, handle_rename_char );
|
|
|
|
void handle_msg_B5( Client* client, PKTIN_B5* msg )
|
|
{
|
|
OnChatButton( client );
|
|
}
|
|
MESSAGE_HANDLER( PKTIN_B5, handle_msg_B5 );
|
|
|
|
void handle_msg_B8( Client* client, PKTBI_B8* msg )
|
|
{
|
|
handle_unknown_packet( client );
|
|
}
|
|
MESSAGE_HANDLER_VARLEN( PKTBI_B8, handle_msg_B8 );
|
|
|
|
void handle_msg_BB( Client* client, PKTBI_BB* msg )
|
|
{
|
|
handle_unknown_packet( client );
|
|
}
|
|
MESSAGE_HANDLER( PKTBI_BB, handle_msg_BB );
|
|
|
|
void handle_client_version( Client* client, PKTBI_BD* msg )
|
|
{
|
|
u16 len = cfBEu16(msg->msglen)-3;
|
|
if (len < 100)
|
|
{
|
|
int c=0;
|
|
char ch;
|
|
string ver2 ="";
|
|
while (c<len)
|
|
{
|
|
ch = msg->version[c];
|
|
if (ch==0) break; // seems to be null-terminated
|
|
ver2+=ch;
|
|
++c;
|
|
}
|
|
client->setversion( ver2 );
|
|
|
|
VersionDetailStruct vers_det;
|
|
client->itemizeclientversion(ver2, vers_det);
|
|
client->setversiondetail(vers_det);
|
|
|
|
if (client->compareVersion(CLIENT_VER_60171)) //Grid-loc support
|
|
client->is_greq_6017=true;
|
|
send_season_info( client ); // Scott 10/11/2007 added for login fixes and handling 1.x clients.
|
|
// Season info needs to check client version to keep from crashing 1.x
|
|
// version not set until shortly after login complete.
|
|
//send_feature_enable(client); //dave commented out 8/21/03, unexpected problems with people sending B9 via script with this too.
|
|
if( (client->UOExpansionFlag & AOS) )
|
|
{
|
|
send_object_cache(client, dynamic_cast<const UObject*>(client->chr));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Log2( "Suspect string length in PKTBI_BD packet: %u\n", (unsigned) len );
|
|
}
|
|
}
|
|
MESSAGE_HANDLER_VARLEN( PKTBI_BD, handle_client_version );
|
|
|
|
void ext_stats_in (Client* client, PKTBI_BF* msg)
|
|
{
|
|
if (ssopt.core_handled_locks) {
|
|
const Attribute *attrib = NULL;
|
|
switch (msg->extstatin.stat) {
|
|
case PKTBI_BF_1A::STAT_STR:
|
|
attrib = pAttrStrength;
|
|
break;
|
|
case PKTBI_BF_1A::STAT_DEX:
|
|
attrib = pAttrDexterity;
|
|
break;
|
|
case PKTBI_BF_1A::STAT_INT:
|
|
attrib = pAttrIntelligence;
|
|
break;
|
|
default: // sent an illegal stat. Should report to console?
|
|
return;
|
|
}
|
|
|
|
if (attrib == NULL) // there's no attribute for this (?)
|
|
return;
|
|
|
|
u8 state = msg->extstatin.mode;
|
|
if (state > 2) // FIXME hard-coded value
|
|
return;
|
|
|
|
client->chr->attribute(attrib->attrid).lock(state);
|
|
}
|
|
}
|
|
|
|
void handle_msg_BF( Client* client, PKTBI_BF* msg )
|
|
{
|
|
UObject* obj = NULL;
|
|
UMulti* multi = NULL;
|
|
UHouse* house = NULL;
|
|
switch(cfBEu16(msg->subcmd))
|
|
{
|
|
case PKTBI_BF::TYPE_CLIENT_LANGUAGE:
|
|
client->chr->uclang = strlower(msg->client_lang);
|
|
break;
|
|
case PKTBI_BF::TYPE_REQ_FULL_CUSTOM_HOUSE:
|
|
if( (client->UOExpansionFlag & AOS) == 0 )
|
|
return;
|
|
multi = system_find_multi(cfBEu32(msg->reqfullcustomhouse.house_serial));
|
|
if(multi != NULL)
|
|
{
|
|
house = multi->as_house();
|
|
if(house != NULL)
|
|
{
|
|
if(client->UOExpansionFlag & AOS)
|
|
{
|
|
send_object_cache(client, (UObject*)(house));
|
|
}
|
|
//consider sending working design to certain players, to assist building, or GM help
|
|
CustomHousesSendFull( house, client, HOUSE_DESIGN_CURRENT );
|
|
}
|
|
}
|
|
break;
|
|
case PKTBI_BF::TYPE_OBJECT_CACHE:
|
|
if( (client->UOExpansionFlag & AOS) == 0)
|
|
return;
|
|
obj = system_find_object(cfBEu32(msg->objectcache.serial));
|
|
if(obj != NULL)
|
|
{
|
|
SendAOSTooltip(client,obj);
|
|
}
|
|
break;
|
|
case PKTBI_BF::TYPE_SESPAM:
|
|
return;
|
|
break;
|
|
case PKTBI_BF::TYPE_SPELL_SELECT:
|
|
do_cast(client, cfBEu16(msg->spellselect.selected_spell) );
|
|
break;
|
|
case PKTBI_BF::TYPE_CHARACTER_RACE_CHANGER:
|
|
character_race_changer_handler( client, msg );
|
|
break;
|
|
case PKTBI_BF::TYPE_PARTY_SYSTEM:
|
|
party_cmd_handler( client, msg );
|
|
break;
|
|
case PKTBI_BF::TYPE_EXTENDED_STATS_IN:
|
|
ext_stats_in(client, msg);
|
|
break;
|
|
case PKTBI_BF::TYPE_CLOSED_STATUS_GUMP:
|
|
return;
|
|
break;
|
|
case PKTBI_BF::TYPE_SCREEN_SIZE:
|
|
return;
|
|
break;
|
|
default:
|
|
handle_unknown_packet( client );
|
|
}
|
|
}
|
|
MESSAGE_HANDLER_VARLEN( PKTBI_BF, handle_msg_BF );
|
|
|
|
void handle_unknown_C4( Client* client, PKTOUT_C4* msg )
|
|
{
|
|
handle_unknown_packet( client );
|
|
}
|
|
MESSAGE_HANDLER( PKTOUT_C4, handle_unknown_C4 );
|
|
|
|
void handle_update_range_change( Client* client, PKTBI_C8* msg )
|
|
{
|
|
handle_unknown_packet( client );
|
|
}
|
|
MESSAGE_HANDLER( PKTBI_C8, handle_update_range_change );
|
|
|
|
void handle_allnames( Client *client, PKTBI_98_IN *msg )
|
|
{
|
|
|
|
u32 serial = cfBEu32( msg->serial );
|
|
Character *the_mob = find_character( serial );
|
|
if (the_mob != NULL)
|
|
{
|
|
if (!client->chr->is_visible_to_me(the_mob)) {
|
|
return;
|
|
}
|
|
if (pol_distance(client->chr->x, client->chr->y, the_mob->x, the_mob->y) > 20) {
|
|
return;
|
|
}
|
|
|
|
PKTBI_98_OUT allnames;
|
|
allnames.msgtype = PKTBI_98_OUT_ID;
|
|
allnames.msglen = ctBEu16(0x25); // 0x25 = 37. Static Length.
|
|
allnames.serial = the_mob->serial_ext;
|
|
strzcpy( allnames.name, the_mob->name().c_str(), sizeof allnames.name );
|
|
transmit( client, &allnames, sizeof allnames );
|
|
|
|
}
|
|
else
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
MESSAGE_HANDLER( PKTBI_98_IN, handle_allnames );
|
|
|
|
void handle_se_object_list( Client* client, PKTBI_D6_IN* msgin )
|
|
{
|
|
UObject* obj = NULL;
|
|
int length=cfBEu16(msgin->msglen)-3;
|
|
if ( length < 0 || (length%4) != 0 )
|
|
return;
|
|
int count = length/4;
|
|
|
|
for( int i = 0; i < count; ++i )
|
|
{
|
|
obj = system_find_object(cfBEu32( msgin->serials[i].serial ));
|
|
if (obj != NULL)
|
|
SendAOSTooltip(client,obj);
|
|
}
|
|
}
|
|
MESSAGE_HANDLER_VARLEN( PKTBI_D6_IN, handle_se_object_list );
|
|
|
|
void handle_ef_seed( Client *client, PKTIN_EF *msg )
|
|
{
|
|
VersionDetailStruct detail;
|
|
detail.major=cfBEu32(msg->ver_Major);
|
|
detail.minor=cfBEu32(msg->ver_Minor);
|
|
detail.rev=cfBEu32(msg->ver_Revision);
|
|
detail.patch=cfBEu32(msg->ver_Patch);
|
|
client->setversiondetail(detail);
|
|
if (client->compareVersion(CLIENT_VER_60171)) //Grid-loc support
|
|
client->is_greq_6017=true;
|
|
|
|
// detail->patch is since 5.0.7 always numeric, so no need to make it complicated
|
|
OSTRINGSTREAM os;
|
|
os << detail.major << "." << detail.minor << "." << detail.rev << "." << detail.patch;
|
|
client->setversion(OSTRINGSTREAM_STR(os));
|
|
}
|
|
MESSAGE_HANDLER( PKTIN_EF, handle_ef_seed );
|
|
|
|
void handle_aos_commands (Client *client, PKTBI_D7* msg)
|
|
{
|
|
//cout <<" Sizeof: " << sizeof(PKTBI_D7) << endl;
|
|
//cout << "Received AOS command: " << cfBEu16(msg->msglen) << " " << cfBEu16(msg->subcmd) << endl;
|
|
//fdump (stdout, client->buffer, client->bytes_received);
|
|
|
|
//should check if serial is valid? client->chr->serial == msg->serial?
|
|
|
|
switch (cfBEu16(msg->subcmd)) {
|
|
case PKTBI_D7::CUSTOM_HOUSE_BACKUP:
|
|
CustomHousesBackup(msg);
|
|
break;
|
|
|
|
case PKTBI_D7::CUSTOM_HOUSE_RESTORE:
|
|
CustomHousesRestore(msg);
|
|
break;
|
|
|
|
case PKTBI_D7::CUSTOM_HOUSE_COMMIT:
|
|
CustomHousesCommit(msg);
|
|
break;
|
|
|
|
case PKTBI_D7::CUSTOM_HOUSE_ERASE:
|
|
CustomHousesErase(msg);
|
|
break;
|
|
|
|
case PKTBI_D7::CUSTOM_HOUSE_ADD:
|
|
CustomHousesAdd(msg);
|
|
break;
|
|
|
|
case PKTBI_D7::CUSTOM_HOUSE_QUIT:
|
|
CustomHousesQuit(msg);
|
|
break;
|
|
|
|
case PKTBI_D7::CUSTOM_HOUSE_ADD_MULTI:
|
|
CustomHousesAddMulti(msg);
|
|
break;
|
|
|
|
case PKTBI_D7::CUSTOM_HOUSE_SYNCH:
|
|
CustomHousesSynch(msg);
|
|
break;
|
|
|
|
case PKTBI_D7::CUSTOM_HOUSE_CLEAR:
|
|
CustomHousesClear(msg);
|
|
break;
|
|
|
|
case PKTBI_D7::CUSTOM_HOUSE_SELECT_FLOOR:
|
|
CustomHousesSelectFloor(msg);
|
|
break;
|
|
|
|
case PKTBI_D7::CUSTOM_HOUSE_REVERT:
|
|
CustomHousesRevert(msg);
|
|
break;
|
|
case PKTBI_D7::GUILD_BUTTON:
|
|
OnGuildButton(client);
|
|
break;
|
|
case PKTBI_D7::QUEST_BUTTON:
|
|
OnQuestButton(client);
|
|
break;
|
|
//missing combat book abilities
|
|
default:
|
|
handle_unknown_packet(client);
|
|
}
|
|
}
|
|
MESSAGE_HANDLER_VARLEN( PKTBI_D7, handle_aos_commands );
|
|
|
|
void OnGuildButton(Client* client)
|
|
{
|
|
ref_ptr<EScriptProgram> prog = find_script( "misc/guildbutton",
|
|
true,
|
|
config.cache_interactive_scripts );
|
|
if (prog.get() != NULL)
|
|
{
|
|
client->chr->start_script( prog.get(), false );
|
|
}
|
|
}
|
|
|
|
void OnQuestButton(Client* client)
|
|
{
|
|
ref_ptr<EScriptProgram> prog = find_script( "misc/questbutton",
|
|
true,
|
|
config.cache_interactive_scripts );
|
|
if (prog.get() != NULL)
|
|
{
|
|
client->chr->start_script( prog.get(), false );
|
|
}
|
|
}
|
|
|
|
void OnChatButton(Client* client)
|
|
{
|
|
ref_ptr<EScriptProgram> prog = find_script( "misc/chatbutton",
|
|
true,
|
|
config.cache_interactive_scripts );
|
|
if (prog.get() != NULL)
|
|
{
|
|
client->chr->start_script( prog.get(), false );
|
|
}
|
|
}
|
|
|