Pol  Revision:cb584c9
pol.cpp
Go to the documentation of this file.
1 
59 #include "pol.h"
60 
61 #include <errno.h>
62 
63 #include "pol_global_config.h"
64 
65 #include "../bscript/bobject.h"
66 #include "../bscript/escriptv.h"
67 #include "../clib/Debugging/ExceptionParser.h"
68 #include "../clib/Program/ProgramConfig.h"
69 #include "../clib/clib_endian.h"
70 #include "../clib/esignal.h"
71 #include "../clib/fileutil.h"
72 #include "../clib/kbhit.h"
73 #include "../clib/logfacility.h"
74 #include "../clib/passert.h"
75 #include "../clib/rawtypes.h"
76 #include "../clib/refptr.h"
77 #include "../clib/stlutil.h"
78 #include "../clib/streamsaver.h"
79 #include "../clib/threadhelp.h"
80 #include "../clib/timer.h"
81 #include "../clib/tracebuf.h"
82 #include "../plib/pkg.h"
83 #include "../plib/systemstate.h"
84 #include "accounts/account.h"
85 #include "checkpnt.h"
86 #include "console.h"
87 #include "core.h"
88 #include "decay.h"
89 #include "extobj.h"
90 #include "fnsearch.h"
91 #include "gameclck.h"
92 #include "globals/network.h"
93 #include "globals/object_storage.h"
94 #include "globals/state.h"
95 #include "globals/uvars.h"
96 #include "guardrgn.h"
97 #include "item/armor.h"
98 #include "item/equipmnt.h"
99 #include "item/itemdesc.h"
100 #include "loadunld.h"
101 #include "menu.h"
102 #include "miscrgn.h"
103 #include "mobile/charactr.h"
104 #include "multi/house.h"
105 #include "multi/multi.h"
106 #include "musicrgn.h"
107 #include "network/cgdata.h"
108 #include "network/client.h"
109 #include "network/clientthread.h"
110 #include "network/clienttransmit.h"
111 #include "network/cliface.h"
112 #include "network/packethelper.h"
113 #include "network/packethooks.h"
114 #include "network/packets.h"
115 #include "party.h"
116 #include "pktboth.h"
117 #include "pktdef.h"
118 #include "pktin.h"
119 #include "polcfg.h"
120 #include "polclock.h"
121 #include "poldbg.h"
122 #include "polsem.h"
123 #include "polsig.h"
124 #include "polwww.h"
125 #include "profile.h"
127 #include "realms/realm.h"
128 #include "savedata.h"
129 #include "scrdef.h"
130 #include "scrsched.h"
131 #include "sockets.h"
132 #include "sockio.h"
133 #include "sqlscrobj.h"
134 #include "ssopt.h"
135 #include "testing/poltest.h"
136 #include "ufunc.h"
137 #include "uimport.h"
138 #include "uoclient.h"
139 #include "uoscrobj.h"
140 #include "uworld.h"
141 #include <format/format.h>
142 
143 #ifndef NDEBUG
144 #include "containr.h"
145 #include "mobile/npc.h"
146 #endif
147 
148 #ifdef _WIN32
149 #include <process.h>
150 
151 #include "../clib/mdump.h"
152 #endif
153 
154 #ifdef __linux__
155 #include <gnu/libc-version.h>
156 #endif
157 
158 
159 #include <cstdio>
160 #include <cstring>
161 #include <exception>
162 #include <iosfwd>
163 #include <string>
164 
165 #ifdef _MSC_VER
166 #pragma warning( disable : 4127 ) // conditional expression is constant (needed because of FD_SET)
167 #endif
168 
169 namespace Pol
170 {
171 namespace Bscript
172 {
175 }
176 namespace Items
177 {
180 }
181 namespace Network
182 {
183 void load_aux_services();
184 void start_aux_services();
185 void read_bannedips_config( bool initial_load );
186 }
187 namespace Core
188 {
189 void cancel_all_trades();
190 void load_system_hooks();
191 bool load_realms();
194 void start_uo_client_listeners( void );
195 void start_tasks();
196 
197 
198 using namespace threadhelp;
199 
200 #define CLIENT_CHECKPOINT( x ) client->checkpoint = x
201 
203 {
204  Mobile::Character* chr = client->chr;
206  msg->Write<u32>( chr->serial_ext );
207  msg->offset += 4; // u8 unk5, unk6, unk7, unk8
208  msg->WriteFlipped<u16>( chr->graphic );
209  msg->WriteFlipped<u16>( chr->x );
210  msg->WriteFlipped<u16>( chr->y );
211  msg->offset++; // u8 unk_15
212  msg->Write<s8>( chr->z );
213  msg->Write<u8>( chr->facing );
214  msg->offset += 3; // u8 unk18,unk19,unk20
215  msg->Write<u8>( 0x7Fu );
216  msg->offset++; // u8 unk22
217  msg->offset += 4; // u16 map_startx, map_starty
218  msg->WriteFlipped<u16>( client->chr->realm->width() );
219  msg->WriteFlipped<u16>( client->chr->realm->height() );
220  msg->offset += 6; // u8 unk31, unk32, unk33, unk34, unk35, unk36
221  msg.Send( client );
222 }
223 
225 {
227  client->chr, [&]( Items::Item* item ) { send_item( client, item ); } );
228 }
229 
231 {
233  client->chr, [&]( Multi::UMulti* multi ) { send_multi( client, multi ); } );
234 }
235 
236 void textcmd_startlog( Network::Client* client );
237 void textcmd_stoplog( Network::Client* client );
239 {
240  client->ready = 1;
241  client->chr->connected( true );
242 
243  // even if this stuff just gets queued, we still want the client to start
244  // getting data now.
245  client->pause();
246 
247  Multi::UMulti* supporting_multi;
248  Items::Item* walkon;
249  short newz;
250  if ( client->chr->realm->walkheight( client->chr, client->chr->x, client->chr->y, client->chr->z,
251  &newz, &supporting_multi, &walkon ) )
252  {
253  client->chr->z = static_cast<s8>( newz );
254  // FIXME: Need to add Walkon checks for multi right here if type is house.
255  if ( supporting_multi != nullptr )
256  {
257  supporting_multi->register_object( client->chr );
258  Multi::UHouse* this_house = supporting_multi->as_house();
259  if ( client->chr->registered_house == 0 )
260  {
261  client->chr->registered_house = supporting_multi->serial;
262 
263  if ( this_house != nullptr )
264  this_house->walk_on( client->chr );
265  }
266  }
267  else
268  {
269  if ( client->chr->registered_house > 0 )
270  {
272  if ( multi != nullptr )
273  {
274  multi->unregister_object( client->chr );
275  }
276  client->chr->registered_house = 0;
277  }
278  }
279  client->chr->position_changed();
280  }
281 
282  send_startup( client );
283 
284  send_realm_change( client, client->chr->realm );
285  send_map_difs( client );
286 
288  send_season_info( client );
289 
290  client->chr->lastx = client->chr->lasty = client->chr->lastz = 0;
291 
292  client->gd->music_region = gamestate.musicdef->getregion( 0, 0, client->chr->realm );
293  client->gd->justice_region = gamestate.justicedef->getregion( 0, 0, client->chr->realm );
294  client->gd->weather_region = gamestate.weatherdef->getregion( 0, 0, client->chr->realm );
295 
296  send_goxyz( client, client->chr );
297  client->chr->check_region_changes();
298 
299  client->chr->send_warmode();
300  login_complete( client );
301  client->chr->tellmove();
302 
303  client->chr->check_weather_region_change( true );
304 
306  send_season_info( client );
307 
308  send_objects_newly_inrange( client );
309 
310  client->chr->send_highlight();
311  send_owncreate( client, client->chr );
312 
313  send_goxyz( client, client->chr );
314 
315  client->restart();
316 
317  client->chr->clear_gotten_item();
318  on_loggon_party( client->chr );
319  client->chr->send_buffs();
320 
321 
322  // Moved login_complete higher to prevent weather regions from messing up client
323  // spell icon packets(made it look like it was raining spell icons from spellbook if logged
324  // into a weather region with rain.
325  // login_complete(client);
326 }
327 
328 
329 void call_chr_scripts( Mobile::Character* chr, const std::string& root_script_ecl,
330  const std::string& pkg_script_ecl, bool offline = false )
331 {
332  ScriptDef sd;
333  sd.quickconfig( root_script_ecl );
334 
335  if ( sd.exists() )
336  {
337  call_script( sd, offline ? new Module::EOfflineCharacterRefObjImp( chr )
338  : new Module::ECharacterRefObjImp( chr ) );
339  }
340 
341  for ( Plib::Packages::iterator itr = Plib::systemstate.packages.begin();
342  itr != Plib::systemstate.packages.end(); ++itr )
343  {
344  Plib::Package* pkg = *itr;
345 
346  sd.quickconfig( pkg, pkg_script_ecl );
347  if ( sd.exists() )
348  {
349  call_script( sd, offline ? new Module::EOfflineCharacterRefObjImp( chr )
350  : new Module::ECharacterRefObjImp( chr ) );
351  }
352  }
353 }
354 
356 {
357  call_chr_scripts( chr, "scripts/misc/logon.ecl", "logon.ecl" );
358 }
360 {
361  call_chr_scripts( chr, "scripts/misc/reconnect.ecl", "reconnect.ecl" );
362 }
363 bool can_delete_character( Mobile::Character* chr, int delete_by )
364 {
365  ScriptDef sd;
366  sd.quickconfig( "scripts/misc/candelete.ecl" );
367 
368  if ( sd.exists() )
369  {
370  return call_script( sd, new Module::EOfflineCharacterRefObjImp( chr ),
371  new Bscript::BLong( delete_by ) );
372  }
373  else
374  {
375  return true;
376  }
377 }
379 {
380  call_chr_scripts( chr, "scripts/misc/ondelete.ecl", "ondelete.ecl", true );
381 }
382 
383 // FIXME: Consider moving most of this into a function, so character
384 // creation can use the same code.
385 void char_select( Network::Client* client, PKTIN_5D* msg )
386 {
387  bool reconnecting = false;
388  int charidx = cfBEu32( msg->charidx );
389  if ( ( charidx >= Plib::systemstate.config.character_slots ) || ( client->acct == nullptr ) ||
390  ( client->acct->get_character( charidx ) == nullptr ) )
391  {
393  client->Disconnect();
394  return;
395  }
396 
397  Mobile::Character* chosen_char = client->acct->get_character( charidx );
398 
399  POLLOG.Format( "Account {} selecting character {}\n" )
400  << client->acct->name() << chosen_char->name();
401 
402  if ( Plib::systemstate.config.min_cmdlevel_to_login > chosen_char->cmdlevel() )
403  {
404  POLLOG.Format(
405  "Account {} with character {} doesn't fit MinCmdlevelToLogin from pol.cfg. Client "
406  "disconnected by Core.\n" )
407  << client->acct->name() << chosen_char->name();
408 
410  client->Disconnect();
411  return;
412  }
413 
414  // Dave moved this from login.cpp so client cmdlevel can be checked before denying login
415  if ( ( ( std::count_if( networkManager.clients.begin(), networkManager.clients.end(),
418  {
419  POLLOG.Format(
420  "To much clients connected. Check MaximumClients and/or MaximumClientsBypassCmdLevel in "
421  "pol.cfg.\nAccount {} with character {} Client disconnected by Core.\n" )
422  << client->acct->name() << chosen_char->name();
423 
425  client->Disconnect();
426  return;
427  }
428 
429  if ( chosen_char->client )
430  {
431  // we're reattaching to a character that is in-game. If there is still
432  // a client attached, disconnect it.
433 
434  chosen_char->client->gd->clear();
435  chosen_char->client->forceDisconnect();
436  chosen_char->client->ready = 0;
438 
439  // disassociate the objects from each other.
440  chosen_char->client->acct = nullptr;
441  chosen_char->client->chr = nullptr;
442 
443  chosen_char->client = nullptr;
444  reconnecting = true;
445  }
446  else if ( !Plib::systemstate.config.allow_multi_clients_per_account &&
447  client->acct->has_active_characters() )
448  {
449  // We are trying to attach a new character, but AllowMultiCharacters is not set
451  client->Disconnect();
452  return;
453  }
454  else
455  {
456  // logging in a character that's offline.
458  chosen_char->logged_in( true );
459  }
460 
461  client->chr = chosen_char;
462  chosen_char->client = client;
463  chosen_char->acct.set( client->acct );
464 
465  client->UOExpansionFlagClient = cfBEu32( msg->clientflags );
466 
467  client->msgtype_filter = networkManager.game_filter.get();
468  start_client_char( client );
469 
470  if ( !chosen_char->lastx && !chosen_char->lasty )
471  {
472  chosen_char->lastx = chosen_char->x;
473  chosen_char->lasty = chosen_char->y;
474  }
475 
476  if ( !reconnecting )
477  run_logon_script( chosen_char );
478  else
479  run_reconnect_script( chosen_char );
480 }
481 
484 {
485  send_goxyz( client, client->chr );
486 
487  client->send_pause(); // dave removed force=true 5/10/3, let uoclient.cfg option determine xflow
488  // packets (else this hangs 4.0.0e clients)
489 
491  client->chr,
492  [&]( Mobile::Character* zonechr ) { send_client_char_data( zonechr, client ); } );
493 
494  send_inrange_items( client );
495  send_inrange_multis( client );
496 
497  client->send_restart(); // dave removed force=true 5/10/3
498 }
499 
501 {
502  transmit( client, msg, sizeof *msg );
503 }
504 
506 {
508  return;
509  for ( Clients::iterator itr = networkManager.clients.begin(), end = networkManager.clients.end();
510  itr != end; ++itr )
511  {
512  Network::Client* client = ( *itr );
513  if ( client->pause_count )
514  {
515  client->restart();
516  }
517  }
518 }
519 
521 {
523 }
524 
525 #define clock_t_to_ms( x ) ( x )
526 
527 void tasks_thread( void )
528 {
529  polclock_t sleeptime;
530  bool activity;
531  try
532  {
533  while ( !Clib::exit_signalled )
534  {
535  THREAD_CHECKPOINT( tasks, 1 );
536  {
537  PolLock lck;
539  THREAD_CHECKPOINT( tasks, 2 );
540  INC_PROFILEVAR( scheduler_passes );
541  check_scheduled_tasks( &sleeptime, &activity );
542  THREAD_CHECKPOINT( tasks, 3 );
544  THREAD_CHECKPOINT( tasks, 5 );
545  }
546 
547  THREAD_CHECKPOINT( tasks, 6 );
548  if ( activity )
549  send_pulse();
550  else
551  INC_PROFILEVAR( noactivity_scheduler_passes );
552  THREAD_CHECKPOINT( tasks, 7 );
553 
554  passert( sleeptime > 0 );
555 
556  TRACEBUF_ADDELEM( "tasks wait_for_pulse now", polclock() );
557  TRACEBUF_ADDELEM( "tasks wait_for_pulse sleeptime", sleeptime );
558 
559  THREAD_CHECKPOINT( tasks, 8 );
560  tasks_thread_sleep( polticks_t_to_ms( sleeptime ) );
561  THREAD_CHECKPOINT( tasks, 9 );
562  }
563  }
564  catch ( const char* msg )
565  {
566  POLLOG.Format( "Tasks Thread exits due to exception: {}\n" ) << msg;
567  throw;
568  }
569  catch ( std::string& str )
570  {
571  POLLOG.Format( "Tasks Thread exits due to exception: {}\n" ) << str;
572  throw;
573  }
574  catch ( std::exception& ex )
575  {
576  POLLOG.Format( "Tasks Thread exits due to exception: {}\n" ) << ex.what();
577  throw;
578  }
579 }
580 
581 void scripts_thread( void )
582 {
583  polclock_t sleeptime;
584  bool activity;
585  while ( !Clib::exit_signalled )
586  {
587  THREAD_CHECKPOINT( scripts, 0 );
588  {
589  PolLock lck;
591  TRACEBUF_ADDELEM( "scripts thread now", polclock() );
593  THREAD_CHECKPOINT( scripts, 1 );
594 
595  step_scripts( &sleeptime, &activity );
596 
597  THREAD_CHECKPOINT( scripts, 50 );
598 
600 
601  THREAD_CHECKPOINT( scripts, 52 );
602 
603  if ( TaskScheduler::is_dirty() )
604  {
605  THREAD_CHECKPOINT( scripts, 53 );
606 
608  }
609  }
610 
611  if ( activity )
612  {
614  }
615  else
616  {
618  }
619 
620  if ( sleeptime )
621  {
622  THREAD_CHECKPOINT( scripts, 54 );
623 
624  wait_for_pulse( polticks_t_to_ms( sleeptime ) );
625 
626  THREAD_CHECKPOINT( scripts, 55 );
627  }
628  }
629 }
630 
631 void combined_thread( void )
632 {
633  polclock_t sleeptime;
634  bool activity;
635  polclock_t script_clocksleft, scheduler_clocksleft;
636  polclock_t sleep_clocks;
637  polclock_t now;
638  while ( !Clib::exit_signalled )
639  {
641  do
642  {
643  PolLock lck;
644  step_scripts( &sleeptime, &activity );
645  check_scheduled_tasks( &sleeptime, &activity );
647  now = polclock();
648  script_clocksleft = calc_script_clocksleft( now );
649  scheduler_clocksleft = calc_scheduler_clocksleft( now );
650  if ( script_clocksleft < scheduler_clocksleft )
651  sleep_clocks = script_clocksleft;
652  else
653  sleep_clocks = scheduler_clocksleft;
654  } while ( sleep_clocks <= 0 );
655 
656  wait_for_pulse( clock_t_to_ms( sleep_clocks ) );
657  }
658 }
659 
660 void decay_thread( void* );
661 void decay_thread_shadow( void* );
662 void decay_single_thread( void* );
663 
664 template <class T>
665 inline void Delete( T* p )
666 {
667  delete p;
668 }
669 
670 template <class T>
672 {
673 public:
674  void operator()( T* p ) { delete p; }
675 };
676 
677 void reap_thread( void )
678 {
679  while ( !Clib::exit_signalled )
680  {
681  {
682  PolLock lck;
685  for ( auto& item : gamestate.dynamic_item_descriptors )
686  {
687  delete item;
688  }
690  }
691 
693  }
694 }
695 
696 
698 {
699  int timeouts_remaining = 1;
700  bool sent_wakeups = false;
701  // we want this thread to be the last out, so that it can report stuff at shutdown.
703  {
705  {
706  polclock_t now = polclock();
708  {
709  ERROR_PRINT << "########################################################\n";
710  ERROR_PRINT << "No clock movement in 30 seconds. Dumping thread status.\n";
713  }
714  }
715 
717  {
718  fmt::Writer tmp;
719  tmp << "*Thread Info*\n";
720  tmp << "Semaphore TID: " << locker << "\n";
721 
722  if ( Plib::systemstate.config.log_traces_when_stuck )
724 
725  tmp << "Scripts Thread Checkpoint: " << stateManager.polsig.scripts_thread_checkpoint << "\n";
726  tmp << "Last Script: " << Clib::scripts_thread_script
727  << " PC: " << Clib::scripts_thread_scriptPC << "\n";
728  tmp << "Escript Instruction Cycles: " << Bscript::escript_instr_cycles << "\n";
729  tmp << "Tasks Thread Checkpoint: " << stateManager.polsig.tasks_thread_checkpoint << "\n";
730  tmp << "Active Client Thread Checkpoint: "
732  tmp << "Number of clients: " << Core::networkManager.clients.size() << "\n";
733  for ( const auto& client : Core::networkManager.clients )
734  tmp << " " << Network::AddressToString( &client->ipaddr ) << " "
735  << ( client->acct == nullptr ? "prelogin " : client->acct->name() ) << " "
736  << client->checkpoint << "\n";
738  tmp << "check_attack_after_move() Checkpoint: "
740  tmp << "Current Threads:"
741  << "\n";
742  ThreadMap::Contents contents;
743  threadmap.CopyContents( contents );
744  for ( ThreadMap::Contents::const_iterator citr = contents.begin(); citr != contents.end();
745  ++citr )
746  {
747  tmp << ( *citr ).first << " - " << ( *citr ).second << "\n";
748  }
749  tmp << "Child threads (child_threads): " << threadhelp::child_threads << "\n";
750  tmp << "Registered threads (ThreadMap): " << contents.size() << "\n";
752  ERROR_PRINT << tmp.str();
753  }
754  if ( Clib::exit_signalled )
755  {
756  if ( !sent_wakeups )
757  {
758  send_pulse();
760  networkManager.clientTransmit->Cancel();
761 #ifdef HAVE_MYSQL
762  networkManager.sql_service->stop();
763 #endif
764  sent_wakeups = true;
765  }
766 
767  --timeouts_remaining;
768  if ( timeouts_remaining == 0 )
769  {
770  INFO_PRINT << "Waiting for " << threadhelp::child_threads << " child threads to exit\n";
771  timeouts_remaining = 5;
772  }
773  }
774  pol_sleep_ms( 1000 );
775  }
776  // cerr << "threadstatus thread exits." << endl;
778 }
779 
780 void catch_signals_thread( void );
781 void reload_configuration();
782 
783 void console_thread( void )
784 {
785 #ifndef _WIN32
786  Clib::KeyboardHook kb; // local to have a defined deconstruction to uninstall the hook
787 #endif
788  while ( !Clib::exit_signalled )
789  {
790  pol_sleep_ms( 1000 );
791 #ifdef _WIN32
793 #else
796  {
797  PolLock lck;
798  INFO_PRINT << "Reloading configuration...";
801  INFO_PRINT << "Done.\n";
802  }
803 #endif
804  }
805 }
806 
808 {
809  threadmap.Register( thread_pid(), "Main" );
810 
811  if ( Plib::systemstate.config.web_server )
813 
814  if ( Plib::systemstate.config.multithread == 1 )
815  {
816  checkpoint( "start tasks thread" );
818  checkpoint( "start scripts thread" );
820  }
821  else
822  {
823  checkpoint( "start combined scripts/tasks thread" );
825  }
826 
828  {
829  checkpoint( "start decay thread" );
830  if ( Plib::systemstate.config.single_thread_decay )
831  {
832  threadhelp::start_thread( decay_single_thread, "Decay", nullptr );
833  }
834  else
835  {
836  std::vector<Realms::Realm*>::iterator itr;
837  for ( itr = gamestate.Realms.begin(); itr != gamestate.Realms.end(); ++itr )
838  {
839  std::ostringstream thname;
840  thname << "Decay_" << ( *itr )->name();
841  if ( ( *itr )->is_shadowrealm )
842  threadhelp::start_thread( decay_thread_shadow, thname.str().c_str(), (void*)( *itr ) );
843  else
844  threadhelp::start_thread( decay_thread, thname.str().c_str(), (void*)( *itr ) );
845  }
846  }
847  }
848  else
849  {
850  checkpoint( "don't start decay thread" );
851  }
852 
853  checkpoint( "start reap thread" );
855 
856  checkpoint( "start dbglisten thread" );
858 
859  checkpoint( "start threadstatus thread" );
860  start_thread( threadstatus_thread, "ThreadStatus" );
861 
862  checkpoint( "start clienttransmit thread" );
863  start_thread( Network::ClientTransmitThread, "ClientTransmit" );
864 
865 #ifdef HAVE_MYSQL
866  checkpoint( "start sql service thread" );
868 #endif
869 }
870 
872 {
873  unsigned cli;
874  SOCKET nfds = 0;
875  FD_ZERO( &networkManager.polsocket.recv_fd );
876  FD_ZERO( &networkManager.polsocket.err_fd );
877  FD_ZERO( &networkManager.polsocket.send_fd );
878 
880 #ifndef _WIN32
882 #endif
883 
884  for ( cli = 0; cli < networkManager.clients.size(); cli++ )
885  {
886  Network::Client* client = networkManager.clients[cli];
887 
888  FD_SET( client->csocket, &networkManager.polsocket.recv_fd );
889  FD_SET( client->csocket, &networkManager.polsocket.err_fd );
890  if ( client->have_queued_data() )
891  FD_SET( client->csocket, &networkManager.polsocket.send_fd );
892 
893  if ( ( SOCKET )( client->csocket + 1 ) > nfds )
894  nfds = client->csocket + 1;
895  }
896 
897  int res;
898  do
899  {
902  res = select( static_cast<int>( nfds ), &networkManager.polsocket.recv_fd,
905  } while ( res < 0 && !Clib::exit_signalled && socket_errno == SOCKET_ERRNO( EINTR ) );
906 
907 
908  if ( res <= 0 )
909  return;
910 
911  for ( cli = 0; cli < networkManager.clients.size(); cli++ )
912  {
913  Network::Client* client = networkManager.clients[cli];
914 
915  if ( !client->isReallyConnected() )
916  continue;
917 
918  if ( FD_ISSET( client->csocket, &networkManager.polsocket.err_fd ) )
919  {
920  client->forceDisconnect();
921  }
922 
923  if ( FD_ISSET( client->csocket, &networkManager.polsocket.recv_fd ) )
924  {
925  process_data( client );
926  }
927 
928  if ( client->have_queued_data() &&
929  FD_ISSET( client->csocket, &networkManager.polsocket.send_fd ) )
930  {
931  client->send_queued_data();
932  }
933  }
934 
936 
938  {
939  struct sockaddr client_addr; // inet_addr
940  socklen_t addrlen = sizeof client_addr;
941  SOCKET client_socket = accept( networkManager.polsocket.listen_socket, &client_addr, &addrlen );
942  if ( client_socket == INVALID_SOCKET )
943  return;
944 
945  Network::apply_socket_options( client_socket );
946  if ( Plib::systemstate.config.disable_nagle )
947  {
948  Network::disable_nagle( client_socket );
949  }
950 
951  fmt::Writer tmp;
952  tmp.Format( "Client connected from {}\n" ) << Network::AddressToString( &client_addr );
953  INFO_PRINT << tmp.str();
954  if ( Plib::systemstate.config.loglevel >= 2 )
955  POLLOG << tmp.str();
956 
957  Network::Client* client =
958  new Network::Client( *Core::networkManager.uo_client_interface.get(),
960  client->csocket = client_socket;
961  memcpy( &client->ipaddr, &client_addr, sizeof client->ipaddr );
962  // Added null setting for pre-char selection checks using nullptr validation
963  client->acct = nullptr;
964 
965  networkManager.clients.push_back( client );
966  INFO_PRINT << "Client connected (Total: " << networkManager.clients.size() << ")\n";
967  }
968 }
969 #if REFPTR_DEBUG
970 unsigned int ref_counted::_ctor_calls;
971 #endif
972 
974 void display_reftypes();
975 
977 {
980 #if BOBJECTIMP_DEBUG
982 #endif
984  std::ofstream ofs;
985  Clib::OFStreamWriter sw( &ofs );
986  sw.init( "leftovers.txt" );
988  fmt::Writer tmp;
990  tmp << "Remaining UObjects: " << stateManager.uobjcount.uobject_count << "\n";
992  tmp << "Remaining Mobiles: " << stateManager.uobjcount.ucharacter_count << "\n";
993  if ( stateManager.uobjcount.npc_count != 0 )
994  tmp << "Remaining NPCs: " << stateManager.uobjcount.npc_count << "\n";
996  tmp << "Remaining Items: " << stateManager.uobjcount.uitem_count << "\n";
998  tmp << "Remaining Multis: " << stateManager.uobjcount.umulti_count << "\n";
1000  tmp << "Unreaped orphans: " << stateManager.uobjcount.unreaped_orphans << "\n";
1002  tmp << "Remaining EChrRef objects: " << stateManager.uobjcount.uobj_count_echrref << "\n";
1004  tmp << "Remaining Executors: " << Bscript::executor_count << "\n";
1006  tmp << "Remaining script objectimps: " << Bscript::eobject_imp_count << "\n";
1007  INFO_PRINT << tmp.str();
1008 }
1009 
1011 {
1012  INFO_PRINT << "Running startup script.\n";
1013  run_script_to_completion( "start" );
1014  for ( const auto& pkg : Plib::systemstate.packages )
1015  {
1016  std::string scriptname = pkg->dir() + "start.ecl";
1017 
1018  if ( Clib::FileExists( scriptname.c_str() ) )
1019  {
1020  ScriptDef script( "start", pkg, "" );
1021  Bscript::BObject obj( run_script_to_completion( script ) );
1022  }
1023  }
1024  INFO_PRINT << "Startup script complete.\n";
1025 }
1026 
1027 #ifdef _WIN32
1028 typedef BOOL( WINAPI* DynHeapSetInformation )( PVOID HeapHandle,
1029  HEAP_INFORMATION_CLASS HeapInformationClass,
1030  PVOID HeapInformation,
1031  SIZE_T HeapInformationLength );
1032 
1033 const char* Use_low_fragmentation_Heap()
1034 {
1036  {
1037  HINSTANCE hKernel32;
1038 
1039  hKernel32 = LoadLibrary( "Kernel32" );
1040  if ( hKernel32 != nullptr )
1041  {
1042  DynHeapSetInformation ProcAdd;
1043  ProcAdd = (DynHeapSetInformation)GetProcAddress( hKernel32, "HeapSetInformation" );
1044  if ( ProcAdd != nullptr )
1045  {
1046  ULONG HeapFragValue = 2;
1047 
1048  if ( ( ProcAdd )( GetProcessHeap(), HeapCompatibilityInformation, &HeapFragValue,
1049  sizeof( HeapFragValue ) ) )
1050  {
1051  FreeLibrary( hKernel32 );
1052  return "low-fragmentation Heap ...activated";
1053  }
1054  else
1055  {
1056  FreeLibrary( hKernel32 );
1057  return "low-fragmentation Heap ...not activated";
1058  }
1059  }
1060  else
1061  {
1062  FreeLibrary( hKernel32 );
1063  return "low-fragmentation Heap ...not available on your Windows";
1064  }
1065  }
1066  else
1067  return "low-fragmentation Heap ...not available on your Windows";
1068  }
1069  else
1070  return "low-fragmentation Heap ...disabled via ServSpecOpt";
1071 }
1072 #endif
1073 
1074 #ifdef __linux__
1075 void Check_libc_version()
1076 {
1077  const char* libc_version = gnu_get_libc_version();
1078 
1079  int main_version = 0;
1080  int sub_version = 0;
1081  int build = 0;
1082  ISTRINGSTREAM is( libc_version );
1083 
1084  if ( is >> main_version )
1085  {
1086  char delimiter;
1087  if ( is >> delimiter >> sub_version )
1088  {
1089  is >> delimiter >> build;
1090  }
1091  }
1092  else
1093  POLLOG_ERROR << "Error in analyzing libc version string [" << libc_version
1094  << "]. Please contact Core-Team.\n";
1095 
1096  if ( main_version * 100000000 + sub_version * 10000 + build >= 2 * 100000000 + 3 * 10000 + 2 )
1097  POLLOG_INFO << "Found libc " << libc_version << " - ok\n";
1098  else
1099  POLLOG_ERROR << "Found libc " << libc_version << " - Please update to 2.3.2 or above.\n";
1100 }
1101 #endif
1102 
1103 
1104 } // namespace Core
1105 
1106 int xmain_inner( bool testing )
1107 {
1108 #ifdef _WIN32
1110  // Aug. 15, 2006 Austin
1111  // Added atexit() call to remove the tray icon.
1113 #else
1114 #ifdef __linux__
1115  std::ofstream polpid;
1116 
1117  polpid.open( ( Plib::systemstate.config.pidfile_path + "pol.pid" ).c_str(),
1118  std::ios::out | std::ios::trunc );
1119 
1120  if ( polpid.is_open() )
1121  polpid << Clib::decint( getpid() );
1122  else
1123  INFO_PRINT << "Cannot create pid file in " << Plib::systemstate.config.pidfile_path << "\n";
1124 
1125  polpid.close();
1126 #endif
1127 #endif
1128 
1129  // problem with order of global construction, threads cannot be registered in the constructor of
1130  // gamestate :(
1132  std::max( 2u, std::thread::hardware_concurrency() / 2 ), "generic_task_thread" );
1133 
1134  int res;
1135 
1136  // for profiling:
1137  // chdir( "d:\\pol" );
1138  // PrintAllocationData();
1139 
1140  Clib::MakeDirectory( "log" );
1141 
1142  POLLOG_INFO << POL_VERSION_ID << " - " << Clib::ProgramConfig::build_target() << "\ncompiled on "
1144  << POL_COPYRIGHT << "\n\n";
1145  if ( testing )
1146  POLLOG_INFO << "TESTING MODE\n\n";
1147 
1148 #ifndef NDEBUG
1149  POLLOG_INFO << "Sizes: \n"
1150  << " UObject: " << sizeof( Core::UObject ) << "\n"
1151  << " Item: " << sizeof( Items::Item ) << "\n"
1152  << " UContainer: " << sizeof( Core::UContainer ) << "\n"
1153  << " Character: " << sizeof( Mobile::Character ) << "\n"
1154  << " Client: " << sizeof( Network::Client ) << "\n"
1155  << " NPC: " << sizeof( Mobile::NPC ) << "\n";
1156 
1157 #ifdef __unix__
1158 #ifdef PTHREAD_THREADS_MAX
1159  POLLOG_INFO << " Max Threads: " << PTHREAD_THREADS_MAX << "\n";
1160 #endif
1161 #endif
1162  POLLOG_INFO << "\n";
1163 #endif
1164  POLLOG_INFO << "Using " << Core::gamestate.task_thread_pool.size() << " out of "
1165  << std::thread::hardware_concurrency() << " worldsave threads\n";
1166 
1167  Core::checkpoint( "installing signal handlers" );
1169 
1170  Core::checkpoint( "starting POL clocks" );
1173 
1174  POLLOG_INFO << "Reading Configuration.\n";
1175 
1177 
1178  Core::checkpoint( "reading pol.cfg" );
1180 
1181  Core::checkpoint( "reading config/bannedips.cfg" );
1183 
1184  Core::checkpoint( "reading servspecopt.cfg" );
1186 
1187  Core::checkpoint( "reading extobj.cfg" );
1189 
1190 #ifdef _WIN32
1191  Core::checkpoint( Core::Use_low_fragmentation_Heap() );
1192 #endif
1193 
1194 #ifdef __linux__
1195  Core::checkpoint( "checking libc version" );
1196  Core::Check_libc_version();
1197 #endif
1198 
1199  Core::checkpoint( "init default itemdesc defaults" );
1200  Core::gamestate.empty_itemdesc->doubleclick_range =
1203 
1204  Core::checkpoint( "loading POL map file" );
1205  if ( !Core::load_realms() )
1206  {
1207  POLLOG_ERROR << "Unable to load Realms. Please make sure your Realms have been generated by "
1208  "UOConvert and your RealmDataPath is set correctly in Pol.cfg.\n";
1209  return 1;
1210  }
1211 
1212  // PrintAllocationData();
1213 
1214  Core::checkpoint( "initializing IPC structures" );
1217 
1218 #ifdef _WIN32
1220 #endif
1221 
1222  Core::checkpoint( "initializing sockets library" );
1224  if ( res < 0 )
1225  {
1226  POLLOG_ERROR << "Unable to initialize sockets library.\n";
1227  return 1;
1228  }
1229 
1230  Core::checkpoint( "loading configuration" );
1231  Core::load_data();
1232 
1233  Core::checkpoint( "loading system hooks" );
1235 
1236  Core::checkpoint( "loading packet hooks" );
1238 
1239  Core::checkpoint( "loading auxservice configuration" );
1241 
1242  Core::checkpoint( "reading menus" );
1244 
1245  Core::checkpoint( "loading intrinsic weapons" );
1247  Core::checkpoint( "validating intrinsic shield template" );
1249  Core::checkpoint( "reading gameservers" );
1251  Core::checkpoint( "reading starting locations" );
1253 
1254  if ( testing )
1255  {
1256  POLLOG_INFO << "Running POL test suite.\n";
1261  return 0;
1262  }
1263 
1264  // PrintAllocationData();
1265  POLLOG_INFO << "Reading data files:\n";
1266  {
1267  Tools::Timer<> timer;
1268  Core::checkpoint( "reading account data" );
1270 
1271  Core::checkpoint( "reading data" );
1272  Core::read_data();
1273  POLLOG_INFO << "Done! " << timer.ellapsed() << " milliseconds.\n";
1274  }
1275 
1276 
1279 
1280  // PrintAllocationData();
1281 
1282  // onetime_create_stubdata();
1283 
1284  Core::checkpoint( "running start scripts" );
1286 
1287  Core::checkpoint( "starting client listeners" );
1289 
1290  if ( Plib::systemstate.config.listen_port )
1291  {
1292  if ( Plib::systemstate.config.multithread )
1293  {
1294  // TODO: remove this warning after some releases...
1295 
1296  POLLOG_ERROR << "\n\n"
1297  << "+----------------------------------------------------------------------+\n"
1298  << "| Option ListenPort in pol.cfg is now only for non-multithreading |\n"
1299  << "| systems. If you still haven't done it, please read the documentation |\n"
1300  << "| on how to create a uoclients.cfg. |\n"
1301  << "+----------------------------------------------------------------------+\n"
1302  << "\n\n";
1303 
1304  throw std::runtime_error(
1305  "ListenPort is no longer used for multithreading programs (Multithread == 1)." );
1306  }
1307  Core::checkpoint( "opening listen socket" );
1309  Network::open_listen_socket( Plib::systemstate.config.listen_port );
1310  if ( Core::networkManager.polsocket.listen_socket == INVALID_SOCKET )
1311  {
1312  POLLOG_ERROR << "Unable to listen on socket " << Plib::systemstate.config.listen_port << "\n";
1313  return 1;
1314  }
1315  }
1316 
1317  // if( 1 )
1318  {
1319  POLLOG_INFO << "Initialization complete. POL is active. Ctrl-C to stop.\n\n";
1320  }
1321  // if( 1 )
1322  {
1323  DEINIT_STARTLOG();
1324  }
1325  POLLOG.Format( "{0:s} ({1:s}) compiled on {2:s} running.\n" )
1326  << POL_VERSION_ID << Clib::ProgramConfig::build_target()
1328  // if( 1 )
1329  {
1330  if ( Plib::systemstate.config.multithread == 0 )
1331  {
1332  POLLOG_INFO << "\n"
1333  "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
1334  "WARNING: Threading is disabled (Multithread==0 in pol.cfg). \n"
1335  " This setting is deprecated and will be removed from \n"
1336  " the next version of POL. It may not even work now! \n"
1337  " Only use this option if you really know what you are \n"
1338  " doing. And you probably don't. \n"
1339  "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
1340  "\n";
1341  }
1342  POLLOG_INFO << "Game is active.\n";
1343  }
1345 
1346  // goto skip;
1347 
1350 
1351  // this is done right after reading globals from pol.txt:
1352  // checkpoint( "starting game clock" );
1353  // start_gameclock();
1354 
1355  Core::checkpoint( "starting periodic tasks" );
1357 
1358  if ( Plib::systemstate.config.multithread )
1359  {
1360  Core::checkpoint( "starting threads" );
1363 
1364 #ifdef _WIN32
1366  Core::checkpoint( "exit signal detected" );
1368 #else
1369  // On Linux, signals are directed to a particular thread, if we use pthread_sigmask like we're
1370  // supposed to.
1371  // therefore, we have to do this signal checking in this thread.
1373 
1375 #endif
1376  Core::checkpoint( "waiting for child threads to exit" );
1377  // NOTE that it's possible that the thread_status thread not have exited yet..
1378  // it signals the catch_signals_thread (this one) just before it exits.
1379  // and on windows, we get here right after the console thread exits.
1380  while ( threadhelp::child_threads )
1381  {
1382  Core::pol_sleep_ms( 1000 );
1383  }
1384  Core::checkpoint( "child threads have shut down" );
1385  }
1386  else
1387  {
1388  Core::polclock_t sleeptime;
1389  bool activity;
1390  while ( !Clib::exit_signalled )
1391  {
1392  Core::stateManager.last_checkpoint = "receiving TCP/IP data";
1394  Core::stateManager.last_checkpoint = "running scheduled tasks";
1395  Core::check_scheduled_tasks( &sleeptime, &activity );
1396  Core::stateManager.last_checkpoint = "stepping scripts";
1397  Core::step_scripts( &sleeptime, &activity );
1398  Core::stateManager.last_checkpoint = "performing decay";
1399  if ( Core::settingsManager.ssopt.decay_items )
1401  Core::stateManager.last_checkpoint = "reaping objects";
1403  Core::stateManager.last_checkpoint = "restarting clients";
1404 
1406 
1408  }
1409  }
1412  POLLOG_INFO << "Shutting down...\n";
1413 
1414  Core::checkpoint( "writing data" );
1415  if ( Core::should_write_data() )
1416  {
1418  POLLOG_INFO << "Writing data files...";
1419 
1420  Core::PolLock lck;
1421  unsigned int dirty, clean;
1422  long long elapsed_ms;
1423  int savetype;
1424 
1427  else
1429 
1430  // TODO: full save if incremental_saves_disabled ?
1431  // otherwise could have really, really bad timewarps
1432  Tools::Timer<> timer;
1433  if ( savetype == Core::SAVE_FULL )
1434  Core::write_data( dirty, clean, elapsed_ms );
1435  else
1436  Core::save_incremental( dirty, clean, elapsed_ms );
1438  POLLOG_INFO << "Data save completed in " << elapsed_ms << " ms. " << timer.ellapsed()
1439  << " total.\n";
1440  }
1441  else
1442  {
1444  POLLOG_INFO << "Not writing data due to assertion failure.\n";
1445  else if ( Plib::systemstate.config.inhibit_saves )
1446  POLLOG_INFO << "Not writing data due to pol.cfg InhibitSaves=1 setting.\n";
1447  }
1449  return 0;
1450 }
1451 
1452 int xmain_outer( bool testing )
1453 {
1454  try
1455  {
1456  return xmain_inner( testing );
1457  }
1458  catch ( std::exception& )
1459  {
1460  if ( Core::stateManager.last_checkpoint != nullptr )
1461  {
1462  POLLOG_INFO << "Server Shutdown: " << Core::stateManager.last_checkpoint << "\n";
1463  // pol_sleep_ms( 10000 );
1464  }
1466 
1467  throw;
1468  }
1469 }
1470 }
#define clock_t_to_ms(x)
Definition: pol.cpp:525
void install_signal_handlers()
Definition: polsig.cpp:80
void decay_thread_shadow(void *arg)
Definition: decay.cpp:188
void pol_sleep_ms(unsigned int millis)
Definition: polclock.cpp:46
unsigned char u8
Definition: rawtypes.h:25
int assertion_shutdown_save_type
Definition: polcfg.h:86
void display_unreaped_orphan_instances()
Definition: uobject.cpp:57
std::atomic< int > eobject_imp_count
unsigned short default_doubleclick_range
Definition: ssopt.h:46
void allocate_intrinsic_weapon_serials()
void send_objects_newly_inrange(Network::Client *client)
Definition: movement.cpp:64
void check_weather_region_change(bool force=false)
Definition: charactr.cpp:3535
void load_aux_services()
Definition: auxclient.cpp:318
bool have_queued_data() const
Definition: client.h:281
virtual void walk_on(Mobile::Character *chr) POL_OVERRIDE
Definition: house.cpp:964
void run_reconnect_script(Mobile::Character *chr)
Definition: pol.cpp:359
void login_complete(Client *c)
Definition: ufunc.cpp:1947
void check_incoming_data(void)
Definition: pol.cpp:871
unsigned scripts_thread_checkpoint
Definition: polsig.h:26
void scripts_thread(void)
Definition: pol.cpp:581
void tasks_thread(void)
Definition: pol.cpp:527
void quickconfig(const Plib::Package *pkg, const std::string &name_ecl)
Definition: scrdef.cpp:112
const char * last_checkpoint
Definition: state.h:33
void MakeDirectory(const char *dir)
Definition: fileutil.cpp:62
void send_queued_data()
Definition: client.cpp:554
void apply_socket_options(SOCKET sck)
Definition: sockio.cpp:143
void forceDisconnect()
Definition: client.h:288
void textcmd_stoplog(Network::Client *client)
Definition: textcmd.cpp:389
std::vector< Items::ItemDesc * > dynamic_item_descriptors
Definition: uvars.h:206
void char_select(Network::Client *client, PKTIN_5D *msg)
Definition: pol.cpp:385
unsigned short max_clients
Definition: polcfg.h:64
static void ready()
blocks till possible last commit finishes
Definition: uimport.cpp:798
SystemState systemstate
Definition: systemstate.cpp:12
#define INVALID_SOCKET
Definition: wnsckt.h:12
std::string scripts_thread_script
Definition: passert.cpp:36
sockaddr ipaddr
Definition: client.h:213
int SOCKET
Definition: wnsckt.h:10
Network::Client * client
Definition: charactr.h:871
void send_pulse()
Definition: polsem.cpp:188
polclock_t polclock()
Definition: polclock.cpp:72
void wake_tasks_thread()
Definition: polsem.cpp:230
Core::PolConfig config
Definition: systemstate.h:43
const int SAVE_FULL
Definition: core.h:77
volatile bool reload_configuration_signalled
Definition: polsig.h:19
Accounts::Account * acct
Definition: client.h:181
bool walkheight(unsigned short x, unsigned short y, short oldz, short *newz, Multi::UMulti **pmulti, Items::Item **pwalkon, bool doors_block, Core::MOVEMODE movemode, short *gradual_boost=nullptr)
Definition: realmfunc.cpp:340
threadhelp::TaskThreadPool task_thread_pool
Definition: uvars.h:248
void SetCharacterWorldPosition(Mobile::Character *chr, Realms::WorldChangeReason reason)
Definition: uworld.cpp:128
std::atomic< int > pause_count
Definition: client.h:231
static void read_pol_config(bool initial_load)
Definition: polcfg.cpp:46
void cancel_all_trades()
Definition: dropitem.cpp:1088
#define cfBEu32(x)
Definition: clib_endian.h:43
#define POLLOG_INFO
Definition: logfacility.h:213
std::string decint(unsigned short v)
Definition: strutil.cpp:64
size_t thread_pid()
Definition: threadhelp.cpp:107
MusicDef * musicdef
Definition: uvars.h:152
unsigned short listen_port
Definition: polcfg.h:31
polticks_t polticks_t_to_ms(polticks_t ticks)
Definition: polclock.h:55
bool load_realms()
Definition: realms.cpp:28
static void check_console_commands(Clib::KeyboardHook *kb)
Definition: console.cpp:248
static void Initialize()
Definition: mdump.cpp:60
polclock_t calc_scheduler_clocksleft(polclock_t now)
Definition: schedule.cpp:245
std::unique_ptr< MessageTypeFilter > disconnected_filter
Definition: network.h:75
void start_pol_clocks()
Definition: polclock.cpp:111
Mobile::Character * get_character(int index)
Definition: account.cpp:169
void start_aux_services()
Definition: auxclient.cpp:304
unsigned char cmdlevel() const
Definition: charactr.h:993
void start_client_char(Network::Client *client)
Definition: pol.cpp:238
void reload_configuration()
Definition: loadunld.cpp:263
#define THREAD_CHECKPOINT(thread, check)
Definition: polsig.h:48
Core::WeatherRegion * weather_region
Definition: cgdata.h:75
void debug_listen_thread(void)
Definition: poldbg.cpp:1319
void start_thread(void(*entry)(void *), const char *thread_name, void *arg)
Definition: threadhelp.cpp:233
std::atomic< size_t > script_passes_activity
Definition: profile.h:76
unsigned short max_clients_bypass_cmdlevel
Definition: polcfg.h:66
unsigned tasks_thread_checkpoint
Definition: polsig.h:38
void transmit(Client *client, const void *data, int len)
Definition: clientio.cpp:291
#define TRACEBUF_ADDELEM(tag, value)
Definition: tracebuf.h:45
void send_inrange_items(Network::Client *client)
Definition: pol.cpp:224
void ClientTransmitThread()
bool connected() const
Definition: charactr.cpp:438
bool logged_in() const
Definition: charactr.cpp:428
void call_ondelete_scripts(Mobile::Character *chr)
Definition: pol.cpp:378
void init_pool(unsigned int max_count, const std::string &name)
Definition: threadhelp.cpp:379
int init_sockets_library(void)
Definition: sockio.cpp:88
virtual void register_object(UObject *obj)
Definition: multis.cpp:60
#define POLLOG_ERROR
Definition: logfacility.h:207
std::unique_ptr< SQLService > sql_service
Definition: network.h:61
bool has_active_characters()
Returns true if at least one character from this account is already logged in.
Definition: account.cpp:185
void display_leftover_objects()
Definition: pol.cpp:976
virtual T * getregion(xcoord x, ycoord y, Realms::Realm *realm)
Definition: region.h:126
void CoreSetSysTrayToolTip(const std::string &text, Priority priority)
Definition: core.cpp:36
void init_ipc_vars()
Definition: polsem.cpp:165
ProfileVars profilevars
Definition: state.h:47
void start_uo_client_listeners(void)
Definition: uolisten.cpp:164
void reap_thread(void)
Definition: pol.cpp:677
void allocate_intrinsic_equipment_serials()
Deferred allocator for serials during startup, see comments in register_intrinsic_equipment() ...
Definition: equipmnt.cpp:167
void start_threads()
Definition: pol.cpp:807
bool process_data(Network::Client *client)
void read_extobj()
Definition: extobj.cpp:22
Mobile::Character * chr
Definition: client.h:182
void handle_keep_alive(Network::Client *client, PKTBI_73 *msg)
Definition: pol.cpp:500
bool core_sends_season
Definition: ssopt.h:78
static void read_menus()
Definition: menu.cpp:101
void send_inrange_multis(Network::Client *client)
Definition: pol.cpp:230
std::unique_ptr< Items::ItemDesc > empty_itemdesc
Definition: uvars.h:208
unsigned short u16
Definition: rawtypes.h:26
unsigned int u32
Definition: rawtypes.h:27
void init_threadhelp()
Definition: threadhelp.cpp:94
void on_loggon_party(Mobile::Character *chr)
Definition: party.cpp:923
Multi::UMulti * system_find_multi(u32 serial)
Definition: fnsearch.cpp:50
size_t locker
Definition: polsem.cpp:27
bool exists() const
Definition: scrdef.cpp:126
int xmain_outer(bool testing)
Definition: pol.cpp:1452
std::unique_ptr< Network::ClientTransmit > clientTransmit
Definition: network.h:97
bool call_script(const ScriptDef &script, Bscript::BObjectImp *param0)
Definition: scrsched.cpp:546
int shutdown_save_type
Definition: polcfg.h:85
virtual class UHouse * as_house()
Definition: multis.cpp:55
void read_bannedips_config(bool initial_load)
Definition: bannedips.cpp:45
void combined_thread(void)
Definition: pol.cpp:631
void send_login_error(Network::Client *client, unsigned char reason)
Definition: login.cpp:60
void checkpoint(const char *msg, unsigned short minlvl)
Definition: checkpnt.cpp:17
Crypt::TCryptInfo client_encryption_version
Definition: polcfg.h:43
void send_goxyz(Client *client, const Character *chr)
Definition: ufunc.cpp:149
u64 escript_instr_cycles
Definition: escriptv.cpp:22
std::vector< Realms::Realm * > Realms
Definition: uvars.h:163
void stop_gameclock()
Stops the game clock and saves the current value into "gameclock".
Definition: gameclck.cpp:52
NetworkManager networkManager
Definition: network.cpp:28
bool passert_nosave
Definition: passert.cpp:33
unsigned short height() const
Definition: realm.h:245
void Send(Client *client, int len=-1) const
Definition: packethelper.h:69
Core::MusicRegion * music_region
Definition: cgdata.h:74
void CopyContents(Contents &out) const
Definition: threadhelp.cpp:307
polclock_t calc_script_clocksleft(polclock_t now)
Definition: scrsched.cpp:111
unsigned short select_timeout_usecs
Definition: polcfg.h:34
static bool is_dirty()
Definition: schedule.h:31
const char * name() const
Definition: account.cpp:193
void decay_single_thread(void *arg)
Definition: decay.cpp:235
JusticeDef * justicedef
Definition: uvars.h:148
void handle_resync_request(Network::Client *client, PKTBI_22_SYNC *msg)
Definition: pol.cpp:483
void display_bobjectimp_instances()
Definition: object.cpp:170
volatile bool report_status_signalled
Definition: polsig.h:20
#define socket_errno
Definition: wnsckt.cpp:34
void InitializeSystemTrayHandling()
Definition: polservice.cpp:269
typedef BOOL(WINAPI *MINIDUMPWRITEDUMP)(HANDLE hProcess
#define SOCKET_ERRNO(x)
Definition: wnsckt.cpp:33
#define passert(exp)
Definition: passert.h:62
const char * AddressToString(struct sockaddr *addr)
Definition: sockio.cpp:212
void start_sql_service()
Definition: sqlscrobj.cpp:501
void send_highlight() const
Definition: charactr.cpp:2937
#define POLLOG
Definition: logfacility.h:219
std::string pidfile_path
Definition: polcfg.h:30
signed char s8
Definition: rawtypes.h:29
int polclock_t
Definition: polclock.h:26
void run_start_scripts()
Definition: pol.cpp:1010
ClientGameData * gd
Definition: client.h:252
#define LOGIN_ERROR_MISC
Definition: pktdef.h:69
int xmain_inner(bool testing)
Definition: pol.cpp:1106
void read_gameservers()
Definition: uimport.cpp:1298
void signal_catch_thread()
Definition: polsig.cpp:110
void start_http_server()
Definition: polwww.cpp:898
GameState gamestate
Definition: uvars.cpp:74
void textcmd_startlog(Network::Client *client)
Definition: textcmd.cpp:341
void kill_disconnected_clients()
Definition: network.cpp:74
void send_realm_change(Client *client, Realms::Realm *realm)
Definition: ufunc.cpp:2034
std::atomic< clock_t > polclock_paused_at
Definition: state.h:42
void polclock_checkin()
Definition: pol.cpp:520
SOCKET open_listen_socket(unsigned short port)
Definition: sockio.cpp:159
SettingsManager settingsManager
Definition: settings.cpp:14
void disable_nagle(SOCKET sck)
Definition: sockio.cpp:131
static void InVisualRange(const UObject *obj, F &&f)
Definition: uworld.h:245
bool should_write_data()
Definition: uimport.cpp:1015
void run_pol_tests()
Definition: poltest.cpp:21
std::atomic< int > checkin_clock_times_out_at
Definition: state.h:64
struct timeval select_timeout
Definition: sockio.h:40
StateManager stateManager
Definition: state.cpp:8
unsigned check_attack_after_move_function_checkpoint
Definition: polsig.h:45
std::atomic< unsigned int > child_threads
unsigned int default_decay_time
Definition: ssopt.h:45
UoClientProtocol uoclient_protocol
Definition: network.h:68
void step_scripts(polclock_t *clocksleft, bool *pactivity)
Definition: scrsched.cpp:133
Core::AccountRef acct
Definition: charactr.h:914
virtual void init(const std::string &filepath) POL_OVERRIDE
Definition: streamsaver.cpp:64
Core::JusticeRegion * justice_region
Definition: cgdata.h:70
const Core::MessageTypeFilter * msgtype_filter
Definition: client.h:219
std::map< size_t, std::string > Contents
Definition: threadhelp.h:43
void operator()(T *p)
Definition: pol.cpp:674
#define ISTRINGSTREAM
Definition: stlutil.h:73
bool isReallyConnected() const
Definition: client.h:295
void position_changed(void)
Definition: charactr.cpp:3590
int save_incremental(unsigned int &dirty, unsigned int &clean, long long &elapsed_ms)
Definition: savedata.cpp:229
void check_scheduled_tasks(polclock_t *clocksleft, bool *pactivity)
Definition: schedule.cpp:186
Realms::Realm * realm
Definition: baseobject.h:56
void ShutdownSystemTrayHandling()
Definition: polservice.cpp:292
ObjectStorageManager objStorageManager
unsigned short width() const
Definition: realm.h:241
void run_logon_script(Mobile::Character *chr)
Definition: pol.cpp:355
long long ellapsed() const
Definition: timer.cpp:46
u32 UOExpansionFlagClient
Definition: client.h:259
static void logAllStackTraces()
Logs stack traces of all threads to stdout and error output.
bool run_script_to_completion(const char *filename, Bscript::BObjectImp *parameter)
Definition: scrsched.cpp:333
void PrintContents(Clib::StreamWriter &sw) const
Definition: objecthash.cpp:131
void send_startup(Network::Client *client)
Definition: pol.cpp:202
void console_thread(void)
Definition: pol.cpp:783
std::unique_ptr< MessageTypeFilter > game_filter
Definition: network.h:74
std::atomic< size_t > script_passes_noactivity
Definition: profile.h:77
static void read_servspecopt()
Definition: ssopt.cpp:44
bool passert_shutdown_due_to_assertion
Definition: passert.cpp:34
#define ERROR_PRINT
Definition: logfacility.h:230
void restart_all_clients()
Definition: pol.cpp:505
WeatherDef * weatherdef
Definition: uvars.h:151
void catch_signals_thread(void)
Definition: polsig.cpp:119
void load_intrinsic_weapons()
Creates the intrinsic wrestling weapon for PCs must be called at startup.
Definition: weapon.cpp:244
void send_client_char_data(Mobile::Character *chr, Network::Client *client)
Definition: ufunc.cpp:803
bool can_delete_character(Mobile::Character *chr, int delete_by)
Definition: pol.cpp:363
bool FileExists(const char *filename)
Definition: fileutil.cpp:118
void set(T *ptr)
Definition: refptr.h:276
void thread_sleep_ms(unsigned millis)
Definition: threadhelp.cpp:103
void read_account_data()
Definition: accounts.cpp:36
void Delete(T *p)
Definition: pol.cpp:665
int write_data(unsigned int &dirty_writes, unsigned int &clean_writes, long long &elapsed_ms)
Definition: uimport.cpp:1025
bool gflag_in_system_startup
Definition: state.h:40
void send_season_info(Client *client)
Definition: ufunc.cpp:2090
bool clientHasCharacter(Client *c)
Definition: ufunc.cpp:1942
#define INFO_PRINT
Definition: logfacility.h:223
void tasks_thread_sleep(unsigned int millis)
Definition: polsem.cpp:237
virtual std::string name() const
Definition: uobject.cpp:196
void decay_items()
Definition: decay.cpp:114
void send_owncreate(Client *client, const Character *chr)
Definition: ufunc.cpp:206
virtual void unregister_object(UObject *obj)
Definition: multis.cpp:62
void load_packet_hooks()
void start_tasks()
Definition: tasks.cpp:335
void display_reftypes()
Definition: reftypes.cpp:25
void call_chr_scripts(Mobile::Character *chr, const std::string &root_script_ecl, const std::string &pkg_script_ecl, bool offline=false)
Definition: pol.cpp:329
int executor_count
Definition: escriptv.cpp:18
static std::string build_target()
void send_map_difs(Client *client)
Sends number of maps used and number of map/static patches for each map.
Definition: ufunc.cpp:2044
Definition: berror.cpp:12
const polclock_t POLCLOCKS_PER_SEC
Definition: polclock.h:29
#define LOGIN_ERROR_OTHER_CHAR_INUSE
Definition: pktdef.h:64
void restart_pol_clocks()
Definition: polclock.cpp:126
Network::PolSocket polsocket
Definition: network.h:103
void pause_pol_clocks()
Definition: polclock.cpp:121
void load_data()
Definition: loadunld.cpp:152
void threadstatus_thread(void)
Definition: pol.cpp:697
std::atomic< bool > exit_signalled
void load_system_hooks()
Definition: syshook.cpp:232
void validate_intrinsic_shield_template()
Must be called at startup, validates the intrinsic shield element.
Definition: armor.cpp:202
void wait_for_pulse(unsigned int millis)
Definition: polsem.cpp:217
ThreadMap threadmap
Definition: threadhelp.cpp:40
int read_data()
Definition: uimport.cpp:609
static std::string build_datetime()
void read_starting_locations()
Definition: uimport.cpp:1230
void decay_thread(void *arg)
Definition: decay.cpp:163
unsigned active_client_thread_checkpoint
Definition: polsig.h:43
unsigned scripts_thread_scriptPC
Definition: passert.cpp:37
void Register(size_t pid, const std::string &name)
Definition: threadhelp.cpp:281
#define DEINIT_STARTLOG
Definition: logfacility.h:254
void display_executor_instances()
Definition: executor.cpp:61
UObjCount uobjcount
Definition: state.h:49
#define INC_PROFILEVAR(counter)
Definition: profile.h:85