ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/bin/deliantra
(Generate patch)

Comparing deliantra/Deliantra-Client/bin/deliantra (file contents):
Revision 1.83 by root, Sun Jan 4 10:22:19 2009 UTC vs.
Revision 1.106 by root, Sat Apr 3 03:02:28 2010 UTC

17 $zip->extractMember ("SPLASH.bmp", "$ENV{PAR_TEMP}/SPLASH.bmp"); 17 $zip->extractMember ("SPLASH.bmp", "$ENV{PAR_TEMP}/SPLASH.bmp");
18 } 18 }
19 19
20 require Win32::GUI::SplashScreen; 20 require Win32::GUI::SplashScreen;
21 21
22 # initialise the resolver now, as vista forces us back to the desktop
23 # when doing this.
24 use AnyEvent::DNS ();
25 AnyEvent::DNS::resolver;
26
22 Win32::GUI::SplashScreen::Show ( 27 Win32::GUI::SplashScreen::Show (
23 -file => "$ENV{PAR_TEMP}/SPLASH.bmp", 28 -file => "$ENV{PAR_TEMP}/SPLASH.bmp",
24 ); 29 );
25 30
26 $startup_done = sub { 31 $startup_done = sub {
27 Win32::GUI::SplashScreen::Done (1); 32 Win32::GUI::SplashScreen::Done (1);
28 }; 33 };
29 } 34 }
30} 35}
31 36
32use strict; 37use common::sense;
33use utf8;
34 38
35use Carp 'verbose'; 39use Carp 'verbose';
36 40
37# do things only needed for single-binary version (par) 41# do things only needed for single-binary version (par)
38BEGIN { 42BEGIN {
51 55
52 if ($^O eq "MSWin32") { 56 if ($^O eq "MSWin32") {
53 # pango is relocatable on win32 57 # pango is relocatable on win32
54 } else { 58 } else {
55 # OS X 59 # OS X
56 $ENV{FONTCONFIG_FILE} = "$root/fonts.conf"; # no effect??!?!
57 $ENV{FONTCONFIG_DIR} = $root; # no effect??!?!
58 $ENV{PANGO_RC_FILE} = "$root/pango.rc"; 60 $ENV{PANGO_RC_FILE} = "$root/pango.rc";
59 $ENV{DYLD_LIBRARY_PATH} = $root; 61 $ENV{DYLD_LIBRARY_PATH} = $root;
60 chdir $root; # for pango modules, maybe other things 62 chdir $root; # for pango modules, maybe other things
61 } 63 }
62 64
63 unshift @INC, $root; 65 unshift @INC, $root;
64 } 66 }
65} 67}
66 68
67# prepend private library directory 69# prepend private library directory and prepare env
68BEGIN { 70BEGIN {
69 for (grep !ref, @INC) { 71 for (grep !ref, @INC) {
70 my $path = "$_/Deliantra/Client/private"; 72 my $path = "$_/Deliantra/Client/private";
71 if (-d $path) { 73 if (-d $path) {
72 unshift @INC, $path; 74 unshift @INC, $path;
86 88
87use Deliantra; 89use Deliantra;
88use Deliantra::Protocol::Constants; 90use Deliantra::Protocol::Constants;
89 91
90use AnyEvent::Util (); 92use AnyEvent::Util ();
91use AnyEvent::DNS;
92use AnyEvent::Socket (); 93use AnyEvent::Socket ();
93use AnyEvent::DNS (); 94use AnyEvent::DNS ();
94 95
95use Compress::LZF; 96use Compress::LZF;
96use JSON::XS; 97use JSON::XS;
132 DC::fatal Carp::longmess $@; 133 DC::fatal Carp::longmess $@;
133}; 134};
134 135
135my $MAX_FPS = 60; 136my $MAX_FPS = 60;
136 137
138our $DEFAULT_SERVER = "gameserver.deliantra.net";
139
137our $META_SERVER = "http://metaserver.schmorp.de/current.json"; 140our $META_SERVER = "http://metaserver.schmorp.de/current.json";
138 141
139our $LAST_REFRESH; 142our $LAST_REFRESH;
140our $NOW; 143our $NOW;
141 144
162 165
163our $MAP; 166our $MAP;
164our $MAPMAP; 167our $MAPMAP;
165our $MAPWIDGET; 168our $MAPWIDGET;
166our $COMPLETER; 169our $COMPLETER;
167our $BUTTONBAR; 170our $MENUFRAME; # the rectangle at the top
171our $MENUBAR; # the hbox at the top
172our $MENUPOPUP;
173our $BUTTONBAR; # the menu buttons
168our $METASERVER; 174our $METASERVER;
169our $LOGIN_BUTTON; 175our $LOGIN_BUTTON;
170our $QUIT_DIALOG; 176our $QUIT_DIALOG;
171our $HOST_ENTRY; 177our $HOST_ENTRY;
172our $FULLSCREEN_ENABLE; 178our $FULLSCREEN_ENABLE;
198our $FLOORBOX; 204our $FLOORBOX;
199our $GAUGES; 205our $GAUGES;
200our $STATWIDS; 206our $STATWIDS;
201 207
202our $SDL_ACTIVE; 208our $SDL_ACTIVE;
203our %SDL_CB; 209our @SDL_CB;
204 210
205our $ALT_ENTER_MESSAGE; 211our $ALT_ENTER_MESSAGE;
206our $STATUSBOX; 212our $STATUSBOX;
207our $MODBOX; 213our $MODBOX;
208our $DEBUG_STATUS; 214our $DEBUG_STATUS;
339 or return; 345 or return;
340 346
341 $meta->{data} 347 $meta->{data}
342 or return; 348 or return;
343 349
344 # if its a jingle, play it as ambient music 350 # if it's a jingle, play it as ambient music
345 if ($meta->{data}{jingle}) { 351 if ($meta->{data}{jingle}) {
346 if (delete $AUDIO_PLAY{$face}) { # take the jingle out of the sound queue 352 if (delete $AUDIO_PLAY{$face}) { # take the jingle out of the sound queue
347 push @MUSIC_JINGLE, $meta; # push it oto the music/jingle queue 353 push @MUSIC_JINGLE, $meta; # push it unto the music/jingle queue
348 &audio_music_push ($face); 354 &audio_music_push ($face);
349 } 355 }
350 } else { 356 } else {
351 # fetch from database 357 # fetch from database
352 DC::DB::get res_data => $meta->{name}, sub { 358 DC::DB::get res_data => $meta->{name}, sub {
353 my $rwops = new DC::RW $_[0]; 359 my $rwops = new DC::RW $_[0];
354 my $chunk = new DC::MixChunk $rwops 360 my $chunk = new DC::MixChunk $rwops
355 or Carp::confess "sound face " . (JSON::XS::encode_json $meta) . " unloadable: " . DC::Mix_GetError; 361 or Carp::confess "sound face " . (JSON::XS::encode_json $meta) . " (" . (unpack "H64", $_[0]) . ") unloadable: " . DC::Mix_GetError;
356 $chunk->volume (($meta->{data}{volume} || 1) * 128); 362 $chunk->volume (($meta->{data}{volume} || 1) * 128);
357 $AUDIO_CHUNK{$face} = $chunk; 363 $AUDIO_CHUNK{$face} = $chunk;
358 364
359 audio_sound_push ($face); 365 audio_sound_push ($face);
360 }; 366 };
407 413
408 audio_music_update_volume; 414 audio_music_update_volume;
409 415
410 $MUSIC_PLAYING_DATA = \$_[0]; 416 $MUSIC_PLAYING_DATA = \$_[0];
411 417
418 $meta->{path} or length $_[0]
419 or return clienterror "empty music face from res_data ($meta->{face})";#d#
420
412 my $rwops = $meta->{path} 421 my $rwops = $meta->{path}
413 ? new_from_file DC::RW $meta->{path} 422 ? (new_from_file DC::RW $meta->{path} or return clienterror "unable to load music face $meta->{path}: $!")#d#clienterror
414 : new DC::RW $$MUSIC_PLAYING_DATA; 423 : new DC::RW $$MUSIC_PLAYING_DATA;
415 424
416 $MUSIC_PLAYER = new DC::MixMusic $rwops 425 $MUSIC_PLAYER = new DC::MixMusic $rwops
417 or return clienterror "music face $meta->{face} unloadable: " . DC::Mix_GetError => 1; 426 or return clienterror "music face $meta->{face} unloadable: " . DC::Mix_GetError => 1;
418 427
531 sub audio_tab_update; 540 sub audio_tab_update;
532 audio_tab_update; 541 audio_tab_update;
533} 542}
534 543
535sub audio_shutdown { 544sub audio_shutdown {
545 if ($SDL_MIXER) {
546 DC::MixMusic::halt;
547 DC::Mix_AllocateChannels 0;
548 }
549
536 undef $MUSIC_PLAYER; 550 undef $MUSIC_PLAYER;
537 undef $MUSIC_PLAYING_META; 551 undef $MUSIC_PLAYING_META;
538 undef $MUSIC_PLAYING_DATA; 552 undef $MUSIC_PLAYING_DATA;
539 553
540 $MUSIC_WANT = []; 554 $MUSIC_WANT = [];
808 822
809 on_connect => sub { 823 on_connect => sub {
810 if ($_[0]) { 824 if ($_[0]) {
811 DC::lowdelay fileno $CONN->{fh}; 825 DC::lowdelay fileno $CONN->{fh};
812 826
813 status "login successful"; 827 status "successfully connected to the server";
814 } else { 828 } else {
815 undef $CONN; 829 undef $CONN;
816 status "unable to connect: $!"; 830 status "unable to connect: $!";
817 stop_game(); 831 stop_game();
818 } 832 }
820 ; 834 ;
821} 835}
822 836
823sub start_game { 837sub start_game {
824 status "logging in..."; 838 status "logging in...";
839
840 my $server = $PROFILE->{host} || $DEFAULT_SERVER;
841 my ($host, $port) = AnyEvent::Socket::parse_hostport $server, "deliantra=13327"
842 or return status "$server: unable to parse server address, try an empty field.";
825 843
826 $LOGIN_BUTTON->set_text ("Logout"); 844 $LOGIN_BUTTON->set_text ("Logout");
827 $SETUP_DIALOG->hide; 845 $SETUP_DIALOG->hide;
828
829 my ($host, $port) = AnyEvent::Socket::parse_hostport $PROFILE->{host}, "deliantra=13327";
830 846
831 $MAP = new DC::Map; 847 $MAP = new DC::Map;
832 848
833 # hack to make SURE we find the IP address all right 849 # hack to make SURE we find the IP address all right
834 # can be removed once AnyEvent::DNS is proven stable. 850 # can be removed once AnyEvent::DNS is proven stable.
835 if ($host eq "gameserver.deliantra.net") { 851 if ($host eq "gameserver.deliantra.net") {
836 AnyEvent::DNS::a "dnstest.deliantra.net", sub { 852 AnyEvent::DNS::a "dnstest.deliantra.net", sub {
837 if ($_[0] ne "80.101.114.108") { # Perl 853 if ($_[0] ne "80.101.114.108") { # Perl
854 status "dns failure, trying differently";
855 $host = eval { Socket::inet_ntoa Socket::inet_aton "gameserver.deliantra.net" };
856 unless (defined $host) {
838 status "dns failure, using hardcoded address"; 857 status "dns failure, using hardcoded address";
839 $host = "129.13.162.95"; 858 $host = "129.13.162.95";
859 }
840 } 860 }
841 861
842 dc_connect $host, $port; 862 dc_connect $host, $port;
843 }; 863 };
844 } else { 864 } else {
911 931
912 $table->add_at (0, $row, new DC::UI::Label align => 1, text => "Video Mode"); 932 $table->add_at (0, $row, new DC::UI::Label align => 1, text => "Video Mode");
913 $table->add_at (1, $row++, my $hbox = new DC::UI::HBox); 933 $table->add_at (1, $row++, my $hbox = new DC::UI::HBox);
914 934
915 $hbox->add ($MODE_SLIDER = new DC::UI::Slider 935 $hbox->add ($MODE_SLIDER = new DC::UI::Slider
936 c_rescale => 1,
916 force_w => $WIDTH * 0.1, expand => 1, 937 force_w => $WIDTH * 0.1, expand => 1,
917 range => [ ($CFG->{sdl_mode}) x 3 ], 938 range => [ ($CFG->{sdl_mode}) x 3 ],
918 tooltip => $vidmode_tooltip); 939 tooltip => $vidmode_tooltip);
919 $hbox->add (my $mode_label = new DC::UI::Label 940 $hbox->add (my $mode_label = new DC::UI::Label
920 height => 0.8, template => "9999x9999@9+9", 941 height => 0.8, template => "9999x9999@9+9",
1012 . "If you have a very slow system, non-accelerated drivers or plain dislike smooth scrolling, " 1033 . "If you have a very slow system, non-accelerated drivers or plain dislike smooth scrolling, "
1013 . "then disable this option. Changes take effect immdiately.", 1034 . "then disable this option. Changes take effect immdiately.",
1014 on_changed => sub { my ($self, $value) = @_; $CFG->{smooth_movement} = $value; 0 } 1035 on_changed => sub { my ($self, $value) = @_; $CFG->{smooth_movement} = $value; 0 }
1015 ); 1036 );
1016 1037
1038 $table->add_at (0, $row, new DC::UI::Label align => 1, text => "Smooth Transitions");
1039 $table->add_at (1, $row++, new DC::UI::CheckBox
1040 state => $CFG->{smooth_transitions},
1041 tooltip => "<b>Smooth Transitions</b> tries to blend the fog of war and lighting smoothly between updates. "
1042 . "If you have a very slow system, non-accelerated drivers or plain dislike smooth scrolling, "
1043 . "then disable this option. Requires Smooth Movement and OpenGL Multitexturing. Changes take effect immdiately.",
1044 on_changed => sub { my ($self, $value) = @_; $CFG->{smooth_transitions} = $value; 0 }
1045 );
1046
1047
1017 $table->add_at (0, $row, new DC::UI::Label align => 1, text => "Map Scale"); 1048 $table->add_at (0, $row, new DC::UI::Label align => 1, text => "Map Scale");
1018 $table->add_at (1, $row++, new DC::UI::Slider 1049 $table->add_at (1, $row++, new DC::UI::Slider
1019 range => [(log $CFG->{map_scale}) / (log 2), -3, 1, 0, 1], 1050 range => [(log $CFG->{map_scale}) / (log 2), -3, 1, 0, 1],
1020 tooltip => "Enlarge or shrink the displayed map. Changes are instant.", 1051 tooltip => "Enlarge or shrink the displayed map. Changes are instant.",
1021 on_changed => sub { my ($self, $value) = @_; $CFG->{map_scale} = 2 ** $value; 0 } 1052 on_changed => sub { my ($self, $value) = @_; $CFG->{map_scale} = 2 ** $value; 0 }
1033 $table->add_at (0, $row, new DC::UI::Label align => 1, text => "Fog of War"); 1064 $table->add_at (0, $row, new DC::UI::Label align => 1, text => "Fog of War");
1034 $table->add_at (1, $row++, new DC::UI::CheckBox 1065 $table->add_at (1, $row++, new DC::UI::CheckBox
1035 state => $CFG->{fow_enable}, 1066 state => $CFG->{fow_enable},
1036 tooltip => "<b>Fog-of-War</b> marks areas that cannot be seen by the player. Changes are instant.", 1067 tooltip => "<b>Fog-of-War</b> marks areas that cannot be seen by the player. Changes are instant.",
1037 on_changed => sub { my ($self, $value) = @_; $CFG->{fow_enable} = $value; 0 } 1068 on_changed => sub { my ($self, $value) = @_; $CFG->{fow_enable} = $value; 0 }
1069 );
1070
1071 $table->add_at (0, $row, new DC::UI::Label align => 1, text => "FoW Pattern");
1072 $table->add_at (1, $row++, new DC::UI::ImageButton
1073 tex => $DC::MapWidget::TEX_HIDDEN[$CFG->{fow_texture}],
1074 bg => [0.3, 0.3, 0.2],
1075 force_w => 64,
1076 force_h => 64,
1077 tooltip => "<b>Fog of War Pattern.</b> The pattern that is overlaid over areas hidden from view. Click to cycle through various alternatives. Changes are instant.",
1078 on_activate => sub {
1079 my ($self) = @_;
1080 $CFG->{fow_texture} = ($CFG->{fow_texture} + 1) % @DC::MapWidget::TEX_HIDDEN;
1081 $self->set_texture ($DC::MapWidget::TEX_HIDDEN[$CFG->{fow_texture}]);
1082 $MAPWIDGET->update;
1083 }
1038 ); 1084 );
1039 1085
1040 $table->add_at (0, $row, new DC::UI::Label align => 1, text => "FoW Intensity"); 1086 $table->add_at (0, $row, new DC::UI::Label align => 1, text => "FoW Intensity");
1041 $table->add_at (1, $row++, new DC::UI::Slider 1087 $table->add_at (1, $row++, new DC::UI::Slider
1042 range => [$CFG->{fow_intensity}, 0, 1, 0, 1 / 256], 1088 range => [$CFG->{fow_intensity}, 0, 1, 0, 1 / 256],
1094 1140
1095 my $text = !$freq 1141 my $text = !$freq
1096 ? "audio is off" 1142 ? "audio is off"
1097 : "audio is enabled\n" 1143 : "audio is enabled\n"
1098 . "frequency (Hz): $freq\n" 1144 . "frequency (Hz): $freq\n"
1099 . "channels: $chans"; 1145 . "channels: $chans\n"
1146 . "chunk decoders available: " . (join ", ", DC::MixChunk::decoders) . "\n"
1147 . "music decoders available: " . (join ", ", DC::MixMusic::decoders);
1100 1148
1101 $AUDIO_INFO->set_text ($text); 1149 $AUDIO_INFO->set_text ($text);
1102} 1150}
1103 1151
1104sub audio_setup { 1152sub audio_setup {
1244} 1292}
1245 1293
1246sub make_gauge_window { 1294sub make_gauge_window {
1247 my $gh = int $HEIGHT * $CFG->{gauge_size}; 1295 my $gh = int $HEIGHT * $CFG->{gauge_size};
1248 1296
1249 my $win = new DC::UI::Frame ( 1297 $GAUGES->{win} = my $win = new DC::UI::Frame (
1250 force_x => 0, 1298 force_x => 0,
1251 force_y => "max", 1299 force_y => "max",
1252 force_w => $WIDTH, 1300 force_w => $WIDTH,
1253 force_h => $gh, 1301 force_h => $gh,
1254 ); 1302 );
1270 (new DC::UI::Empty expand => 1), 1318 (new DC::UI::Empty expand => 1),
1271 (my $hb = new DC::UI::HBox), 1319 (my $hb = new DC::UI::HBox),
1272 ], 1320 ],
1273 ); 1321 );
1274 1322
1275 $hb->add (my $hg = new DC::UI::Gauge type => 'hp', tooltip => "#stat_health"); 1323 $hb->add ($GAUGES->{hp} = new DC::UI::Gauge type => 'hp', tooltip => "#stat_health");
1276 $hb->add (my $mg = new DC::UI::Gauge type => 'mana', tooltip => "#stat_mana"); 1324 $hb->add ($GAUGES->{mana} = new DC::UI::Gauge type => 'mana', tooltip => "#stat_mana");
1277 $hb->add (my $gg = new DC::UI::Gauge type => 'grace', tooltip => "#stat_grace"); 1325 $hb->add ($GAUGES->{grace} = new DC::UI::Gauge type => 'grace', tooltip => "#stat_grace");
1278 $hb->add (my $fg = new DC::UI::Gauge type => 'food', tooltip => "#stat_food"); 1326 $hb->add ($GAUGES->{food} = new DC::UI::Gauge type => 'food', tooltip => "#stat_food");
1279
1280 $vbox->add (my $exp = new DC::UI::Label align => 1, can_hover => 1, can_events => 1, tooltip => "#stat_exp");
1281 $vbox->add (my $prg = new DC::UI::ExperienceProgress);
1282 $vbox->add (my $sklprg = new DC::UI::ExperienceProgress);
1283 $vbox->add (my $rng = new DC::UI::Label align => 1, can_hover => 1, can_events => 1, tooltip => "#stat_ranged");
1284
1285 $GAUGES = {
1286 exp => $exp, prg => $prg, sklprg => $sklprg,
1287 win => $win, range => $rng,
1288 hp => $hg, mana => $mg, grace => $gg, food => $fg,
1289 };
1290 1327
1291 &set_gauge_window_fontsize; 1328 &set_gauge_window_fontsize;
1292 1329
1293 $win 1330 $win
1294} 1331}
1635 child => (my $table = new DC::UI::Table expand => 1, col_expand => [0, 1]), 1672 child => (my $table = new DC::UI::Table expand => 1, col_expand => [0, 1]),
1636 ); 1673 );
1637 1674
1638 $table->add_at (0, 4, new DC::UI::Label align => 1, text => "Username"); 1675 $table->add_at (0, 4, new DC::UI::Label align => 1, text => "Username");
1639 $table->add_at (1, 4, new DC::UI::Entry 1676 $table->add_at (1, 4, new DC::UI::Entry
1640 text => $CFG->{profile}{default}{user}, 1677 text => $PROFILE->{user},
1641 tooltip => "The name of your character on the server.", 1678 tooltip => "The name of your character on the server. The name is case-sensitive!",
1642 on_changed => sub { my ($self, $value) = @_; $CFG->{profile}{default}{user} = $value; 1 } 1679 on_changed => sub { my ($self, $value) = @_; $PROFILE->{user} = $value; 1 }
1643 ); 1680 );
1644 1681
1645 $table->add_at (0, 5, new DC::UI::Label align => 1, text => "Password"); 1682 $table->add_at (0, 5, new DC::UI::Label align => 1, text => "Password");
1646 $table->add_at (1, 5, new DC::UI::Entry 1683 $table->add_at (1, 5, new DC::UI::Entry
1647 text => $CFG->{profile}{default}{password}, 1684 text => $PROFILE->{password},
1648 hidden => 1, 1685 hidden => 1,
1649 tooltip => "The password for your character.", 1686 tooltip => "The password for your character.",
1650 on_changed => sub { my ($self, $value) = @_; $CFG->{profile}{default}{password} = $value; 1 } 1687 on_changed => sub { my ($self, $value) = @_; $PROFILE->{password} = $value; 1 }
1651 ); 1688 );
1652 1689
1653 $table->add_at (1, 11, $LOGIN_BUTTON = new DC::UI::Button 1690 $table->add_at (1, 11, $LOGIN_BUTTON = new DC::UI::Button
1654 expand => 1, 1691 expand => 1,
1655 text => "Login / Register", 1692 text => "Login / Register",
1691 $table->add_at (1, $row, my $vbox = new DC::UI::VBox); 1728 $table->add_at (1, $row, my $vbox = new DC::UI::VBox);
1692 1729
1693 $vbox->add ( 1730 $vbox->add (
1694 $HOST_ENTRY = new DC::UI::Entry 1731 $HOST_ENTRY = new DC::UI::Entry
1695 expand => 1, 1732 expand => 1,
1696 text => $CFG->{profile}{default}{host}, 1733 text => $PROFILE->{host},
1697 tooltip => "The hostname or ip address of the Deliantra server to connect to (e.g. <b>gameserver.deliantra.net</b>)", 1734 tooltip => "The hostname or ip address of the Deliantra server to connect to (e.g. <b>gameserver.deliantra.net</b>)",
1698 on_changed => sub { 1735 on_changed => sub {
1699 my ($self, $value) = @_; 1736 my ($self, $value) = @_;
1700 $CFG->{profile}{default}{host} = $value; 1737 $PROFILE->{host} = $value;
1701 1 1738 1
1702 } 1739 }
1703 ); 1740 );
1704 1741
1705 if (0) { #d# disabled 1742 if (0) { #d# disabled
1748 1785
1749 my $row = 0; 1786 my $row = 0;
1750 1787
1751 $table->add_at (0, $row, new DC::UI::Label align => 1, text => "Tip of the day"); 1788 $table->add_at (0, $row, new DC::UI::Label align => 1, text => "Tip of the day");
1752 $table->add_at (1, $row++, new DC::UI::CheckBox 1789 $table->add_at (1, $row++, new DC::UI::CheckBox
1790 c_colspan => 2,
1753 state => $CFG->{show_tips}, 1791 state => $CFG->{show_tips},
1754 tooltip => "Show the <b>Tip of the day</b> window at startup?", 1792 tooltip => "Show the <b>Tip of the day</b> window at startup?",
1755 on_changed => sub { 1793 on_changed => sub {
1756 my ($self, $value) = @_; 1794 my ($self, $value) = @_;
1757 $CFG->{show_tips} = $value; 1795 $CFG->{show_tips} = $value;
1759 } 1797 }
1760 ); 1798 );
1761 1799
1762 $table->add_at (0, $row, new DC::UI::Label align => 1, text => "Message Window Size"); 1800 $table->add_at (0, $row, new DC::UI::Label align => 1, text => "Message Window Size");
1763 $table->add_at (1, $row++, my $saycmd = new DC::UI::Entry 1801 $table->add_at (1, $row++, my $saycmd = new DC::UI::Entry
1802 c_colspan => 2,
1764 text => $CFG->{logview_max_par}, 1803 text => $CFG->{logview_max_par},
1765 tooltip => "This is maximum number of messages remembered in the <b>Message</b> window. If the server " 1804 tooltip => "This is maximum number of messages remembered in the <b>Message</b> window. If the server "
1766 . "sends more messages than this number, older messages get removed to save memory and " 1805 . "sends more messages than this number, older messages get removed to save memory and "
1767 . "computing time. A value of <b>0</b> disables this feature, but that is not recommended.", 1806 . "computing time. A value of <b>0</b> disables this feature, but that is not recommended.",
1768 on_changed => sub { 1807 on_changed => sub {
1770 $MESSAGE_DIST->set_max_par ($CFG->{logview_max_par} = $value*1); 1809 $MESSAGE_DIST->set_max_par ($CFG->{logview_max_par} = $value*1);
1771 0 1810 0
1772 }, 1811 },
1773 ); 1812 );
1774 1813
1814 $table->add_at (0, $row, new DC::UI::Label align => 1, text => "Config Autosave");
1815 $table->add_at (1, $row, new DC::UI::CheckBox
1816 state => $CFG->{config_autosave},
1817 tooltip => "Normally, configuration settings and the user interface layout "
1818 . "are saved on client exit. You can disable this behaviour by "
1819 . "unchecking this checkbox.",
1820 on_changed => sub {
1821 my ($self, $value) = @_;
1822 $CFG->{config_autosave} = $value;
1823 0
1824 }
1825 );
1826 $table->add_at (2, $row++, new DC::UI::Button
1827 text => "Save Now",
1828 tooltip => "Use this to manually save configuration and UI layout when "
1829 . "autosave is disabled.",
1830 on_activate => sub {
1831 DC::write_cfg;
1832 0
1833 }
1834 );
1835
1775 $table 1836 $table
1776} 1837}
1777 1838
1778sub autopickup_setup { 1839sub autopickup_setup {
1779 my $r = new DC::UI::ScrolledWindow ( 1840 my $r = new DC::UI::ScrolledWindow (
1785 col_expand => [0, 1, 0, 1], 1846 col_expand => [0, 1, 0, 1],
1786 ); 1847 );
1787 1848
1788 for ( 1849 for (
1789 ["General", 0, 0, 1850 ["General", 0, 0,
1790 ["Enable autopickup" => PICKUP_NEWMODE, \$PICKUP_ENABLE],
1791 ["Inhibit autopickup" => PICKUP_INHIBIT], 1851# ["Inhibit autopickup" => PICKUP_INHIBIT],
1792 ["Stop before pickup" => PICKUP_STOP], 1852 ["Stop before pickup" => PICKUP_STOP],
1793 ["Debug autopickup" => PICKUP_DEBUG], 1853 ["Debug autopickup" => PICKUP_DEBUG],
1794 ], 1854 ],
1795 ["Weapons", 0, 6, 1855 ["Weapons", 0, 6,
1796 ["All weapons" => PICKUP_ALLWEAPON], 1856 ["All weapons" => PICKUP_ALLWEAPON],
1844 $::CFG->{pickup} |= $mask; 1904 $::CFG->{pickup} |= $mask;
1845 } else { 1905 } else {
1846 $::CFG->{pickup} &= ~$mask; 1906 $::CFG->{pickup} &= ~$mask;
1847 } 1907 }
1848 1908
1849 $::CONN->send_command ("pickup $::CFG->{pickup}") 1909 $::CONN->send_pickup ($::CFG->{pickup})
1850 if defined $::CONN; 1910 if defined $::CONN;
1851 1911
1852 0 1912 0
1853 }); 1913 });
1854 1914
1871 }); 1931 });
1872 1932
1873 $table->add_at (3, 18, new DC::UI::Button 1933 $table->add_at (3, 18, new DC::UI::Button
1874 text => "set", 1934 text => "set",
1875 on_activate => sub { 1935 on_activate => sub {
1876 $::CONN->send_command ("pickup $::CFG->{pickup}") 1936 $::CONN->send_pickup ($::CFG->{pickup})
1877 if defined $::CONN; 1937 if defined $::CONN;
1878 0 1938 0
1879 }); 1939 });
1880 1940
1881 $r 1941 $r
1882} 1942}
1883 1943
1884my %SORT_ORDER = ( 1944my %SORT_ORDER = (
1885 type => sub { 1945 type => sub {
1946 use sort 'stable';
1886 sort { $a->{type} <=> $b->{type} or $a->{name} cmp $b->{name} } @_ 1947 sort { $a->{type} <=> $b->{type} or $a->{name} cmp $b->{name} } @_
1887 }, 1948 },
1888 mtime => sub { 1949 mtime => sub {
1950 use sort 'stable';
1889 my $NOW = time; 1951 my $NOW = time;
1890 sort { 1952 sort {
1891 my $atime = $a->{mtime} - $NOW; $atime = $atime < 5 * 60 ? int $atime / 60 : 6; 1953 my $atime = $a->{mtime} - $NOW; $atime = $atime < 5 * 60 ? int $atime / 60 : 6;
1892 my $btime = $b->{mtime} - $NOW; $btime = $btime < 5 * 60 ? int $btime / 60 : 6; 1954 my $btime = $b->{mtime} - $NOW; $btime = $btime < 5 * 60 ? int $btime / 60 : 6;
1893 1955
1894 ($a->{flags} & F_LOCKED) <=> ($b->{flags} & F_LOCKED) 1956 ($a->{flags} & F_LOCKED) <=> ($b->{flags} & F_LOCKED)
1895 or $btime <=> $atime 1957 or $btime <=> $atime
1896 or $a->{type} <=> $b->{type} 1958 or $a->{type} <=> $b->{type}
1897 } @_ 1959 } @_
1898 }, 1960 },
1899 weight => sub { sort { 1961 weight => sub {
1962 use sort 'stable';
1963 sort {
1900 $a->{weight} * ($a->{nrof} || 1) <=> $b->{weight} * ($b->{nrof} || 1) 1964 $a->{weight} * ($a->{nrof} || 1) <=> $b->{weight} * ($b->{nrof} || 1)
1901 or $a->{type} <=> $b->{type} 1965 or $a->{type} <=> $b->{type}
1902 } @_ }, 1966 } @_
1967 },
1903); 1968);
1904 1969
1905sub inventory_widget { 1970sub inventory_widget {
1906 my $hb = new DC::UI::HBox homogeneous => 1; 1971 my $hb = new DC::UI::HBox homogeneous => 1;
1907 1972
1994 $PL_NOTEBOOK->set_current_page ($widget); 2059 $PL_NOTEBOOK->set_current_page ($widget);
1995 $PL_WINDOW->show; 2060 $PL_WINDOW->show;
1996 } 2061 }
1997} 2062}
1998 2063
1999sub player_window { 2064sub make_playerbook {
2000 my $plwin = $PL_WINDOW = new DC::UI::Toplevel 2065 my $plwin = $PL_WINDOW = new DC::UI::Toplevel
2001 x => "center", 2066 x => "center",
2002 y => "center", 2067 y => "center",
2003 force_w => $WIDTH * 9/10, 2068 force_w => $WIDTH * 9/10,
2004 force_h => $HEIGHT * 9/10, 2069 force_h => $HEIGHT * 9/10,
2038 "License, Author and Source info for media sent by the server."); 2103 "License, Author and Source info for media sent by the server.");
2039 2104
2040 $ntb->set_current_page ($INVENTORY_PAGE); 2105 $ntb->set_current_page ($INVENTORY_PAGE);
2041 2106
2042 $plwin->add ($ntb); 2107 $plwin->add ($ntb);
2043 $plwin
2044} 2108}
2045 2109
2046sub keyboard_setup { 2110sub keyboard_setup {
2047 DC::Macro::keyboard_setup 2111 DC::Macro::keyboard_setup
2048} 2112}
2049 2113
2050sub help_window { 2114sub make_help_window {
2051 my $win = new DC::UI::Toplevel 2115 my $win = new DC::UI::Toplevel
2052 x => 'center', 2116 x => 'center',
2053 y => 'center', 2117 y => 'center',
2054 z => 4, 2118 z => 4,
2055 name => 'doc_browser', 2119 name => 'doc_browser',
2144 2208
2145 $load_node->((DC::Pod::find @path)[0]); 2209 $load_node->((DC::Pod::find @path)[0]);
2146 $win->show; 2210 $win->show;
2147 }; 2211 };
2148 2212
2149 $win 2213 $HELP_WINDOW = $win;
2150}
2151
2152sub open_string_query {
2153 my ($title, $cb, $txt, $tooltip) = @_;
2154 my $dialog = new DC::UI::Toplevel
2155 x => "center",
2156 y => "center",
2157 z => 50,
2158 force_w => $WIDTH * 4/5,
2159 title => $title;
2160
2161 $dialog->add (
2162 my $e = new DC::UI::Entry
2163 on_activate => sub { $cb->(@_); $dialog->hide; 0 },
2164 on_key_down => sub { $_[1]->{sym} == 27 and $dialog->hide; 0 },
2165 tooltip => $tooltip
2166 );
2167
2168 $e->grab_focus;
2169 $e->set_text ($txt) if $txt;
2170 $dialog->show;
2171} 2214}
2172 2215
2173sub open_quit_dialog { 2216sub open_quit_dialog {
2174 unless ($QUIT_DIALOG) { 2217 unless ($QUIT_DIALOG) {
2175 $QUIT_DIALOG = new DC::UI::Toplevel 2218 $QUIT_DIALOG = new DC::UI::Toplevel
2208 2251
2209 $QUIT_DIALOG->show; 2252 $QUIT_DIALOG->show;
2210 $QUIT_DIALOG->grab_focus; 2253 $QUIT_DIALOG->grab_focus;
2211} 2254}
2212 2255
2256sub make_menubar {
2257 $MENUFRAME = new DC::UI::Toplevel
2258 border => 0,
2259 force_x => 0,
2260 force_y => 0,
2261 force_w => $::WIDTH,
2262 child => ($MENUBAR = new DC::UI::HBox),
2263 ;
2264
2265 $MENUBAR->add ($BUTTONBAR = new DC::UI::Buttonbar);
2266
2267 # XXX: this has to be done before make_stats_window as make_stats_window calls update_stats_window which updated the gauges also X-D
2268 make_gauge_window->show;
2269
2270# $BUTTONBAR->add (new DC::UI::Flopper text => "Message Window", other => $MESSAGE_WINDOW,
2271# tooltip => "Toggles the server message log, where the client collects <i>all</i> messages from the server.");
2272
2273 make_playerbook;
2274
2275 $MENUPOPUP = DC::UI::Menu->new (items => [
2276 ["Setup…\tF9" , sub { $SETUP_DIALOG->toggle_visibility }],
2277 ["Playerbook…\tTab" , sub { $PL_WINDOW ->toggle_visibility }],
2278 ["…Statistics\tF2" , sub { toggle_player_page ($::STATS_PAGE) }],
2279 ["…Skills\tF3" , sub { toggle_player_page ($::SKILL_PAGE) }],
2280 ["…Spells\tF4" , sub { toggle_player_page ($::SPELL_PAGE) }],
2281 ["…Inventory\tF5" , sub { toggle_player_page ($::INVENTORY_PAGE) }],
2282 ["Help Browser…\tF1" , sub { $HELP_WINDOW ->toggle_visibility }],
2283 ["Quit…" , sub {
2284 if ($CONN) {
2285 open_quit_dialog;
2286 } else {
2287 EV::unloop EV::UNLOOP_ALL;
2288 }
2289 }],
2290 ]);
2291
2292 $BUTTONBAR->add (new DC::UI::Button text => "Menu…",
2293 tooltip => "Shows the main menu",
2294 on_button_down => sub {
2295 my ($self, $ev) = @_;
2296 local $ev->{x} = 0;
2297 local $ev->{y} = 0;
2298 $MENUPOPUP->popup ($ev);
2299 },
2300 );
2301
2302 $MENUBAR->add ($GAUGES->{exp} = new DC::UI::ExperienceProgress
2303 padding_x => 6,
2304 padding_y => 3,
2305 tooltip => "This progress bar shows your overall experience and your progress towards the next character level.",
2306 template => " Exp: 888,888,888,888 (lvl 188) ",
2307 );
2308
2309 $MENUBAR->add ($PICKUP_ENABLE = new DC::UI::CheckBox # checkbox bad, button better?
2310 tooltip => "Automatic Pickup Enable - when this checkbox is enabled, then your character "
2311 . "will automatically pick up items as defined by your item pickup settings "
2312 . "in the playerbook. Often (e.g. in apartments) you want to temporarily "
2313 . "disable autopickup by disabling this checkbox.",
2314 state => $CFG->{pickup} & PICKUP_INHIBIT ? 0 : 1,
2315 on_changed => sub {
2316 my ($self, $value) = @_;
2317 $CFG->{pickup} &= ~PICKUP_INHIBIT;
2318 $CFG->{pickup} |= PICKUP_INHIBIT unless $_[1];
2319 $CONN->send_pickup ($CFG->{pickup})
2320 if $CONN;
2321 },
2322 );
2323
2324 $MENUBAR->add ($GAUGES->{skillexp} = new DC::UI::ExperienceProgress
2325 c_rescale => 1,
2326 padding_x => 6,
2327 padding_y => 3,
2328 force_w => $::WIDTH * 0.2,
2329 tooltip => "This progress bar shows the currently used skill and your progress towards the next skill level of that skill.",
2330 template => "two handed weapons 99%",
2331 );
2332
2333 $MENUBAR->add ($GAUGES->{range} = new DC::UI::Label
2334 expand => 1,
2335 align => 1, can_hover => 1, can_events => 1,
2336 text => "Range and Combat Slots",
2337 tooltip => "#stat_ranged",
2338 );
2339
2340 $MENUFRAME->show;
2341}
2342
2343sub open_string_query {
2344 my ($title, $cb, $txt, $tooltip) = @_;
2345 my $dialog = new DC::UI::Toplevel
2346 x => "center",
2347 y => "center",
2348 z => 50,
2349 force_w => $WIDTH * 4/5,
2350 title => $title;
2351
2352 $dialog->add (
2353 my $e = new DC::UI::Entry
2354 on_activate => sub { $cb->(@_); $dialog->hide; 0 },
2355 on_key_down => sub { $_[1]->{sym} == 27 and $dialog->hide; 0 },
2356 tooltip => $tooltip
2357 );
2358
2359 $e->grab_focus;
2360 $e->set_text ($txt) if $txt;
2361 $dialog->show;
2362}
2363
2213sub show_tip_of_the_day { 2364sub show_tip_of_the_day {
2214 # find all tips 2365 # find all tips
2215 my @tod = DC::Pod::find tip_of_the_day => "*"; 2366 my @tod = DC::Pod::find tip_of_the_day => "*";
2216 2367
2217 DC::DB::get state => "tip_of_the_day", sub { 2368 DC::DB::get state => "tip_of_the_day", sub {
2356 2507
2357 (new DC::UI::Frame 2508 (new DC::UI::Frame
2358 bg => [0, 0, 0, 0.4], 2509 bg => [0, 0, 0, 0.4],
2359 force_x => 0, 2510 force_x => 0,
2360 force_y => "max", 2511 force_y => "max",
2361 child => (my $LR = new DC::UI::VBox), 2512 child => (my $LL = new DC::UI::VBox),
2362 )->show; 2513 )->show;
2363 2514
2364 $LR->add ($STATUSBOX); 2515 $LL->add ($STATUSBOX);
2365 $LR->add ($MODBOX); 2516 $LL->add ($MODBOX);
2366 $LR->add (new DC::UI::Label 2517 $LL->add (new DC::UI::Label
2367 align => 0, 2518 align => 0,
2368 markup => "Use <b>Alt-Enter</b> to toggle fullscreen mode", 2519 markup => "Use <b>Alt-Enter</b> to toggle fullscreen mode",
2369 fontsize => 0.5, 2520 fontsize => 0.5,
2370 fg => [1, 1, 0, 0.7], 2521 fg => [1, 1, 0, 0.7],
2371 ); 2522 );
2372 2523
2373 DC::UI::Toplevel->new ( 2524 DC::UI::Toplevel->new (
2374 title => "Minimap", 2525 title => "Minimap",
2375 name => "mapmap", 2526 name => "mapmap",
2376 x => 0, 2527 x => 0,
2377 y => $FONTSIZE + 8, 2528 y => $::FONTSIZE + 8,#d# hack to move messages window below the menubar
2378 border_bg => [1, 1, 1, 192/255], 2529 border_bg => [1, 1, 1, 192/255],
2379 bg => [1, 1, 1, 0], 2530 bg => [1, 1, 1, 0],
2380 child => ($MAPMAP = new DC::MapWidget::MapMap 2531 child => ($MAPMAP = new DC::MapWidget::MapMap
2381 tooltip => "<b>Minimap</b>. This will display an overview of the surrounding areas.", 2532 tooltip => "<b>Minimap</b>. This will display an overview of the surrounding areas.",
2382 ), 2533 ),
2411 $METASERVER = metaserver_dialog; 2562 $METASERVER = metaserver_dialog;
2412 # the name is changed to not conflict with the older name as users could have hidden it 2563 # the name is changed to not conflict with the older name as users could have hidden it
2413 $MESSAGE_WINDOW = new DC::UI::Dockbar 2564 $MESSAGE_WINDOW = new DC::UI::Dockbar
2414 name => "message_window2", 2565 name => "message_window2",
2415 title => 'Messages', 2566 title => 'Messages',
2567 y => $::FONTSIZE + 8,#d# hack to move messages window below the menubar
2416 force_w => $::WIDTH * 0.6, 2568 force_w => $::WIDTH * 0.6,
2417 force_h => $::HEIGHT * 0.25, 2569 force_h => $::HEIGHT * 0.25,
2418 ; 2570 ;
2419 2571
2420 $MESSAGE_DIST = new DC::MessageDistributor dockbar => $MESSAGE_WINDOW; 2572 $MESSAGE_DIST = new DC::MessageDistributor dockbar => $MESSAGE_WINDOW;
2440 . "After pressing the combo the binding will be saved automatically and the " 2592 . "After pressing the combo the binding will be saved automatically and the "
2441 . "binding editor closes"); 2593 . "binding editor closes");
2442 $SETUP_NOTEBOOK->add_tab (Debug => debug_setup, 2594 $SETUP_NOTEBOOK->add_tab (Debug => debug_setup,
2443 "Some debuggin' options. Do not ask."); 2595 "Some debuggin' options. Do not ask.");
2444 2596
2445 $BUTTONBAR = new DC::UI::Buttonbar x => 0, y => 0, z => 200; # put on top 2597 make_help_window;
2598 make_menubar;
2446 2599
2447 $BUTTONBAR->add (new DC::UI::Flopper text => "Setup", other => $SETUP_DIALOG,
2448 tooltip => "Toggles a dialog where you can configure all aspects of this client.");
2449
2450# $BUTTONBAR->add (new DC::UI::Flopper text => "Message Window", other => $MESSAGE_WINDOW,
2451# tooltip => "Toggles the server message log, where the client collects <i>all</i> messages from the server.");
2452
2453 make_gauge_window->show; # XXX: this has to be set before make_stats_window as make_stats_window calls update_stats_window which updated the gauges also X-D
2454
2455 $BUTTONBAR->add (new DC::UI::Flopper text => "Playerbook", other => player_window,
2456 tooltip => "Toggles the player view, where you can manage Inventory, Spells, Skills and see your Stats.");
2457
2458 $BUTTONBAR->add (new DC::UI::Button
2459 text => "Save Config",
2460 tooltip => "Saves the options chosen in the client setting, server settings and the window layout to be restored on later runs.",
2461 on_activate => sub {
2462 $::CFG->{layout} = DC::UI::get_layout;
2463 DC::write_cfg;
2464 status "Configuration Saved";
2465 0
2466 },
2467 );
2468
2469 $BUTTONBAR->add (new DC::UI::Flopper text => "Help!", other => $HELP_WINDOW = help_window,
2470 tooltip => "View Documentation");
2471
2472 $BUTTONBAR->add (new DC::UI::Button
2473 text => "Quit",
2474 tooltip => "Terminates the program",
2475 on_activate => sub {
2476 if ($CONN) {
2477 open_quit_dialog;
2478 } else {
2479 EV::unloop EV::UNLOOP_ALL;
2480 }
2481 0
2482 },
2483 );
2484
2485 $BUTTONBAR->show;
2486 $SETUP_DIALOG->show; 2600 $SETUP_DIALOG->show;
2487 $MESSAGE_WINDOW->show; 2601 $MESSAGE_WINDOW->show;
2488 } 2602 }
2489 2603
2490 $MODE_SLIDER->set_range ([$CFG->{sdl_mode}, 0, scalar @SDL_MODES, 1, 1]); 2604 $MODE_SLIDER->set_range ([$CFG->{sdl_mode}, 0, scalar @SDL_MODES, 1, 1]);
2491 $MODE_SLIDER->emit (changed => $CFG->{sdl_mode}); 2605 $MODE_SLIDER->emit (changed => $CFG->{sdl_mode});
2492 2606
2493 $CAVEAT_LABEL->set_text ("None :)"); 2607 $CAVEAT_LABEL->set_text ("None :)");
2608 $CAVEAT_LABEL->set_text ("Apple/NVIDIA Texture bug (slow)")
2609 if $DC::OpenGL::APPLE_NVIDIA_BUG;
2494 $CAVEAT_LABEL->set_text ("Software Rendering (very slow)") 2610 $CAVEAT_LABEL->set_text ("Software Rendering (very slow)")
2495 unless DC::SDL_GL_GetAttribute DC::SDL_GL_ACCELERATED_VISUAL; 2611 unless DC::SDL_GL_GetAttribute DC::SDL_GL_ACCELERATED_VISUAL;
2496 2612
2497 $STATUSBOX->add ("Set video mode $WIDTH×$HEIGHT", timeout => 10, fg => [1, 1, 1, 0.5]); 2613 $STATUSBOX->add ("Set video mode $WIDTH×$HEIGHT", timeout => 10, fg => [1, 1, 1, 0.5]);
2498} 2614}
2526my $want_refresh = EV::prepare_ns \&force_refresh; 2642my $want_refresh = EV::prepare_ns \&force_refresh;
2527 2643
2528my $input = EV::periodic 0, 1 / $MAX_FPS, undef, sub { 2644my $input = EV::periodic 0, 1 / $MAX_FPS, undef, sub {
2529 $NOW = EV::now; 2645 $NOW = EV::now;
2530 2646
2531 ($SDL_CB{$_->{type}} || sub { warn "unhandled event $_->{type}" })->($_) 2647 ($SDL_CB[$_->{type}] || sub { warn "unhandled event $_->{type}" })->($_)
2532 for DC::poll_events; 2648 for DC::poll_events;
2533 2649
2534 if (%animate_object) { 2650 if (%animate_object) {
2535 $_->animate ($LAST_REFRESH - $NOW) for values %animate_object; 2651 $_->animate ($LAST_REFRESH - $NOW) for values %animate_object;
2536 $WANT_REFRESH = 1; 2652 $WANT_REFRESH = 1;
2548sub animation_stop { 2664sub animation_stop {
2549 my ($widget) = @_; 2665 my ($widget) = @_;
2550 delete $animate_object{$widget}; 2666 delete $animate_object{$widget};
2551} 2667}
2552 2668
2553%SDL_CB = (
2554 DC::SDL_QUIT => sub { 2669$SDL_CB[DC::SDL_QUIT] = sub {
2555 crash "SDL_QUIT"; 2670 crash "SDL_QUIT";
2556 EV::unloop EV::UNLOOP_ALL; 2671 EV::unloop EV::UNLOOP_ALL;
2557 }, 2672};
2558 DC::SDL_VIDEORESIZE => sub { 2673$SDL_CB[DC::SDL_VIDEORESIZE] = sub { };
2559 },
2560 DC::SDL_VIDEOEXPOSE => sub { 2674$SDL_CB[DC::SDL_VIDEOEXPOSE] = sub {
2561 DC::UI::full_refresh; 2675 DC::UI::full_refresh;
2562 }, 2676};
2563 DC::SDL_ACTIVEEVENT => sub { 2677$SDL_CB[DC::SDL_ACTIVEEVENT] = sub {
2564# not useful, as APPACTIVE includes only iconified state, not unmapped 2678# not useful, as APPACTIVE includes only iconified state, not unmapped
2565# printf "active %x %x %x\n", $_[0]{gain}, $_[0]{state}, DC::SDL_GetAppState;#d# 2679# printf "active %x %x %x\n", $_[0]{gain}, $_[0]{state}, DC::SDL_GetAppState;#d#
2566# printf "a %x\n", DC::SDL_GetAppState & DC::SDL_APPACTIVE;#d# 2680# printf "a %x\n", DC::SDL_GetAppState & DC::SDL_APPACTIVE;#d#
2567# printf "A\n" if $_[0]{state} & DC::SDL_APPACTIVE; 2681# printf "A\n" if $_[0]{state} & DC::SDL_APPACTIVE;
2568# printf "K\n" if $_[0]{state} & DC::SDL_APPINPUTFOCUS; 2682# printf "K\n" if $_[0]{state} & DC::SDL_APPINPUTFOCUS;
2569# printf "M\n" if $_[0]{state} & DC::SDL_APPMOUSEFOCUS; 2683# printf "M\n" if $_[0]{state} & DC::SDL_APPMOUSEFOCUS;
2570 }, 2684};
2571 DC::SDL_KEYDOWN => sub { 2685$SDL_CB[DC::SDL_KEYDOWN] = sub {
2572 if ($_[0]{mod} & DC::KMOD_ALT && $_[0]{sym} == 13) { 2686 if ($_[0]{mod} & DC::KMOD_ALT && $_[0]{sym} == 13) {
2573 # alt-enter 2687 # alt-enter
2574 video_shutdown; 2688 video_shutdown;
2575 $FULLSCREEN_ENABLE->toggle; 2689 $FULLSCREEN_ENABLE->toggle;
2576 video_init; 2690 video_init;
2577 } else { 2691 } else {
2578 &DC::UI::feed_sdl_key_down_event; 2692 &DC::UI::feed_sdl_key_down_event;
2579 } 2693 }
2580 update_modbox; 2694 update_modbox;
2581 }, 2695};
2582 DC::SDL_KEYUP => sub { 2696$SDL_CB[DC::SDL_KEYUP] = sub {
2583 &DC::UI::feed_sdl_key_up_event; 2697 &DC::UI::feed_sdl_key_up_event;
2584 update_modbox; 2698 update_modbox;
2585 }, 2699};
2586 DC::SDL_MOUSEMOTION => \&DC::UI::feed_sdl_motion_event, 2700$SDL_CB[DC::SDL_MOUSEMOTION] = \&DC::UI::feed_sdl_motion_event,
2587 DC::SDL_MOUSEBUTTONDOWN => \&DC::UI::feed_sdl_button_down_event, 2701$SDL_CB[DC::SDL_MOUSEBUTTONDOWN] = \&DC::UI::feed_sdl_button_down_event,
2588 DC::SDL_MOUSEBUTTONUP => \&DC::UI::feed_sdl_button_up_event, 2702$SDL_CB[DC::SDL_MOUSEBUTTONUP] = \&DC::UI::feed_sdl_button_up_event,
2589 DC::SDL_USEREVENT => sub { 2703$SDL_CB[DC::SDL_USEREVENT] = sub {
2590 if ($_[0]{code} == 1) { 2704 if ($_[0]{code} == 1) {
2591 audio_channel_finished $_[0]{data1}; 2705 audio_channel_finished $_[0]{data1};
2592 } elsif ($_[0]{code} == 0) { 2706 } elsif ($_[0]{code} == 0) {
2593 audio_music_finished; 2707 audio_music_finished;
2594 }
2595 }, 2708 }
2596); 2709};
2597 2710
2598############################################################################# 2711#############################################################################
2599 2712
2600$SIG{INT} = $SIG{TERM} = sub { 2713$SIG{INT} = $SIG{TERM} = sub {
2601 EV::unloop; 2714 EV::unloop;
2602 #d# TODO calling exit here hangs the process in some futex 2715 #d# TODO calling exit here hangs the process in some futex
2603}; 2716};
2604
2605# initialise the resolver now, as vista forces us back to the desktop
2606# when doing this.
2607AnyEvent::DNS::resolver;
2608 2717
2609# due to mac os x + sdl combined braindamage, we need this contortion 2718# due to mac os x + sdl combined braindamage, we need this contortion
2610sub main { 2719sub main {
2611 { 2720 {
2612 DC::Pod::load_docwiki DC::find_rcfile "docwiki.pst"; 2721 DC::Pod::load_docwiki DC::find_rcfile "docwiki.pst";
2631 DC::DB::open_db; 2740 DC::DB::open_db;
2632 2741
2633 DC::UI::set_layout ($::CFG->{layout}); 2742 DC::UI::set_layout ($::CFG->{layout});
2634 2743
2635 my %DEF_CFG = ( 2744 my %DEF_CFG = (
2745 config_autosave => 1,
2636 sdl_mode => undef, 2746 sdl_mode => undef,
2637 fullscreen => 1, 2747 fullscreen => 1,
2638 fast => 0, 2748 fast => 0,
2639 force_opengl11 => undef, 2749 force_opengl11 => undef,
2640 disable_alpha => 0, 2750 disable_alpha => 0,
2641 smooth_movement => 1, 2751 smooth_movement => 1,
2752 smooth_transitions => 1,
2642 texture_compression => 1, 2753 texture_compression => 1,
2643 map_scale => 1, 2754 map_scale => 1,
2644 fow_enable => 1, 2755 fow_enable => 1,
2645 fow_intensity => 0, 2756 fow_intensity => 0,
2757 fow_texture => 0,
2646 map_smoothing => 1, 2758 map_smoothing => 1,
2647 gui_fontsize => 1, 2759 gui_fontsize => 1,
2648 log_fontsize => 0.7, 2760 log_fontsize => 0.7,
2649 gauge_fontsize => 1, 2761 gauge_fontsize => 1,
2650 gauge_size => 0.35, 2762 gauge_size => 0.35,
2658 effects_enable => 1, 2770 effects_enable => 1,
2659 effects_volume => 1, 2771 effects_volume => 1,
2660 bgm_enable => 1, 2772 bgm_enable => 1,
2661 bgm_volume => 0.5, 2773 bgm_volume => 0.5,
2662 output_rate => "", 2774 output_rate => "",
2663 pickup => 0, 2775 pickup => PICKUP_SPELLBOOK | PICKUP_SKILLSCROLL | PICKUP_VALUABLES,
2664 inv_sort => "mtime", 2776 inv_sort => "mtime",
2665 default => "profile", # default profile 2777 default => "profile", # default profile
2666 show_tips => 1, 2778 show_tips => 1,
2667 logview_max_par => 1000, 2779 logview_max_par => 1000,
2668 shift_fire_stop => 0, 2780 shift_fire_stop => 0,
2669 uitheme => "wood", 2781 uitheme => "wood",
2670 ); 2782 map_shift_x => -24, # arbitrary
2783 map_shift_y => +24, # arbitrary
2671 2784 );
2785
2672 while (my ($k, $v) = each %DEF_CFG) { 2786 while (my ($k, $v) = each %DEF_CFG) {
2673 $CFG->{$k} = $v unless exists $CFG->{$k}; 2787 $CFG->{$k} = $v unless exists $CFG->{$k};
2674 } 2788 }
2675 2789
2676 $CFG->{profile}{default}{host} ||= "gameserver.deliantra.net"; 2790 my @args = @ARGV;
2791
2792 my $profile = 'default';
2793
2794 for (my $i = 0; $i < @args; $i++) {
2795 if ($args[$i] =~ /^--?profile$/) {
2796 $profile = $args[$i + 1];
2797 splice @args, $i, 2, ();
2798 $i = 0;
2799 } elsif ($args[$i] =~ /^--?h/) {
2800 print STDERR "Usage: $0 [--profile name] [host [user [password]]]\n";
2801 exit 0;
2802 }
2803 }
2804
2805 $CFG->{profile}{$profile} ||= {};
2677 $PROFILE = $CFG->{profile}{default}; 2806 $PROFILE = $CFG->{profile}{$profile};
2807 $PROFILE->{host} ||= "gameserver.deliantra.net";
2808
2809 $PROFILE->{host} = $args[0] if @args > 0;
2810 $PROFILE->{user} = $args[1] if @args > 1;
2811 $PROFILE->{password} = $args[2] if @args > 2;
2678 2812
2679 # convert old bindings (only default profile matters) 2813 # convert old bindings (only default profile matters)
2680 if (my $bindings = delete $PROFILE->{bindings}) { 2814 if (my $bindings = delete $PROFILE->{bindings}) {
2681 while (my ($mod, $syms) = each %$bindings) { 2815 while (my ($mod, $syms) = each %$bindings) {
2682 while (my ($sym, $cmds) = each %$syms) { 2816 while (my ($sym, $cmds) = each %$syms) {
2688 } 2822 }
2689 } 2823 }
2690 2824
2691 sdl_init; 2825 sdl_init;
2692 2826
2827 $ENV{FONTCONFIG_FILE} = DC::find_rcfile "fonts/fonts.conf";
2828 $ENV{FONTCONFIG_DIR} = DC::find_rcfile "fonts";
2829
2693 { 2830 {
2694 my @fonts = map DC::find_rcfile "fonts/$_", qw( 2831 my @fonts = map DC::find_rcfile "fonts/$_", qw(
2695 DejaVuSans.ttf 2832 DejaVuSans.ttf
2696 DejaVuSansMono.ttf 2833 DejaVuSansMono.ttf
2697 DejaVuSans-Bold.ttf 2834 DejaVuSans-Bold.ttf
2698 DejaVuSansMono-Bold.ttf 2835 DejaVuSansMono-Bold.ttf
2699 DejaVuSans-Oblique.ttf 2836 DejaVuSans-Oblique.ttf
2700 DejaVuSansMono-Oblique.ttf 2837 DejaVuSansMono-Oblique.ttf
2701 DejaVuSans-BoldOblique.ttf 2838 DejaVuSans-BoldOblique.ttf
2702 DejaVuSansMono-BoldOblique.ttf 2839 DejaVuSansMono-BoldOblique.ttf
2840 mona.ttf
2703 ); 2841 );
2704 2842
2705 DC::add_font $_ for @fonts; 2843 DC::add_font $_ for @fonts;
2706 2844
2707 $FONT_PROP = new_from_file DC::Font $fonts[0]; 2845 $FONT_PROP = new_from_file DC::Font $fonts[0];
2708 $FONT_FIXED = new_from_file DC::Font $fonts[1]; 2846 $FONT_FIXED = new_from_file DC::Font $fonts[1];
2709 2847
2710 $FONT_PROP->make_default; 2848 $FONT_PROP->make_default;
2711 2849
2737 }; 2875 };
2738 2876
2739 delete $SIG{__DIE__}; 2877 delete $SIG{__DIE__};
2740 EV::loop; 2878 EV::loop;
2741 2879
2880 DC::write_cfg if $CFG->{config_autosave};
2881
2742#video_shutdown; 2882 #video_shutdown;
2743#audio_shutdown; 2883 #audio_shutdown;
2884
2744 DC::OpenGL::quit; 2885 DC::OpenGL::quit;
2745 DC::SDL_Quit; 2886 DC::SDL_Quit;
2746 DC::DB::Server::stop; 2887 DC::DB::Server::stop;
2747} 2888}
2748 2889
2752 2893
2753deliantra - A Deliantra MORPG game client 2894deliantra - A Deliantra MORPG game client
2754 2895
2755=head1 SYNOPSIS 2896=head1 SYNOPSIS
2756 2897
2757Just run it - no commandline arguments are supported. 2898 deliantra [--profile name] [host [user [password]]]
2899 deliantra --help
2758 2900
2759=head1 USAGE 2901=head1 USAGE
2760 2902
2761deliantra utilises OpenGL for all UI elements and the game. It is supposed to 2903The deliantra client utilises OpenGL for all UI elements and the game. It
2762be used in fullscreen mode and interactively. 2904is supposed to be used in fullscreen mode and interactively.
2763 2905
2764=head1 DEBUGGING 2906=head1 DEBUGGING
2765
2766 2907
2767CFPLUS_DEBUG - environment variable 2908CFPLUS_DEBUG - environment variable
2768 2909
2769 1 draw borders around widgets 2910 1 draw borders around widgets
2770 2 add low-level widget info to tooltips 2911 2 add low-level widget info to tooltips

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines