@@ -93,11 +93,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
93
93
#ifdef HAVE_TOUCHSCREENGUI
94
94
#include " touchscreengui.h"
95
95
#endif
96
+
96
97
/*
97
98
Settings.
98
99
These are loaded from the config file.
99
100
*/
100
- Settings main_settings;
101
+ static Settings main_settings;
101
102
Settings *g_settings = &main_settings;
102
103
std::string g_settings_path;
103
104
@@ -125,6 +126,66 @@ std::ostream *derr_server_ptr = &errorstream;
125
126
std::ostream *dout_client_ptr = &infostream;
126
127
std::ostream *derr_client_ptr = &errorstream;
127
128
129
+ #define DEBUGFILE " debug.txt"
130
+ #define DEFAULT_SERVER_PORT 30000
131
+
132
+ typedef std::map<std::string, ValueSpec> OptionList;
133
+
134
+ struct GameParams {
135
+ u16 socket_port;
136
+ std::string world_path;
137
+ SubgameSpec game_spec;
138
+ bool is_dedicated_server;
139
+ int log_level;
140
+ };
141
+
142
+ /* *********************************************************************
143
+ * Private functions
144
+ **********************************************************************/
145
+
146
+ static bool get_cmdline_opts (int argc, char *argv[], Settings *cmd_args);
147
+ static void set_allowed_options (OptionList *allowed_options);
148
+
149
+ static void print_help (const OptionList &allowed_options);
150
+ static void print_allowed_options (const OptionList &allowed_options);
151
+ static void print_version ();
152
+ static void print_worldspecs (const std::vector<WorldSpec> &worldspecs,
153
+ std::ostream &os);
154
+ static void print_modified_quicktune_values ();
155
+
156
+ static void list_game_ids ();
157
+ static void list_worlds ();
158
+ static void setup_log_params (const Settings &cmd_args);
159
+ static bool create_userdata_path ();
160
+ static bool init_common (int *log_level, const Settings &cmd_args);
161
+ static void startup_message ();
162
+ static bool read_config_file (const Settings &cmd_args);
163
+ static void init_debug_streams (int *log_level, const Settings &cmd_args);
164
+
165
+ static bool game_configure (GameParams *game_params, const Settings &cmd_args);
166
+ static void game_configure_port (GameParams *game_params, const Settings &cmd_args);
167
+
168
+ static bool game_configure_world (GameParams *game_params, const Settings &cmd_args);
169
+ static bool get_world_from_cmdline (GameParams *game_params, const Settings &cmd_args);
170
+ static bool get_world_from_config (GameParams *game_params, const Settings &cmd_args);
171
+ static bool auto_select_world (GameParams *game_params);
172
+ static std::string get_clean_world_path (const std::string &path);
173
+
174
+ static bool game_configure_subgame (GameParams *game_params, const Settings &cmd_args);
175
+ static bool get_game_from_cmdline (GameParams *game_params, const Settings &cmd_args);
176
+ static bool determine_subgame (GameParams *game_params);
177
+
178
+ static bool run_dedicated_server (const GameParams &game_params, const Settings &cmd_args);
179
+ static bool migrate_database (const GameParams &game_params, const Settings &cmd_args,
180
+ Server *server);
181
+
182
+ #ifndef SERVER
183
+ static bool print_video_modes ();
184
+ static void speed_tests ();
185
+ #endif
186
+
187
+ /* *********************************************************************/
188
+
128
189
#ifndef SERVER
129
190
/*
130
191
Random stuff
@@ -285,7 +346,7 @@ class MyEventReceiver : public IEventReceiver
285
346
}
286
347
#endif
287
348
// handle mouse events
288
- if (event.EventType == irr::EET_MOUSE_INPUT_EVENT) {
349
+ if (event.EventType == irr::EET_MOUSE_INPUT_EVENT) {
289
350
if (noMenuActive () == false ) {
290
351
left_active = false ;
291
352
middle_active = false ;
@@ -312,8 +373,9 @@ class MyEventReceiver : public IEventReceiver
312
373
}
313
374
}
314
375
}
315
- if (event.EventType == irr::EET_LOG_TEXT_EVENT) {
316
- dstream<< std::string (" Irrlicht log: " ) + std::string (event.LogEvent .Text )<<std::endl;
376
+ if (event.EventType == irr::EET_LOG_TEXT_EVENT) {
377
+ dstream << std::string (" Irrlicht log: " ) + std::string (event.LogEvent .Text )
378
+ << std::endl;
317
379
return true ;
318
380
}
319
381
/* always return false in order to continue processing events */
@@ -649,334 +711,447 @@ class RandomInputHandler : public InputHandler
649
711
bool rightreleased;
650
712
};
651
713
714
+
715
+ class ClientLauncher
716
+ {
717
+ public:
718
+ ClientLauncher () :
719
+ list_video_modes (false ),
720
+ skip_main_menu (false ),
721
+ use_freetype (false ),
722
+ random_input (false ),
723
+ address (" " ),
724
+ playername (" " ),
725
+ password (" " ),
726
+ device (NULL ),
727
+ input (NULL ),
728
+ receiver (NULL ),
729
+ skin (NULL ),
730
+ font (NULL ),
731
+ simple_singleplayer_mode (false ),
732
+ current_playername (" inv£lid" ),
733
+ current_password (" " ),
734
+ current_address (" does-not-exist" ),
735
+ current_port (0 )
736
+ {}
737
+
738
+ ~ClientLauncher ();
739
+
740
+ bool run (GameParams &game_params, const Settings &cmd_args);
741
+
742
+ protected:
743
+ void init_args (GameParams &game_params, const Settings &cmd_args);
744
+ bool init_engine (int log_level);
745
+
746
+ bool launch_game (std::wstring *error_message, GameParams &game_params,
747
+ const Settings &cmd_args);
748
+
749
+ void main_menu (MainMenuData *menudata);
750
+ bool create_engine_device (int log_level);
751
+
752
+ bool list_video_modes;
753
+ bool skip_main_menu;
754
+ bool use_freetype;
755
+ bool random_input;
756
+ std::string address;
757
+ std::string playername;
758
+ std::string password;
759
+ IrrlichtDevice *device;
760
+ InputHandler *input;
761
+ MyEventReceiver *receiver;
762
+ gui::IGUISkin *skin;
763
+ gui::IGUIFont *font;
764
+ scene::ISceneManager *smgr;
765
+ SubgameSpec gamespec;
766
+ WorldSpec worldspec;
767
+ bool simple_singleplayer_mode;
768
+
769
+ // These are set up based on the menu and other things
770
+ // TODO: Are these required since there's already playername, password, etc
771
+ std::string current_playername;
772
+ std::string current_password;
773
+ std::string current_address;
774
+ int current_port;
775
+ };
776
+
652
777
#endif // !SERVER
653
778
654
- // These are defined global so that they're not optimized too much.
655
- // Can't change them to volatile.
656
- s16 temp16;
657
- f32 tempf;
658
- v3f tempv3f1;
659
- v3f tempv3f2;
660
- std::string tempstring;
661
- std::string tempstring2;
779
+ static OptionList allowed_options;
662
780
663
- void SpeedTests ( )
781
+ int main ( int argc, char *argv[] )
664
782
{
665
- {
666
- infostream << " The following test should take around 20ms." << std::endl;
667
- TimeTaker timer (" Testing std::string speed" );
668
- const u32 jj = 10000 ;
669
- for (u32 j = 0 ; j < jj; j++) {
670
- tempstring = " " ;
671
- tempstring2 = " " ;
672
- const u32 ii = 10 ;
673
- for (u32 i = 0 ; i < ii; i++) {
674
- tempstring2 += " asd" ;
675
- }
676
- for (u32 i = 0 ; i < ii+1 ; i++) {
677
- tempstring += " asd" ;
678
- if (tempstring == tempstring2)
679
- break ;
680
- }
681
- }
682
- }
783
+ int retval;
683
784
684
- infostream << " All of the following tests should take around 100ms each. "
685
- << std::endl ;
785
+ log_add_output_maxlev (&main_stderr_log_out, LMT_ACTION);
786
+ log_add_output_all_levs (&main_dstream_no_stderr_log_out) ;
686
787
687
- {
688
- TimeTaker timer (" Testing floating-point conversion speed" );
689
- tempf = 0.001 ;
690
- for (u32 i = 0 ; i < 4000000 ; i++) {
691
- temp16 += tempf;
692
- tempf += 0.001 ;
693
- }
694
- }
788
+ log_register_thread (" main" );
695
789
696
- {
697
- TimeTaker timer (" Testing floating-point vector speed" );
790
+ Settings cmd_args;
791
+ bool cmd_args_ok = get_cmdline_opts (argc, argv, &cmd_args);
792
+ if (!cmd_args_ok
793
+ || cmd_args.getFlag (" help" )
794
+ || cmd_args.exists (" nonopt1" )) {
795
+ print_help (allowed_options);
796
+ return cmd_args_ok ? 0 : 1 ;
797
+ }
698
798
699
- tempv3f1 = v3f (1 , 2 , 3 );
700
- tempv3f2 = v3f (4 , 5 , 6 );
701
- for (u32 i = 0 ; i < 10000000 ; i++) {
702
- tempf += tempv3f1.dotProduct (tempv3f2);
703
- tempv3f2 += v3f (7 , 8 , 9 );
704
- }
799
+ if (cmd_args.getFlag (" version" )) {
800
+ print_version ();
801
+ return 0 ;
705
802
}
706
803
707
- {
708
- TimeTaker timer (" Testing std::map speed" );
804
+ setup_log_params (cmd_args);
709
805
710
- std::map<v2s16, f32> map1;
711
- tempf = -324 ;
712
- const s16 ii = 300 ;
713
- for (s16 y = 0 ; y < ii; y++) {
714
- for (s16 x = 0 ; x < ii; x++) {
715
- map1[v2s16 (x, y)] = tempf;
716
- tempf += 1 ;
717
- }
718
- }
719
- for (s16 y = ii - 1 ; y >= 0 ; y--) {
720
- for (s16 x = 0 ; x < ii; x++) {
721
- tempf = map1[v2s16 (x, y)];
722
- }
723
- }
806
+ porting::signal_handler_init ();
807
+ porting::initializePaths ();
808
+
809
+ if (!create_userdata_path ()) {
810
+ errorstream << " Cannot create user data directory" << std::endl;
811
+ return 1 ;
724
812
}
725
813
726
- {
727
- infostream << " Around 5000/ms should do well here. " << std::endl ;
728
- TimeTaker timer ( " Testing mutex speed " );
814
+ // Initialize debug stacks
815
+ debug_stacks_init () ;
816
+ DSTACK (__FUNCTION_NAME );
729
817
730
- JMutex m;
731
- u32 n = 0 ;
732
- u32 i = 0 ;
733
- do {
734
- n += 10000 ;
735
- for (; i < n; i++) {
736
- m.Lock ();
737
- m.Unlock ();
738
- }
739
- }
740
- // Do at least 10ms
741
- while (timer.getTimerTime () < 10 );
818
+ // Debug handler
819
+ BEGIN_DEBUG_EXCEPTION_HANDLER
742
820
743
- u32 dtime = timer.stop ();
744
- u32 per_ms = n / dtime;
745
- infostream << " Done. " << dtime << " ms, " << per_ms << " /ms" << std::endl;
821
+ // List gameids if requested
822
+ if (cmd_args.exists (" gameid" ) && cmd_args.get (" gameid" ) == " list" ) {
823
+ list_game_ids ();
824
+ return 0 ;
746
825
}
747
- }
748
826
749
- static void print_worldspecs (const std::vector<WorldSpec> &worldspecs, std::ostream &os)
750
- {
751
- for (u32 i = 0 ; i < worldspecs.size (); i++) {
752
- std::string name = worldspecs[i].name ;
753
- std::string path = worldspecs[i].path ;
754
- if (name.find (" " ) != std::string::npos)
755
- name = std::string (" '" ) + name + " '" ;
756
- path = std::string (" '" ) + path + " '" ;
757
- name = padStringRight (name, 14 );
758
- os << " " << name << " " << path << std::endl;
827
+ // List worlds if requested
828
+ if (cmd_args.exists (" world" ) && cmd_args.get (" world" ) == " list" ) {
829
+ list_worlds ();
830
+ return 0 ;
831
+ }
832
+
833
+ GameParams game_params;
834
+ if (!init_common (&game_params.log_level , cmd_args))
835
+ return 1 ;
836
+
837
+ #ifndef __ANDROID__
838
+ // Run unit tests
839
+ if ((ENABLE_TESTS && cmd_args.getFlag (" disable-unittests" ) == false )
840
+ || cmd_args.getFlag (" enable-unittests" ) == true ) {
841
+ run_tests ();
759
842
}
843
+ #endif
844
+
845
+ #ifdef SERVER
846
+ game_params.is_dedicated_server = true ;
847
+ #else
848
+ game_params.is_dedicated_server = cmd_args.getFlag (" server" );
849
+ #endif
850
+
851
+ if (!game_configure (&game_params, cmd_args))
852
+ return 1 ;
853
+
854
+ assert (game_params.world_path != " " );
855
+
856
+ infostream << " Using commanded world path ["
857
+ << game_params.world_path << " ]" << std::endl;
858
+
859
+ // Run dedicated server if asked to or no other option
860
+ g_settings->set (" server_dedicated" ,
861
+ game_params.is_dedicated_server ? " true" : " false" );
862
+
863
+ if (game_params.is_dedicated_server )
864
+ return run_dedicated_server (game_params, cmd_args) ? 0 : 1 ;
865
+
866
+ #ifndef SERVER
867
+ ClientLauncher launcher;
868
+ retval = launcher.run (game_params, cmd_args) ? 0 : 1 ;
869
+ #else
870
+ retval = 0 ;
871
+ #endif
872
+
873
+ // Update configuration file
874
+ if (g_settings_path != " " )
875
+ g_settings->updateConfigFile (g_settings_path.c_str ());
876
+
877
+ print_modified_quicktune_values ();
878
+
879
+ // Stop httpfetch thread (if started)
880
+ httpfetch_cleanup ();
881
+
882
+ END_DEBUG_EXCEPTION_HANDLER (errorstream)
883
+
884
+ return retval;
760
885
}
761
886
762
- int main (int argc, char *argv[])
763
- {
764
- int retval = 0 ;
765
887
766
- / *
767
- Initialization
768
- */
888
+ /* *************************************************************************** *
889
+ * Startup / Init
890
+ **************************************************************************** */
769
891
770
- log_add_output_maxlev (&main_stderr_log_out, LMT_ACTION);
771
- log_add_output_all_levs (&main_dstream_no_stderr_log_out);
772
892
773
- log_register_thread (" main" );
774
- /*
775
- Parse command line
776
- */
893
+ static bool get_cmdline_opts (int argc, char *argv[], Settings *cmd_args)
894
+ {
895
+ set_allowed_options (&allowed_options);
896
+
897
+ return cmd_args->parseCommandLine (argc, argv, allowed_options);
898
+ }
899
+
900
+ static void set_allowed_options (OptionList *allowed_options)
901
+ {
902
+ allowed_options->clear ();
777
903
778
- // List all allowed options
779
- std::map<std::string, ValueSpec> allowed_options;
780
- allowed_options.insert (std::make_pair (" help" , ValueSpec (VALUETYPE_FLAG,
904
+ allowed_options->insert (std::make_pair (" help" , ValueSpec (VALUETYPE_FLAG,
781
905
_ (" Show allowed options" ))));
782
- allowed_options. insert (std::make_pair (" version" , ValueSpec (VALUETYPE_FLAG,
906
+ allowed_options-> insert (std::make_pair (" version" , ValueSpec (VALUETYPE_FLAG,
783
907
_ (" Show version information" ))));
784
- allowed_options. insert (std::make_pair (" config" , ValueSpec (VALUETYPE_STRING,
908
+ allowed_options-> insert (std::make_pair (" config" , ValueSpec (VALUETYPE_STRING,
785
909
_ (" Load configuration from specified file" ))));
786
- allowed_options. insert (std::make_pair (" port" , ValueSpec (VALUETYPE_STRING,
910
+ allowed_options-> insert (std::make_pair (" port" , ValueSpec (VALUETYPE_STRING,
787
911
_ (" Set network port (UDP)" ))));
788
- allowed_options. insert (std::make_pair (" disable-unittests" , ValueSpec (VALUETYPE_FLAG,
912
+ allowed_options-> insert (std::make_pair (" disable-unittests" , ValueSpec (VALUETYPE_FLAG,
789
913
_ (" Disable unit tests" ))));
790
- allowed_options. insert (std::make_pair (" enable-unittests" , ValueSpec (VALUETYPE_FLAG,
914
+ allowed_options-> insert (std::make_pair (" enable-unittests" , ValueSpec (VALUETYPE_FLAG,
791
915
_ (" Enable unit tests" ))));
792
- allowed_options. insert (std::make_pair (" map-dir" , ValueSpec (VALUETYPE_STRING,
916
+ allowed_options-> insert (std::make_pair (" map-dir" , ValueSpec (VALUETYPE_STRING,
793
917
_ (" Same as --world (deprecated)" ))));
794
- allowed_options. insert (std::make_pair (" world" , ValueSpec (VALUETYPE_STRING,
918
+ allowed_options-> insert (std::make_pair (" world" , ValueSpec (VALUETYPE_STRING,
795
919
_ (" Set world path (implies local game) ('list' lists all)" ))));
796
- allowed_options. insert (std::make_pair (" worldname" , ValueSpec (VALUETYPE_STRING,
920
+ allowed_options-> insert (std::make_pair (" worldname" , ValueSpec (VALUETYPE_STRING,
797
921
_ (" Set world by name (implies local game)" ))));
798
- allowed_options. insert (std::make_pair (" quiet" , ValueSpec (VALUETYPE_FLAG,
922
+ allowed_options-> insert (std::make_pair (" quiet" , ValueSpec (VALUETYPE_FLAG,
799
923
_ (" Print to console errors only" ))));
800
- allowed_options. insert (std::make_pair (" info" , ValueSpec (VALUETYPE_FLAG,
924
+ allowed_options-> insert (std::make_pair (" info" , ValueSpec (VALUETYPE_FLAG,
801
925
_ (" Print more information to console" ))));
802
- allowed_options. insert (std::make_pair (" verbose" , ValueSpec (VALUETYPE_FLAG,
926
+ allowed_options-> insert (std::make_pair (" verbose" , ValueSpec (VALUETYPE_FLAG,
803
927
_ (" Print even more information to console" ))));
804
- allowed_options. insert (std::make_pair (" trace" , ValueSpec (VALUETYPE_FLAG,
928
+ allowed_options-> insert (std::make_pair (" trace" , ValueSpec (VALUETYPE_FLAG,
805
929
_ (" Print enormous amounts of information to log and console" ))));
806
- allowed_options. insert (std::make_pair (" logfile" , ValueSpec (VALUETYPE_STRING,
930
+ allowed_options-> insert (std::make_pair (" logfile" , ValueSpec (VALUETYPE_STRING,
807
931
_ (" Set logfile path ('' = no logging)" ))));
808
- allowed_options. insert (std::make_pair (" gameid" , ValueSpec (VALUETYPE_STRING,
932
+ allowed_options-> insert (std::make_pair (" gameid" , ValueSpec (VALUETYPE_STRING,
809
933
_ (" Set gameid (\" --gameid list\" prints available ones)" ))));
810
- allowed_options. insert (std::make_pair (" migrate" , ValueSpec (VALUETYPE_STRING,
934
+ allowed_options-> insert (std::make_pair (" migrate" , ValueSpec (VALUETYPE_STRING,
811
935
_ (" Migrate from current map backend to another (Only works when using minetestserver or with --server)" ))));
812
936
#ifndef SERVER
813
- allowed_options. insert (std::make_pair (" videomodes" , ValueSpec (VALUETYPE_FLAG,
937
+ allowed_options-> insert (std::make_pair (" videomodes" , ValueSpec (VALUETYPE_FLAG,
814
938
_ (" Show available video modes" ))));
815
- allowed_options. insert (std::make_pair (" speedtests" , ValueSpec (VALUETYPE_FLAG,
939
+ allowed_options-> insert (std::make_pair (" speedtests" , ValueSpec (VALUETYPE_FLAG,
816
940
_ (" Run speed tests" ))));
817
- allowed_options. insert (std::make_pair (" address" , ValueSpec (VALUETYPE_STRING,
941
+ allowed_options-> insert (std::make_pair (" address" , ValueSpec (VALUETYPE_STRING,
818
942
_ (" Address to connect to. ('' = local game)" ))));
819
- allowed_options. insert (std::make_pair (" random-input" , ValueSpec (VALUETYPE_FLAG,
943
+ allowed_options-> insert (std::make_pair (" random-input" , ValueSpec (VALUETYPE_FLAG,
820
944
_ (" Enable random user input, for testing" ))));
821
- allowed_options. insert (std::make_pair (" server" , ValueSpec (VALUETYPE_FLAG,
945
+ allowed_options-> insert (std::make_pair (" server" , ValueSpec (VALUETYPE_FLAG,
822
946
_ (" Run dedicated server" ))));
823
- allowed_options. insert (std::make_pair (" name" , ValueSpec (VALUETYPE_STRING,
947
+ allowed_options-> insert (std::make_pair (" name" , ValueSpec (VALUETYPE_STRING,
824
948
_ (" Set player name" ))));
825
- allowed_options. insert (std::make_pair (" password" , ValueSpec (VALUETYPE_STRING,
949
+ allowed_options-> insert (std::make_pair (" password" , ValueSpec (VALUETYPE_STRING,
826
950
_ (" Set password" ))));
827
- allowed_options. insert (std::make_pair (" go" , ValueSpec (VALUETYPE_FLAG,
951
+ allowed_options-> insert (std::make_pair (" go" , ValueSpec (VALUETYPE_FLAG,
828
952
_ (" Disable main menu" ))));
829
953
#endif
830
954
831
- Settings cmd_args;
955
+ }
832
956
833
- bool ret = cmd_args.parseCommandLine (argc, argv, allowed_options);
834
-
835
- if (ret == false || cmd_args.getFlag (" help" ) || cmd_args.exists (" nonopt1" )) {
836
- dstream << _ (" Allowed options:" ) << std::endl;
837
- for (std::map<std::string, ValueSpec>::iterator
838
- i = allowed_options.begin ();
839
- i != allowed_options.end (); ++i) {
840
- std::ostringstream os1 (std::ios::binary);
841
- os1 << " --" <<i->first ;
842
- if (i->second .type == VALUETYPE_FLAG) {
843
- } else
844
- os1 << _ (" <value>" );
845
- dstream << padStringRight (os1.str (), 24 );
846
-
847
- if (i->second .help != NULL )
848
- dstream << i->second .help ;
849
- dstream << std::endl;
850
- }
957
+ static void print_help (const OptionList &allowed_options)
958
+ {
959
+ dstream << _ (" Allowed options:" ) << std::endl;
960
+ print_allowed_options (allowed_options);
961
+ }
962
+
963
+ static void print_allowed_options (const OptionList &allowed_options)
964
+ {
965
+ for (OptionList::const_iterator i = allowed_options.begin ();
966
+ i != allowed_options.end (); ++i) {
967
+ std::ostringstream os1 (std::ios::binary);
968
+ os1 << " --" << i->first ;
969
+ if (i->second .type != VALUETYPE_FLAG)
970
+ os1 << _ (" <value>" );
851
971
852
- return cmd_args.getFlag (" help" ) ? 0 : 1 ;
972
+ dstream << padStringRight (os1.str (), 24 );
973
+
974
+ if (i->second .help != NULL )
975
+ dstream << i->second .help ;
976
+
977
+ dstream << std::endl;
853
978
}
979
+ }
854
980
855
- if (cmd_args.getFlag (" version" )) {
981
+ static void print_version ()
982
+ {
856
983
#ifdef SERVER
857
- dstream << " minetestserver " << minetest_version_hash << std::endl;
984
+ dstream << " minetestserver " << minetest_version_hash << std::endl;
858
985
#else
859
- dstream << " Minetest " << minetest_version_hash << std::endl;
860
- dstream << " Using Irrlicht " << IRRLICHT_SDK_VERSION << std::endl;
986
+ dstream << " Minetest " << minetest_version_hash << std::endl;
987
+ dstream << " Using Irrlicht " << IRRLICHT_SDK_VERSION << std::endl;
861
988
#endif
862
- dstream << " Build info: " << minetest_build_info << std::endl;
863
- return 0 ;
989
+ dstream << " Build info: " << minetest_build_info << std::endl;
990
+ }
991
+
992
+ static void list_game_ids ()
993
+ {
994
+ std::set<std::string> gameids = getAvailableGameIds ();
995
+ for (std::set<std::string>::const_iterator i = gameids.begin ();
996
+ i != gameids.end (); i++)
997
+ dstream << (*i) <<std::endl;
998
+ }
999
+
1000
+ static void list_worlds ()
1001
+ {
1002
+ dstream << _ (" Available worlds:" ) << std::endl;
1003
+ std::vector<WorldSpec> worldspecs = getAvailableWorlds ();
1004
+ print_worldspecs (worldspecs, dstream);
1005
+ }
1006
+
1007
+ static void print_worldspecs (const std::vector<WorldSpec> &worldspecs,
1008
+ std::ostream &os)
1009
+ {
1010
+ for (size_t i = 0 ; i < worldspecs.size (); i++) {
1011
+ std::string name = worldspecs[i].name ;
1012
+ std::string path = worldspecs[i].path ;
1013
+ if (name.find (" " ) != std::string::npos)
1014
+ name = std::string (" '" ) + name + " '" ;
1015
+ path = std::string (" '" ) + path + " '" ;
1016
+ name = padStringRight (name, 14 );
1017
+ os << " " << name << " " << path << std::endl;
864
1018
}
1019
+ }
865
1020
866
- /*
867
- Low-level initialization
868
- */
1021
+ static void print_modified_quicktune_values ()
1022
+ {
1023
+ bool header_printed = false ;
1024
+ std::vector<std::string> names = getQuicktuneNames ();
1025
+
1026
+ for (u32 i = 0 ; i < names.size (); i++) {
1027
+ QuicktuneValue val = getQuicktuneValue (names[i]);
1028
+ if (!val.modified )
1029
+ continue ;
1030
+ if (!header_printed) {
1031
+ dstream << " Modified quicktune values:" << std::endl;
1032
+ header_printed = true ;
1033
+ }
1034
+ dstream << names[i] << " = " << val.getString () << std::endl;
1035
+ }
1036
+ }
869
1037
1038
+ static void setup_log_params (const Settings &cmd_args)
1039
+ {
870
1040
// Quiet mode, print errors only
871
1041
if (cmd_args.getFlag (" quiet" )) {
872
1042
log_remove_output (&main_stderr_log_out);
873
1043
log_add_output_maxlev (&main_stderr_log_out, LMT_ERROR);
874
1044
}
1045
+
875
1046
// If trace is enabled, enable logging of certain things
876
1047
if (cmd_args.getFlag (" trace" )) {
877
1048
dstream << _ (" Enabling trace level debug output" ) << std::endl;
878
1049
log_trace_level_enabled = true ;
879
1050
dout_con_ptr = &verbosestream; // this is somewhat old crap
880
1051
socket_enable_debug_output = true ; // socket doesn't use log.h
881
1052
}
1053
+
882
1054
// In certain cases, output info level on stderr
883
1055
if (cmd_args.getFlag (" info" ) || cmd_args.getFlag (" verbose" ) ||
884
1056
cmd_args.getFlag (" trace" ) || cmd_args.getFlag (" speedtests" ))
885
1057
log_add_output (&main_stderr_log_out, LMT_INFO);
1058
+
886
1059
// In certain cases, output verbose level on stderr
887
1060
if (cmd_args.getFlag (" verbose" ) || cmd_args.getFlag (" trace" ))
888
1061
log_add_output (&main_stderr_log_out, LMT_VERBOSE);
1062
+ }
889
1063
890
- porting::signal_handler_init ();
891
- bool &kill = *porting::signal_handler_killstatus ();
892
-
893
- porting::initializePaths ();
1064
+ static bool create_userdata_path ()
1065
+ {
1066
+ bool success;
894
1067
895
1068
#ifdef __ANDROID__
896
1069
porting::initAndroid ();
897
1070
898
1071
porting::setExternalStorageDir (porting::jnienv);
899
1072
if (!fs::PathExists (porting::path_user)) {
900
- fs::CreateDir (porting::path_user);
1073
+ success = fs::CreateDir (porting::path_user);
901
1074
}
902
1075
porting::copyAssets ();
903
1076
#else
904
1077
// Create user data directory
905
- fs::CreateDir (porting::path_user);
1078
+ success = fs::CreateDir (porting::path_user);
906
1079
#endif
907
1080
908
1081
infostream << " path_share = " << porting::path_share << std::endl;
909
1082
infostream << " path_user = " << porting::path_user << std::endl;
910
1083
911
- // Initialize debug stacks
912
- debug_stacks_init ();
913
- DSTACK (__FUNCTION_NAME);
1084
+ return success;
1085
+ }
914
1086
915
- // Debug handler
916
- BEGIN_DEBUG_EXCEPTION_HANDLER
1087
+ static bool init_common (int *log_level, const Settings &cmd_args)
1088
+ {
1089
+ startup_message ();
1090
+ set_default_settings (g_settings);
917
1091
918
- // List gameids if requested
919
- if (cmd_args.exists (" gameid" ) && cmd_args.get (" gameid" ) == " list" ) {
920
- std::set<std::string> gameids = getAvailableGameIds ();
921
- for (std::set<std::string>::const_iterator i = gameids.begin ();
922
- i != gameids.end (); i++)
923
- dstream<<(*i)<<std::endl;
924
- return 0 ;
925
- }
1092
+ // Initialize sockets
1093
+ sockets_init ();
1094
+ atexit (sockets_cleanup);
926
1095
927
- // List worlds if requested
928
- if (cmd_args.exists (" world" ) && cmd_args.get (" world" ) == " list" ) {
929
- dstream << _ (" Available worlds:" ) << std::endl;
930
- std::vector<WorldSpec> worldspecs = getAvailableWorlds ();
931
- print_worldspecs (worldspecs, dstream);
932
- return 0 ;
933
- }
1096
+ if (!read_config_file (cmd_args))
1097
+ return false ;
934
1098
935
- // Print startup message
936
- infostream<<PROJECT_NAME << " " << _ (" with" ) << " SER_FMT_VER_HIGHEST_READ="
937
- << (int )SER_FMT_VER_HIGHEST_READ << " , " << minetest_build_info << std::endl;
1099
+ init_debug_streams (log_level, cmd_args);
938
1100
939
- /*
940
- Basic initialization
941
- */
1101
+ // Initialize random seed
1102
+ srand ( time ( 0 ));
1103
+ mysrand ( time ( 0 ));
942
1104
943
- // Initialize default settings
944
- set_default_settings (g_settings);
1105
+ // Initialize HTTP fetcher
1106
+ httpfetch_init (g_settings-> getS32 ( " curl_parallel_limit " ) );
945
1107
946
- // Initialize sockets
947
- sockets_init ();
948
- atexit (sockets_cleanup);
1108
+ #ifdef _MSC_VER
1109
+ init_gettext ((porting::path_share + DIR_DELIM + " locale" ).c_str (),
1110
+ g_settings->get (" language" ), argc, argv);
1111
+ #else
1112
+ init_gettext ((porting::path_share + DIR_DELIM + " locale" ).c_str (),
1113
+ g_settings->get (" language" ));
1114
+ #endif
949
1115
950
- /*
951
- Read config file
952
- */
1116
+ return true ;
1117
+ }
1118
+
1119
+ static void startup_message ()
1120
+ {
1121
+ infostream << PROJECT_NAME << " " << _ (" with" )
1122
+ << " SER_FMT_VER_HIGHEST_READ="
1123
+ << (int )SER_FMT_VER_HIGHEST_READ << " , "
1124
+ << minetest_build_info << std::endl;
1125
+ }
953
1126
1127
+ static bool read_config_file (const Settings &cmd_args)
1128
+ {
954
1129
// Path of configuration file in use
955
- g_settings_path = " " ;
1130
+ assert ( g_settings_path == " " ); // Sanity check
956
1131
957
1132
if (cmd_args.exists (" config" )) {
958
1133
bool r = g_settings->readConfigFile (cmd_args.get (" config" ).c_str ());
959
- if (r == false ) {
1134
+ if (!r ) {
960
1135
errorstream << " Could not read configuration from \" "
961
- << cmd_args.get (" config" ) << " \" " << std::endl;
962
- return 1 ;
1136
+ << cmd_args.get (" config" ) << " \" " << std::endl;
1137
+ return false ;
963
1138
}
964
1139
g_settings_path = cmd_args.get (" config" );
965
1140
} else {
966
1141
std::vector<std::string> filenames;
967
- filenames.push_back (porting::path_user +
968
- DIR_DELIM + " minetest.conf" );
1142
+ filenames.push_back (porting::path_user + DIR_DELIM + " minetest.conf" );
969
1143
// Legacy configuration file location
970
1144
filenames.push_back (porting::path_user +
971
1145
DIR_DELIM + " .." + DIR_DELIM + " minetest.conf" );
1146
+
972
1147
#if RUN_IN_PLACE
973
1148
// Try also from a lower level (to aid having the same configuration
974
1149
// for many RUN_IN_PLACE installs)
975
1150
filenames.push_back (porting::path_user +
976
1151
DIR_DELIM + " .." + DIR_DELIM + " .." + DIR_DELIM + " minetest.conf" );
977
1152
#endif
978
1153
979
- for (u32 i = 0 ; i < filenames.size (); i++) {
1154
+ for ( size_t i = 0 ; i < filenames.size (); i++) {
980
1155
bool r = g_settings->readConfigFile (filenames[i].c_str ());
981
1156
if (r) {
982
1157
g_settings_path = filenames[i];
@@ -989,566 +1164,474 @@ int main(int argc, char *argv[])
989
1164
g_settings_path = filenames[0 ];
990
1165
}
991
1166
992
- // Initialize debug streams
993
- #define DEBUGFILE " debug.txt"
1167
+ return true ;
1168
+ }
1169
+
1170
+ static void init_debug_streams (int *log_level, const Settings &cmd_args)
1171
+ {
994
1172
#if RUN_IN_PLACE
995
1173
std::string logfile = DEBUGFILE;
996
1174
#else
997
- std::string logfile = porting::path_user+ DIR_DELIM+ DEBUGFILE;
1175
+ std::string logfile = porting::path_user + DIR_DELIM + DEBUGFILE;
998
1176
#endif
999
1177
if (cmd_args.exists (" logfile" ))
1000
1178
logfile = cmd_args.get (" logfile" );
1001
1179
1002
1180
log_remove_output (&main_dstream_no_stderr_log_out);
1003
- int loglevel = g_settings->getS32 (" debug_log_level" );
1181
+ *log_level = g_settings->getS32 (" debug_log_level" );
1004
1182
1005
- if (loglevel == 0 ) // no logging
1183
+ if (*log_level == 0 ) // no logging
1006
1184
logfile = " " ;
1007
- else if (loglevel > 0 && loglevel <= LMT_NUM_VALUES)
1008
- log_add_output_maxlev (&main_dstream_no_stderr_log_out,
1009
- (LogMessageLevel)(loglevel - 1 ));
1185
+ if (*log_level < 0 ) {
1186
+ dstream << " WARNING: Supplied debug_log_level < 0; Using 0" << std::endl;
1187
+ *log_level = 0 ;
1188
+ } else if (*log_level > LMT_NUM_VALUES) {
1189
+ dstream << " WARNING: Supplied debug_log_level > " << LMT_NUM_VALUES
1190
+ << " ; Using " << LMT_NUM_VALUES << std::endl;
1191
+ *log_level = LMT_NUM_VALUES;
1192
+ }
1010
1193
1011
- if (logfile != " " )
1012
- debugstreams_init ( false , logfile. c_str ( ));
1013
- else
1014
- debugstreams_init (false , NULL );
1194
+ log_add_output_maxlev (&main_dstream_no_stderr_log_out,
1195
+ (LogMessageLevel)(*log_level - 1 ));
1196
+
1197
+ debugstreams_init (false , logfile == " " ? NULL : logfile. c_str () );
1015
1198
1016
1199
infostream << " logfile = " << logfile << std::endl;
1017
1200
1018
- // Initialize random seed
1019
- srand (time (0 ));
1020
- mysrand (time (0 ));
1201
+ atexit (debugstreams_deinit);
1202
+ }
1021
1203
1022
- // Initialize HTTP fetcher
1023
- httpfetch_init (g_settings->getS32 (" curl_parallel_limit" ));
1204
+ static bool game_configure (GameParams *game_params, const Settings &cmd_args)
1205
+ {
1206
+ game_configure_port (game_params, cmd_args);
1024
1207
1025
- #ifndef __ANDROID__
1026
- /*
1027
- Run unit tests
1028
- */
1029
- if ((ENABLE_TESTS && cmd_args.getFlag (" disable-unittests" ) == false )
1030
- || cmd_args.getFlag (" enable-unittests" ) == true ) {
1031
- run_tests ();
1208
+ if (!game_configure_world (game_params, cmd_args)) {
1209
+ errorstream << " No world path specified or found." << std::endl;
1210
+ return false ;
1032
1211
}
1033
- #endif
1034
- #ifdef _MSC_VER
1035
- init_gettext ((porting::path_share + DIR_DELIM + " locale" ).c_str (),
1036
- g_settings->get (" language" ), argc, argv);
1037
- #else
1038
- init_gettext ((porting::path_share + DIR_DELIM + " locale" ).c_str (),
1039
- g_settings->get (" language" ));
1040
- #endif
1041
1212
1042
- /*
1043
- Game parameters
1044
- */
1213
+ game_configure_subgame (game_params, cmd_args);
1214
+
1215
+ return true ;
1216
+ }
1045
1217
1046
- // Port
1047
- u16 port = 30000 ;
1218
+ static void game_configure_port (GameParams *game_params, const Settings &cmd_args)
1219
+ {
1048
1220
if (cmd_args.exists (" port" ))
1049
- port = cmd_args.getU16 (" port" );
1050
- else if (g_settings->exists (" port" ))
1051
- port = g_settings->getU16 (" port" );
1052
- if (port == 0 )
1053
- port = 30000 ;
1221
+ game_params->socket_port = cmd_args.getU16 (" port" );
1222
+ else
1223
+ game_params->socket_port = g_settings->getU16 (" port" );
1054
1224
1055
- // World directory
1225
+ if (game_params->socket_port == 0 )
1226
+ game_params->socket_port = DEFAULT_SERVER_PORT;
1227
+ }
1228
+
1229
+ static bool game_configure_world (GameParams *game_params, const Settings &cmd_args)
1230
+ {
1231
+ if (get_world_from_cmdline (game_params, cmd_args))
1232
+ return true ;
1233
+ if (get_world_from_config (game_params, cmd_args))
1234
+ return true ;
1235
+
1236
+ return auto_select_world (game_params);
1237
+ }
1238
+
1239
+ static bool get_world_from_cmdline (GameParams *game_params, const Settings &cmd_args)
1240
+ {
1056
1241
std::string commanded_world = " " ;
1057
- if (cmd_args.exists (" world" ))
1058
- commanded_world = cmd_args.get (" world" );
1059
- else if (cmd_args.exists (" map-dir" ))
1060
- commanded_world = cmd_args.get (" map-dir" );
1061
- else if (cmd_args.exists (" nonopt0" )) // First nameless argument
1062
- commanded_world = cmd_args.get (" nonopt0" );
1063
- else if (g_settings->exists (" map-dir" ))
1064
- commanded_world = g_settings->get (" map-dir" );
1065
1242
1066
1243
// World name
1067
1244
std::string commanded_worldname = " " ;
1068
1245
if (cmd_args.exists (" worldname" ))
1069
1246
commanded_worldname = cmd_args.get (" worldname" );
1070
1247
1071
- // Strip world.mt from commanded_world
1072
- {
1073
- std::string worldmt = " world.mt" ;
1074
- if (commanded_world.size () > worldmt.size () &&
1075
- commanded_world.substr (commanded_world.size () - worldmt.size ())
1076
- == worldmt) {
1077
- dstream << _ (" Supplied world.mt file - stripping it off." ) << std::endl;
1078
- commanded_world = commanded_world.substr (0 ,
1079
- commanded_world.size () - worldmt.size ());
1080
- }
1081
- }
1082
-
1083
1248
// If a world name was specified, convert it to a path
1084
1249
if (commanded_worldname != " " ) {
1085
1250
// Get information about available worlds
1086
1251
std::vector<WorldSpec> worldspecs = getAvailableWorlds ();
1087
1252
bool found = false ;
1088
- for (u32 i = 0 ; i < worldspecs.size (); i++) {
1253
+ for (u32 i = 0 ; i < worldspecs.size (); i++) {
1089
1254
std::string name = worldspecs[i].name ;
1090
1255
if (name == commanded_worldname) {
1091
- if (commanded_world != " " ) {
1092
- dstream << _ (" --worldname takes precedence over previously "
1093
- " selected world." ) << std::endl;
1094
- }
1256
+ dstream << _ (" Using world specified by --worldname on the "
1257
+ " command line" ) << std::endl;
1095
1258
commanded_world = worldspecs[i].path ;
1096
1259
found = true ;
1097
1260
break ;
1098
1261
}
1099
1262
}
1100
1263
if (!found) {
1101
- dstream << _ (" World" ) << " '" <<commanded_worldname << _ ( " ' not "
1102
- " available. Available worlds:" ) << std::endl;
1264
+ dstream << _ (" World" ) << " '" << commanded_worldname
1265
+ << _ ( " ' not available. Available worlds:" ) << std::endl;
1103
1266
print_worldspecs (worldspecs, dstream);
1104
- return 1 ;
1267
+ return false ;
1105
1268
}
1269
+
1270
+ game_params->world_path = get_clean_world_path (commanded_world);
1271
+ return commanded_world != " " ;
1272
+ }
1273
+
1274
+ if (cmd_args.exists (" world" ))
1275
+ commanded_world = cmd_args.get (" world" );
1276
+ else if (cmd_args.exists (" map-dir" ))
1277
+ commanded_world = cmd_args.get (" map-dir" );
1278
+ else if (cmd_args.exists (" nonopt0" )) // First nameless argument
1279
+ commanded_world = cmd_args.get (" nonopt0" );
1280
+
1281
+ game_params->world_path = get_clean_world_path (commanded_world);
1282
+ return commanded_world != " " ;
1283
+ }
1284
+
1285
+ static bool get_world_from_config (GameParams *game_params, const Settings &cmd_args)
1286
+ {
1287
+ // World directory
1288
+ std::string commanded_world = " " ;
1289
+
1290
+ if (g_settings->exists (" map-dir" ))
1291
+ commanded_world = g_settings->get (" map-dir" );
1292
+
1293
+ game_params->world_path = get_clean_world_path (commanded_world);
1294
+
1295
+ return commanded_world != " " ;
1296
+ }
1297
+
1298
+ static bool auto_select_world (GameParams *game_params)
1299
+ {
1300
+ // No world was specified; try to select it automatically
1301
+ // Get information about available worlds
1302
+
1303
+ verbosestream << _ (" Determining world path" ) << std::endl;
1304
+
1305
+ std::vector<WorldSpec> worldspecs = getAvailableWorlds ();
1306
+ std::string world_path;
1307
+
1308
+ // If there is only a single world, use it
1309
+ if (worldspecs.size () == 1 ) {
1310
+ world_path = worldspecs[0 ].path ;
1311
+ dstream <<_ (" Automatically selecting world at" ) << " ["
1312
+ << world_path << " ]" << std::endl;
1313
+ // If there are multiple worlds, list them
1314
+ } else if (worldspecs.size () > 1 && game_params->is_dedicated_server ) {
1315
+ dstream << _ (" Multiple worlds are available." ) << std::endl;
1316
+ dstream << _ (" Please select one using --worldname <name>"
1317
+ " or --world <path>" ) << std::endl;
1318
+ print_worldspecs (worldspecs, dstream);
1319
+ return false ;
1320
+ // If there are no worlds, automatically create a new one
1321
+ } else {
1322
+ // This is the ultimate default world path
1323
+ world_path = porting::path_user + DIR_DELIM + " worlds" +
1324
+ DIR_DELIM + " world" ;
1325
+ infostream << " Creating default world at ["
1326
+ << world_path << " ]" << std::endl;
1327
+ }
1328
+
1329
+ assert (world_path != " " );
1330
+ game_params->world_path = world_path;
1331
+ return true ;
1332
+ }
1333
+
1334
+ static std::string get_clean_world_path (const std::string &path)
1335
+ {
1336
+ const std::string worldmt = " world.mt" ;
1337
+ std::string clean_path;
1338
+
1339
+ if (path.size () > worldmt.size ()
1340
+ && path.substr (path.size () - worldmt.size ()) == worldmt) {
1341
+ dstream << _ (" Supplied world.mt file - stripping it off." ) << std::endl;
1342
+ clean_path = path.substr (0 , path.size () - worldmt.size ());
1343
+ } else {
1344
+ clean_path = path;
1106
1345
}
1346
+ return path;
1347
+ }
1348
+
1107
1349
1108
- // Gamespec
1350
+ static bool game_configure_subgame (GameParams *game_params, const Settings &cmd_args)
1351
+ {
1352
+ bool success;
1353
+
1354
+ success = get_game_from_cmdline (game_params, cmd_args);
1355
+ if (!success)
1356
+ success = determine_subgame (game_params);
1357
+
1358
+ return success;
1359
+ }
1360
+
1361
+ static bool get_game_from_cmdline (GameParams *game_params, const Settings &cmd_args)
1362
+ {
1109
1363
SubgameSpec commanded_gamespec;
1364
+
1110
1365
if (cmd_args.exists (" gameid" )) {
1111
1366
std::string gameid = cmd_args.get (" gameid" );
1112
1367
commanded_gamespec = findSubgame (gameid);
1113
1368
if (!commanded_gamespec.isValid ()) {
1114
1369
errorstream << " Game \" " << gameid << " \" not found" << std::endl;
1115
- return 1 ;
1370
+ return false ;
1116
1371
}
1372
+ dstream << _ (" Using game specified by --gameid on the command line" )
1373
+ << std::endl;
1374
+ game_params->game_spec = commanded_gamespec;
1375
+ return true ;
1117
1376
}
1118
1377
1378
+ return false ;
1379
+ }
1119
1380
1120
- /*
1121
- Run dedicated server if asked to or no other option
1122
- */
1123
- #ifdef SERVER
1124
- bool run_dedicated_server = true ;
1125
- #else
1126
- bool run_dedicated_server = cmd_args.getFlag (" server" );
1127
- #endif
1128
- g_settings->set (" server_dedicated" , run_dedicated_server ? " true" : " false" );
1129
- if (run_dedicated_server)
1130
- {
1131
- DSTACK (" Dedicated server branch" );
1132
- // Create time getter if built with Irrlicht
1133
- #ifndef SERVER
1134
- g_timegetter = new SimpleTimeGetter ();
1135
- #endif
1136
-
1137
- // World directory
1138
- std::string world_path;
1139
- verbosestream << _ (" Determining world path" ) << std::endl;
1140
- bool is_legacy_world = false ;
1141
- // If a world was commanded, use it
1142
- if (commanded_world != " " ) {
1143
- world_path = commanded_world;
1144
- infostream << " Using commanded world path [" << world_path << " ]"
1145
- << std::endl;
1146
- } else { // No world was specified; try to select it automatically
1147
- // Get information about available worlds
1148
- std::vector<WorldSpec> worldspecs = getAvailableWorlds ();
1149
- // If a world name was specified, select it
1150
- if (commanded_worldname != " " ) {
1151
- world_path = " " ;
1152
- for (u32 i = 0 ; i < worldspecs.size (); i++) {
1153
- std::string name = worldspecs[i].name ;
1154
- if (name == commanded_worldname) {
1155
- world_path = worldspecs[i].path ;
1156
- break ;
1157
- }
1158
- }
1159
- if (world_path == " " ) {
1160
- dstream << _ (" World" ) << " '" << commanded_worldname << " ' " << _ (" not "
1161
- " available. Available worlds:" ) << std::endl;
1162
- print_worldspecs (worldspecs, dstream);
1163
- return 1 ;
1164
- }
1165
- }
1166
- // If there is only a single world, use it
1167
- if (worldspecs.size () == 1 ) {
1168
- world_path = worldspecs[0 ].path ;
1169
- dstream <<_ (" Automatically selecting world at" ) << " ["
1170
- << world_path << " ]" << std::endl;
1171
- // If there are multiple worlds, list them
1172
- } else if (worldspecs.size () > 1 ) {
1173
- dstream << _ (" Multiple worlds are available." ) << std::endl;
1174
- dstream << _ (" Please select one using --worldname <name>"
1175
- " or --world <path>" ) << std::endl;
1176
- print_worldspecs (worldspecs, dstream);
1177
- return 1 ;
1178
- // If there are no worlds, automatically create a new one
1179
- } else {
1180
- // This is the ultimate default world path
1181
- world_path = porting::path_user + DIR_DELIM + " worlds" +
1182
- DIR_DELIM + " world" ;
1183
- infostream << " Creating default world at ["
1184
- << world_path << " ]" << std::endl;
1185
- }
1186
- }
1187
-
1188
- if (world_path == " " ) {
1189
- errorstream << " No world path specified or found." << std::endl;
1190
- return 1 ;
1381
+ static bool determine_subgame (GameParams *game_params)
1382
+ {
1383
+ SubgameSpec gamespec;
1384
+
1385
+ assert (game_params->world_path != " " ); // pre-condition
1386
+
1387
+ verbosestream << _ (" Determining gameid/gamespec" ) << std::endl;
1388
+ // If world doesn't exist
1389
+ if (game_params->world_path != " "
1390
+ && !getWorldExists (game_params->world_path )) {
1391
+ // Try to take gamespec from command line
1392
+ if (game_params->game_spec .isValid ()) {
1393
+ gamespec = game_params->game_spec ;
1394
+ infostream << " Using commanded gameid [" << gamespec.id << " ]" << std::endl;
1395
+ } else { // Otherwise we will be using "minetest"
1396
+ gamespec = findSubgame (g_settings->get (" default_game" ));
1397
+ infostream << " Using default gameid [" << gamespec.id << " ]" << std::endl;
1191
1398
}
1192
- verbosestream << _ (" Using world path" ) << " [" << world_path << " ]" << std::endl;
1193
-
1194
- // We need a gamespec.
1195
- SubgameSpec gamespec;
1196
- verbosestream << _ (" Determining gameid/gamespec" ) << std::endl;
1197
- // If world doesn't exist
1198
- if (!getWorldExists (world_path)) {
1199
- // Try to take gamespec from command line
1200
- if (commanded_gamespec.isValid ()) {
1201
- gamespec = commanded_gamespec;
1202
- infostream << " Using commanded gameid [" << gamespec.id << " ]" << std::endl;
1203
- } else { // Otherwise we will be using "minetest"
1204
- gamespec = findSubgame (g_settings->get (" default_game" ));
1205
- infostream << " Using default gameid [" << gamespec.id << " ]" << std::endl;
1206
- }
1207
- } else { // World exists
1208
- std::string world_gameid = getWorldGameId (world_path, is_legacy_world);
1209
- // If commanded to use a gameid, do so
1210
- if (commanded_gamespec.isValid ()) {
1211
- gamespec = commanded_gamespec;
1212
- if (commanded_gamespec.id != world_gameid) {
1213
- errorstream << " WARNING: Using commanded gameid ["
1214
- << gamespec.id << " ]" << " instead of world gameid ["
1215
- << world_gameid << " ]" << std::endl;
1216
- }
1217
- } else {
1218
- // If world contains an embedded game, use it;
1219
- // Otherwise find world from local system.
1220
- gamespec = findWorldSubgame (world_path);
1221
- infostream << " Using world gameid [" << gamespec.id << " ]" << std::endl;
1399
+ } else { // World exists
1400
+ std::string world_gameid = getWorldGameId (game_params->world_path , false );
1401
+ // If commanded to use a gameid, do so
1402
+ if (game_params->game_spec .isValid ()) {
1403
+ gamespec = game_params->game_spec ;
1404
+ if (game_params->game_spec .id != world_gameid) {
1405
+ errorstream << " WARNING: Using commanded gameid ["
1406
+ << gamespec.id << " ]" << " instead of world gameid ["
1407
+ << world_gameid << " ]" << std::endl;
1222
1408
}
1409
+ } else {
1410
+ // If world contains an embedded game, use it;
1411
+ // Otherwise find world from local system.
1412
+ gamespec = findWorldSubgame (game_params->world_path );
1413
+ infostream << " Using world gameid [" << gamespec.id << " ]" << std::endl;
1223
1414
}
1224
- if (!gamespec.isValid ()) {
1225
- errorstream << " Subgame [" << gamespec.id << " ] could not be found."
1226
- << std::endl;
1227
- return 1 ;
1228
- }
1229
- verbosestream << _ (" Using gameid" ) << " [" << gamespec.id <<" ]" << std::endl;
1230
-
1231
- // Bind address
1232
- std::string bind_str = g_settings->get (" bind_address" );
1233
- Address bind_addr (0 , 0 , 0 , 0 , port);
1234
-
1235
- if (g_settings->getBool (" ipv6_server" )) {
1236
- bind_addr.setAddress ((IPv6AddressBytes*) NULL );
1237
- }
1238
- try {
1239
- bind_addr.Resolve (bind_str.c_str ());
1240
- } catch (ResolveError &e) {
1241
- infostream << " Resolving bind address \" " << bind_str
1242
- << " \" failed: " << e.what ()
1243
- << " -- Listening on all addresses." << std::endl;
1244
- }
1245
- if (bind_addr.isIPv6 () && !g_settings->getBool (" enable_ipv6" )) {
1246
- errorstream << " Unable to listen on "
1247
- << bind_addr.serializeString ()
1248
- << L" because IPv6 is disabled" << std::endl;
1249
- return 1 ;
1250
- }
1251
-
1252
- // Create server
1253
- Server server (world_path, gamespec, false , bind_addr.isIPv6 ());
1254
-
1255
- // Database migration
1256
- if (cmd_args.exists (" migrate" )) {
1257
- std::string migrate_to = cmd_args.get (" migrate" );
1258
- Settings world_mt;
1259
- bool success = world_mt.readConfigFile ((world_path + DIR_DELIM
1260
- + " world.mt" ).c_str ());
1261
- if (!success) {
1262
- errorstream << " Cannot read world.mt" << std::endl;
1263
- return 1 ;
1264
- }
1265
- if (!world_mt.exists (" backend" )) {
1266
- errorstream << " Please specify your current backend in world.mt file:"
1267
- << std::endl << " backend = {sqlite3|leveldb|redis|dummy}" << std::endl;
1268
- return 1 ;
1269
- }
1270
- std::string backend = world_mt.get (" backend" );
1271
- Database *new_db;
1272
- if (backend == migrate_to) {
1273
- errorstream << " Cannot migrate: new backend is same"
1274
- <<" as the old one" << std::endl;
1275
- return 1 ;
1276
- }
1277
- if (migrate_to == " sqlite3" )
1278
- new_db = new Database_SQLite3 (&(ServerMap&)server.getMap (), world_path);
1279
- #if USE_LEVELDB
1280
- else if (migrate_to == " leveldb" )
1281
- new_db = new Database_LevelDB (&(ServerMap&)server.getMap (), world_path);
1282
- #endif
1283
- #if USE_REDIS
1284
- else if (migrate_to == " redis" )
1285
- new_db = new Database_Redis (&(ServerMap&)server.getMap (), world_path);
1286
- #endif
1287
- else {
1288
- errorstream << " Migration to " << migrate_to
1289
- << " is not supported" << std::endl;
1290
- return 1 ;
1291
- }
1292
-
1293
- std::list<v3s16> blocks;
1294
- ServerMap &old_map = ((ServerMap&)server.getMap ());
1295
- old_map.listAllLoadableBlocks (blocks);
1296
- int count = 0 ;
1297
- new_db->beginSave ();
1298
- for (std::list<v3s16>::iterator i = blocks.begin (); i != blocks.end (); i++) {
1299
- MapBlock *block = old_map.loadBlock (*i);
1300
- if (!block) {
1301
- errorstream << " Failed to load block " << PP (*i) << " , skipping it." ;
1302
- } else {
1303
- old_map.saveBlock (block, new_db);
1304
- MapSector *sector = old_map.getSectorNoGenerate (v2s16 (i->X , i->Z ));
1305
- sector->deleteBlock (block);
1306
- }
1307
- ++count;
1308
- if (count % 500 == 0 )
1309
- actionstream << " Migrated " << count << " blocks "
1310
- << (100.0 * count / blocks.size ()) << " % completed" << std::endl;
1311
- }
1312
- new_db->endSave ();
1313
- delete new_db;
1314
-
1315
- actionstream << " Successfully migrated " << count << " blocks" << std::endl;
1316
- world_mt.set (" backend" , migrate_to);
1317
- if (!world_mt.updateConfigFile ((world_path + DIR_DELIM + " world.mt" ).c_str ()))
1318
- errorstream << " Failed to update world.mt!" << std::endl;
1319
- else
1320
- actionstream << " world.mt updated" << std::endl;
1415
+ }
1321
1416
1322
- return 0 ;
1323
- }
1417
+ if (!gamespec.isValid ()) {
1418
+ errorstream << " Subgame [" << gamespec.id << " ] could not be found."
1419
+ << std::endl;
1420
+ return false ;
1421
+ }
1324
1422
1325
- server.start (bind_addr);
1423
+ game_params->game_spec = gamespec;
1424
+ return true ;
1425
+ }
1326
1426
1327
- // Run server
1328
- dedicated_server_loop (server, kill );
1329
1427
1330
- return 0 ;
1428
+ /* ****************************************************************************
1429
+ * Dedicated server
1430
+ *****************************************************************************/
1431
+ static bool run_dedicated_server (const GameParams &game_params, const Settings &cmd_args)
1432
+ {
1433
+ DSTACK (" Dedicated server branch" );
1434
+
1435
+ verbosestream << _ (" Using world path" ) << " ["
1436
+ << game_params.world_path << " ]" << std::endl;
1437
+ verbosestream << _ (" Using gameid" ) << " ["
1438
+ << game_params.game_spec .id << " ]" << std::endl;
1439
+
1440
+ // Bind address
1441
+ std::string bind_str = g_settings->get (" bind_address" );
1442
+ Address bind_addr (0 , 0 , 0 , 0 , game_params.socket_port );
1443
+
1444
+ if (g_settings->getBool (" ipv6_server" )) {
1445
+ bind_addr.setAddress ((IPv6AddressBytes*) NULL );
1446
+ }
1447
+ try {
1448
+ bind_addr.Resolve (bind_str.c_str ());
1449
+ } catch (ResolveError &e) {
1450
+ infostream << " Resolving bind address \" " << bind_str
1451
+ << " \" failed: " << e.what ()
1452
+ << " -- Listening on all addresses." << std::endl;
1453
+ }
1454
+ if (bind_addr.isIPv6 () && !g_settings->getBool (" enable_ipv6" )) {
1455
+ errorstream << " Unable to listen on "
1456
+ << bind_addr.serializeString ()
1457
+ << L" because IPv6 is disabled" << std::endl;
1458
+ return false ;
1331
1459
}
1332
1460
1333
- #ifndef SERVER // Exclude from dedicated server build
1334
-
1335
- /*
1336
- More parameters
1337
- */
1461
+ // Create server
1462
+ Server server (game_params.world_path ,
1463
+ game_params.game_spec , false , bind_addr.isIPv6 ());
1338
1464
1339
- std::string address = g_settings->get (" address" );
1340
- if (commanded_world != " " )
1341
- address = " " ;
1342
- else if (cmd_args.exists (" address" ))
1343
- address = cmd_args.get (" address" );
1465
+ // Database migration
1466
+ if (cmd_args.exists (" migrate" ))
1467
+ return migrate_database (game_params, cmd_args, &server);
1344
1468
1345
- std::string playername = g_settings->get (" name" );
1346
- if (cmd_args.exists (" name" ))
1347
- playername = cmd_args.get (" name" );
1469
+ server.start (bind_addr);
1348
1470
1349
- bool skip_main_menu = cmd_args.getFlag (" go" );
1471
+ // Run server
1472
+ bool &kill = *porting::signal_handler_killstatus ();
1473
+ dedicated_server_loop (server, kill );
1350
1474
1351
- /*
1352
- Device initialization
1353
- */
1475
+ return true ;
1476
+ }
1354
1477
1355
- // Resolution selection
1478
+ static bool migrate_database (const GameParams &game_params, const Settings &cmd_args,
1479
+ Server *server)
1480
+ {
1481
+ Settings world_mt;
1482
+ bool success = world_mt.readConfigFile ((game_params.world_path
1483
+ + DIR_DELIM + " world.mt" ).c_str ());
1484
+ if (!success) {
1485
+ errorstream << " Cannot read world.mt" << std::endl;
1486
+ return false ;
1487
+ }
1356
1488
1357
- bool fullscreen = g_settings->getBool (" fullscreen" );
1358
- u16 screenW = g_settings->getU16 (" screenW" );
1359
- u16 screenH = g_settings->getU16 (" screenH" );
1489
+ if (!world_mt.exists (" backend" )) {
1490
+ errorstream << " Please specify your current backend in world.mt file:"
1491
+ << std::endl << " backend = {sqlite3|leveldb|redis|dummy}"
1492
+ << std::endl;
1493
+ return false ;
1494
+ }
1360
1495
1361
- // bpp, fsaa, vsync
1496
+ std::string backend = world_mt.get (" backend" );
1497
+ Database *new_db;
1498
+ std::string migrate_to = cmd_args.get (" migrate" );
1362
1499
1363
- bool vsync = g_settings->getBool (" vsync" );
1364
- u16 bits = g_settings->getU16 (" fullscreen_bpp" );
1365
- u16 fsaa = g_settings->getU16 (" fsaa" );
1500
+ if (backend == migrate_to) {
1501
+ errorstream << " Cannot migrate: new backend is same as the old one"
1502
+ << std::endl;
1503
+ return false ;
1504
+ }
1366
1505
1367
- // Determine driver
1368
- video::E_DRIVER_TYPE driverType = video::EDT_OPENGL;
1369
- static const char * driverids[] = {
1370
- " null" ,
1371
- " software" ,
1372
- " burningsvideo" ,
1373
- " direct3d8" ,
1374
- " direct3d9" ,
1375
- " opengl"
1376
- #ifdef _IRR_COMPILE_WITH_OGLES1_
1377
- ," ogles1"
1506
+ if (migrate_to == " sqlite3" )
1507
+ new_db = new Database_SQLite3 (&(ServerMap&)server->getMap (),
1508
+ game_params.world_path );
1509
+ #if USE_LEVELDB
1510
+ else if (migrate_to == " leveldb" )
1511
+ new_db = new Database_LevelDB (&(ServerMap&)server->getMap (),
1512
+ game_params.world_path );
1378
1513
#endif
1379
- #ifdef _IRR_COMPILE_WITH_OGLES2_
1380
- ," ogles2"
1514
+ #if USE_REDIS
1515
+ else if (migrate_to == " redis" )
1516
+ new_db = new Database_Redis (&(ServerMap&)server->getMap (),
1517
+ game_params.requested_world_path );
1381
1518
#endif
1382
- ," invalid"
1383
- };
1519
+ else {
1520
+ errorstream << " Migration to " << migrate_to << " is not supported"
1521
+ << std::endl;
1522
+ return false ;
1523
+ }
1384
1524
1385
- std::string driverstring = g_settings->get (" video_driver" );
1386
- for (unsigned int i = 0 ;
1387
- i < (sizeof (driverids)/sizeof (driverids[0 ]));
1388
- i++)
1389
- {
1390
- if (strcasecmp (driverstring.c_str (), driverids[i]) == 0 ) {
1391
- driverType = (video::E_DRIVER_TYPE) i;
1392
- break ;
1525
+ std::list<v3s16> blocks;
1526
+ ServerMap &old_map = ((ServerMap&)server->getMap ());
1527
+ old_map.listAllLoadableBlocks (blocks);
1528
+ int count = 0 ;
1529
+ new_db->beginSave ();
1530
+ for (std::list<v3s16>::iterator i = blocks.begin (); i != blocks.end (); i++) {
1531
+ MapBlock *block = old_map.loadBlock (*i);
1532
+ if (!block) {
1533
+ errorstream << " Failed to load block " << PP (*i) << " , skipping it." ;
1534
+ } else {
1535
+ old_map.saveBlock (block, new_db);
1536
+ MapSector *sector = old_map.getSectorNoGenerate (v2s16 (i->X , i->Z ));
1537
+ sector->deleteBlock (block);
1393
1538
}
1539
+ ++count;
1540
+ if (count % 500 == 0 )
1541
+ actionstream << " Migrated " << count << " blocks "
1542
+ << (100.0 * count / blocks.size ()) << " % completed" << std::endl;
1543
+ }
1544
+ new_db->endSave ();
1545
+ delete new_db;
1546
+
1547
+ actionstream << " Successfully migrated " << count << " blocks" << std::endl;
1548
+ world_mt.set (" backend" , migrate_to);
1549
+ if (!world_mt.updateConfigFile (
1550
+ (game_params.world_path + DIR_DELIM + " world.mt" ).c_str ()))
1551
+ errorstream << " Failed to update world.mt!" << std::endl;
1552
+ else
1553
+ actionstream << " world.mt updated" << std::endl;
1394
1554
1395
- if (strcasecmp (" invalid" , driverids[i]) == 0 ) {
1396
- errorstream << " WARNING: Invalid video_driver specified; defaulting "
1397
- << " to opengl" << std::endl;
1398
- break ;
1399
- }
1400
- }
1555
+ return true ;
1556
+ }
1401
1557
1402
- /*
1403
- List video modes if requested
1404
- */
1405
- MyEventReceiver* receiver = new MyEventReceiver ();
1406
1558
1407
- if (cmd_args.getFlag (" videomodes" )) {
1408
- IrrlichtDevice *nulldevice;
1559
+ /* ****************************************************************************
1560
+ * Client
1561
+ *****************************************************************************/
1562
+ #ifndef SERVER
1409
1563
1410
- SIrrlichtCreationParameters params = SIrrlichtCreationParameters ();
1411
- params.DriverType = video::EDT_NULL;
1412
- params.WindowSize = core::dimension2d<u32>(640 , 480 );
1413
- params.Bits = 24 ;
1414
- params.AntiAlias = fsaa;
1415
- params.Fullscreen = false ;
1416
- params.Stencilbuffer = false ;
1417
- params.Vsync = vsync;
1418
- params.EventReceiver = receiver;
1419
- params.HighPrecisionFPU = g_settings->getBool (" high_precision_fpu" );
1564
+ ClientLauncher::~ClientLauncher ()
1565
+ {
1566
+ if (receiver)
1567
+ delete receiver;
1420
1568
1421
- nulldevice = createDeviceEx (params);
1569
+ if (input)
1570
+ delete input;
1422
1571
1423
- if (nulldevice == 0 )
1424
- return 1 ;
1572
+ if (device )
1573
+ device-> drop () ;
1425
1574
1426
- dstream << _ (" Available video modes (WxHxD):" ) << std::endl;
1575
+ #if USE_FREETYPE
1576
+ if (use_freetype && font != NULL )
1577
+ font->drop ();
1578
+ #endif
1579
+ }
1427
1580
1428
- video::IVideoModeList *videomode_list =
1429
- nulldevice->getVideoModeList ();
1581
+ bool ClientLauncher::run (GameParams &game_params, const Settings &cmd_args)
1582
+ {
1583
+ init_args (game_params, cmd_args);
1430
1584
1431
- if (videomode_list == 0 ) {
1432
- nulldevice->drop ();
1433
- return 1 ;
1434
- }
1585
+ // List video modes if requested
1586
+ if (list_video_modes)
1587
+ return print_video_modes ();
1435
1588
1436
- s32 videomode_count = videomode_list->getVideoModeCount ();
1437
- core::dimension2d<u32> videomode_res;
1438
- s32 videomode_depth;
1439
- for (s32 i = 0 ; i < videomode_count; ++i) {
1440
- videomode_res = videomode_list->getVideoModeResolution (i);
1441
- videomode_depth = videomode_list->getVideoModeDepth (i);
1442
- dstream<<videomode_res.Width << " x" << videomode_res.Height
1443
- << " x" << videomode_depth << std::endl;
1444
- }
1589
+ if (!init_engine (game_params.log_level )) {
1590
+ errorstream << " Could not initialize game engine." << std::endl;
1591
+ return false ;
1592
+ }
1445
1593
1446
- dstream << _ (" Active video mode (WxHxD):" ) << std::endl;
1447
- videomode_res = videomode_list->getDesktopResolution ();
1448
- videomode_depth = videomode_list->getDesktopDepth ();
1449
- dstream << videomode_res.Width << " x" << videomode_res.Height
1450
- << " x" << videomode_depth << std::endl;
1594
+ late_init_default_settings (g_settings);
1451
1595
1452
- nulldevice->drop ();
1596
+ // Speed tests (done after irrlicht is loaded to get timer)
1597
+ if (cmd_args.getFlag (" speedtests" )) {
1598
+ dstream << " Running speed tests" << std::endl;
1599
+ speed_tests ();
1600
+ return true ;
1601
+ }
1453
1602
1454
- delete receiver;
1455
- return 0 ;
1603
+ if (device->getVideoDriver () == NULL ) {
1604
+ errorstream << " Could not initialize video driver." << std::endl;
1605
+ return false ;
1456
1606
}
1457
1607
1458
1608
/*
1459
- Create device and exit if creation failed
1609
+ This changes the minimum allowed number of vertices in a VBO.
1610
+ Default is 500.
1460
1611
*/
1461
- SIrrlichtCreationParameters params = SIrrlichtCreationParameters ();
1462
- params.DriverType = driverType;
1463
- params.WindowSize = core::dimension2d<u32>(screenW, screenH);
1464
- params.Bits = bits;
1465
- params.AntiAlias = fsaa;
1466
- params.Fullscreen = fullscreen;
1467
- params.Stencilbuffer = false ;
1468
- params.Vsync = vsync;
1469
- params.EventReceiver = receiver;
1470
- params.HighPrecisionFPU = g_settings->getBool (" high_precision_fpu" );
1471
- #ifdef __ANDROID__
1472
- params.PrivateData = porting::app_global;
1473
- params.OGLES2ShaderPath = std::string (porting::path_user + DIR_DELIM +
1474
- " media" + DIR_DELIM + " Shaders" + DIR_DELIM).c_str ();
1475
- #endif
1612
+ // driver->setMinHardwareBufferVertexCount(50);
1476
1613
1477
- IrrlichtDevice * device = createDeviceEx (params);
1614
+ // Create time getter
1615
+ g_timegetter = new IrrlichtTimeGetter (device);
1478
1616
1479
- if (device == 0 ) {
1480
- delete receiver;
1481
- return 1 ; // could not create selected driver.
1482
- }
1483
-
1484
- // Map our log level to irrlicht engine one.
1485
- static const irr::ELOG_LEVEL irr_log_level[5 ] = {
1486
- ELL_NONE,
1487
- ELL_ERROR,
1488
- ELL_WARNING,
1489
- ELL_INFORMATION,
1490
- #if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8)
1491
- ELL_INFORMATION
1492
- #else
1493
- ELL_DEBUG
1494
- #endif
1495
- };
1496
-
1497
- ILogger* irr_logger = device->getLogger ();
1498
- irr_logger->setLogLevel (irr_log_level[loglevel]);
1499
-
1500
- porting::initIrrlicht (device);
1501
- late_init_default_settings (g_settings);
1502
-
1503
- /*
1504
- Continue initialization
1505
- */
1506
-
1507
- video::IVideoDriver* driver = device->getVideoDriver ();
1508
-
1509
- /*
1510
- This changes the minimum allowed number of vertices in a VBO.
1511
- Default is 500.
1512
- */
1513
- // driver->setMinHardwareBufferVertexCount(50);
1514
-
1515
- // Create time getter
1516
- g_timegetter = new IrrlichtTimeGetter (device);
1517
-
1518
- // Create game callback for menus
1519
- g_gamecallback = new MainGameCallback (device);
1520
-
1521
- /*
1522
- Speed tests (done after irrlicht is loaded to get timer)
1523
- */
1524
- if (cmd_args.getFlag (" speedtests" ))
1525
- {
1526
- dstream << " Running speed tests" << std::endl;
1527
- SpeedTests ();
1528
- device->drop ();
1529
- return 0 ;
1530
- }
1617
+ // Create game callback for menus
1618
+ g_gamecallback = new MainGameCallback (device);
1531
1619
1532
1620
device->setResizable (true );
1533
1621
1534
- bool random_input = g_settings->getBool (" random_input" )
1535
- || cmd_args.getFlag (" random-input" );
1536
- InputHandler *input = NULL ;
1537
-
1538
- if (random_input) {
1622
+ if (random_input)
1539
1623
input = new RandomInputHandler ();
1540
- } else {
1541
- input = new RealInputHandler (device,receiver);
1542
- }
1624
+ else
1625
+ input = new RealInputHandler (device, receiver);
1543
1626
1544
- scene::ISceneManager* smgr = device->getSceneManager ();
1627
+ smgr = device->getSceneManager ();
1545
1628
1546
1629
guienv = device->getGUIEnvironment ();
1547
- gui::IGUISkin* skin = guienv->getSkin ();
1630
+ skin = guienv->getSkin ();
1548
1631
std::string font_path = g_settings->get (" font_path" );
1549
- gui::IGUIFont *font;
1550
- #if USE_FREETYPE
1551
- bool use_freetype = g_settings-> getBool ( " freetype " );
1632
+
1633
+ #if USE_FREETYPE
1634
+
1552
1635
if (use_freetype) {
1553
1636
std::string fallback;
1554
1637
if (is_yes (gettext (" needs_fallback_font" )))
@@ -1557,21 +1640,22 @@ int main(int argc, char *argv[])
1557
1640
font_path = g_settings->get (fallback + " font_path" );
1558
1641
u32 font_shadow = g_settings->getU16 (fallback + " font_shadow" );
1559
1642
u32 font_shadow_alpha = g_settings->getU16 (fallback + " font_shadow_alpha" );
1560
- font = gui::CGUITTFont::createTTFont (guienv, font_path.c_str (), font_size,
1561
- true , true , font_shadow, font_shadow_alpha);
1643
+ font = gui::CGUITTFont::createTTFont (guienv,
1644
+ font_path.c_str (), font_size, true , true ,
1645
+ font_shadow, font_shadow_alpha);
1562
1646
} else {
1563
1647
font = guienv->getFont (font_path.c_str ());
1564
1648
}
1565
- #else
1649
+ #else
1566
1650
font = guienv->getFont (font_path.c_str ());
1567
- #endif
1651
+ #endif
1568
1652
if (font)
1569
1653
skin->setFont (font);
1570
1654
else
1571
- errorstream << " WARNING: Font file was not found."
1572
- << " Using default font. " << std::endl;
1573
- // If font was not found, this will get us one
1574
- font = skin->getFont ();
1655
+ errorstream << " WARNING: Font file was not found. Using default font. "
1656
+ << std::endl;
1657
+
1658
+ font = skin->getFont (); // If font was not found, this will get us one
1575
1659
assert (font);
1576
1660
1577
1661
u32 text_height = font->getDimension (L" Hello, world!" ).Height ;
@@ -1589,13 +1673,12 @@ int main(int argc, char *argv[])
1589
1673
skin->setColor (gui::EGDC_FOCUSED_EDITABLE, video::SColor (255 , 96 , 134 , 49 ));
1590
1674
#endif
1591
1675
1592
-
1593
1676
// Create the menu clouds
1594
1677
if (!g_menucloudsmgr)
1595
1678
g_menucloudsmgr = smgr->createNewSceneManager ();
1596
1679
if (!g_menuclouds)
1597
1680
g_menuclouds = new Clouds (g_menucloudsmgr->getRootSceneNode (),
1598
- g_menucloudsmgr, -1 , rand (), 100 );
1681
+ g_menucloudsmgr, -1 , rand (), 100 );
1599
1682
g_menuclouds->update (v2f (0 , 0 ), video::SColor (255 , 200 , 200 , 255 ));
1600
1683
scene::ICameraSceneNode* camera;
1601
1684
camera = g_menucloudsmgr->addCameraSceneNode (0 ,
@@ -1608,260 +1691,74 @@ int main(int argc, char *argv[])
1608
1691
1609
1692
ChatBackend chat_backend;
1610
1693
1611
- /*
1612
- If an error occurs, this is set to something and the
1613
- menu-game loop is restarted. It is then displayed before
1614
- the menu.
1615
- */
1694
+ // If an error occurs, this is set to something by menu().
1695
+ // It is then displayed before the menu shows on the next call to menu()
1616
1696
std::wstring error_message = L" " ;
1617
1697
1618
- // The password entered during the menu screen,
1619
- std::string password;
1620
-
1621
1698
bool first_loop = true ;
1622
1699
1623
1700
/*
1624
1701
Menu-game loop
1625
1702
*/
1626
- while (device->run () && (kill == false ) &&
1627
- (g_gamecallback->shutdown_requested == false ))
1703
+ bool retval = true ;
1704
+ bool *kill = porting::signal_handler_killstatus ();
1705
+
1706
+ while (device->run () && !*kill && !g_gamecallback->shutdown_requested )
1628
1707
{
1629
1708
// Set the window caption
1630
- wchar_t * text = wgettext (" Main Menu" );
1709
+ wchar_t * text = wgettext (" Main Menu" );
1631
1710
device->setWindowCaption ((std::wstring (L" Minetest [" ) + text + L" ]" ).c_str ());
1632
1711
delete[] text;
1633
1712
1634
- // This is used for catching disconnects
1635
- try
1636
- {
1713
+ try { // This is used for catching disconnects
1637
1714
1638
- /*
1639
- Clear everything from the GUIEnvironment
1640
- */
1641
1715
guienv->clear ();
1642
1716
1643
1717
/*
1644
1718
We need some kind of a root node to be able to add
1645
1719
custom gui elements directly on the screen.
1646
1720
Otherwise they won't be automatically drawn.
1647
1721
*/
1648
- guiroot = guienv->addStaticText (L" " ,
1649
- core::rect<s32>(0 , 0 , 10000 , 10000 ));
1722
+ guiroot = guienv->addStaticText (L" " , core::rect<s32>(0 , 0 , 10000 , 10000 ));
1650
1723
1651
- SubgameSpec gamespec;
1652
- WorldSpec worldspec;
1653
- bool simple_singleplayer_mode = false ;
1724
+ bool game_has_run = launch_game (&error_message, game_params, cmd_args);
1654
1725
1655
- // These are set up based on the menu and other things
1656
- std::string current_playername = " inv£lid" ;
1657
- std::string current_password = " " ;
1658
- std::string current_address = " does-not-exist" ;
1659
- int current_port = 0 ;
1726
+ // If skip_main_menu, we only want to startup once
1727
+ if (skip_main_menu && !first_loop)
1728
+ break ;
1660
1729
1661
- /*
1662
- Out-of-game menu loop.
1730
+ first_loop = false ;
1663
1731
1664
- Loop quits when menu returns proper parameters.
1665
- */
1666
- while (kill == false ) {
1667
- // If skip_main_menu, only go through here once
1668
- if (skip_main_menu && !first_loop) {
1669
- kill = true ;
1732
+ if (!game_has_run) {
1733
+ if (skip_main_menu)
1670
1734
break ;
1671
- }
1672
- first_loop = false ;
1673
-
1674
- // Cursor can be non-visible when coming from the game
1675
- #ifndef ANDROID
1676
- device->getCursorControl ()->setVisible (true );
1677
- #endif
1678
- // Some stuff are left to scene manager when coming from the game
1679
- // (map at least?)
1680
- smgr->clear ();
1681
-
1682
- // Initialize menu data
1683
- MainMenuData menudata;
1684
- menudata.address = address;
1685
- menudata.name = playername;
1686
- menudata.port = itos (port);
1687
- menudata.errormessage = wide_to_narrow (error_message);
1688
- error_message = L" " ;
1689
- if (cmd_args.exists (" password" ))
1690
- menudata.password = cmd_args.get (" password" );
1691
-
1692
- driver->setTextureCreationFlag (video::ETCF_CREATE_MIP_MAPS, g_settings->getBool (" mip_map" ));
1693
-
1694
- menudata.enable_public = g_settings->getBool (" server_announce" );
1695
-
1696
- std::vector<WorldSpec> worldspecs = getAvailableWorlds ();
1697
-
1698
- // If a world was commanded, append and select it
1699
- if (commanded_world != " " ) {
1700
- worldspec.gameid = getWorldGameId (commanded_world, true );
1701
- worldspec.name = _ (" [--world parameter]" );
1702
- if (worldspec.gameid == " " ) {
1703
- worldspec.gameid = g_settings->get (" default_game" );
1704
- worldspec.name += " [new]" ;
1705
- }
1706
- worldspec.path = commanded_world;
1707
- }
1708
-
1709
- if (skip_main_menu == false ) {
1710
- video::IVideoDriver* driver = device->getVideoDriver ();
1711
-
1712
- infostream << " Waiting for other menus" << std::endl;
1713
- while (device->run () && kill == false ) {
1714
- if (noMenuActive ())
1715
- break ;
1716
- driver->beginScene (true , true ,
1717
- video::SColor (255 , 128 , 128 , 128 ));
1718
- guienv->drawAll ();
1719
- driver->endScene ();
1720
- // On some computers framerate doesn't seem to be
1721
- // automatically limited
1722
- sleep_ms (25 );
1723
- }
1724
- infostream << " Waited for other menus" << std::endl;
1725
-
1726
- /* show main menu */
1727
- GUIEngine mymenu (device, guiroot, &g_menumgr,smgr,&menudata,kill );
1728
-
1729
- // once finished you'll never end up here
1730
- smgr->clear ();
1731
- }
1732
-
1733
- if (menudata.errormessage != " " ) {
1734
- error_message = narrow_to_wide (menudata.errormessage );
1735
- continue ;
1736
- }
1737
-
1738
- // update worldspecs (necessary as new world may have been created)
1739
- worldspecs = getAvailableWorlds ();
1740
-
1741
- if (menudata.name == " " )
1742
- menudata.name = std::string (" Guest" ) + itos (myrand_range (1000 ,9999 ));
1743
1735
else
1744
- playername = menudata.name ;
1745
-
1746
- password = translatePassword (playername, narrow_to_wide (menudata.password ));
1747
- // infostream<<"Main: password hash: '"<<password<<"'"<<std::endl;
1748
-
1749
- address = menudata.address ;
1750
- int newport = stoi (menudata.port );
1751
- if (newport != 0 )
1752
- port = newport;
1753
-
1754
- simple_singleplayer_mode = menudata.simple_singleplayer_mode ;
1755
-
1756
- // Save settings
1757
- g_settings->set (" name" , playername);
1758
-
1759
- // Break out of menu-game loop to shut down cleanly
1760
- if (device->run () == false || kill == true )
1761
- break ;
1762
-
1763
- current_playername = playername;
1764
- current_password = password;
1765
- current_address = address;
1766
- current_port = port;
1767
-
1768
- // If using simple singleplayer mode, override
1769
- if (simple_singleplayer_mode) {
1770
- current_playername = " singleplayer" ;
1771
- current_password = " " ;
1772
- current_address = " " ;
1773
- current_port = myrand_range (49152 , 65535 );
1774
- } else if (address != " " ) {
1775
- ServerListSpec server;
1776
- server[" name" ] = menudata.servername ;
1777
- server[" address" ] = menudata.address ;
1778
- server[" port" ] = menudata.port ;
1779
- server[" description" ] = menudata.serverdescription ;
1780
- ServerList::insert (server);
1781
- }
1782
-
1783
- if ((!skip_main_menu) &&
1784
- (menudata.selected_world >= 0 ) &&
1785
- (menudata.selected_world < (int )worldspecs.size ())) {
1786
- g_settings->set (" selected_world_path" ,
1787
- worldspecs[menudata.selected_world ].path );
1788
- worldspec = worldspecs[menudata.selected_world ];
1789
-
1790
- }
1791
-
1792
- infostream <<" Selected world: " << worldspec.name
1793
- << " [" <<worldspec.path <<" ]" <<std::endl;
1794
-
1795
-
1796
- // If local game
1797
- if (current_address == " " ) {
1798
- if (worldspec.path == " " ) {
1799
- error_message = wgettext (" No world selected and no address "
1800
- " provided. Nothing to do." );
1801
- errorstream << wide_to_narrow (error_message) << std::endl;
1802
- continue ;
1803
- }
1804
-
1805
- if (!fs::PathExists (worldspec.path )) {
1806
- error_message = wgettext (" Provided world path doesn't exist: " )
1807
- + narrow_to_wide (worldspec.path );
1808
- errorstream << wide_to_narrow (error_message) << std::endl;
1809
- continue ;
1810
- }
1811
-
1812
- // Load gamespec for required game
1813
- gamespec = findWorldSubgame (worldspec.path );
1814
- if (!gamespec.isValid () && !commanded_gamespec.isValid ()) {
1815
- error_message = wgettext (" Could not find or load game \" " )
1816
- + narrow_to_wide (worldspec.gameid ) + L" \" " ;
1817
- errorstream << wide_to_narrow (error_message) << std::endl;
1818
- continue ;
1819
- }
1820
- if (commanded_gamespec.isValid () &&
1821
- commanded_gamespec.id != worldspec.gameid ) {
1822
- errorstream<<" WARNING: Overriding gamespec from \" "
1823
- << worldspec.gameid << " \" to \" "
1824
- << commanded_gamespec.id << " \" " << std::endl;
1825
- gamespec = commanded_gamespec;
1826
- }
1827
-
1828
- if (!gamespec.isValid ()) {
1829
- error_message = wgettext (" Invalid gamespec." );
1830
- error_message += L" (world_gameid="
1831
- + narrow_to_wide (worldspec.gameid ) + L" )" ;
1832
- errorstream << wide_to_narrow (error_message) << std::endl;
1833
- continue ;
1834
- }
1835
- }
1836
-
1837
- // Continue to game
1838
- break ;
1736
+ continue ;
1839
1737
}
1840
1738
1841
1739
// Break out of menu-game loop to shut down cleanly
1842
- if (device->run () == false || kill == true ) {
1843
- if (g_settings_path != " " ) {
1740
+ if (! device->run () || * kill ) {
1741
+ if (g_settings_path != " " )
1844
1742
g_settings->updateConfigFile (g_settings_path.c_str ());
1845
- }
1846
1743
break ;
1847
1744
}
1848
1745
1849
1746
if (current_playername.length () > PLAYERNAME_SIZE-1 ) {
1850
1747
error_message = wgettext (" Player name too long." );
1851
- playername = current_playername.substr (0 ,PLAYERNAME_SIZE-1 );
1748
+ playername = current_playername.substr (0 , PLAYERNAME_SIZE-1 );
1852
1749
g_settings->set (" name" , playername);
1853
1750
continue ;
1854
1751
}
1855
1752
1856
- /*
1857
- Run game
1858
- */
1753
+ device-> getVideoDriver ()-> setTextureCreationFlag (
1754
+ video::ETCF_CREATE_MIP_MAPS, g_settings-> getBool ( " mip_map " ));
1755
+
1859
1756
#ifdef HAVE_TOUCHSCREENGUI
1860
- receiver->m_touchscreengui = new TouchScreenGUI (device, receiver);
1861
- g_touchscreengui = receiver->m_touchscreengui ;
1757
+ receiver->m_touchscreengui = new TouchScreenGUI (device, receiver);
1758
+ g_touchscreengui = receiver->m_touchscreengui ;
1862
1759
#endif
1863
1760
the_game (
1864
- & kill ,
1761
+ kill ,
1865
1762
random_input,
1866
1763
input,
1867
1764
device,
@@ -1877,21 +1774,21 @@ int main(int argc, char *argv[])
1877
1774
simple_singleplayer_mode
1878
1775
);
1879
1776
smgr->clear ();
1777
+
1880
1778
#ifdef HAVE_TOUCHSCREENGUI
1881
- delete g_touchscreengui;
1882
- g_touchscreengui = NULL ;
1883
- receiver->m_touchscreengui = NULL ;
1779
+ delete g_touchscreengui;
1780
+ g_touchscreengui = NULL ;
1781
+ receiver->m_touchscreengui = NULL ;
1884
1782
#endif
1885
1783
1886
1784
} // try
1887
- catch (con::PeerNotFoundException &e)
1888
- {
1785
+ catch (con::PeerNotFoundException &e) {
1889
1786
error_message = wgettext (" Connection error (timed out?)" );
1890
1787
errorstream << wide_to_narrow (error_message) << std::endl;
1891
1788
}
1789
+
1892
1790
#ifdef NDEBUG
1893
- catch (std::exception &e)
1894
- {
1791
+ catch (std::exception &e) {
1895
1792
std::string narrow_message = " Some exception: \" " ;
1896
1793
narrow_message += e.what ();
1897
1794
narrow_message += " \" " ;
@@ -1904,60 +1801,457 @@ int main(int argc, char *argv[])
1904
1801
if (skip_main_menu) {
1905
1802
if (error_message != L" " ) {
1906
1803
verbosestream << " error_message = "
1907
- << wide_to_narrow (error_message) << std::endl;
1908
- retval = 1 ;
1804
+ << wide_to_narrow (error_message) << std::endl;
1805
+ retval = false ;
1909
1806
}
1910
1807
break ;
1911
1808
}
1912
1809
} // Menu-game loop
1913
1810
1914
-
1915
1811
g_menuclouds->drop ();
1916
1812
g_menucloudsmgr->drop ();
1917
1813
1918
- delete input;
1814
+ return retval;
1815
+ }
1816
+
1817
+ void ClientLauncher::init_args (GameParams &game_params, const Settings &cmd_args)
1818
+ {
1819
+ address = g_settings->get (" address" );
1820
+ if (game_params.world_path != " " )
1821
+ address = " " ;
1822
+ else if (cmd_args.exists (" address" ))
1823
+ address = cmd_args.get (" address" );
1919
1824
1920
- /*
1921
- In the end, delete the Irrlicht device.
1922
- */
1923
- device->drop ();
1825
+ playername = g_settings->get (" name" );
1826
+ if (cmd_args.exists (" name" ))
1827
+ playername = cmd_args.get (" name" );
1924
1828
1925
- #if USE_FREETYPE
1926
- if (use_freetype)
1927
- font->drop ();
1829
+ skip_main_menu = cmd_args.getFlag (" go" );
1830
+
1831
+ list_video_modes = cmd_args.getFlag (" videomodes" );
1832
+
1833
+ use_freetype = g_settings->getBool (" freetype" );
1834
+
1835
+ random_input = g_settings->getBool (" random_input" )
1836
+ || cmd_args.getFlag (" random-input" );
1837
+ }
1838
+
1839
+ bool ClientLauncher::init_engine (int log_level)
1840
+ {
1841
+ receiver = new MyEventReceiver ();
1842
+ create_engine_device (log_level);
1843
+ return device != NULL ;
1844
+ }
1845
+
1846
+ bool ClientLauncher::launch_game (std::wstring *error_message,
1847
+ GameParams &game_params, const Settings &cmd_args)
1848
+ {
1849
+ // Initialize menu data
1850
+ MainMenuData menudata;
1851
+ menudata.address = address;
1852
+ menudata.name = playername;
1853
+ menudata.port = itos (game_params.socket_port );
1854
+ menudata.errormessage = wide_to_narrow (*error_message);
1855
+
1856
+ *error_message = L" " ;
1857
+
1858
+ if (cmd_args.exists (" password" ))
1859
+ menudata.password = cmd_args.get (" password" );
1860
+
1861
+ menudata.enable_public = g_settings->getBool (" server_announce" );
1862
+
1863
+ // If a world was commanded, append and select it
1864
+ if (game_params.world_path != " " ) {
1865
+ worldspec.gameid = getWorldGameId (game_params.world_path , true );
1866
+ worldspec.name = _ (" [--world parameter]" );
1867
+
1868
+ if (worldspec.gameid == " " ) { // Create new
1869
+ worldspec.gameid = g_settings->get (" default_game" );
1870
+ worldspec.name += " [new]" ;
1871
+ }
1872
+ worldspec.path = game_params.world_path ;
1873
+ }
1874
+
1875
+ /* Show the GUI menu
1876
+ */
1877
+ if (!skip_main_menu) {
1878
+ main_menu (&menudata);
1879
+
1880
+ address = menudata.address ;
1881
+ int newport = stoi (menudata.port );
1882
+ if (newport != 0 )
1883
+ game_params.socket_port = newport;
1884
+
1885
+ simple_singleplayer_mode = menudata.simple_singleplayer_mode ;
1886
+
1887
+ std::vector<WorldSpec> worldspecs = getAvailableWorlds ();
1888
+ worldspecs = getAvailableWorlds ();
1889
+
1890
+ if (menudata.selected_world >= 0
1891
+ && menudata.selected_world < (int )worldspecs.size ()) {
1892
+ g_settings->set (" selected_world_path" ,
1893
+ worldspecs[menudata.selected_world ].path );
1894
+ worldspec = worldspecs[menudata.selected_world ];
1895
+ }
1896
+ }
1897
+
1898
+ if (menudata.errormessage != " " ) {
1899
+ /* The calling function will pass this back into this function upon the
1900
+ * next iteration (if any) causing it to be displayed by the GUI
1901
+ */
1902
+ *error_message = narrow_to_wide (menudata.errormessage );
1903
+ return false ;
1904
+ }
1905
+
1906
+ if (menudata.name == " " )
1907
+ menudata.name = std::string (" Guest" ) + itos (myrand_range (1000 , 9999 ));
1908
+ else
1909
+ playername = menudata.name ;
1910
+
1911
+ password = translatePassword (playername, narrow_to_wide (menudata.password ));
1912
+
1913
+ g_settings->set (" name" , playername);
1914
+
1915
+ current_playername = playername;
1916
+ current_password = password;
1917
+ current_address = address;
1918
+ current_port = game_params.socket_port ;
1919
+
1920
+ // If using simple singleplayer mode, override
1921
+ if (simple_singleplayer_mode) {
1922
+ assert (skip_main_menu == false );
1923
+ current_playername = " singleplayer" ;
1924
+ current_password = " " ;
1925
+ current_address = " " ;
1926
+ current_port = myrand_range (49152 , 65535 );
1927
+ } else if (address != " " ) {
1928
+ ServerListSpec server;
1929
+ server[" name" ] = menudata.servername ;
1930
+ server[" address" ] = menudata.address ;
1931
+ server[" port" ] = menudata.port ;
1932
+ server[" description" ] = menudata.serverdescription ;
1933
+ ServerList::insert (server);
1934
+ }
1935
+
1936
+ infostream << " Selected world: " << worldspec.name
1937
+ << " [" << worldspec.path << " ]" << std::endl;
1938
+
1939
+ if (current_address == " " ) { // If local game
1940
+ if (worldspec.path == " " ) {
1941
+ *error_message = wgettext (" No world selected and no address "
1942
+ " provided. Nothing to do." );
1943
+ errorstream << wide_to_narrow (*error_message) << std::endl;
1944
+ return false ;
1945
+ }
1946
+
1947
+ if (!fs::PathExists (worldspec.path )) {
1948
+ *error_message = wgettext (" Provided world path doesn't exist: " )
1949
+ + narrow_to_wide (worldspec.path );
1950
+ errorstream << wide_to_narrow (*error_message) << std::endl;
1951
+ return false ;
1952
+ }
1953
+
1954
+ // Load gamespec for required game
1955
+ gamespec = findWorldSubgame (worldspec.path );
1956
+ if (!gamespec.isValid () && !game_params.game_spec .isValid ()) {
1957
+ *error_message = wgettext (" Could not find or load game \" " )
1958
+ + narrow_to_wide (worldspec.gameid ) + L" \" " ;
1959
+ errorstream << wide_to_narrow (*error_message) << std::endl;
1960
+ return false ;
1961
+ }
1962
+ if (game_params.game_spec .isValid () &&
1963
+ game_params.game_spec .id != worldspec.gameid ) {
1964
+ errorstream << " WARNING: Overriding gamespec from \" "
1965
+ << worldspec.gameid << " \" to \" "
1966
+ << game_params.game_spec .id << " \" " << std::endl;
1967
+ gamespec = game_params.game_spec ;
1968
+ }
1969
+
1970
+ if (!gamespec.isValid ()) {
1971
+ *error_message = wgettext (" Invalid gamespec." );
1972
+ *error_message += L" (world_gameid="
1973
+ + narrow_to_wide (worldspec.gameid ) + L" )" ;
1974
+ errorstream << wide_to_narrow (*error_message) << std::endl;
1975
+ return false ;
1976
+ }
1977
+ }
1978
+
1979
+ return true ;
1980
+ }
1981
+
1982
+ void ClientLauncher::main_menu (MainMenuData *menudata)
1983
+ {
1984
+ bool *kill = porting::signal_handler_killstatus ();
1985
+ video::IVideoDriver *driver = device->getVideoDriver ();
1986
+
1987
+ infostream << " Waiting for other menus" << std::endl;
1988
+ while (device->run () && *kill == false ) {
1989
+ if (noMenuActive ())
1990
+ break ;
1991
+ driver->beginScene (true , true , video::SColor (255 , 128 , 128 , 128 ));
1992
+ guienv->drawAll ();
1993
+ driver->endScene ();
1994
+ // On some computers framerate doesn't seem to be automatically limited
1995
+ sleep_ms (25 );
1996
+ }
1997
+ infostream << " Waited for other menus" << std::endl;
1998
+
1999
+ // Cursor can be non-visible when coming from the game
2000
+ #ifndef ANDROID
2001
+ device->getCursorControl ()->setVisible (true );
2002
+ #endif
2003
+
2004
+ /* show main menu */
2005
+ GUIEngine mymenu (device, guiroot, &g_menumgr, smgr, menudata, *kill );
2006
+
2007
+ smgr->clear (); /* leave scene manager in a clean state */
2008
+ }
2009
+
2010
+ bool ClientLauncher::create_engine_device (int log_level)
2011
+ {
2012
+ static const char *driverids[] = {
2013
+ " null" ,
2014
+ " software" ,
2015
+ " burningsvideo" ,
2016
+ " direct3d8" ,
2017
+ " direct3d9" ,
2018
+ " opengl"
2019
+ #ifdef _IRR_COMPILE_WITH_OGLES1_
2020
+ ," ogles1"
2021
+ #endif
2022
+ #ifdef _IRR_COMPILE_WITH_OGLES2_
2023
+ ," ogles2"
1928
2024
#endif
2025
+ ," invalid"
2026
+ };
2027
+
2028
+ static const irr::ELOG_LEVEL irr_log_level[5 ] = {
2029
+ ELL_NONE,
2030
+ ELL_ERROR,
2031
+ ELL_WARNING,
2032
+ ELL_INFORMATION,
2033
+ #if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8)
2034
+ ELL_INFORMATION
2035
+ #else
2036
+ ELL_DEBUG
2037
+ #endif
2038
+ };
2039
+
2040
+ // Resolution selection
2041
+ bool fullscreen = g_settings->getBool (" fullscreen" );
2042
+ u16 screenW = g_settings->getU16 (" screenW" );
2043
+ u16 screenH = g_settings->getU16 (" screenH" );
2044
+
2045
+ // bpp, fsaa, vsync
2046
+ bool vsync = g_settings->getBool (" vsync" );
2047
+ u16 bits = g_settings->getU16 (" fullscreen_bpp" );
2048
+ u16 fsaa = g_settings->getU16 (" fsaa" );
2049
+
2050
+ // Determine driver
2051
+ video::E_DRIVER_TYPE driverType = video::EDT_OPENGL;
2052
+
2053
+ std::string driverstring = g_settings->get (" video_driver" );
2054
+ for (size_t i = 0 ; i < sizeof driverids / sizeof driverids[0 ]; i++) {
2055
+ if (strcasecmp (driverstring.c_str (), driverids[i]) == 0 ) {
2056
+ driverType = (video::E_DRIVER_TYPE) i;
2057
+ break ;
2058
+ }
2059
+
2060
+ if (strcasecmp (" invalid" , driverids[i]) == 0 ) {
2061
+ errorstream << " WARNING: Invalid video_driver specified;"
2062
+ << " defaulting to opengl" << std::endl;
2063
+ break ;
2064
+ }
2065
+ }
2066
+
2067
+ SIrrlichtCreationParameters params = SIrrlichtCreationParameters ();
2068
+ params.DriverType = driverType;
2069
+ params.WindowSize = core::dimension2d<u32>(screenW, screenH);
2070
+ params.Bits = bits;
2071
+ params.AntiAlias = fsaa;
2072
+ params.Fullscreen = fullscreen;
2073
+ params.Stencilbuffer = false ;
2074
+ params.Vsync = vsync;
2075
+ params.EventReceiver = receiver;
2076
+ params.HighPrecisionFPU = g_settings->getBool (" high_precision_fpu" );
2077
+ #ifdef __ANDROID__
2078
+ params.PrivateData = porting::app_global;
2079
+ params.OGLES2ShaderPath = std::string (porting::path_user + DIR_DELIM +
2080
+ " media" + DIR_DELIM + " Shaders" + DIR_DELIM).c_str ();
2081
+ #endif
2082
+
2083
+ device = createDeviceEx (params);
2084
+
2085
+ if (device) {
2086
+ // Map our log level to irrlicht engine one.
2087
+ ILogger* irr_logger = device->getLogger ();
2088
+ irr_logger->setLogLevel (irr_log_level[log_level]);
2089
+
2090
+ porting::initIrrlicht (device);
2091
+ }
2092
+
2093
+ return device != NULL ;
2094
+ }
2095
+
2096
+ // Misc functions
2097
+
2098
+ static bool print_video_modes ()
2099
+ {
2100
+ IrrlichtDevice *nulldevice;
2101
+
2102
+ bool vsync = g_settings->getBool (" vsync" );
2103
+ u16 fsaa = g_settings->getU16 (" fsaa" );
2104
+ MyEventReceiver* receiver = new MyEventReceiver ();
2105
+
2106
+ SIrrlichtCreationParameters params = SIrrlichtCreationParameters ();
2107
+ params.DriverType = video::EDT_NULL;
2108
+ params.WindowSize = core::dimension2d<u32>(640 , 480 );
2109
+ params.Bits = 24 ;
2110
+ params.AntiAlias = fsaa;
2111
+ params.Fullscreen = false ;
2112
+ params.Stencilbuffer = false ;
2113
+ params.Vsync = vsync;
2114
+ params.EventReceiver = receiver;
2115
+ params.HighPrecisionFPU = g_settings->getBool (" high_precision_fpu" );
2116
+
2117
+ nulldevice = createDeviceEx (params);
2118
+
2119
+ if (nulldevice == NULL ) {
2120
+ delete receiver;
2121
+ return false ;
2122
+ }
2123
+
2124
+ dstream << _ (" Available video modes (WxHxD):" ) << std::endl;
2125
+
2126
+ video::IVideoModeList *videomode_list = nulldevice->getVideoModeList ();
2127
+
2128
+ if (videomode_list != NULL ) {
2129
+ s32 videomode_count = videomode_list->getVideoModeCount ();
2130
+ core::dimension2d<u32> videomode_res;
2131
+ s32 videomode_depth;
2132
+ for (s32 i = 0 ; i < videomode_count; ++i) {
2133
+ videomode_res = videomode_list->getVideoModeResolution (i);
2134
+ videomode_depth = videomode_list->getVideoModeDepth (i);
2135
+ dstream << videomode_res.Width << " x" << videomode_res.Height
2136
+ << " x" << videomode_depth << std::endl;
2137
+ }
2138
+
2139
+ dstream << _ (" Active video mode (WxHxD):" ) << std::endl;
2140
+ videomode_res = videomode_list->getDesktopResolution ();
2141
+ videomode_depth = videomode_list->getDesktopDepth ();
2142
+ dstream << videomode_res.Width << " x" << videomode_res.Height
2143
+ << " x" << videomode_depth << std::endl;
2144
+
2145
+ }
2146
+
2147
+ nulldevice->drop ();
1929
2148
delete receiver;
2149
+
2150
+ return videomode_list != NULL ;
2151
+ }
2152
+
1930
2153
#endif // !SERVER
1931
2154
1932
- // Update configuration file
1933
- if (g_settings_path != " " )
1934
- g_settings->updateConfigFile (g_settings_path.c_str ());
2155
+ /* ****************************************************************************
2156
+ * Performance tests
2157
+ *****************************************************************************/
2158
+ #ifndef SERVER
2159
+ static void speed_tests ()
2160
+ {
2161
+ // volatile to avoid some potential compiler optimisations
2162
+ volatile static s16 temp16;
2163
+ volatile static f32 tempf;
2164
+ static v3f tempv3f1;
2165
+ static v3f tempv3f2;
2166
+ static std::string tempstring;
2167
+ static std::string tempstring2;
2168
+
2169
+ tempv3f1 = v3f ();
2170
+ tempv3f2 = v3f ();
2171
+ tempstring = std::string ();
2172
+ tempstring2 = std::string ();
1935
2173
1936
- // Print modified quicktune values
1937
2174
{
1938
- bool header_printed = false ;
1939
- std::vector<std::string> names = getQuicktuneNames ();
1940
- for (u32 i = 0 ; i < names.size (); i++) {
1941
- QuicktuneValue val = getQuicktuneValue (names[i]);
1942
- if (!val.modified )
1943
- continue ;
1944
- if (!header_printed) {
1945
- dstream << " Modified quicktune values:" << std::endl;
1946
- header_printed = true ;
2175
+ infostream << " The following test should take around 20ms." << std::endl;
2176
+ TimeTaker timer (" Testing std::string speed" );
2177
+ const u32 jj = 10000 ;
2178
+ for (u32 j = 0 ; j < jj; j++) {
2179
+ tempstring = " " ;
2180
+ tempstring2 = " " ;
2181
+ const u32 ii = 10 ;
2182
+ for (u32 i = 0 ; i < ii; i++) {
2183
+ tempstring2 += " asd" ;
2184
+ }
2185
+ for (u32 i = 0 ; i < ii+1 ; i++) {
2186
+ tempstring += " asd" ;
2187
+ if (tempstring == tempstring2)
2188
+ break ;
1947
2189
}
1948
- dstream<<names[i] << " = " << val.getString () << std::endl;
1949
2190
}
1950
2191
}
1951
2192
1952
- // Stop httpfetch thread (if started)
1953
- httpfetch_cleanup () ;
2193
+ infostream << " All of the following tests should take around 100ms each. "
2194
+ << std::endl ;
1954
2195
1955
- END_DEBUG_EXCEPTION_HANDLER (errorstream)
2196
+ {
2197
+ TimeTaker timer (" Testing floating-point conversion speed" );
2198
+ tempf = 0.001 ;
2199
+ for (u32 i = 0 ; i < 4000000 ; i++) {
2200
+ temp16 += tempf;
2201
+ tempf += 0.001 ;
2202
+ }
2203
+ }
1956
2204
1957
- debugstreams_deinit ();
2205
+ {
2206
+ TimeTaker timer (" Testing floating-point vector speed" );
1958
2207
2208
+ tempv3f1 = v3f (1 , 2 , 3 );
2209
+ tempv3f2 = v3f (4 , 5 , 6 );
2210
+ for (u32 i = 0 ; i < 10000000 ; i++) {
2211
+ tempf += tempv3f1.dotProduct (tempv3f2);
2212
+ tempv3f2 += v3f (7 , 8 , 9 );
2213
+ }
2214
+ }
1959
2215
1960
- return retval;
1961
- }
2216
+ {
2217
+ TimeTaker timer (" Testing std::map speed" );
2218
+
2219
+ std::map<v2s16, f32> map1;
2220
+ tempf = -324 ;
2221
+ const s16 ii = 300 ;
2222
+ for (s16 y = 0 ; y < ii; y++) {
2223
+ for (s16 x = 0 ; x < ii; x++) {
2224
+ map1[v2s16 (x, y)] = tempf;
2225
+ tempf += 1 ;
2226
+ }
2227
+ }
2228
+ for (s16 y = ii - 1 ; y >= 0 ; y--) {
2229
+ for (s16 x = 0 ; x < ii; x++) {
2230
+ tempf = map1[v2s16 (x, y)];
2231
+ }
2232
+ }
2233
+ }
1962
2234
1963
- // END
2235
+ {
2236
+ infostream << " Around 5000/ms should do well here." << std::endl;
2237
+ TimeTaker timer (" Testing mutex speed" );
2238
+
2239
+ JMutex m;
2240
+ u32 n = 0 ;
2241
+ u32 i = 0 ;
2242
+ do {
2243
+ n += 10000 ;
2244
+ for (; i < n; i++) {
2245
+ m.Lock ();
2246
+ m.Unlock ();
2247
+ }
2248
+ }
2249
+ // Do at least 10ms
2250
+ while (timer.getTimerTime () < 10 );
2251
+
2252
+ u32 dtime = timer.stop ();
2253
+ u32 per_ms = n / dtime;
2254
+ infostream << " Done. " << dtime << " ms, " << per_ms << " /ms" << std::endl;
2255
+ }
2256
+ }
2257
+ #endif
0 commit comments