• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

polserver / polserver / 21100551564

17 Jan 2026 08:40PM UTC coverage: 60.504% (+0.01%) from 60.492%
21100551564

Pull #857

github

turleypol
fixed scope
Pull Request #857: ClangTidy readability-else-after-return

837 of 1874 new or added lines in 151 files covered. (44.66%)

48 existing lines in 26 files now uncovered.

44445 of 73458 relevant lines covered (60.5%)

515341.61 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

18.98
/pol-core/pol/miscmsg.cpp
1
/** @file
2
 *
3
 * @par History
4
 * - 2005/11/25 MuadDib:   Added PKTBI_BF::TYPE_SESPAM: to do away with spam.
5
 * - 2005/11/23 MuadDib:   Altered handle_mode_set for 0x72 Packet. Nows reads
6
 *                         from combat.cfg for warmode_wait object. Sends the
7
 *                         0x77 Packet and returns 0 when out of timer.
8
 * - 2005/12/09 MuadDib:   Added TYPE_CLIENT_LANGUAGE for setting member uclang.
9
 * - 2006/05/24 Shinigami: Added PKTBI_BF::TYPE_CHARACTER_RACE_CHANGER to support Elfs
10
 * - 2006/05/30 Shinigami: Changed params of character_race_changer_handler()
11
 * - 2009/07/23 MuadDib:   updates for new Enum::Packet IDs
12
 * - 2009/08/14 Turley:    Added PKTBI_BF::TYPE_SCREEN_SIZE & TYPE_CLOSED_STATUS_GUMP (anti spam)
13
 * - 2009/09/03 MuadDib:   Relocation of account related cpp/h
14
 * - 2009/09/03 MuadDib:   Relocation of multi related cpp/h
15
 * - 2009/09/06 Turley:    Changed Version checks to bitfield client->ClientType
16
 *                         Added 0xE1 packet (UO3D clienttype packet)
17
 * - 2009/11/19 Turley:    ssopt.core_sends_season & .core_handled_tags - Tomi
18
 * - 2009/12/03 Turley:    toggle gargoyle flying support
19
 */
20

21

22
/* MISCMSG.CPP: Miscellaneous message handlers.  Handlers shouldn't stay here long,
23
   only until they find a better home - but this is better than putting them in POL.CPP. */
24

25
#include <algorithm>
26
#include <cstddef>
27
#include <ctype.h>
28
#include <iterator>
29
#include <string>
30

31
#include "../bscript/eprog.h"
32
#include "../bscript/impstr.h"
33
#include "../clib/clib_endian.h"
34
#include "../clib/fdump.h"
35
#include "../clib/logfacility.h"
36
#include "../clib/rawtypes.h"
37
#include "../clib/refptr.h"
38
#include "../clib/stlutil.h"
39
#include "../plib/systemstate.h"
40
#include "../plib/uconst.h"
41
#include "accounts/account.h"
42
#include "cmbtcfg.h"
43
#include "fnsearch.h"
44
#include "gameclck.h"
45
#include "globals/settings.h"
46
#include "globals/uvars.h"
47
#include "guilds.h"
48
#include "mobile/attribute.h"
49
#include "mobile/charactr.h"
50
#include "module/uomod.h"
51
#include "multi/customhouses.h"
52
#include "multi/multi.h"
53
#include "network/cgdata.h"
54
#include "network/client.h"
55
#include "network/clientio.h"
56
#include "network/packethelper.h"
57
#include "network/packets.h"
58
#include "network/pktboth.h"
59
#include "network/pktdef.h"
60
#include "network/pktin.h"
61
#include "network/sockio.h"
62
#include "party.h"
63
#include "polclass.h"
64
#include "realms/realm.h"
65
#include "scrstore.h"
66
#include "spells.h"
67
#include "systems/suspiciousacts.h"
68
#include "tooltips.h"
69
#include "ufunc.h"
70
#include "uobject.h"
71
#include "uoexec.h"
72
#include "uoscrobj.h"
73

74

