Pol  Revision:cb584c9
uimport.cpp
Go to the documentation of this file.
1 
14 #include "uimport.h"
15 
16 #include <cerrno>
17 #include <cstdio>
18 #include <cstring>
19 #include <exception>
20 #include <future>
21 #include <string>
22 #include <time.h>
23 
24 #include "../clib/Program/ProgramConfig.h"
25 #include "../clib/cfgelem.h"
26 #include "../clib/cfgfile.h"
27 #include "../clib/clib.h"
28 #include "../clib/clib_endian.h"
29 #include "../clib/esignal.h"
30 #include "../clib/fileutil.h"
31 #include "../clib/logfacility.h"
32 #include "../clib/passert.h"
33 #include "../clib/rawtypes.h"
34 #include "../clib/threadhelp.h"
35 #include "../clib/timer.h"
36 #include "../plib/systemstate.h"
37 #include "accounts/accounts.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 "poltype.h"
55 #include "polvar.h"
56 #include "resource.h"
57 #include "savedata.h"
58 #include "servdesc.h"
59 #include "startloc.h"
60 #include "storage.h"
61 #include "ufunc.h"
62 #include "uobject.h"
63 #include "uworld.h"
64 
65 namespace Pol
66 {
67 namespace Module
68 {
69 void commit_datastore();
70 void read_datastore_dat();
71 void write_datastore( Clib::StreamWriter& sw );
72 }
73 namespace Core
74 {
75 void read_party_dat();
76 void write_party( Clib::StreamWriter& sw );
77 void read_guilds_dat();
78 void write_guilds( Clib::StreamWriter& sw );
79 
80 std::shared_future<bool> SaveContext::finished;
81 
82 /****************** POL Native Files *******************/
83 // Dave changed 3/8/3 to use objecthash
85 {
86  // if this object is modified in a subsequent incremental save,
87  // don't load it now.
88  pol_serial_t serial = 0;
89  elem.get_prop( "SERIAL", &serial );
91  return;
92 
93  CharacterRef chr( new Mobile::Character( elem.remove_ushort( "OBJTYPE" ) ) );
94 
95  try
96  {
97  // note chr->logged_in is true..
98  chr->readProperties( elem );
99 
100  // Allows the realm to recognize this char as offline
101  chr->realm->add_mobile( *chr, Realms::WorldChangeReason::PlayerLoad );
102 
103  chr->clear_dirty();
104 
105  // readProperties gets the serial, so we can't add to the objecthash until now.
106  objStorageManager.objecthash.Insert( chr.get() );
107  }
108  catch ( std::exception& )
109  {
110  if ( chr.get() != nullptr )
111  chr->destroy();
112  throw;
113  }
114 }
115 
116 // Dave changed 3/8/3 to use objecthash
118 {
119  // if this object is modified in a subsequent incremental save,
120  // don't load it now.
121  pol_serial_t serial = 0;
122  elem.get_prop( "SERIAL", &serial );
124  return;
125 
126  NpcRef npc( new Mobile::NPC( elem.remove_ushort( "OBJTYPE" ), elem ) );
127 
128  try
129  {
130  npc->readProperties( elem );
131 
133  npc->clear_dirty();
134 
138  }
139  catch ( std::exception& )
140  {
141  if ( npc.get() != nullptr )
142  npc->destroy();
143  throw;
144  }
145 }
146 
147 // hmm, an interesting idea, what if there was an
148 // Item::create( ConfigElem& elem ) member,
149 // which would do this?
150 // Item would need a constructor (ConfigElem&) also.
151 // Polymorphism would then take
152 // care of it, and move the logic into the derived
153 // classes.
155 {
156  u32 serial;
157  u32 objtype;
158  if ( elem.remove_prop( "SERIAL", &serial ) == false )
159  {
160  ERROR_PRINT << "Item element has no SERIAL property, omitting.\n";
161  return nullptr;
162  }
163 
164  if ( !IsItem( serial ) )
165  {
166  elem.warn_with_line(
167  "Item element does not have an item serial\n(should be larger than 0x40000000)" );
168  if ( Plib::systemstate.config.check_integrity )
169  {
170  throw std::runtime_error( "Data integrity error" );
171  }
172  return nullptr;
173  }
174 
175  if ( Plib::systemstate.config.check_integrity )
176  {
177  if ( system_find_item( serial ) )
178  {
179  ERROR_PRINT.Format( "Duplicate item read from datafiles (Serial=0x{:X})\n" ) << serial;
180  throw std::runtime_error( "Data integrity error" );
181  }
182  }
183  if ( elem.remove_prop( "OBJTYPE", &objtype ) == false )
184  {
185  ERROR_PRINT.Format( "Item (Serial 0x{:X}) has no OBJTYPE property, omitting." ) << serial;
186  return nullptr;
187  }
188  if ( gamestate.old_objtype_conversions.count( objtype ) )
189  objtype = gamestate.old_objtype_conversions[objtype];
190 
191  Items::Item* item = Items::Item::create( objtype, serial );
192  if ( item == nullptr )
193  {
194  ERROR_PRINT.Format( "Unable to create item: objtype=0x{:X}, serial=0x{:X}" )
195  << objtype << serial;
196  if ( !Plib::systemstate.config.ignore_load_errors )
197  throw std::runtime_error( "Item::create failed!" );
198  else
199  return nullptr;
200  }
201  item->realm = find_realm( "britannia" );
202 
203  item->readProperties( elem );
204 
205  item->clear_dirty();
206 
207  return item;
208 }
209 
210 #define USE_PARENT_CONTS 1
211 
212 typedef std::stack<UContainer*> ContStack;
213 static ContStack parent_conts;
214 
215 void read_global_item( Clib::ConfigElem& elem, int /*sysfind_flags*/ )
216 {
217  // if this object is modified in a subsequent incremental save,
218  // don't load it now.
219  pol_serial_t serial = 0;
220  elem.get_prop( "SERIAL", &serial );
222  return;
223 
224 
225  u32 container_serial = 0; // defaults to item in the world's top-level
226  (void)elem.remove_prop( "CONTAINER",
227  &container_serial ); // therefore we don't need to check the return value
228 
229  Items::Item* item = read_item( elem );
230  // dave added 1/15/3, protect against further crash if item is null. Should throw instead?
231  if ( item == nullptr )
232  {
233  elem.warn_with_line( "Error reading item SERIAL or OBJTYPE." );
234  return;
235  }
236 
237  ItemRef itemref( item ); // dave 1/28/3 prevent item from being destroyed before function ends
238  if ( container_serial == 0 )
239  {
240  add_item_to_world( item );
241  if ( item->isa( UOBJ_CLASS::CLASS_CONTAINER ) )
242  parent_conts.push( static_cast<UContainer*>( item ) );
243  }
244  else
245  {
246  if ( IsCharacter( container_serial ) ) // it's equipped on a character
247  {
248  Mobile::Character* chr = system_find_mobile( container_serial );
249  if ( chr != nullptr )
250  {
251  equip_loaded_item( chr, item );
252  }
253  else
254  {
255  defer_item_insertion( item, container_serial );
256  }
257  return;
258  }
259  Items::Item* cont_item = nullptr;
260  // bool new_parent_cont = false;
261 
262  while ( !parent_conts.empty() )
263  {
264  UContainer* cont = parent_conts.top();
265  if ( cont->serial == container_serial )
266  {
267  cont_item = cont;
268  break;
269  }
270  else
271  {
272  parent_conts.pop();
273  }
274  }
275 
276  if ( cont_item == nullptr )
277  {
278  cont_item = system_find_item( container_serial );
279  // new_parent_cont = true;
280  }
281 
282  if ( cont_item )
283  {
284  add_loaded_item( cont_item, item );
285  }
286  else
287  {
288  defer_item_insertion( item, container_serial );
289  }
290  }
291 }
292 
294 {
295  settingsManager.polvar.DataWrittenBy = elem.remove_ushort( "CoreVersion" );
297  elem.remove_ulong( "LastItemSerialNumber", UINT_MAX ); // dave 3/9/3
299  elem.remove_ulong( "LastCharSerialNumber", UINT_MAX ); // dave 3/9/3
300 }
301 
303 {
304  std::string name = elem.remove_string( "Name" );
305  Realms::Realm* baserealm = find_realm( elem.remove_string( "BaseRealm" ) );
306  if ( !baserealm )
307  elem.warn_with_line( "BaseRealm not found." );
308  else if ( defined_realm( name ) )
309  elem.warn_with_line( "Realmname already defined" );
310  else
311  {
312  add_realm( name, baserealm );
313  INFO_PRINT << "\nShadowrealm " << name << "\n";
314  }
315 }
316 
318 {
319  // if this object is modified in a subsequent incremental save,
320  // don't load it now.
321  pol_serial_t serial = 0;
322  elem.get_prop( "SERIAL", &serial );
324  return;
325 
326  u32 objtype;
327  if ( elem.remove_prop( "SERIAL", &serial ) == false )
328  {
329  ERROR_PRINT << "A Multi has no SERIAL property.\n";
330  throw std::runtime_error( "Config File error." );
331  }
332  if ( system_find_multi( serial ) || system_find_item( serial ) )
333  {
334  ERROR_PRINT.Format( "Duplicate item read from datafiles (Serial=0x{:X})\n" ) << serial;
335  throw std::runtime_error( "Data integrity error" );
336  }
337  if ( elem.remove_prop( "OBJTYPE", &objtype ) == false )
338  {
339  ERROR_PRINT.Format( "Multi (Serial 0x{:X}) has no OBJTYPE property, omitting." ) << serial;
340  return;
341  }
342  if ( gamestate.old_objtype_conversions.count( objtype ) )
343  objtype = gamestate.old_objtype_conversions[objtype];
344 
345  Multi::UMulti* multi = Multi::UMulti::create( Items::find_itemdesc( objtype ), serial );
346  if ( multi == nullptr )
347  {
348  ERROR_PRINT.Format( "Unable to create multi: objtype=0x{:X}, serial=0x{:X}\n" )
349  << objtype << serial;
350  throw std::runtime_error( "Multi::create failed!" );
351  }
352  multi->readProperties( elem );
353 
354  add_multi_to_world( multi );
355 }
356 
357 std::string elapsed( clock_t start, clock_t end )
358 {
359  size_t ms = static_cast<size_t>( ( end - start ) * 1000.0 / CLOCKS_PER_SEC );
360  return Clib::decint( ms ) + " ms";
361 }
362 
363 void slurp( const char* filename, const char* tags, int sysfind_flags )
364 {
365  static int num_until_dot = 1000;
366 
367  if ( Clib::FileExists( filename ) )
368  {
369  INFO_PRINT << " " << filename << ":";
370  Clib::ConfigFile cf( filename, tags );
371  Clib::ConfigElem elem;
372 
373  Tools::Timer<> timer;
374 
375  unsigned int nobjects = 0;
376  while ( cf.read( elem ) )
377  {
378  if ( --num_until_dot == 0 )
379  {
380  INFO_PRINT << ".";
381  num_until_dot = 1000;
382  }
383  try
384  {
385  if ( stricmp( elem.type(), "CHARACTER" ) == 0 )
386  read_character( elem );
387  else if ( stricmp( elem.type(), "NPC" ) == 0 )
388  read_npc( elem );
389  else if ( stricmp( elem.type(), "ITEM" ) == 0 )
390  read_global_item( elem, sysfind_flags );
391  else if ( stricmp( elem.type(), "GLOBALPROPERTIES" ) == 0 )
392  gamestate.global_properties->readProperties( elem );
393  else if ( elem.type_is( "SYSTEM" ) )
394  read_system_vars( elem );
395  else if ( elem.type_is( "MULTI" ) )
396  read_multi( elem );
397  else if ( elem.type_is( "STORAGEAREA" ) )
398  {
399  StorageArea* storage_area = gamestate.storage.create_area( elem );
400  // this will be followed by an item
401  if ( !cf.read( elem ) )
402  throw std::runtime_error( "Expected an item to exist after the storagearea." );
403 
404  storage_area->load_item( elem );
405  }
406  else if ( elem.type_is( "REALM" ) )
407  read_shadow_realms( elem );
408  }
409  catch ( std::exception& )
410  {
411  if ( !Plib::systemstate.config.ignore_load_errors )
412  throw;
413  }
414  ++nobjects;
415  }
416 
417  timer.stop();
418 
419  INFO_PRINT << " " << nobjects << " elements in " << timer.ellapsed() << " ms.\n";
420  }
421 }
422 
424 {
425  std::string polfile = Plib::systemstate.config.world_data_path + "pol.txt";
426 
427  slurp( polfile.c_str(), "GLOBALPROPERTIES SYSTEM REALM" );
428 
430  {
432  << "CoreVersion not found in " << polfile << "\n\n"
433  << polfile << " must contain a section similar to: \n"
434  << "System\n"
435  << "{\n"
436  << "\tCoreVersion 99\n"
437  << "}\n\n"
438  << "Ensure that the CoreVersion matches the version that created your data files!\n";
439  throw std::runtime_error( "Data file error" );
440  }
441 }
442 
444 {
445  slurp( ( Plib::systemstate.config.world_data_path + "objects.txt" ).c_str(),
446  "CHARACTER NPC ITEM GLOBALPROPERTIES" );
447 }
448 
450 {
451  slurp( ( Plib::systemstate.config.world_data_path + "pcs.txt" ).c_str(), "CHARACTER ITEM",
453 }
454 
456 {
457  slurp( ( Plib::systemstate.config.world_data_path + "pcequip.txt" ).c_str(), "ITEM",
459 }
460 
462 {
463  slurp( ( Plib::systemstate.config.world_data_path + "npcs.txt" ).c_str(), "NPC ITEM",
465 }
466 
468 {
469  slurp( ( Plib::systemstate.config.world_data_path + "npcequip.txt" ).c_str(), "ITEM",
471 }
472 
474 {
475  slurp( ( Plib::systemstate.config.world_data_path + "items.txt" ).c_str(), "ITEM" );
476 }
477 
479 {
480  slurp( ( Plib::systemstate.config.world_data_path + "multis.txt" ).c_str(), "MULTI" );
481  // string multisfile = config.world_data_path + "multis.txt";
482  // if (FileExists( multisfile ))
483  // {
484  // cout << multisfile << ":";
485  // ConfigFile cf( multisfile, "MULTI" );
486  // ConfigElem elem;
487  // while( cf.read( elem ))
488  // {
489  // UMulti* multi = read_multi( elem );
490  // if (multi == nullptr) throw runtime_error( "multi creation returned nullptr!" );
491  //
492  // add_multi_to_world( multi );
493  // }
494  // }
495 }
496 
498 {
499  std::string storagefile = Plib::systemstate.config.world_data_path + "storage.txt";
500 
501  if ( Clib::FileExists( storagefile ) )
502  {
503  INFO_PRINT << " " << storagefile << ":";
504  Clib::ConfigFile cf2( storagefile );
505  gamestate.storage.read( cf2 );
506  }
507 }
508 
510 {
511  unsigned short wx, wy;
512  zone_convert( x, y, &wx, &wy, realm );
513  for ( auto& item : realm->zone[wx][wy].items )
514  {
515  // FIXME won't find doors which have been perturbed
516  if ( item->objtype_ == objtype && item->x == x && item->y == y && item->z == z )
517  {
518  return item;
519  }
520  }
521  return nullptr;
522 }
523 
526 
527 void import( Clib::ConfigElem& elem )
528 {
529  u32 objtype;
530  objtype = elem.remove_unsigned( "OBJTYPE" );
531  if ( objtype > Plib::systemstate.config.max_tile_id )
532  {
533  ERROR_PRINT.Format( "Importing file: 0x{:X} is out of range.\n" ) << objtype;
534  throw std::runtime_error( "Error while importing file." );
535  }
536 
537  Items::Item* item = Items::Item::create( objtype, 0x40000000 ); // dummy serial
538 
539  if ( item == nullptr )
540  {
541  ERROR_PRINT.Format( "Unable to import item: objtype=0x{:X}\n" ) << objtype;
542  throw std::runtime_error( "Item::create failed!" );
543  }
544 
545  item->readProperties( elem );
546 
547  if ( find_existing_item( item->objtype_, item->x, item->y, item->z, item->realm ) )
548  {
549  item->destroy();
550  ++dupe_count;
551  }
552  else
553  {
554  item->serial = GetNewItemSerialNumber();
555 
556  item->serial_ext = ctBEu32( item->serial );
557 
558  add_item_to_world( item );
560  ++import_count;
561  }
562 }
563 
565 {
566  std::string importfile = Plib::systemstate.config.world_data_path + "import.txt";
567 
568  if ( Clib::FileExists( importfile ) )
569  {
570  Clib::ConfigFile cf( importfile, "ITEM" );
571  Clib::ConfigElem elem;
572  while ( cf.read( elem ) )
573  {
574  import( elem );
575  }
576  unlink( importfile.c_str() );
577  INFO_PRINT << "Import Results: " << import_count << " imported, " << dupe_count
578  << " duplicates.\n";
579  }
580 }
581 
582 void rndat( const std::string& basename )
583 {
584  std::string datname = Plib::systemstate.config.world_data_path + basename + ".dat";
585  std::string txtname = Plib::systemstate.config.world_data_path + basename + ".txt";
586 
587  if ( Clib::FileExists( datname.c_str() ) )
588  {
589  rename( datname.c_str(), txtname.c_str() );
590  }
591 }
592 
594 {
595  rndat( "pol" );
596  rndat( "objects" );
597  rndat( "pcs" );
598  rndat( "pcequip" );
599  rndat( "npcs" );
600  rndat( "npcequip" );
601  rndat( "items" );
602  rndat( "multis" );
603  rndat( "storage" );
604  rndat( "resource" );
605  rndat( "guilds" );
606  rndat( "parties" );
607 }
608 
610 {
611  std::string objectsndtfile = Plib::systemstate.config.world_data_path + "objects.ndt";
612  std::string storagendtfile = Plib::systemstate.config.world_data_path + "storage.ndt";
613 
615  if ( Clib::FileExists( objectsndtfile ) )
616  {
617  // Display reads "Reading data files..."
618  ERROR_PRINT << "Error!\n"
619  << "'" << objectsndtfile << " exists. This probably means the system\n"
620  << "exited while writing its state. To avoid loss of data,\n"
621  << "forcing human intervention.\n";
622  throw std::runtime_error( "Human intervention required." );
623  }
624  if ( Clib::FileExists( storagendtfile ) )
625  {
626  ERROR_PRINT << "Error!\n"
627  << "'" << storagendtfile << " exists. This probably means the system\n"
628  << "exited while writing its state. To avoid loss of data,\n"
629  << "forcing human intervention.\n";
630  throw std::runtime_error( "Human intervention required." );
631  }
632 
634 
636 
637  read_pol_dat();
638 
639  // POL clock should be paused at this point.
640  start_gameclock();
641 
643  read_pcs_dat();
645  read_npcs_dat();
647  read_items_dat();
648  read_multis_dat();
651  read_guilds_dat();
653  read_party_dat();
654 
657 
660 
661  import_new_data();
662  // import_wsc();
663 
664  // dave 3/9/3
669 
670  while ( !parent_conts.empty() )
671  parent_conts.pop();
672 
673  for ( ObjectHash::hs::const_iterator citr = objStorageManager.objecthash.begin(),
674  citrend = objStorageManager.objecthash.end();
675  citr != citrend; ++citr )
676  {
677  UObject* obj = ( *citr ).second.get();
678  if ( obj->ismobile() )
679  {
680  Mobile::Character* chr = static_cast<Mobile::Character*>( obj );
681 
682  if ( chr->acct != nullptr )
683  chr->logged_in( false );
684  }
685  }
686 
688  return 0;
689 }
690 
691 
693  : _pol(),
694  _objects(),
695  _pcs(),
696  _pcequip(),
697  _npcs(),
698  _npcequip(),
699  _items(),
700  _multis(),
701  _storage(),
702  _resource(),
703  _guilds(),
704  _datastore(),
705  _party(),
706  pol( &_pol ),
707  objects( &_objects ),
708  pcs( &_pcs ),
709  pcequip( &_pcequip ),
710  npcs( &_npcs ),
711  npcequip( &_npcequip ),
712  items( &_items ),
713  multis( &_multis ),
714  storage( &_storage ),
715  resource( &_resource ),
716  guilds( &_guilds ),
717  datastore( &_datastore ),
718  party( &_party )
719 {
720  pol.init( Plib::systemstate.config.world_data_path + "pol.ndt" );
721  objects.init( Plib::systemstate.config.world_data_path + "objects.ndt" );
722  pcs.init( Plib::systemstate.config.world_data_path + "pcs.ndt" );
723  pcequip.init( Plib::systemstate.config.world_data_path + "pcequip.ndt" );
724  npcs.init( Plib::systemstate.config.world_data_path + "npcs.ndt" );
725  npcequip.init( Plib::systemstate.config.world_data_path + "npcequip.ndt" );
726  items.init( Plib::systemstate.config.world_data_path + "items.ndt" );
727  multis.init( Plib::systemstate.config.world_data_path + "multis.ndt" );
728  storage.init( Plib::systemstate.config.world_data_path + "storage.ndt" );
729  resource.init( Plib::systemstate.config.world_data_path + "resource.ndt" );
730  guilds.init( Plib::systemstate.config.world_data_path + "guilds.ndt" );
731  datastore.init( Plib::systemstate.config.world_data_path + "datastore.ndt" );
732  party.init( Plib::systemstate.config.world_data_path + "parties.ndt" );
733 
734  pcs() << "#" << pf_endl << "# PCS.TXT: Player-Character Data" << pf_endl << "#" << pf_endl
735  << "# In addition to PC data, this also contains hair, beards, death shrouds," << pf_endl
736  << "# and backpacks, but not the contents of each backpack." << pf_endl << "#" << pf_endl
737  << pf_endl;
738 
739  pcequip() << "#" << pf_endl << "# PCEQUIP.TXT: Player-Character Equipment Data" << pf_endl << "#"
740  << pf_endl
741  << "# This file can be deleted to wipe all items held/equipped by characters"
742  << pf_endl
743  << "# Note that hair, beards, empty backpacks, and death shrouds are in PCS.TXT."
744  << pf_endl << "#" << pf_endl << pf_endl;
745 
746  npcs() << "#" << pf_endl << "# NPCS.TXT: Nonplayer-Character Data" << pf_endl << "#" << pf_endl
747  << "# If you delete this file to perform an NPC wipe," << pf_endl
748  << "# be sure to also delete NPCEQUIP.TXT" << pf_endl << "#" << pf_endl << pf_endl;
749 
750  npcequip() << "#" << pf_endl << "# NPCEQUIP.TXT: Nonplayer-Character Equipment Data" << pf_endl
751  << "#" << pf_endl << "# Delete this file along with NPCS.TXT to perform an NPC wipe"
752  << pf_endl << "#" << pf_endl << pf_endl;
753 
754  items() << "#" << pf_endl << "# ITEMS.TXT: Item data" << pf_endl << "#" << pf_endl
755  << "# This file also contains ship and house components (doors, planks etc)" << pf_endl
756  << "#" << pf_endl << pf_endl;
757 
758  multis() << "#" << pf_endl << "# MULTIS.TXT: Ship and House data" << pf_endl << "#" << pf_endl
759  << "# Deleting this file will not properly wipe houses and ships," << pf_endl
760  << "# because doors, planks, and tillermen will be left in the world." << pf_endl << "#"
761  << pf_endl << pf_endl;
762 
763  storage() << "#" << pf_endl
764  << "# STORAGE.TXT: Contains bank boxes, vendor inventories, and other data." << pf_endl
765  << "#" << pf_endl
766  << "# This file can safely be deleted to wipe bank boxes and vendor inventories."
767  << pf_endl << "# Note that scripts may use this for other types of storage as well"
768  << pf_endl << "#" << pf_endl << pf_endl;
769 
770  resource() << "#" << pf_endl << "# RESOURCE.TXT: Resource System Data" << pf_endl << "#"
771  << pf_endl << pf_endl;
772 
773  guilds() << "#" << pf_endl << "# GUILDS.TXT: Guild Data" << pf_endl << "#" << pf_endl << pf_endl;
774 
775  datastore() << "#" << pf_endl << "# DATASTORE.TXT: DataStore Data" << pf_endl << "#" << pf_endl
776  << pf_endl;
777  party() << "#" << pf_endl << "# PARTIES.TXT: Party Data" << pf_endl << "#" << pf_endl << pf_endl;
778 }
779 
781 {
782  pol.flush_file();
784  pcs.flush_file();
786  npcs.flush_file();
788  items.flush_file();
789  multis.flush_file();
792  guilds.flush_file();
794  party.flush_file();
795 }
796 
799 {
800  if ( SaveContext::finished.valid() )
801  {
802  // Tools::Timer<Tools::DebugT> t("future");
803  SaveContext::finished.wait();
804  }
805 }
806 
807 
809 {
810  sw() << "GlobalProperties" << pf_endl << "{" << pf_endl;
811  gamestate.global_properties->printProperties( sw );
812  sw() << "}" << pf_endl << pf_endl;
813  // sw.flush();
814 }
815 
817 {
818  sw() << "System" << pf_endl << "{" << pf_endl << "\tCoreVersion\t" << POL_VERSION << pf_endl
819  << "\tCoreVersionString\t" << POL_VERSION_ID << pf_endl << "\tCompileDateTime\t"
820  << Clib::ProgramConfig::build_datetime() << pf_endl << "\tLastItemSerialNumber\t"
821  << GetCurrentItemSerialNumber() << pf_endl // dave 3/9/3
822  << "\tLastCharSerialNumber\t" << GetCurrentCharSerialNumber() << pf_endl // dave 3/9/3
823  << "}" << pf_endl << pf_endl;
824  // sw.flush();
825 }
826 
828 {
829  for ( const auto& realm : gamestate.Realms )
830  {
831  if ( realm->is_shadowrealm )
832  {
833  sw() << "Realm" << pf_endl << "{" << pf_endl << "\tName\t" << realm->shadowname << pf_endl
834  << "\tBaseRealm\t" << realm->baserealm->name() << pf_endl << "}" << pf_endl << pf_endl;
835  }
836  }
837  // sw.flush();
838 }
839 
840 // Austin (Oct. 17, 2006)
841 // Added to handle gotten item saving.
843 {
844  if ( item == nullptr || item->orphan() )
845  return;
846  // For now, it just saves the item in items.txt
847  item->x = chr->x;
848  item->y = chr->y;
849  item->z = chr->z;
850  item->realm = chr->realm;
851 
852  item->printOn( sw );
853 
854  item->x = item->y = item->z = 0;
855 }
856 
858 {
859  for ( const auto& objitr : objStorageManager.objecthash )
860  {
861  UObject* obj = objitr.second.get();
862  if ( obj->ismobile() && !obj->orphan() )
863  {
864  Mobile::Character* chr = static_cast<Mobile::Character*>( obj );
865  if ( !chr->isa( UOBJ_CLASS::CLASS_NPC ) )
866  {
867  chr->printOn( sc.pcs );
868  chr->clear_dirty();
869  chr->printWornItems( sc.pcs, sc.pcequip );
870  }
871  }
872  }
873 }
874 
876 {
877  for ( const auto& objitr : objStorageManager.objecthash )
878  {
879  UObject* obj = objitr.second.get();
880  if ( obj->ismobile() && !obj->orphan() )
881  {
882  Mobile::Character* chr = static_cast<Mobile::Character*>( obj );
883  if ( chr->isa( UOBJ_CLASS::CLASS_NPC ) )
884  {
885  if ( chr->saveonexit() )
886  {
887  chr->printOn( sc.npcs );
888  chr->clear_dirty();
889  chr->printWornItems( sc.npcs, sc.npcequip );
890  }
891  }
892  }
893  }
894 }
895 
897 {
898  for ( const auto& realm : gamestate.Realms )
899  {
900  unsigned wgridx = realm->grid_width();
901  unsigned wgridy = realm->grid_height();
902 
903  for ( unsigned wx = 0; wx < wgridx; ++wx )
904  {
905  for ( unsigned wy = 0; wy < wgridy; ++wy )
906  {
907  for ( const auto& item : realm->zone[wx][wy].items )
908  {
909  if ( item->itemdesc().save_on_exit && item->saveonexit() )
910  {
911  sw_items << *item;
912  item->clear_dirty();
913  }
914  }
915  }
916  }
917  }
918 
919  for ( const auto& objitr : objStorageManager.objecthash )
920  {
921  UObject* obj = objitr.second.get();
922  if ( obj->ismobile() && !obj->orphan() )
923  {
924  Mobile::Character* chr = static_cast<Mobile::Character*>( obj );
925  if ( !chr->isa( UOBJ_CLASS::CLASS_NPC ) )
926  {
927  // Figure out where to save the 'gotten item' - Austin (Oct. 17, 2006)
928  if ( chr->has_gotten_item() )
929  WriteGottenItem( chr, chr->gotten_item(), sw_items );
930  }
931  }
932  }
933 }
934 
936 {
937  for ( const auto& realm : gamestate.Realms )
938  {
939  unsigned wgridx = realm->grid_width();
940  unsigned wgridy = realm->grid_height();
941 
942  for ( unsigned wx = 0; wx < wgridx; ++wx )
943  {
944  for ( unsigned wy = 0; wy < wgridy; ++wy )
945  {
946  for ( auto& multi : realm->zone[wx][wy].multis )
947  {
948  if ( Clib::exit_signalled ) // drop waiting commit on shutdown
949  {
950  Multi::UHouse* house = multi->as_house();
951  if ( house != nullptr )
952  {
953  if ( house->IsCustom() )
954  {
955  if ( house->IsWaitingForAccept() )
956  house->AcceptHouseCommit( nullptr, false );
957  }
958  }
959  }
960  ofs << *multi;
961  multi->clear_dirty();
962  }
963  }
964  }
965  }
966 }
967 
968 bool commit( const std::string& basename )
969 {
970  std::string bakfile = Plib::systemstate.config.world_data_path + basename + ".bak";
971  std::string datfile = Plib::systemstate.config.world_data_path + basename + ".txt";
972  std::string ndtfile = Plib::systemstate.config.world_data_path + basename + ".ndt";
973  const char* bakfile_c = bakfile.c_str();
974  const char* datfile_c = datfile.c_str();
975  const char* ndtfile_c = ndtfile.c_str();
976 
977  bool any = false;
978 
979  if ( Clib::FileExists( bakfile_c ) )
980  {
981  any = true;
982  if ( unlink( bakfile_c ) )
983  {
984  int err = errno;
985  POLLOG_ERROR.Format( "Unable to remove {}: {} ({})\n" )
986  << bakfile_c << strerror( err ) << err;
987  }
988  }
989 
990  if ( Clib::FileExists( datfile_c ) )
991  {
992  any = true;
993  if ( rename( datfile_c, bakfile_c ) )
994  {
995  int err = errno;
996  POLLOG_ERROR.Format( "Unable to rename {} to {}: {} ({})\n" )
997  << datfile_c << bakfile_c << strerror( err ) << err;
998  }
999  }
1000 
1001  if ( Clib::FileExists( ndtfile_c ) )
1002  {
1003  any = true;
1004  if ( rename( ndtfile_c, datfile_c ) )
1005  {
1006  int err = errno;
1007  POLLOG_ERROR.Format( "Unable to rename {} to {}: {} ({})\n" )
1008  << ndtfile_c << datfile_c << strerror( err ) << err;
1009  }
1010  }
1011 
1012  return any;
1013 }
1014 
1016 {
1017  if ( Plib::systemstate.config.inhibit_saves )
1018  return false;
1020  return false;
1021 
1022  return true;
1023 }
1024 
1025 int write_data( unsigned int& dirty_writes, unsigned int& clean_writes, long long& elapsed_ms )
1026 {
1027  SaveContext::ready(); // allow only one active
1028  if ( !should_write_data() )
1029  {
1030  dirty_writes = clean_writes = 0;
1031  elapsed_ms = 0;
1032  return -1;
1033  }
1034 
1037 
1038  Tools::Timer<> timer;
1039  // launch complete save as seperate thread
1040  // but wait till the first critical part is finished
1041  // which means all objects got written into a format object
1042  // the remaining operations are only pure buffered i/o
1043  auto critical_promise = std::make_shared<std::promise<bool>>();
1044  auto critical_future = critical_promise->get_future();
1045  SaveContext::finished = std::async( std::launch::async, [&, critical_promise]() -> bool {
1046  try
1047  {
1048  SaveContext sc;
1049  bool result = true;
1050  std::vector<std::future<bool>> critical_parts;
1051  critical_parts.push_back( gamestate.task_thread_pool.checked_push( [&]() {
1052  try
1053  {
1054  sc.pol() << "#" << pf_endl << "# Created by Version: " << POL_VERSION_ID << pf_endl
1055  << "# Mobiles: " << get_mobile_count() << pf_endl
1056  << "# Top-level Items: " << get_toplevel_item_count() << pf_endl << "#"
1057  << pf_endl << pf_endl;
1058 
1059  write_system_data( sc.pol );
1060  write_global_properties( sc.pol );
1061  write_shadow_realms( sc.pol );
1062  }
1063  catch ( ... )
1064  {
1065  POLLOG_ERROR << "failed to store pol datafile!\n";
1067  result = false;
1068  }
1069  } ) );
1070  critical_parts.push_back( gamestate.task_thread_pool.checked_push( [&]() {
1071  try
1072  {
1073  write_items( sc.items );
1074  }
1075  catch ( ... )
1076  {
1077  POLLOG_ERROR << "failed to store items datafile!\n";
1079  result = false;
1080  }
1081  } ) );
1082  critical_parts.push_back( gamestate.task_thread_pool.checked_push( [&]() {
1083  try
1084  {
1085  write_characters( sc );
1086  }
1087  catch ( ... )
1088  {
1089  POLLOG_ERROR << "failed to store character datafile!\n";
1091  result = false;
1092  }
1093  } ) );
1094  critical_parts.push_back( gamestate.task_thread_pool.checked_push( [&]() {
1095  try
1096  {
1097  write_npcs( sc );
1098  }
1099  catch ( ... )
1100  {
1101  POLLOG_ERROR << "failed to store npcs datafile!\n";
1103  result = false;
1104  }
1105  } ) );
1106  critical_parts.push_back( gamestate.task_thread_pool.checked_push( [&]() {
1107  try
1108  {
1109  write_multis( sc.multis );
1110  }
1111  catch ( ... )
1112  {
1113  POLLOG_ERROR << "failed to store multis datafile!\n";
1115  result = false;
1116  }
1117  } ) );
1118  critical_parts.push_back( gamestate.task_thread_pool.checked_push( [&]() {
1119  try
1120  {
1121  gamestate.storage.print( sc.storage );
1122  }
1123  catch ( ... )
1124  {
1125  POLLOG_ERROR << "failed to store storage datafile!\n";
1127  result = false;
1128  }
1129  } ) );
1130  critical_parts.push_back( gamestate.task_thread_pool.checked_push( [&]() {
1131  try
1132  {
1133  write_resources_dat( sc.resource );
1134  }
1135  catch ( ... )
1136  {
1137  POLLOG_ERROR << "failed to store resource datafile!\n";
1139  result = false;
1140  }
1141  } ) );
1142  critical_parts.push_back( gamestate.task_thread_pool.checked_push( [&]() {
1143  try
1144  {
1145  write_guilds( sc.guilds );
1146  }
1147  catch ( ... )
1148  {
1149  POLLOG_ERROR << "failed to store guilds datafile!\n";
1151  result = false;
1152  }
1153  } ) );
1154  critical_parts.push_back( gamestate.task_thread_pool.checked_push( [&]() {
1155  try
1156  {
1157  Module::write_datastore( sc.datastore );
1158  // Atomically (hopefully) perform the switch.
1159  Module::commit_datastore();
1160  }
1161  catch ( ... )
1162  {
1163  POLLOG_ERROR << "failed to store datastore datafile!\n";
1165  result = false;
1166  }
1167  } ) );
1168  critical_parts.push_back( gamestate.task_thread_pool.checked_push( [&]() {
1169  try
1170  {
1171  write_party( sc.party );
1172  }
1173  catch ( ... )
1174  {
1175  POLLOG_ERROR << "failed to store party datafile!\n";
1177  result = false;
1178  }
1179  } ) );
1180  for ( auto& task : critical_parts )
1181  task.wait();
1182 
1183  critical_promise->set_value( result ); // critical part end
1184  } // deconstructor of the SaveContext flushes and joins the queues
1185  catch ( ... )
1186  {
1187  POLLOG_ERROR << "failed to save datafiles!\n";
1189  critical_promise->set_value( false ); // critical part end
1190  }
1191  commit( "pol" );
1192  commit( "objects" );
1193  commit( "pcs" );
1194  commit( "pcequip" );
1195  commit( "npcs" );
1196  commit( "npcequip" );
1197  commit( "items" );
1198  commit( "multis" );
1199  commit( "storage" );
1200  commit( "resource" );
1201  commit( "guilds" );
1202  commit( "datastore" );
1203  commit( "parties" );
1204  return true;
1205  } );
1206  critical_future.wait(); // wait for end of critical part
1207 
1208  if ( Plib::systemstate.accounts_txt_dirty ) // write accounts extra, since it uses extra thread
1209  // for io operations would be to many threads working
1210  {
1212  }
1213 
1216  timer.stop();
1218  // optimize_zones(); // shrink zone vectors TODO this takes way to much time!
1219 
1220  // cout << "Clean: " << UObject::clean_writes << " Dirty: " <<
1221  // UObject::dirty_writes << endl;
1222  clean_writes = UObject::clean_writes;
1223  dirty_writes = UObject::dirty_writes;
1224  elapsed_ms = timer.ellapsed();
1225 
1227  return 0;
1228 }
1229 
1231 {
1232  Clib::ConfigFile cf( "config/startloc.cfg" );
1233 
1234  Clib::ConfigElem elem;
1235  while ( cf.read( elem ) )
1236  {
1237  if ( stricmp( elem.type(), "StartingLocation" ) != 0 )
1238  {
1239  ERROR_PRINT << "Unknown element type in startloc.cfg: " << elem.type() << "\n";
1240  throw std::runtime_error( "Error in configuration file." );
1241  }
1242 
1243  std::unique_ptr<StartingLocation> loc( new StartingLocation );
1244  loc->city = elem.remove_string( "CITY" );
1245  loc->desc = elem.remove_string( "DESCRIPTION" );
1246  loc->mapid = elem.remove_ushort( "MAPID", 0 );
1247  loc->cliloc_desc = elem.remove_unsigned( "CLILOC", 1075072 );
1248  loc->realm = find_realm( elem.remove_string( "REALM", "britannia" ) );
1249 
1250  std::string coord;
1251  while ( elem.remove_prop( "Coordinate", &coord ) )
1252  {
1253  int x, y, z;
1254  if ( sscanf( coord.c_str(), "%d,%d,%d", &x, &y, &z ) == 3 )
1255  {
1256  loc->coords.push_back(
1257  Coordinate( static_cast<u16>( x ), static_cast<u16>( y ), static_cast<s8>( z ) ) );
1258  }
1259  else
1260  {
1261  ERROR_PRINT << "Poorly formed coordinate in startloc.cfg: '" << coord << "' for city "
1262  << loc->city << ", description " << loc->desc << "\n";
1263  throw std::runtime_error( "Configuration file error in startloc.cfg." );
1264  }
1265  }
1266  if ( loc->coords.size() == 0 )
1267  {
1268  ERROR_PRINT << "STARTLOC.CFG: StartingLocation (" << loc->city << "," << loc->desc
1269  << ") has no Coordinate properties."
1270  << "\n";
1271  throw std::runtime_error( "Configuration file error." );
1272  }
1273  gamestate.startlocations.push_back( loc.release() );
1274  }
1275 
1276  if ( gamestate.startlocations.empty() )
1277  throw std::runtime_error(
1278  "STARTLOC.CFG: No starting locations found. Clients will crash on character creation." );
1279 }
1280 
1281 ServerDescription::ServerDescription() : name( "" ), port( 0 ), hostname( "" )
1282 {
1283  memset( ip, 0, sizeof ip );
1284 }
1285 
1287 {
1288  size_t size = name.capacity() + 4 * sizeof( unsigned char ) /*ip*/
1289  + sizeof( unsigned short ) /*port*/
1290  + 3 * sizeof( unsigned int* ) + ip_match.capacity() * sizeof( unsigned int ) +
1291  3 * sizeof( unsigned int* ) + ip_match_mask.capacity() * sizeof( unsigned int ) +
1292  3 * sizeof( std::string* ) + hostname.capacity();
1293  for ( const auto& s : acct_match )
1294  size += s.capacity();
1295  return size;
1296 }
1297 
1299 {
1300  std::string accttext;
1301 
1302  Clib::ConfigFile cf( "config/servers.cfg" );
1303 
1304  Clib::ConfigElem elem;
1305  while ( cf.read( elem ) )
1306  {
1307  if ( !elem.type_is( "GameServer" ) )
1308  continue;
1309 
1310  std::unique_ptr<ServerDescription> svr( new ServerDescription );
1311 
1312  svr->name = elem.remove_string( "NAME" );
1313 
1314  std::string iptext;
1315  int ip0, ip1, ip2, ip3;
1316  iptext = elem.remove_string( "IP" );
1317  if ( iptext == "--ip--" )
1318  {
1319  iptext = networkManager.ipaddr_str;
1320  if ( iptext == "" )
1321  {
1322  INFO_PRINT << "Skipping server " << svr->name
1323  << " because there is no Internet IP address.\n";
1324  continue;
1325  }
1326  }
1327  else if ( iptext == "--lan--" )
1328  {
1329  iptext = networkManager.lanaddr_str;
1330  if ( iptext == "" )
1331  {
1332  INFO_PRINT << "Skipping server " << svr->name << " because there is no LAN IP address.\n";
1333  continue;
1334  }
1335  }
1336 
1337  if ( isdigit( iptext[0] ) )
1338  {
1339  if ( sscanf( iptext.c_str(), "%d.%d.%d.%d", &ip0, &ip1, &ip2, &ip3 ) != 4 )
1340  {
1341  ERROR_PRINT << "SERVERS.CFG: Poorly formed IP (" << iptext << ") for GameServer '"
1342  << svr->name << "'.\n";
1343  throw std::runtime_error( "Configuration file error." );
1344  }
1345  svr->ip[0] = static_cast<unsigned char>( ip3 );
1346  svr->ip[1] = static_cast<unsigned char>( ip2 );
1347  svr->ip[2] = static_cast<unsigned char>( ip1 );
1348  svr->ip[3] = static_cast<unsigned char>( ip0 );
1349  }
1350  else
1351  {
1352  svr->hostname = iptext;
1353 
1354 #ifdef __linux__
1355  /* try to look up */
1356  struct hostent host_ret;
1357  struct hostent* host_result = nullptr;
1358  char tmp_buf[1024];
1359  int my_h_errno;
1360  int res = gethostbyname_r( svr->hostname.c_str(), &host_ret, tmp_buf, sizeof tmp_buf,
1361  &host_result, &my_h_errno );
1362  if ( res == 0 && host_result && host_result->h_addr_list[0] )
1363  {
1364  char* addr = host_result->h_addr_list[0];
1365  svr->ip[0] = addr[3];
1366  svr->ip[1] = addr[2];
1367  svr->ip[2] = addr[1];
1368  svr->ip[3] = addr[0];
1369  /*
1370  struct sockaddr_in saddr;
1371  memcpy( &saddr.sin_addr, he->h_addr_list[0], he->h_length);
1372  server->ip[0] = saddr.sin_addr.S_un.S_un_b.s_b1;
1373  server->ip[1] = saddr.sin_addr.S_un.S_un_b.s_b2;
1374  server->ip[2] = saddr.sin_addr.S_un.S_un_b.s_b3;
1375  server->ip[3] = saddr.sin_addr.S_un.S_un_b.s_b4;
1376  */
1377  }
1378  else
1379  {
1380  POLLOG_ERROR.Format( "Warning: gethostbyname_r failed for server {} ({}): {}\n" )
1381  << svr->name << svr->hostname << my_h_errno;
1382  }
1383 #endif
1384  }
1385 
1386  svr->port = elem.remove_ushort( "PORT" );
1387 
1388  while ( elem.remove_prop( "IPMATCH", &iptext ) )
1389  {
1390  auto delim = iptext.find_first_of( '/' );
1391  if ( delim != std::string::npos )
1392  {
1393  std::string ipaddr_str = iptext.substr( 0, delim );
1394  std::string ipmask_str = iptext.substr( delim + 1 );
1395  unsigned int ipaddr = inet_addr( ipaddr_str.c_str() );
1396  unsigned int ipmask = inet_addr( ipmask_str.c_str() );
1397  svr->ip_match.push_back( ipaddr );
1398  svr->ip_match_mask.push_back( ipmask );
1399  }
1400  else
1401  {
1402  unsigned int ipaddr = inet_addr( iptext.c_str() );
1403  svr->ip_match.push_back( ipaddr );
1404  svr->ip_match_mask.push_back( 0xFFffFFffLu );
1405  }
1406  }
1407 
1408  while ( elem.remove_prop( "ACCTMATCH", &accttext ) )
1409  {
1410  svr->acct_match.push_back( accttext );
1411  }
1412 
1413  networkManager.servers.push_back( svr.release() );
1414  }
1415  if ( networkManager.servers.empty() )
1416  throw std::runtime_error( "There must be at least one GameServer in SERVERS.CFG." );
1417 }
1418 }
1419 }
void read_storage_dat()
Definition: uimport.cpp:497
void register_with_supporting_multi(Item *item)
Definition: ufunc.cpp:1875
static Item * create(u32 objtype, u32 serial=0)
Definition: itemcr.cpp:53
size_t estimateSize() const
Definition: uimport.cpp:1286
void read_system_vars(Clib::ConfigElem &elem)
Definition: uimport.cpp:293
static std::atomic< unsigned int > dirty_writes
Definition: uobject.h:224
SaveStrategy items
Definition: savedata.h:50
bool defined_realm(const std::string &name)
Definition: realms.cpp:74
void warn_with_line(const std::string &errmsg) const
Definition: cfgfile.cpp:304
void write_items(Clib::StreamWriter &sw_items)
Definition: uimport.cpp:896
std::string remove_string(const char *propname)
Definition: cfgfile.cpp:381
void read_npcequip_dat()
Definition: uimport.cpp:467
SaveStrategy guilds
Definition: savedata.h:54
void add_item_to_world(Items::Item *item)
Definition: uworld.cpp:31
void SetCurrentCharSerialNumber(u32 serial)
Definition: ufunc.cpp:101
static void ready()
blocks till possible last commit finishes
Definition: uimport.cpp:798
void get_prop(const char *propname, unsigned int *plong) const
Definition: cfgfile.cpp:185
void add_loaded_item(Items::Item *cont_item, Items::Item *item)
Definition: loaddata.cpp:248
SaveStrategy npcequip
Definition: savedata.h:49
SystemState systemstate
Definition: systemstate.cpp:12
Core::PolConfig config
Definition: systemstate.h:43
std::string world_data_path
Definition: polcfg.h:28
void read_pol_dat()
Definition: uimport.cpp:423
threadhelp::TaskThreadPool task_thread_pool
Definition: uvars.h:248
void SetCharacterWorldPosition(Mobile::Character *chr, Realms::WorldChangeReason reason)
Definition: uworld.cpp:128
void write_system_data(Clib::StreamWriter &sw)
Definition: uimport.cpp:816
unsigned int stored_last_char_serial
Definition: state.h:45
bool ismobile() const
Definition: baseobject.h:104
T * get() const
Definition: refptr.h:176
std::string decint(unsigned short v)
Definition: strutil.cpp:64
void printWornItems(Clib::StreamWriter &sw_pc, Clib::StreamWriter &sw_equip) const
Definition: charactr.cpp:767
hs::const_iterator begin() const
Definition: objecthash.cpp:239
void write_account_data()
Definition: accounts.cpp:71
unsigned int remove_ulong(const char *propname)
Definition: cfgfile.cpp:461
std::string elapsed(clock_t start, clock_t end)
Definition: uimport.cpp:357
void read_global_item(Clib::ConfigElem &elem, int)
Definition: uimport.cpp:215
StorageArea * create_area(const std::string &name)
Definition: storage.cpp:144
void insert_deferred_items()
Definition: loaddata.cpp:117
SaveStrategy pcequip
Definition: savedata.h:47
std::vector< unsigned int > ip_match
Definition: servdesc.h:25
std::future< bool > checked_push(const msg &msg)
returns a future which will be set once the msg is processed
Definition: threadhelp.cpp:411
void force_backtrace(bool complete)
Definition: passert.cpp:53
void read_guilds_dat()
Definition: guilds.cpp:197
bool logged_in() const
Definition: charactr.cpp:428
std::unique_ptr< Core::PropertyList > global_properties
Definition: uvars.h:142
#define POLLOG_ERROR
Definition: logfacility.h:207
bool gflag_in_system_load
Definition: state.h:39
unsigned short DataWrittenBy
Definition: polvar.h:16
static std::shared_future< bool > finished
Definition: savedata.h:57
const ItemDesc & find_itemdesc(unsigned int objtype)
Definition: itemdesc.cpp:933
unsigned char ip[4]
Definition: servdesc.h:23
void read_multis_dat()
Definition: uimport.cpp:478
void load_incremental_indexes()
Definition: loaddata.cpp:39
SaveStrategy pol
Definition: savedata.h:44
void read_items_dat()
Definition: uimport.cpp:473
void write_shadow_realms(Clib::StreamWriter &sw)
Definition: uimport.cpp:827
void add_multi_to_world(Multi::UMulti *multi)
Definition: uworld.cpp:69
void read_incremental_saves()
Definition: loaddata.cpp:79
void write_npcs(SaveContext &sc)
Definition: uimport.cpp:875
void clear_save_index()
Definition: loaddata.cpp:106
virtual void readProperties(Clib::ConfigElem &elem) POL_OVERRIDE
Definition: item.cpp:434
unsigned short u16
Definition: rawtypes.h:26
unsigned int u32
Definition: rawtypes.h:27
void read_npc(Clib::ConfigElem &elem)
Definition: uimport.cpp:117
void read_pcs_dat()
Definition: uimport.cpp:449
bool IsItem(u32 serial)
Definition: uobject.h:316
Multi::UMulti * system_find_multi(u32 serial)
Definition: fnsearch.cpp:50
static std::atomic< unsigned int > clean_writes
Definition: uobject.h:225
const unsigned SYSFIND_SKIP_WORLD
Definition: fnsearch.h:33
virtual void destroy()
Definition: uobject.cpp:122
void read_resources_dat()
Definition: resource.cpp:408
void write_multis(Clib::StreamWriter &ofs)
Definition: uimport.cpp:935
void read_pcequip_dat()
Definition: uimport.cpp:455
std::vector< Realms::Realm * > Realms
Definition: uvars.h:163
u32 GetNewItemSerialNumber(void)
Definition: ufunc.cpp:142
NetworkManager networkManager
Definition: network.cpp:28
bool passert_nosave
Definition: passert.cpp:33
int import_count
Definition: uimport.cpp:524
SaveStrategy datastore
Definition: savedata.h:55
Items::Item * find_existing_item(u32 objtype, u16 x, u16 y, s8 z, Realms::Realm *realm)
Definition: uimport.cpp:509
SaveStrategy multis
Definition: savedata.h:51
void read_character(Clib::ConfigElem &elem)
Definition: uimport.cpp:84
bool orphan() const
Definition: baseobject.h:119
virtual void flush_file() POL_OVERRIDE
Definition: streamsaver.cpp:86
void commit_incremental_saves()
Definition: savedata.cpp:302
static ContStack parent_conts
Definition: uimport.cpp:213
void AcceptHouseCommit(Mobile::Character *chr, bool accept)
Definition: house.cpp:996
ref_ptr< Mobile::Character > CharacterRef
Definition: reftypes.h:42
bool IsCustom() const
Definition: house.h:84
SaveStrategy party
Definition: savedata.h:56
void write_party(Clib::StreamWriter &sw)
Definition: party.cpp:868
virtual void printOn(Clib::StreamWriter &sw) const POL_OVERRIDE
Definition: charactr.cpp:763
signed char s8
Definition: rawtypes.h:29
unsigned int stored_last_item_serial
Definition: state.h:44
SaveStrategy storage
Definition: savedata.h:52
void equip_loaded_item(Mobile::Character *chr, Items::Item *item)
Definition: loaddata.cpp:199
std::stack< UContainer * > ContStack
Definition: uimport.cpp:212
void read_npcs_dat()
Definition: uimport.cpp:461
void read_gameservers()
Definition: uimport.cpp:1298
const u32 objtype_
Definition: uobject.h:249
GameState gamestate
Definition: uvars.cpp:74
void commit_datastore()
Definition: datastore.cpp:744
SaveStrategy pcs
Definition: savedata.h:46
static UMulti * create(const Items::ItemDesc &descriptor, u32 serial=0)
Definition: multicr.cpp:38
#define ctBEu32(x)
Definition: clib_endian.h:45
SettingsManager settingsManager
Definition: settings.cpp:14
bool should_write_data()
Definition: uimport.cpp:1015
Items::Item * read_item(Clib::ConfigElem &elem)
Definition: uimport.cpp:154
u32 GetCurrentItemSerialNumber(void)
Definition: ufunc.cpp:107
bool saveonexit() const
Definition: uobject.cpp:385
StateManager stateManager
Definition: state.cpp:8
void zone_convert(unsigned short x, unsigned short y, unsigned short *wx, unsigned short *wy, const Realms::Realm *realm)
Definition: uworld.h:76
Mobile::Character * system_find_mobile(u32 serial)
Definition: fnsearch.cpp:32
void write_global_properties(Clib::StreamWriter &sw)
Definition: uimport.cpp:808
void write_datastore(Clib::StreamWriter &sw)
Definition: datastore.cpp:719
bool Insert(UObject *obj)
Definition: objecthash.cpp:30
bool remove_prop(const char *propname, std::string *value)
Definition: cfgfile.cpp:128
ref_ptr< Items::Item > ItemRef
Definition: reftypes.h:43
void read_shadow_realms(Clib::ConfigElem &elem)
Definition: uimport.cpp:302
Core::AccountRef acct
Definition: charactr.h:914
virtual void init(const std::string &filepath) POL_OVERRIDE
Definition: streamsaver.cpp:64
int dupe_count
Definition: uimport.cpp:525
void read(Clib::ConfigFile &cf)
Definition: storage.cpp:209
bool IsCharacter(u32 serial)
Definition: uobject.h:311
ZoneItems items
Definition: uworld.h:72
Items::Item * system_find_item(u32 serial)
Definition: fnsearch.cpp:41
bool type_is(const char *name) const
Definition: cfgfile.cpp:95
Realms::Realm * realm
Definition: baseobject.h:56
u32 GetCurrentCharSerialNumber(void)
Definition: ufunc.cpp:113
void clear_dirty() const
Definition: uobject.cpp:146
u32 pol_serial_t
Definition: poltype.h:23
SaveStrategy npcs
Definition: savedata.h:48
OldObjtypeConversions old_objtype_conversions
Definition: uvars.h:205
virtual void printOn(Clib::StreamWriter &) const
Definition: uobject.cpp:332
ObjectStorageManager objStorageManager
void read_multi(Clib::ConfigElem &elem)
Definition: uimport.cpp:317
void SetCurrentItemSerialNumber(u32 serial)
Definition: ufunc.cpp:95
unsigned short remove_ushort(const char *propname)
Definition: cfgfile.cpp:318
virtual class UHouse * as_house() POL_OVERRIDE
Definition: house.cpp:244
long long ellapsed() const
Definition: timer.cpp:46
Realms::Realm * find_realm(const std::string &name)
Definition: realms.cpp:64
std::string name
Definition: osmod.cpp:943
Core::Zone ** zone
Definition: realm.h:133
hs::const_iterator end() const
Definition: objecthash.cpp:244
void write_guilds(Clib::StreamWriter &sw)
Definition: guilds.cpp:224
void read_datastore_dat()
Definition: datastore.cpp:702
std::vector< std::string > acct_match
Definition: servdesc.h:27
bool isa(UOBJ_CLASS uobj_class) const
Definition: baseobject.h:99
void rename_dat_files()
Definition: uimport.cpp:593
void start_gameclock()
The functions below deal with reading and updating the gameclock. The state is protected by a mutex...
Definition: gameclck.cpp:27
bool passert_shutdown_due_to_assertion
Definition: passert.cpp:34
#define ERROR_PRINT
Definition: logfacility.h:230
void load_item(Clib::ConfigElem &elem)
Definition: storage.cpp:98
void read_party_dat()
Definition: party.cpp:835
void write_characters(SaveContext &sc)
Definition: uimport.cpp:857
void defer_item_insertion(Items::Item *item, pol_serial_t container_serial)
Definition: loaddata.cpp:112
bool FileExists(const char *filename)
Definition: fileutil.cpp:118
StartingLocations startlocations
Definition: uvars.h:145
bool read(ConfigElem &elem)
Definition: cfgfile.cpp:1015
int write_data(unsigned int &dirty_writes, unsigned int &clean_writes, long long &elapsed_ms)
Definition: uimport.cpp:1025
void read_objects_dat()
Definition: uimport.cpp:443
#define INFO_PRINT
Definition: logfacility.h:223
const char * type() const
Definition: cfgfile.cpp:66
bool commit(const std::string &basename)
Definition: uimport.cpp:968
bool IsWaitingForAccept() const
Definition: house.h:89
#define pf_endl
Definition: proplist.cpp:25
void add_realm(const std::string &name, Realms::Realm *base)
Definition: realms.cpp:84
SaveStrategy objects
Definition: savedata.h:45
SaveStrategy resource
Definition: savedata.h:53
void slurp(const char *filename, const char *tags, int sysfind_flags=0)
Definition: uimport.cpp:363
unsigned get_save_index(pol_serial_t serial)
Definition: loaddata.cpp:70
Storage storage
Definition: uvars.h:156
Definition: berror.cpp:12
unsigned remove_unsigned(const char *propname)
Definition: cfgfile.cpp:360
std::atomic< bool > exit_signalled
void import_new_data()
Definition: uimport.cpp:564
void register_deleted_serials()
Definition: loaddata.cpp:91
int read_data()
Definition: uimport.cpp:609
static std::string build_datetime()
std::vector< unsigned int > ip_match_mask
Definition: servdesc.h:26
void read_starting_locations()
Definition: uimport.cpp:1230
void WriteGottenItem(Mobile::Character *chr, Items::Item *item, Clib::StreamWriter &sw)
Definition: uimport.cpp:842
void rndat(const std::string &basename)
Definition: uimport.cpp:582