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

polserver / polserver / 21108840797

18 Jan 2026 08:35AM UTC coverage: 60.508% (+0.02%) from 60.492%
21108840797

push

github

web-flow
ClangTidy readability-else-after-return (#857)

* trigger tidy

* Automated clang-tidy change: readability-else-after-return

* compile test

* rerun

* Automated clang-tidy change: readability-else-after-return

* trigger..

* Automated clang-tidy change: readability-else-after-return

* manually removed a few

* Automated clang-tidy change: readability-else-after-return

* removed duplicate code

* fix remaining warnings

* fixed scope

---------

Co-authored-by: Clang Tidy <clang-tidy@users.noreply.github.com>

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

46 existing lines in 25 files now uncovered.

44448 of 73458 relevant lines covered (60.51%)

525066.38 hits per line

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

66.28
/pol-core/pol/uimport.cpp
1
/** @file
2
 *
3
 * @par History
4
 * - 2005/01/23 Shinigami: for_all_mobiles, write_items & write_multis - Tokuno MapDimension doesn't
5
 * fit blocks of 64x64 (WGRID_SIZE)
6
 * - 2007/06/17 Shinigami: added config.world_data_path
7
 * - 2009/09/03 MuadDib:   Relocation of account related cpp/h
8
 *                         Relocation of multi related cpp/h
9
 * - 2009/09/14 MuadDib:   All UOX3 Import Code commented out. You can script this.
10
 * - 2009/12/02 Turley:    added config.max_tile_id - Tomi
11
 * - 2011/11/28 MuadDib:   Removed last of uox referencing code.
12
 */
13

14
#include "uimport.h"
15

16
#include <atomic>
17
#include <cerrno>
18
#include <cstdio>
19
#include <cstring>
20
#include <exception>
21
#include <future>
22
#include <string>
23
#include <time.h>
24

25
#include "../clib/cfgelem.h"
26
#include "../clib/cfgfile.h"
27
#include "../clib/clib.h"
28
#include "../clib/clib_endian.h"
29
#include "../clib/fileutil.h"
30
#include "../clib/logfacility.h"
31
#include "../clib/passert.h"
32
#include "../clib/rawtypes.h"
33
#include "../clib/stlutil.h"
34
#include "../clib/threadhelp.h"
35
#include "../clib/timer.h"
36
#include "../plib/poltype.h"
37
#include "../plib/systemstate.h"
38
#include "containr.h"
39
#include "fnsearch.h"
40
#include "gameclck.h"
41
#include "globals/network.h"
42
#include "globals/object_storage.h"
43
#include "globals/settings.h"
44
#include "globals/state.h"
45
#include "globals/uvars.h"
46
#include "item/item.h"
47
#include "item/itemdesc.h"
48
#include "loaddata.h"
49
#include "mobile/charactr.h"
50
#include "mobile/npc.h"
51
#include "multi/house.h"
52
#include "multi/multi.h"
53
#include "objecthash.h"
54
#include "polvar.h"
55
#include "regions/resource.h"
56
#include "savedata.h"
57
#include "servdesc.h"
58
#include "startloc.h"
59
#include "storage.h"
60
#include "ufunc.h"
61
#include "uobject.h"
62
#include "uworld.h"
63

64
namespace Pol
65
{
66
namespace Module
67
{
68
void read_datastore_dat();
69
}  // namespace Module
70
namespace Plib
71
{
72
bool version_greater_or_equal( const std::string& version_have, const std::string& version_need );
73
bool version_equal( const std::string& version_have, const std::string& version_need );
74
}  // namespace Plib
75
namespace Core
76
{
77
void read_party_dat();
78
void read_guilds_dat();
79

80

81
/****************** POL Native Files *******************/
82
// Dave changed 3/8/3 to use objecthash
83
void read_character( Clib::ConfigElem& elem )
9✔
84
{
85
  CharacterRef chr( new Mobile::Character( elem.remove_ushort( "OBJTYPE" ) ) );
9✔
86

87
  try
88
  {
89
    // note chr->logged_in is true..
90
    chr->readProperties( elem );
9✔
91

92
    // Allows the realm to recognize this char as offline
93
    chr->realm()->add_mobile( *chr, Realms::WorldChangeReason::PlayerLoad );
9✔
94

95
    chr->clear_dirty();
9✔
96

97
    // readProperties gets the serial, so we can't add to the objecthash until now.
98
    objStorageManager.objecthash.Insert( chr.get() );
9✔
99
  }
100
  catch ( std::exception& )
×
101
  {
102
    if ( chr.get() != nullptr )
×
103
      chr->destroy();
×
104
    throw;
×
105
  }
×
106
}
9✔
107

108
// Dave changed 3/8/3 to use objecthash
109
void read_npc( Clib::ConfigElem& elem )
2✔
110
{
111
  NpcRef npc( new Mobile::NPC( elem.remove_ushort( "OBJTYPE" ), elem ) );
2✔
112

113
  try
114
  {
115
    npc->readProperties( elem );
2✔
116

117
    SetCharacterWorldPosition( npc.get(), Realms::WorldChangeReason::NpcLoad );
2✔
118
    npc->clear_dirty();
2✔
119

120
    ////HASH
121
    objStorageManager.objecthash.Insert( npc.get() );
2✔
122
    ////
123
  }
124
  catch ( std::exception& )
×
125
  {
126
    if ( npc.get() != nullptr )
×
127
      npc->destroy();
×
128
    throw;
×
129
  }
×
130
}
2✔
131

132
// hmm, an interesting idea, what if there was an
133
// Item::create( ConfigElem& elem ) member,
134
// which would do this?
135
// Item would need a constructor (ConfigElem&) also.
136
// Polymorphism would then take
137
// care of it, and move the logic into the derived
138
// classes.
139
Items::Item* read_item( Clib::ConfigElem& elem )
30✔
140
{
141
  u32 serial;
142
  u32 objtype;
143
  if ( elem.remove_prop( "SERIAL", &serial ) == false )
30✔
144
  {
145
    ERROR_PRINTLN( "Item element has no SERIAL property, omitting." );
×
146
    return nullptr;
×
147
  }
148

149
  if ( !IsItem( serial ) )
30✔
150
  {
151
    elem.warn_with_line(
×
152
        "Item element does not have an item serial\n(should be larger than 0x40000000)" );
153
    if ( Plib::systemstate.config.check_integrity )
×
154
    {
155
      throw std::runtime_error( "Data integrity error" );
×
156
    }
157
    return nullptr;
×
158
  }
159

160
  if ( Plib::systemstate.config.check_integrity )
30✔
161
  {
162
    if ( system_find_item( serial ) )
30✔
163
    {
164
      ERROR_PRINTLN( "Duplicate item read from datafiles (Serial={:#x})", serial );
×
165
      throw std::runtime_error( "Data integrity error" );
×
166
    }
167
  }
168
  if ( elem.remove_prop( "OBJTYPE", &objtype ) == false )
30✔
169
  {
170
    ERROR_PRINTLN( "Item (Serial {:#x}) has no OBJTYPE property, omitting.", serial );
×
171
    return nullptr;
×
172
  }
173
  if ( gamestate.old_objtype_conversions.count( objtype ) )
30✔
174
    objtype = gamestate.old_objtype_conversions[objtype];
×
175

176
  Items::Item* item = Items::Item::create( objtype, serial );
30✔
177
  if ( item == nullptr )
30✔
178
  {
179
    ERROR_PRINTLN( "Unable to create item: objtype={:#x}, serial={:#x}", objtype, serial );
×
180
    if ( !Plib::systemstate.config.ignore_load_errors )
×
181
      throw std::runtime_error( "Item::create failed!" );
×
NEW
182
    return nullptr;
×
183
  }
184
  item->setposition( Pos4d( item->pos().xyz(), find_realm( "britannia" ) ) );
30✔
185

186
  item->readProperties( elem );
30✔
187

188
  item->clear_dirty();
30✔
189

190
  return item;
30✔
191
}
192

193
#define USE_PARENT_CONTS 1
194

195
using ContStack = std::stack<UContainer*>;
196
static ContStack parent_conts;
197

198
void read_global_item( Clib::ConfigElem& elem, int /*sysfind_flags*/ )
24✔
199
{
200
  u32 container_serial = 0;  // defaults to item in the world's top-level
24✔
201
  (void)elem.remove_prop( "CONTAINER",
24✔
202
                          &container_serial );  // therefore we don't need to check the return value
203

204
  Items::Item* item = read_item( elem );
24✔
205
  // dave added 1/15/3, protect against further crash if item is null. Should throw instead?
206
  if ( item == nullptr )
24✔
207
  {
208
    elem.warn_with_line( "Error reading item SERIAL or OBJTYPE." );
×
209
    return;
×
210
  }
211

212
  ItemRef itemref( item );  // dave 1/28/3 prevent item from being destroyed before function ends
24✔
213
  if ( container_serial == 0 )
24✔
214
  {
215
    add_item_to_world( item );
23✔
216
    if ( item->isa( UOBJ_CLASS::CLASS_CONTAINER ) )
23✔
217
      parent_conts.push( static_cast<UContainer*>( item ) );
7✔
218
  }
219
  else
220
  {
221
    if ( IsCharacter( container_serial ) )  // it's equipped on a character
1✔
222
    {
223
      Mobile::Character* chr = system_find_mobile( container_serial );
×
224
      if ( chr != nullptr )
×
225
      {
226
        equip_loaded_item( chr, item );
×
227
      }
228
      else
229
      {
230
        defer_item_insertion( item, container_serial );
×
231
      }
232
      return;
×
233
    }
234
    Items::Item* cont_item = nullptr;
1✔
235
    // bool new_parent_cont = false;
236

237
    while ( !parent_conts.empty() )
1✔
238
    {
239
      UContainer* cont = parent_conts.top();
1✔
240
      if ( cont->serial == container_serial )
1✔
241
      {
242
        cont_item = cont;
1✔
243
        break;
1✔
244
      }
245

NEW
246
      parent_conts.pop();
×
247
    }
248

249
    if ( cont_item == nullptr )
1✔
250
    {
251
      cont_item = system_find_item( container_serial );
×
252
      // new_parent_cont = true;
253
    }
254

255
    if ( cont_item )
1✔
256
    {
257
      add_loaded_item( cont_item, item );
1✔
258
    }
259
    else
260
    {
261
      defer_item_insertion( item, container_serial );
×
262
    }
263
  }
264
}
24✔
265

266
void read_system_vars( Clib::ConfigElem& elem )
2✔
267
{
268
  settingsManager.polvar.DataWrittenBy = elem.remove_string( "CoreVersion" );
2✔
269
  settingsManager.polvar.DataWrittenBy99OrLater =
2✔
270
      Plib::version_greater_or_equal( settingsManager.polvar.DataWrittenBy, "99.0.0" );
2✔
271
  settingsManager.polvar.DataWrittenBy93 =
2✔
272
      Plib::version_equal( settingsManager.polvar.DataWrittenBy, "93.0.0" );
2✔
273
  stateManager.stored_last_item_serial =
2✔
274
      elem.remove_ulong( "LastItemSerialNumber", UINT_MAX );  // dave 3/9/3
2✔
275
  stateManager.stored_last_char_serial =
2✔
276
      elem.remove_ulong( "LastCharSerialNumber", UINT_MAX );  // dave 3/9/3
2✔
277
}
2✔
278

279
void read_realms( Clib::ConfigElem& elem )
3✔
280
{
281
  std::string name = elem.remove_string( "Name" );
3✔
282
  bool has_decay = elem.remove_bool( "HasDecay", true );
3✔
283
  if ( elem.has_prop( "BaseRealm" ) )
3✔
284
  {
285
    // this is shadow realm
286
    Realms::Realm* baserealm = find_realm( elem.remove_string( "BaseRealm" ) );
1✔
287
    if ( !baserealm )
1✔
288
      elem.warn_with_line( "BaseRealm not found." );
×
289
    else if ( defined_realm( name ) )
1✔
290
      elem.warn_with_line( "Realmname already defined" );
×
291
    else
292
    {
293
      add_realm( name, baserealm, has_decay );
1✔
294
      INFO_PRINTLN( "\nShadowrealm {}", name );
1✔
295
    }
296
  }
297
  else
298
  {
299
    // these are dynamic settings for base realm
300
    Realms::Realm* realm = find_realm( name );
2✔
301

302
    if ( !realm )
2✔
303
      elem.warn_with_line( "Realm not found." );
×
304
    else
305
      realm->has_decay = has_decay;
2✔
306
  }
307
}
3✔
308

309
void read_multi( Clib::ConfigElem& elem )
3✔
310
{
311
  pol_serial_t serial = 0;
3✔
312
  u32 objtype;
313
  if ( elem.remove_prop( "SERIAL", &serial ) == false )
3✔
314
  {
315
    ERROR_PRINTLN( "A Multi has no SERIAL property." );
×
316
    throw std::runtime_error( "Config File error." );
×
317
  }
318
  if ( system_find_multi( serial ) || system_find_item( serial ) )
3✔
319
  {
320
    ERROR_PRINTLN( "Duplicate item read from datafiles (Serial={:#x})", serial );
×
321
    throw std::runtime_error( "Data integrity error" );
×
322
  }
323
  if ( elem.remove_prop( "OBJTYPE", &objtype ) == false )
3✔
324
  {
325
    ERROR_PRINTLN( "Multi (Serial {:#x}) has no OBJTYPE property, omitting.", serial );
×
326
    return;
×
327
  }
328
  if ( gamestate.old_objtype_conversions.count( objtype ) )
3✔
329
    objtype = gamestate.old_objtype_conversions[objtype];
×
330

331
  Multi::UMulti* multi = Multi::UMulti::create( Items::find_itemdesc( objtype ), serial );
3✔
332
  if ( multi == nullptr )
3✔
333
  {
334
    ERROR_PRINTLN( "Unable to create multi: objtype={:#x}, serial={:#x}", objtype, serial );
×
335
    throw std::runtime_error( "Multi::create failed!" );
×
336
  }
337
  multi->readProperties( elem );
3✔
338

339
  add_multi_to_world( multi );
3✔
340
}
341

342
std::string elapsed( clock_t start, clock_t end )
×
343
{
344
  size_t ms = static_cast<size_t>( ( end - start ) * 1000.0 / CLOCKS_PER_SEC );
×
345
  return Clib::tostring( ms ) + " ms";
×
346
}
347

348
void slurp( const char* filename, const char* tags, int sysfind_flags )
16✔
349
{
350
  static int num_until_dot = 1000;
351

352
  if ( Clib::FileExists( filename ) )
16✔
353
  {
354
    INFO_PRINT( "  {}:", filename );
9✔
355
    Clib::ConfigFile cf( filename, tags );
9✔
356
    Clib::ConfigElem elem;
9✔
357

358
    Tools::Timer<> timer;
9✔
359

360
    unsigned int nobjects = 0;
9✔
361
    while ( cf.read( elem ) )
53✔
362
    {
363
      if ( --num_until_dot == 0 )
44✔
364
      {
365
        INFO_PRINT( "." );
×
366
        num_until_dot = 1000;
×
367
      }
368
      try
369
      {
370
        if ( stricmp( elem.type(), "CHARACTER" ) == 0 )
44✔
371
          read_character( elem );
9✔
372
        else if ( stricmp( elem.type(), "NPC" ) == 0 )
35✔
373
          read_npc( elem );
2✔
374
        else if ( stricmp( elem.type(), "ITEM" ) == 0 )
33✔
375
          read_global_item( elem, sysfind_flags );
24✔
376
        else if ( stricmp( elem.type(), "GLOBALPROPERTIES" ) == 0 )
9✔
377
          gamestate.global_properties->readProperties( elem );
1✔
378
        else if ( elem.type_is( "SYSTEM" ) )
8✔
379
          read_system_vars( elem );
2✔
380
        else if ( elem.type_is( "MULTI" ) )
6✔
381
          read_multi( elem );
3✔
382
        else if ( elem.type_is( "STORAGEAREA" ) )
3✔
383
        {
384
          StorageArea* storage_area = gamestate.storage.create_area( elem );
×
385
          // this will be followed by an item
386
          if ( !cf.read( elem ) )
×
387
            throw std::runtime_error( "Expected an item to exist after the storagearea." );
×
388

389
          storage_area->load_item( elem );
×
390
        }
391
        else if ( elem.type_is( "REALM" ) )
3✔
392
          read_realms( elem );
3✔
393
      }
394
      catch ( std::exception& )
×
395
      {
396
        if ( !Plib::systemstate.config.ignore_load_errors )
×
397
          throw;
×
398
      }
×
399
      ++nobjects;
44✔
400
    }
401

402
    timer.stop();
9✔
403

404
    INFO_PRINTLN( " {} elements in {} ms.", nobjects, timer.ellapsed() );
9✔
405
  }
9✔
406
}
16✔
407

408
void read_pol_dat()
2✔
409
{
410
  std::string polfile = Plib::systemstate.config.world_data_path + "pol.txt";
2✔
411

412
  slurp( polfile.c_str(), "GLOBALPROPERTIES SYSTEM REALM" );
2✔
413

414
  if ( settingsManager.polvar.DataWrittenBy.empty() )
2✔
415
  {
416
    ERROR_PRINTLN(
×
417
        "CoreVersion not found in {}\n"
418
        "\n"
419
        "{} must contain a section similar to: \n"
420
        "System\n"
421
        "{{\n"
422
        "\tCoreVersion 99\n"
423
        "}}\n"
424
        "\n"
425
        "Ensure that the CoreVersion matches the version that created your data files!",
426
        polfile, polfile );
427
    throw std::runtime_error( "Data file error" );
×
428
  }
429
}
2✔
430

431
void read_objects_dat()
2✔
432
{
433
  slurp( ( Plib::systemstate.config.world_data_path + "objects.txt" ).c_str(),
2✔
434
         "CHARACTER NPC ITEM GLOBALPROPERTIES" );
435
}
2✔
436

437
void read_pcs_dat()
2✔
438
{
439
  slurp( ( Plib::systemstate.config.world_data_path + "pcs.txt" ).c_str(), "CHARACTER ITEM",
2✔
440
         SYSFIND_SKIP_WORLD );
441
}
2✔
442

443
void read_pcequip_dat()
2✔
444
{
445
  slurp( ( Plib::systemstate.config.world_data_path + "pcequip.txt" ).c_str(), "ITEM",
2✔
446
         SYSFIND_SKIP_WORLD );
447
}
2✔
448

449
void read_npcs_dat()
2✔
450
{
451
  slurp( ( Plib::systemstate.config.world_data_path + "npcs.txt" ).c_str(), "NPC ITEM",
2✔
452
         SYSFIND_SKIP_WORLD );
453
}
2✔
454

455
void read_npcequip_dat()
2✔
456
{
457
  slurp( ( Plib::systemstate.config.world_data_path + "npcequip.txt" ).c_str(), "ITEM",
2✔
458
         SYSFIND_SKIP_WORLD );
459
}
2✔
460

461
void read_items_dat()
2✔
462
{
463
  slurp( ( Plib::systemstate.config.world_data_path + "items.txt" ).c_str(), "ITEM" );
2✔
464
}
2✔
465

466
void read_multis_dat()
2✔
467
{
468
  slurp( ( Plib::systemstate.config.world_data_path + "multis.txt" ).c_str(), "MULTI" );
2✔
469
  //  string multisfile = config.world_data_path + "multis.txt";
470
  //  if (FileExists( multisfile ))
471
  //  {
472
  //    cout << multisfile << ":";
473
  //    ConfigFile cf( multisfile, "MULTI" );
474
  //    ConfigElem elem;
475
  //    while( cf.read( elem ))
476
  //    {
477
  //      UMulti* multi = read_multi( elem );
478
  //      if (multi == nullptr) throw runtime_error( "multi creation returned nullptr!" );
479
  //
480
  //      add_multi_to_world( multi );
481
  //    }
482
  //  }
483
}
2✔
484

485
void read_storage_dat()
2✔
486
{
487
  std::string storagefile = Plib::systemstate.config.world_data_path + "storage.txt";
2✔
488

489
  if ( Clib::FileExists( storagefile ) )
2✔
490
  {
491
    INFO_PRINT( "  {}:", storagefile );
1✔
492
    Clib::ConfigFile cf2( storagefile );
1✔
493
    gamestate.storage.read( cf2 );
1✔
494
  }
1✔
495
}
2✔
496

497
Items::Item* find_existing_item( u32 objtype, const Pos4d& pos )
×
498
{
499
  Pos2d gridp = zone_convert( pos );
×
500
  for ( auto& item : pos.realm()->getzone_grid( gridp ).items )
×
501
  {
502
    // FIXME won't find doors which have been perturbed
503
    if ( item->objtype_ == objtype && item->pos() == pos )
×
504
    {
505
      return item;
×
506
    }
507
  }
508
  return nullptr;
×
509
}
510

511
int import_count;
512
int dupe_count;
513

514
void import( Clib::ConfigElem& elem )
×
515
{
516
  u32 objtype;
517
  objtype = elem.remove_unsigned( "OBJTYPE" );
×
518
  if ( objtype > Plib::systemstate.config.max_tile_id )
×
519
  {
520
    ERROR_PRINTLN( "Importing file: {:#x} is out of range.", objtype );
×
521
    throw std::runtime_error( "Error while importing file." );
×
522
  }
523

524
  Items::Item* item = Items::Item::create( objtype, 0x40000000 );  // dummy serial
×
525

526
  if ( item == nullptr )
×
527
  {
528
    ERROR_PRINTLN( "Unable to import item: objtype={:#x}", objtype );
×
529
    throw std::runtime_error( "Item::create failed!" );
×
530
  }
531

532
  item->readProperties( elem );
×
533

534
  if ( find_existing_item( item->objtype_, item->pos() ) )
×
535
  {
536
    item->destroy();
×
537
    ++dupe_count;
×
538
  }
539
  else
540
  {
541
    item->serial = GetNewItemSerialNumber();
×
542

543
    item->serial_ext = ctBEu32( item->serial );
×
544

545
    add_item_to_world( item );
×
546
    register_with_supporting_multi( item );
×
547
    ++import_count;
×
548
  }
549
}
×
550

551
void import_new_data()
2✔
552
{
553
  std::string importfile = Plib::systemstate.config.world_data_path + "import.txt";
2✔
554

555
  if ( Clib::FileExists( importfile ) )
2✔
556
  {
557
    Clib::ConfigFile cf( importfile, "ITEM" );
×
558
    Clib::ConfigElem elem;
×
559
    while ( cf.read( elem ) )
×
560
    {
561
      import( elem );
×
562
    }
563
    unlink( importfile.c_str() );
×
564
    INFO_PRINTLN( "Import Results: {} imported, {} duplicates.", import_count, dupe_count );
×
565
  }
×
566
}
2✔
567

568
void rndat( const std::string& basename )
24✔
569
{
570
  std::string datname = Plib::systemstate.config.world_data_path + basename + ".dat";
24✔
571
  std::string txtname = Plib::systemstate.config.world_data_path + basename + ".txt";
24✔
572

573
  if ( Clib::FileExists( datname.c_str() ) )
24✔
574
  {
575
    rename( datname.c_str(), txtname.c_str() );
×
576
  }
577
}
24✔
578

579
void rename_dat_files()
2✔
580
{
581
  rndat( "pol" );
2✔
582
  rndat( "objects" );
2✔
583
  rndat( "pcs" );
2✔
584
  rndat( "pcequip" );
2✔
585
  rndat( "npcs" );
2✔
586
  rndat( "npcequip" );
2✔
587
  rndat( "items" );
2✔
588
  rndat( "multis" );
2✔
589
  rndat( "storage" );
2✔
590
  rndat( "resource" );
2✔
591
  rndat( "guilds" );
2✔
592
  rndat( "parties" );
2✔
593
}
2✔
594

595
int read_data()
2✔
596
{
597
  std::string objectsndtfile = Plib::systemstate.config.world_data_path + "objects.ndt";
2✔
598
  std::string storagendtfile = Plib::systemstate.config.world_data_path + "storage.ndt";
2✔
599

600
  stateManager.gflag_in_system_load = true;
2✔
601
  if ( Clib::FileExists( objectsndtfile ) )
2✔
602
  {
603
    // Display reads "Reading data files..."
604
    ERROR_PRINTLN(
×
605
        "Error!\n"
606
        "'{} exists.  This probably means the system\n"
607
        "exited while writing its state.  To avoid loss of data,\n"
608
        "forcing human intervention.",
609
        objectsndtfile );
610
    throw std::runtime_error( "Human intervention required." );
×
611
  }
612
  if ( Clib::FileExists( storagendtfile ) )
2✔
613
  {
614
    ERROR_PRINTLN(
×
615
        "Error!\n"
616
        "'{} exists.  This probably means the system\n"
617
        "exited while writing its state.  To avoid loss of data,\n"
618
        "forcing human intervention.",
619
        storagendtfile );
620
    throw std::runtime_error( "Human intervention required." );
×
621
  }
622

623
  rename_dat_files();
2✔
624

625
  read_pol_dat();
2✔
626

627
  // POL clock should be paused at this point.
628
  start_gameclock();
2✔
629
  SaveContext::last_worldsave_success = read_gameclock();  // set last success to load time
2✔
630

631
  read_objects_dat();
2✔
632
  read_pcs_dat();
2✔
633
  read_pcequip_dat();
2✔
634
  read_npcs_dat();
2✔
635
  read_npcequip_dat();
2✔
636
  read_items_dat();
2✔
637
  read_multis_dat();
2✔
638
  read_storage_dat();
2✔
639
  read_resources_dat();
2✔
640
  read_guilds_dat();
2✔
641
  Module::read_datastore_dat();
2✔
642
  read_party_dat();
2✔
643

644
  insert_deferred_items();
2✔
645

646
  import_new_data();
2✔
647
  //  import_wsc();
648

649
  // dave 3/9/3
650
  if ( stateManager.stored_last_item_serial < GetCurrentItemSerialNumber() )
2✔
651
    SetCurrentItemSerialNumber( stateManager.stored_last_item_serial );
×
652
  if ( stateManager.stored_last_char_serial < GetCurrentCharSerialNumber() )
2✔
653
    SetCurrentCharSerialNumber( stateManager.stored_last_char_serial );
×
654

655
  while ( !parent_conts.empty() )
9✔
656
    parent_conts.pop();
7✔
657

658
  for ( ObjectHash::hs::const_iterator citr = objStorageManager.objecthash.begin(),
4✔
659
                                       citrend = objStorageManager.objecthash.end();
2✔
660
        citr != citrend; ++citr )
46✔
661
  {
662
    UObject* obj = ( *citr ).second.get();
44✔
663
    if ( obj->ismobile() )
44✔
664
    {
665
      Mobile::Character* chr = static_cast<Mobile::Character*>( obj );
11✔
666

667
      if ( chr->acct != nullptr )
11✔
668
        chr->logged_in( false );
9✔
669
    }
670
  }
671

672
  stateManager.gflag_in_system_load = false;
2✔
673
  return 0;
2✔
674
}
2✔
675

676
void read_starting_locations()
3✔
677
{
678
  Clib::ConfigFile cf( "config/startloc.cfg" );
3✔
679

680
  Clib::ConfigElem elem;
3✔
681
  while ( cf.read( elem ) )
30✔
682
  {
683
    if ( stricmp( elem.type(), "StartingLocation" ) != 0 )
27✔
684
    {
685
      ERROR_PRINTLN( "Unknown element type in startloc.cfg: {}", elem.type() );
×
686
      throw std::runtime_error( "Error in configuration file." );
×
687
    }
688

689
    std::unique_ptr<StartingLocation> loc( new StartingLocation );
27✔
690
    loc->city = elem.remove_string( "CITY" );
27✔
691
    loc->desc = elem.remove_string( "DESCRIPTION" );
27✔
692
    loc->mapid = elem.remove_ushort( "MAPID", 0 );
27✔
693
    loc->cliloc_desc = elem.remove_unsigned( "CLILOC", 1075072 );
27✔
694
    auto realmstr = elem.remove_string( "REALM", "britannia" );
27✔
695
    loc->realm = find_realm( realmstr );
27✔
696
    if ( !loc->realm )
27✔
697
    {
698
      ERROR_PRINTLN( "Unknown realm in startloc.cfg: '{}' for city {}, description {}", realmstr,
×
699
                     loc->city, loc->desc );
×
700
      throw std::runtime_error( "Configuration file error in startloc.cfg." );
×
701
    }
702
    std::string coord;
27✔
703
    while ( elem.remove_prop( "Coordinate", &coord ) )
54✔
704
    {
705
      int x, y, z;
706
      if ( sscanf( coord.c_str(), "%d,%d,%d", &x, &y, &z ) == 3 )
27✔
707
      {
708
        auto pos = Pos3d( Clib::clamp_convert<u16>( x ), Clib::clamp_convert<u16>( y ),
81✔
709
                          Clib::clamp_convert<s8>( z ) );
27✔
710
        pos.crop( loc->realm );
27✔
711
        loc->coords.emplace_back( std::move( pos ) );
27✔
712
      }
713
      else
714
      {
715
        ERROR_PRINTLN( "Poorly formed coordinate in startloc.cfg: '{}' for city {}, description {}",
×
716
                       coord, loc->city, loc->desc );
×
717
        throw std::runtime_error( "Configuration file error in startloc.cfg." );
×
718
      }
719
    }
720
    if ( loc->coords.empty() )
27✔
721
    {
722
      ERROR_PRINTLN( "STARTLOC.CFG: StartingLocation ({},{}) has no Coordinate properties.",
×
723
                     loc->city, loc->desc );
×
724
      throw std::runtime_error( "Configuration file error." );
×
725
    }
726
    gamestate.startlocations.push_back( loc.release() );
27✔
727
  }
27✔
728

729
  if ( gamestate.startlocations.empty() )
3✔
730
    throw std::runtime_error(
×
731
        "STARTLOC.CFG: No starting locations found.  Clients will crash on character creation." );
×
732
}
3✔
733

734
ServerDescription::ServerDescription() : name( "" ), port( 0 ), hostname( "" )
9✔
735
{
736
  memset( ip, 0, sizeof ip );
9✔
737
}
9✔
738

739
size_t ServerDescription::estimateSize() const
2✔
740
{
741
  size_t size = name.capacity() + 4 * sizeof( unsigned char ) /*ip*/
2✔
742
                + sizeof( unsigned short )                    /*port*/
743
                + Clib::memsize( ip_match ) + Clib::memsize( ip_match_mask ) +
2✔
744
                Clib::memsize( proxy_match ) + Clib::memsize( proxy_match_mask ) +
2✔
745
                hostname.capacity();
2✔
746
  for ( const auto& s : acct_match )
2✔
747
    size += s.capacity();
×
748
  return size;
2✔
749
}
750

751
void read_gameservers()
3✔
752
{
753
  std::string accttext;
3✔
754

755
  Clib::ConfigFile cf( "config/servers.cfg" );
3✔
756

757
  Clib::ConfigElem elem;
3✔
758
  while ( cf.read( elem ) )
12✔
759
  {
760
    if ( !elem.type_is( "GameServer" ) )
9✔
761
      continue;
3✔
762

763
    std::unique_ptr<ServerDescription> svr( new ServerDescription );
9✔
764

765
    svr->name = elem.remove_string( "NAME" );
9✔
766

767
    std::string iptext;
9✔
768
    int ip0, ip1, ip2, ip3;
769
    iptext = elem.remove_string( "IP" );
9✔
770
    if ( iptext == "--ip--" )
9✔
771
    {
772
      iptext = networkManager.ipaddr_str;
3✔
773
      if ( iptext.empty() )
3✔
774
      {
775
        INFO_PRINTLN( "Skipping server {} because there is no Internet IP address.", svr->name );
3✔
776
        continue;
3✔
777
      }
778
    }
779
    else if ( iptext == "--lan--" )
6✔
780
    {
781
      iptext = networkManager.lanaddr_str;
3✔
782
      if ( iptext.empty() )
3✔
783
      {
784
        INFO_PRINTLN( "Skipping server {} because there is no LAN IP address.", svr->name );
×
785
        continue;
×
786
      }
787
    }
788

789
    if ( isdigit( iptext[0] ) )
6✔
790
    {
791
      if ( sscanf( iptext.c_str(), "%d.%d.%d.%d", &ip0, &ip1, &ip2, &ip3 ) != 4 )
6✔
792
      {
793
        ERROR_PRINTLN( "SERVERS.CFG: Poorly formed IP ({}) for GameServer '{}'.", iptext,
×
794
                       svr->name );
×
795
        throw std::runtime_error( "Configuration file error." );
×
796
      }
797
      svr->ip[0] = static_cast<unsigned char>( ip3 );
6✔
798
      svr->ip[1] = static_cast<unsigned char>( ip2 );
6✔
799
      svr->ip[2] = static_cast<unsigned char>( ip1 );
6✔
800
      svr->ip[3] = static_cast<unsigned char>( ip0 );
6✔
801
    }
802
    else
803
    {
804
      svr->hostname = iptext;
×
805

806
#ifdef __linux__
807
      /* try to look up */
808
      struct hostent host_ret;
809
      struct hostent* host_result = nullptr;
×
810
      char tmp_buf[1024];
811
      int my_h_errno;
812
      int res = gethostbyname_r( svr->hostname.c_str(), &host_ret, tmp_buf, sizeof tmp_buf,
×
813
                                 &host_result, &my_h_errno );
814
      if ( res == 0 && host_result && host_result->h_addr_list[0] )
×
815
      {
816
        char* addr = host_result->h_addr_list[0];
×
817
        svr->ip[0] = addr[3];
×
818
        svr->ip[1] = addr[2];
×
819
        svr->ip[2] = addr[1];
×
820
        svr->ip[3] = addr[0];
×
821
        /*
822
                        struct sockaddr_in saddr;
823
                        memcpy( &saddr.sin_addr, he->h_addr_list[0], he->h_length);
824
                        server->ip[0] = saddr.sin_addr.S_un.S_un_b.s_b1;
825
                        server->ip[1] = saddr.sin_addr.S_un.S_un_b.s_b2;
826
                        server->ip[2] = saddr.sin_addr.S_un.S_un_b.s_b3;
827
                        server->ip[3] = saddr.sin_addr.S_un.S_un_b.s_b4;
828
                        */
829
      }
×
830
      else
831
      {
832
        POLLOG_ERRORLN( "Warning: gethostbyname_r failed for server {} ({}): {}", svr->name,
×
833
                        svr->hostname, my_h_errno );
×
834
      }
835
#endif
836
    }
837

838
    svr->port = elem.remove_ushort( "PORT" );
6✔
839

840
    while ( elem.remove_prop( "IPMATCH", &iptext ) )
12✔
841
    {
842
      auto delim = iptext.find_first_of( '/' );
6✔
843
      if ( delim != std::string::npos )
6✔
844
      {
845
        std::string ipaddr_str = iptext.substr( 0, delim );
3✔
846
        std::string ipmask_str = iptext.substr( delim + 1 );
3✔
847
        unsigned int ipaddr = inet_addr( ipaddr_str.c_str() );
3✔
848
        unsigned int ipmask = inet_addr( ipmask_str.c_str() );
3✔
849
        svr->ip_match.push_back( ipaddr );
3✔
850
        svr->ip_match_mask.push_back( ipmask );
3✔
851
      }
3✔
852
      else
853
      {
854
        unsigned int ipaddr = inet_addr( iptext.c_str() );
3✔
855
        svr->ip_match.push_back( ipaddr );
3✔
856
        svr->ip_match_mask.push_back( 0xFFffFFffLu );
3✔
857
      }
858
    }
859

860
    while ( elem.remove_prop( "PROXYMATCH", &iptext ) )
6✔
861
    {
862
      auto delim = iptext.find_first_of( '/' );
×
863
      if ( delim != std::string::npos )
×
864
      {
865
        std::string ipaddr_str = iptext.substr( 0, delim );
×
866
        std::string ipmask_str = iptext.substr( delim + 1 );
×
867
        unsigned int ipaddr = inet_addr( ipaddr_str.c_str() );
×
868
        unsigned int ipmask = inet_addr( ipmask_str.c_str() );
×
869
        svr->proxy_match.push_back( ipaddr );
×
870
        svr->proxy_match_mask.push_back( ipmask );
×
871
      }
×
872
      else
873
      {
874
        unsigned int ipaddr = inet_addr( iptext.c_str() );
×
875
        svr->proxy_match.push_back( ipaddr );
×
876
        svr->proxy_match_mask.push_back( 0xFFffFFffLu );
×
877
      }
878
    }
879

880
    while ( elem.remove_prop( "ACCTMATCH", &accttext ) )
6✔
881
    {
882
      svr->acct_match.push_back( accttext );
×
883
    }
884

885
    networkManager.servers.push_back( svr.release() );
6✔
886
  }
12✔
887
  if ( networkManager.servers.empty() )
3✔
888
    throw std::runtime_error( "There must be at least one GameServer in SERVERS.CFG." );
×
889
}
3✔
890
}  // namespace Core
891
}  // 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