75
namespace Pol
76
{
77
namespace Module
78
{
79
void character_race_changer_handler( Network::Client* client, Core::PKTBI_BF* msg );
80
}
81
namespace Core
82
{
83
using namespace Network;
84

85
void handle_unknown_packet( Network::ThreadedClient* session );
86
void handle_unknown_packet( Network::Client* client )
×
87
{
88
  handle_unknown_packet( client->session() );
×
89
}
×
90

91
void party_cmd_handler( Client* client, PKTBI_BF* msg );
92

93
void OnGuildButton( Client* client );
94
void OnQuestButton( Client* client );
95
void OnChatButton( Client* client );
96

97
void handle_bulletin_boards( Client* client, PKTBI_71* /*msg*/ )
×
98
{
99
  handle_unknown_packet( client );
×
100
}
×
101

102
void handle_mode_set( Client* client, PKTBI_72* msg )
×
103
{
104
  if ( client->chr->warmode_wait > read_gameclock() )
×
105
  {
106
    send_move( client, client->chr );
×
107
    return;
×
108
  }
109

NEW
110
  client->chr->warmode_wait = read_gameclock() + settingsManager.combat_config.warmode_delay;
×
111

112

113
  bool msg_warmode = msg->warmode ? true : false;
×
114

115
  // FIXME: Should reply with 0x77 packet!? (so says various docs!) [TJ]
116
  transmit( client, msg, sizeof *msg );
×
117

118
  client->chr->set_warmode( msg_warmode );
×
119
}
120

121
void handle_keep_alive( Network::Client* client, PKTBI_73* msg )
4✔
122
{
123
  transmit( client, msg, sizeof *msg );
4✔
124
}
4✔
125

126
void handle_rename_char( Client* client, PKTIN_75* msg )
×
127
{
128
  Mobile::Character* chr = find_character( cfBEu32( msg->serial ) );
×
129
  if ( chr != nullptr )
×
130
  {
131
    if ( client->chr->can_rename( chr ) )
×
132
    {
133
      msg->name[sizeof msg->name - 1] = '\0';
×
134
      // check for legal characters
135
      for ( char* p = msg->name; *p; p++ )
×
136
      {
137
        // only allow: a-z, A-Z & spaces
138
        if ( *p != ' ' && !isalpha( *p ) )
×
139
        {
140
          std::string tmp = fmt::format(
141
              "Client#{} (account {}) attempted an invalid rename (packet {:#x}):\n{}",
142
              client->instance_, ( client->acct != nullptr ) ? client->acct->name() : "unknown",
×
143
              (int)msg->msgtype, msg->name );
×
144
          Clib::fdump( std::back_inserter( tmp ), msg->name,
×
145
                       static_cast<int>( strlen( msg->name ) ) );
×
146
          POLLOG_INFOLN( tmp );
×
147
          *p = '\0';
×
148
          send_sysmessage( client, "Invalid name!" );
×
149
          return;  // dave 12/26 if invalid name, do not apply to chr!
×
150
        }
×
151
      }
152
      chr->setname( msg->name );
×
153
    }
154
    else
155
    {
156
      send_sysmessage( client, "I can't rename that." );
×
157
    }
158
  }
159
  else
160
  {
161
    send_sysmessage( client, "I can't find that." );
×
162
  }
163
}
164

165
void handle_msg_B5( Client* client, PKTIN_B5* /*msg*/ )
×
166
{
167
  OnChatButton( client );
×
168
}
×
169

170
void handle_char_profile_request( Client* client, PKTBI_B8_IN* msg )
×
171
{
172
  ref_ptr<Bscript::EScriptProgram> prog =
173
      find_script( "misc/charprofile", true, Plib::systemstate.config.cache_interactive_scripts );
×
174
  if ( prog.get() != nullptr )
×
175
  {
176
    Mobile::Character* mobile;
177

178
    if ( msg->mode == msg->MODE_REQUEST )
×
179
    {
180
      mobile = system_find_mobile( cfBEu32( msg->profile_request.serial ) );
×
181
      if ( mobile == nullptr )
×
182
        return;
×
183
      client->chr->start_script( prog.get(), false, new Module::ECharacterRefObjImp( mobile ),
×
184
                                 new Bscript::BLong( msg->mode ), new Bscript::BLong( 0 ) );
×
185
    }
186
    else if ( msg->mode == msg->MODE_UPDATE )
×
187
    {
188
      mobile = system_find_mobile( cfBEu32( msg->profile_update.serial ) );
×
189
      if ( mobile == nullptr )
×
190
        return;
×
191
      u16* themsg = msg->profile_update.wtext;
×
192
      int intextlen = ( cfBEu16( msg->msglen ) - 12 ) / sizeof( msg->profile_update.wtext[0] );
×
193

194
      if ( intextlen < 0 )
×
195
        intextlen = 0;
×
196
      if ( intextlen > SPEECH_MAX_LEN )
×
197
        intextlen = SPEECH_MAX_LEN;
×
198
      std::string text = Bscript::String::fromUTF16( themsg, intextlen, true );
×
199
      client->chr->start_script( prog.get(), false, new Module::ECharacterRefObjImp( mobile ),
×
200
                                 new Bscript::BLong( msg->mode ), new Bscript::String( text ) );
×
201
    }
×
202
  }
203
}
×
204

205
void handle_msg_BB( Client* client, PKTBI_BB* /*msg*/ )
×
206
{
207
  handle_unknown_packet( client );
×
208
}
×
209

210
void handle_client_version( Client* client, PKTBI_BD* msg )
2✔
211
{
212
  u16 len = cfBEu16( msg->msglen ) - 3;
2✔
213
  if ( len < 100 )
2✔
214
  {
215
    int c = 0;
2✔
216
    char ch;
217
    std::string ver2 = "";
2✔
218
    while ( c < len )
16✔
219
    {
220
      ch = msg->version[c];
16✔
221
      if ( ch == 0 )
16✔
222
        break;  // seems to be null-terminated
2✔
223
      ver2 += ch;
14✔
224
      ++c;
14✔
225
    }
226
    client->setversion( ver2 );
2✔
227

228
    VersionDetailStruct vers_det;
229
    client->itemizeclientversion( ver2, vers_det );
2✔
230
    client->setversiondetail( vers_det );
2✔
231

232
    if ( client->compareVersion( CLIENT_VER_70331 ) )
2✔
233
      client->setClientType( CLIENTTYPE_70331 );
×
234
    else if ( client->compareVersion( CLIENT_VER_70300 ) )
2✔
235
      client->setClientType( CLIENTTYPE_70300 );
×
236
    else if ( client->compareVersion( CLIENT_VER_70130 ) )
2✔
237
      client->setClientType( CLIENTTYPE_70130 );
×
238
    else if ( client->compareVersion( CLIENT_VER_7090 ) )
2✔
239
      client->setClientType( CLIENTTYPE_7090 );
2✔
240
    else if ( client->compareVersion( CLIENT_VER_7000 ) )
×
241
      client->setClientType( CLIENTTYPE_7000 );
×
242
    else if ( client->compareVersion( CLIENT_VER_60142 ) )
×
243
      client->setClientType( CLIENTTYPE_60142 );
×
244
    else if ( client->compareVersion( CLIENT_VER_6017 ) )  // Grid-loc support
×
245
      client->setClientType( CLIENTTYPE_6017 );
×
246
    else if ( client->compareVersion( CLIENT_VER_5020 ) )
×
247
      client->setClientType( CLIENTTYPE_5020 );
×
248
    else if ( client->compareVersion( CLIENT_VER_5000 ) )
×
249
      client->setClientType( CLIENTTYPE_5000 );
×
250
    else if ( client->compareVersion( CLIENT_VER_4070 ) )
×
251
      client->setClientType( CLIENTTYPE_4070 );
×
252
    else if ( client->compareVersion( CLIENT_VER_4000 ) )
×
253
      client->setClientType( CLIENTTYPE_4000 );
×
254

255
    if ( settingsManager.ssopt.core_sends_season )
2✔
256
      send_season_info(
2✔
257
          client );  // Scott 10/11/2007 added for login fixes and handling 1.x clients.
258
                     // Season info needs to check client version to keep from crashing 1.x
259
                     // version not set until shortly after login complete.
260
    // send_feature_enable(client); //dave commented out 8/21/03, unexpected problems with people
261
    // sending B9 via script with this too.
262
    if ( client->acctSupports( Plib::ExpansionVersion::AOS ) )
2✔
263
    {
264
      send_object_cache( client, client->chr );
2✔
265
    }
266
  }
2✔
267
  else
268
  {
269
    POLLOG_INFOLN( "Suspect string length in PKTBI_BD packet: {}", len );
×
270
  }
271
}
2✔
272

273
void ext_stats_in( Client* client, PKTBI_BF* msg )
×
274
{
275
  if ( settingsManager.ssopt.core_handled_locks )
×
276
  {
277
    const Mobile::Attribute* attrib = nullptr;
×
278
    switch ( msg->extstatin.stat )
×
279
    {
280
    case PKTBI_BF_1A::STAT_STR:
×
281
      attrib = gamestate.pAttrStrength;
×
282
      break;
×
283
    case PKTBI_BF_1A::STAT_DEX:
×
284
      attrib = gamestate.pAttrDexterity;
×
285
      break;
×
286
    case PKTBI_BF_1A::STAT_INT:
×
287
      attrib = gamestate.pAttrIntelligence;
×
288
      break;
×
289
    default:  // sent an illegal stat. Should report to console?
×
290
      return;
×
291
    }
292

293
    if ( attrib == nullptr )  // there's no attribute for this (?)
×
294
      return;
×
295

296
    u8 state = msg->extstatin.mode;
×
297
    if ( state > 2 )  // FIXME hard-coded value
×
298
      return;
×
299

300
    client->chr->attribute( attrib->attrid ).lock( state );
×
301
  }
302
}
303

304
void handle_msg_BF( Client* client, PKTBI_BF* msg )
8✔
305
{
306
  UObject* obj = nullptr;
8✔
307
  Multi::UMulti* multi = nullptr;
8✔
308
  Multi::UHouse* house = nullptr;
8✔
309
  switch ( cfBEu16( msg->subcmd ) )
8✔
310
  {
311
  case PKTBI_BF::TYPE_CLIENT_LANGUAGE:
2✔
312
    client->chr->uclang = Clib::strlowerASCII( msg->client_lang );
2✔
313
    break;
2✔
314
  case PKTBI_BF::TYPE_REQ_FULL_CUSTOM_HOUSE:
×
315
    if ( !client->acctSupports( Plib::ExpansionVersion::AOS ) )
×
316
      return;
×
317
    multi = system_find_multi( cfBEu32( msg->reqfullcustomhouse.house_serial ) );
×
318
    if ( multi != nullptr )
×
319
    {
320
      house = multi->as_house();
×
321
      if ( house != nullptr )
×
322
      {
323
        if ( client->acctSupports( Plib::ExpansionVersion::AOS ) )
×
324
        {
325
          send_object_cache( client, (UObject*)( house ) );
×
326
        }
327
        // consider sending working design to certain players, to assist building, or GM help
328
        CustomHousesSendFull( house, client, Multi::HOUSE_DESIGN_CURRENT );
×
329
      }
330
    }
331
    break;
×
332
  case PKTBI_BF::TYPE_OBJECT_CACHE:
1✔
333
    if ( !client->acctSupports( Plib::ExpansionVersion::AOS ) )
1✔
334
      return;
×
335
    obj = system_find_object( cfBEu32( msg->objectcache.serial ) );
1✔
336
    if ( obj != nullptr )
1✔
337
    {
338
      SendAOSTooltip( client, obj );
1✔
339
    }
340
    break;
1✔
341
  case PKTBI_BF::TYPE_SESPAM:
×
342
    return;
×
343
    break;
344
  case PKTBI_BF::TYPE_SPELL_SELECT:
×
345
    do_cast( client, cfBEu16( msg->spellselect.selected_spell ) );
×
346
    break;
×
347
  case PKTBI_BF::TYPE_CHARACTER_RACE_CHANGER:
×
348
    Module::character_race_changer_handler( client, msg );
×
349
    break;
×
350
  case PKTBI_BF::TYPE_PARTY_SYSTEM:
×
351
    party_cmd_handler( client, msg );
×
352
    break;
×
353
  case PKTBI_BF::TYPE_EXTENDED_STATS_IN:
×
354
    ext_stats_in( client, msg );
×
355
    break;
×
356
  case PKTBI_BF::TYPE_CLOSED_STATUS_GUMP:
×
357
    return;
×
358
    break;
359
  case PKTBI_BF::TYPE_SCREEN_SIZE:
×
360
    return;
×
361
    break;
362
  case PKTBI_BF::TYPE_TOGGLE_FLYING:
×
363
    if ( client->chr->race == Plib::RACE_GARGOYLE )
×
364
    {
365
      // FIXME: add checks if its possible to stand with new movemode
366
      client->chr->movemode = ( Plib::MOVEMODE )( client->chr->movemode ^ Plib::MOVEMODE_FLY );
×
367
      send_move_mobile_to_nearby_cansee( client->chr );
×
368
      send_goxyz( client, client->chr );
×
369
    }
370
    break;
×
371
  case PKTBI_BF::TYPE_CLIENTTYPE:
2✔
372
    client->UOExpansionFlagClient = ctBEu32( msg->clienttype.clientflag );
2✔
373
    break;
2✔
374
  case PKTBI_BF::TYPE_POPUP_MENU_REQUEST:
×
375
  {
376
    ref_ptr<Bscript::EScriptProgram> prog =
377
        find_script( "misc/popupmenu", true, Plib::systemstate.config.cache_interactive_scripts );
×
378
    if ( prog.get() == nullptr )
×
379
      break;
×
380
    u32 serial = cfBEu32( msg->serial_request_popup_menu );
×
381
    if ( IsCharacter( serial ) )
×
382
    {
383
      Pol::Mobile::Character* chr = system_find_mobile( serial );
×
384
      if ( chr == nullptr )
×
385
        break;
×
386
      client->chr->start_script( prog.get(), false, new Pol::Module::ECharacterRefObjImp( chr ) );
×
387
    }
388
    else
389
    {
390
      Pol::Items::Item* item = system_find_item( serial );
×
391
      if ( item == nullptr )
×
392
        break;
×
393
      client->chr->start_script( prog.get(), false, item->make_ref() );
×
394
    }
395
    break;
×
396
  }
×
397
  case PKTBI_BF::TYPE_POPUP_ENTRY_SELECT:
×
398
  {
399
    if ( client->gd->on_popup_menu_selection == nullptr )
×
400
    {
401
      POLLOG_INFOLN( "{}/{} tried to use a popup menu, but none was active.", client->acct->name(),
×
402
                     client->chr->name() );
×
403
      break;
×
404
    }
405

406
    u32 serial = cfBEu32( msg->popupselect.serial );
×
407
    u16 id = cfBEu16( msg->popupselect.entry_tag );
×
408
    client->gd->on_popup_menu_selection( client, serial, id );
×
409
    break;
×
410
  }
411
  case PKTBI_BF::TYPE_BOAT_MOVE:
3✔
412
  {
413
    Mobile::Character* chr = client->chr;
3✔
414
    multi = chr->realm()->find_supporting_multi( client->chr->pos3d() );
3✔
415

416
    if ( multi == nullptr )
3✔
417
    {
418
      SuspiciousActs::BoatMoveNoMulti( client );
×
419
      break;
×
420
    }
421

422
    if ( !multi->script_isa( Core::POLCLASS_BOAT ) )
3✔
423
    {
424
      SuspiciousActs::BoatMoveNotBoatMulti( client );
×
425
      break;
×
426
    }
427

428
    Multi::UBoat* boat = static_cast<Multi::UBoat*>( multi );
3✔
429
    if ( boat->pilot() != chr )
3✔
430
    {
431
      SuspiciousActs::BoatMoveNotPilot( client, multi->serial );
×
432
      break;
×
433
    }
434

435
    if ( msg->boatmove.direction > 7 || msg->boatmove.speed > 2 )
3✔
436
    {
437
      SuspiciousActs::BoatMoveOutOfRangeParameters( client, multi->serial, msg->boatmove.direction,
×
438
                                                    msg->boatmove.speed );
×
439
      break;
×
440
    }
441

442
    Module::UOExecutorModule* process = multi->process();
3✔
443
    if ( !process )
3✔
444
    {
445
      break;
×
446
    }
447

448
    auto relative_direction =
449
        static_cast<Core::UFACING>( ( msg->boatmove.direction - boat->boat_facing() + 8 ) & 7 );
3✔
450

451
    process->uoexec().signal_event( new Module::BoatMovementEvent(
6✔
452
        chr, msg->boatmove.speed, msg->boatmove.direction, relative_direction ) );
3✔
453

454
    break;
3✔
455
  }
456
  default:
×
457
    handle_unknown_packet( client );
×
458
  }
459
}
460

461
void handle_unknown_C4( Client* client, PKTOUT_C4* /*msg*/ )
×
462
{
463
  handle_unknown_packet( client );
×
464
}
×
465

466
void handle_update_range_change( Client* client, PKTBI_C8* msg )
2✔
467
{
468
  client->set_update_range_by_client( msg->range );
2✔
469
}
2✔
470

471
void handle_krrios_packet( Client* client, PKTBI_F0* msg )
×
472
{
473
  auto* me = client->chr;
×
474
  switch ( msg->subcmd )
×
475
  {
476
  case PKTBI_F0::QUERY_PARTY:
×
477
  {
478
    if ( !settingsManager.ssopt.enable_worldmap_packets )
×
479
      break;
×
480

481
    if ( me->has_party() )
×
482
    {
483
      Party* party = me->party();
×
484
      Network::PktHelper::PacketOut<Network::PktOut_F0_Sub01> outMsg;
×
485
      outMsg->offset += 2;                              // len
×
486
      outMsg->Write<u8>( PKTBI_F0::QUERY_PARTY + 1U );  // sub, response is +1
×
487
      for ( auto member : party->get_members() )
×
488
      {
489
        if ( member->serial == me->serial )
×
490
          continue;
×
491

492
        if ( me->is_visible_to_me( member ) )
×
493
          continue;
×
494

495
        outMsg->Write<u32>( member->serial_ext );
×
496
        outMsg->WriteFlipped<u16>( member->x() );
×
497
        outMsg->WriteFlipped<u16>( member->y() );
×
498
        outMsg->Write<u8>( member->realm()->getUOMapID() );
×
499
      }
×
500

501
      if ( outMsg->offset != 4 )  // only send if there is an update
×
502
      {
503
        outMsg->Write<u32>( 0U );  // end of list marker
×
504
        u16 len = outMsg->offset;
×
505
        outMsg->offset = 1;
×
506
        outMsg->WriteFlipped<u16>( len );
×
507
        outMsg.Send( client, len );
×
508
      }
509
    }
×
510
    break;
×
511
  }
512
  case PKTBI_F0::QUERY_GUILD:
×
513
  {
514
    if ( !settingsManager.ssopt.enable_worldmap_packets )
×
515
      break;
×
516

517
    Guild* guild = me->guild();
×
518
    u8 locations = msg->query_guild.include_locations > 0 ? 1U : 0U;
×
519
    if ( guild != nullptr )
×
520
    {
521
      Network::PktHelper::PacketOut<Network::PktOut_F0_Sub02> outMsg;
×
522
      outMsg->offset += 2;                              // len
×
523
      outMsg->Write<u8>( PKTBI_F0::QUERY_GUILD + 1U );  // sub, response is +1
×
524
      outMsg->Write<u8>( locations );
×
525
      for ( auto member : guild->get_members() )
×
526
      {
527
        if ( member->serial == me->serial )
×
528
          continue;
×
529

530
        if ( locations && me->is_visible_to_me( member ) )
×
531
          continue;
×
532

533
        outMsg->Write<u32>( member->serial_ext );
×
534
        if ( locations )
×
535
        {
536
          outMsg->WriteFlipped<u16>( member->x() );
×
537
          outMsg->WriteFlipped<u16>( member->y() );
×
538
          outMsg->Write<u8>( member->realm()->getUOMapID() );
×
539

540
          if ( member->dead() )
×
541
            outMsg->Write<u8>( 0U );
×
542
          else
543
          {
544
            int current = member->vital( networkManager.uoclient_general.hits.id ).current_ones();
×
545
            int max = member->vital( networkManager.uoclient_general.hits.id ).maximum_ones();
×
546
            u8 ratio = static_cast<u8>( 100 * current / ( max < 1 ? 1 : max ) );
×
547
            outMsg->Write<u8>( ratio );  // hits
×
548
          }
549
        }
550
      }
×
551
      if ( outMsg->offset != 5 )  // only send if there is an update
×
552
      {
553
        outMsg->Write<u32>( 0U );  // end of list marker
×
554
        u16 len = outMsg->offset;
×
555
        outMsg->offset = 1;
×
556
        outMsg->WriteFlipped<u16>( len );
×
557
        outMsg.Send( client, len );
×
558
      }
559
    }
×
560
    break;
×
561
  }
562
  default:
×
563
    handle_unknown_packet( client );
×
564
    break;
×
565
  }
566
}
×
567

568
void handle_open_uo_store( Client* client, PKTIN_FA* /*msg*/ )
×
569
{
570
  handle_unknown_packet( client );
×
571
}
×
572

573
void handle_update_view_public_house_content( Client* client, PKTIN_FB* /*msg*/ )
×
574
{
575
  handle_unknown_packet( client );
×
576
}
×
577

578
void handle_allnames( Client* client, PKTBI_98_IN* msg )
×
579
{
580
  u32 serial = cfBEu32( msg->serial );
×
581
  Mobile::Character* the_mob = find_character( serial );
×
582
  if ( the_mob == nullptr )
×
583
    return;
×
584
  if ( !client->chr->is_visible_to_me( the_mob ) )
×
585
    return;
×
586

587
  PktHelper::PacketOut<PktOut_98> msgOut;
×
588
  msgOut->WriteFlipped<u16>( 37u );  // static length
×
589
  msgOut->Write<u32>( the_mob->serial_ext );
×
590
  msgOut->Write( Clib::strUtf8ToCp1252( the_mob->name() ).c_str(), 30, false );
×
591
  msgOut.Send( client );
×
592
}
×
593

594
void handle_se_object_list( Client* client, PKTBI_D6_IN* msgin )
4✔
595
{
596
  UObject* obj = nullptr;
4✔
597
  int length = cfBEu16( msgin->msglen ) - 3;
4✔
598
  if ( length < 0 || ( length % 4 ) != 0 )
4✔
599
    return;
×
600
  int count = length / 4;
4✔
601

602
  for ( int i = 0; i < count; ++i )
8✔
603
  {
604
    obj = system_find_object( cfBEu32( msgin->serials[i].serial ) );
4✔
605
    if ( obj != nullptr )
4✔
606
      SendAOSTooltip( client, obj );
4✔
607
  }
608
}
609

610
void handle_ef_seed( Client* client, PKTIN_EF* msg )
2✔
611
{
612
  VersionDetailStruct detail;
613
  detail.major = cfBEu32( msg->ver_Major );
2✔
614
  detail.minor = cfBEu32( msg->ver_Minor );
2✔
615
  detail.rev = cfBEu32( msg->ver_Revision );
2✔
616
  detail.patch = cfBEu32( msg->ver_Patch );
2✔
617
  client->setversiondetail( detail );
2✔
618
  if ( client->compareVersion( CLIENT_VER_70331 ) )
2✔
619
    client->setClientType( CLIENTTYPE_70331 );
×
620
  else if ( client->compareVersion( CLIENT_VER_70300 ) )
2✔
621
    client->setClientType( CLIENTTYPE_70300 );
×
622
  else if ( client->compareVersion( CLIENT_VER_70130 ) )
2✔
623
    client->setClientType( CLIENTTYPE_70130 );
×
624
  else if ( client->compareVersion( CLIENT_VER_7090 ) )
2✔
625
    client->setClientType( CLIENTTYPE_7090 );
2✔
626
  else if ( client->compareVersion( CLIENT_VER_7000 ) )
×
627
    client->setClientType( CLIENTTYPE_7000 );
×
628
  else if ( client->compareVersion( CLIENT_VER_60142 ) )
×
629
    client->setClientType( CLIENTTYPE_60142 );
×
630
  else if ( client->compareVersion( CLIENT_VER_6017 ) )  // Grid-loc support
×
631
    client->setClientType( CLIENTTYPE_6017 );
×
632
  else if ( client->compareVersion( CLIENT_VER_5020 ) )
×
633
    client->setClientType( CLIENTTYPE_5020 );
×
634
  else if ( client->compareVersion( CLIENT_VER_5000 ) )
×
635
    client->setClientType( CLIENTTYPE_5000 );
×
636
  else if ( client->compareVersion( CLIENT_VER_4070 ) )
×
637
    client->setClientType( CLIENTTYPE_4070 );
×
638
  else if ( client->compareVersion( CLIENT_VER_4000 ) )
×
639
    client->setClientType( CLIENTTYPE_4000 );
×
640

641
  // detail->patch is since 5.0.7 always numeric, so no need to make it complicated
642
  OSTRINGSTREAM os;
2✔
643
  os << detail.major << "." << detail.minor << "." << detail.rev << "." << detail.patch;
2✔
644
  client->setversion( OSTRINGSTREAM_STR( os ) );
2✔
645
}
2✔
646

647
void handle_e1_clienttype( Client* client, PKTIN_E1* msg )
×
648
{
649
  switch ( cfBEu32( msg->clienttype ) )
×
650
  {
651
  case PKTIN_E1::CLIENTTYPE_KR:
×
652
    client->setClientType( CLIENTTYPE_UOKR );
×
653
    break;
×
654
  case PKTIN_E1::CLIENTTYPE_SA:
×
655
    client->setClientType( CLIENTTYPE_UOSA );
×
656
    break;
×
657
  default:
×
658
    INFO_PRINTLN( "Unknown client type send with packet 0xE1 : {:#x}",
×
659
                  static_cast<unsigned long>( cfBEu32( msg->clienttype ) ) );
×
660
    break;
×
661
  }
662
}
×
663

664

665
/**
666
 * Handler for a 0xD7 packet
667
 */
668
void handle_aos_commands( Client* client, PKTBI_D7* msg )
×
669
{
670
  // nullptr prevention, no need to disturb if client or character is not found
671
  if ( client == nullptr || client->chr == nullptr )
×
672
    return;
×
673

674
  /// Checks that serial written inside packet matches sending character's serial
675
  u32 serial = cfBEu32( msg->serial );
×
676
  if ( client && client->chr && client->chr->serial != serial )
×
677
  {
678
    INFO_PRINTLN( "Ignoring spoofed packet 0xD7 from character {:#x} trying to spoof {:#x}",
×
679
                  client->chr->serial, serial );
×
680
    return;
×
681
  }
682

683
  switch ( cfBEu16( msg->subcmd ) )
×
684
  {
685
  case PKTBI_D7::CUSTOM_HOUSE_BACKUP:
×
686
    Multi::CustomHousesBackup( msg );
×
687
    break;
×
688

689
  case PKTBI_D7::CUSTOM_HOUSE_RESTORE:
×
690
    Multi::CustomHousesRestore( msg );
×
691
    break;
×
692

693
  case PKTBI_D7::CUSTOM_HOUSE_COMMIT:
×
694
    Multi::CustomHousesCommit( msg );
×
695
    break;
×
696

697
  case PKTBI_D7::CUSTOM_HOUSE_ERASE:
×
698
    Multi::CustomHousesErase( msg );
×
699
    break;
×
700

701
  case PKTBI_D7::CUSTOM_HOUSE_ADD:
×
702
    Multi::CustomHousesAdd( msg );
×
703
    break;
×
704

705
  case PKTBI_D7::CUSTOM_HOUSE_QUIT:
×
706
    Multi::CustomHousesQuit( msg );
×
707
    break;
×
708

709
  case PKTBI_D7::CUSTOM_HOUSE_ADD_MULTI:
×
710
    Multi::CustomHousesAddMulti( msg );
×
711
    break;
×
712

713
  case PKTBI_D7::CUSTOM_HOUSE_SYNCH:
×
714
    Multi::CustomHousesSynch( msg );
×
715
    break;
×
716

717
  case PKTBI_D7::CUSTOM_HOUSE_CLEAR:
×
718
    Multi::CustomHousesClear( msg );
×
719
    break;
×
720

721
  case PKTBI_D7::CUSTOM_HOUSE_SELECT_FLOOR:
×
722
    Multi::CustomHousesSelectFloor( msg );
×
723
    break;
×
724

725
  case PKTBI_D7::CUSTOM_HOUSE_REVERT:
×
726
    Multi::CustomHousesRevert( msg );
×
727
    break;
×
728
  case PKTBI_D7::CUSTOM_HOUSE_SELECT_ROOF:
×
729
    Multi::CustomHousesRoofSelect( msg );
×
730
    break;
×
731
  case PKTBI_D7::CUSTOM_HOUSE_DELETE_ROOF:
×
732
    Multi::CustomHousesRoofRemove( msg );
×
733
    break;
×
734
  case PKTBI_D7::GUILD_BUTTON:
×
735
    OnGuildButton( client );
×
736
    break;
×
737
  case PKTBI_D7::QUEST_BUTTON:
×
738
    OnQuestButton( client );
×
739
    break;
×
740
  // missing combat book abilities
741
  default:
×
742
    handle_unknown_packet( client );
×
743
  }
744
}
745

746
void OnGuildButton( Client* client )
×
747
{
748
  ref_ptr<Bscript::EScriptProgram> prog =
749
      find_script( "misc/guildbutton", true, Plib::systemstate.config.cache_interactive_scripts );
×
750
  if ( prog.get() != nullptr )
×
751
  {
752
    client->chr->start_script( prog.get(), false );
×
753
  }
754
}
×
755

756
void OnQuestButton( Client* client )
×
757
{
758
  ref_ptr<Bscript::EScriptProgram> prog =
759
      find_script( "misc/questbutton", true, Plib::systemstate.config.cache_interactive_scripts );
×
760
  if ( prog.get() != nullptr )
×
761
  {
762
    client->chr->start_script( prog.get(), false );
×
763
  }
764
}
×
765

766
void OnChatButton( Client* client )
×
767
{
768
  ref_ptr<Bscript::EScriptProgram> prog =
769
      find_script( "misc/chatbutton", true, Plib::systemstate.config.cache_interactive_scripts );
×
770
  if ( prog.get() != nullptr )
×
771
  {
772
    client->chr->start_script( prog.get(), false );
×
773
  }
774
}
×
775
}  // namespace Core
776
}  // namespace Pol
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc