--- deliantra/Deliantra-Client/bin/cfplus 2006/09/29 00:56:06 1.119
+++ deliantra/Deliantra-Client/bin/cfplus 2006/12/05 16:53:29 1.135
@@ -1,8 +1,31 @@
#!/opt/bin/perl
+my $startup_done = sub { };
+
+# do splash-screen thingy on win32
+BEGIN {
+ if (%PAR::LibCache && $^O eq "MSWin32") {
+ while (my ($filename, $zip) = each %PAR::LibCache) {
+ $zip->extractMember ("SPLASH.bmp", "$ENV{PAR_TEMP}/SPLASH.bmp");
+ }
+
+ require Win32::GUI::SplashScreen;
+
+ Win32::GUI::SplashScreen::Show (
+ -file => "$ENV{PAR_TEMP}/SPLASH.bmp",
+ );
+
+ $startup_done = sub {
+ Win32::GUI::SplashScreen::Done (1);
+ };
+ }
+}
+
use strict;
use utf8;
+use Carp 'verbose';
+
# do things only needed for single-binary version (par)
BEGIN {
if (%PAR::LibCache) {
@@ -10,7 +33,7 @@
while (my ($filename, $zip) = each %PAR::LibCache) {
for ($zip->memberNames) {
- next unless /^\/root\/(.*)/;
+ next unless /^root\/(.*)/;
$zip->extractMember ($_, "$ENV{PAR_TEMP}/$1")
unless -e "$ENV{PAR_TEMP}/$1";
}
@@ -47,24 +70,20 @@
$Event::Eval = 0;
$Event::DIED = sub {
- # TODO: display dialog box or so
- Carp::cluck $_[1];#d#TODO: remove when stable
- return;#d#
- CFPlus::fatal ($_[1]);
+ CFPlus::fatal Carp::longmess $_[1]
};
-our $VERSION = '0.9';
-
my $MAX_FPS = 60;
my $MIN_FPS = 5; # unused as of yet
-our $META_SERVER = "crossfire.real-time.com:13326";
+our $META_SERVER = "http://metaserver.schmorp.de/current.json";
our $LAST_REFRESH;
our $NOW;
our $CFG;
our $CONN;
+our $PROFILE; # current profile
our $FAST; # fast, low-quality mode, possibly useful for software-rendering
our $WANT_REFRESH;
@@ -105,6 +124,7 @@
our $STATS_PAGE;
our $SKILL_PAGE;
our $SPELL_PAGE;
+our $SPELL_LIST;
our $HELP_WINDOW;
our $MESSAGE_WINDOW;
@@ -132,6 +152,9 @@
our $PICKUP_CFG;
+our $IN_BUILD_MODE;
+our $BUILD_BUTTON;
+
sub status {
$STATUSBOX->add (CFPlus::asxml $_[0], pri => -10, group => "status", timeout => 10, fg => [1, 1, 0, 1]);
}
@@ -140,6 +163,17 @@
$DEBUG_STATUS->set_text ($_[0]);
}
+sub message {
+ my ($para) = @_;
+
+ my $time = sprintf "%02d:%02d:%02d", (localtime time)[2,1,0];
+
+ $para->{markup} = "$time $para->{markup}";
+
+ $LOGVIEW->add_paragraph ($para);
+ $LOGVIEW->scroll_to_bottom;
+}
+
sub destroy_query_dialog {
(delete $_[0]{query_dialog})->destroy
if $_[0]{query_dialog};
@@ -346,22 +380,24 @@
$LOGIN_BUTTON->set_text ("Logout");
$SETUP_DIALOG->hide;
+ $PROFILE = $CFG->{profile}{default};
+
my $mapsize = List::Util::min 32, List::Util::max 11, int $WIDTH * $CFG->{mapsize} * 0.01 / 32;
- my ($host, $port) = split /:/, $CFG->{profile}{default}{host};
+ my ($host, $port) = split /:/, $PROFILE->{host};
- $MAP = new CFPlus::Map $mapsize, $mapsize;
+ $MAP = new CFPlus::Map;
$CONN = eval {
new CFPlus::Protocol
host => $host,
port => $port || 13327,
- user => $CFG->{profile}{default}{user},
- pass => $CFG->{profile}{default}{password},
+ user => $PROFILE->{user},
+ pass => $PROFILE->{password},
mapw => $mapsize,
maph => $mapsize,
- client => "cfplus $VERSION $] $^O",
+ client => "cfplus $CFPlus::VERSION $] $^O",
map_widget => $MAPWIDGET,
logview => $LOGVIEW,
@@ -398,7 +434,7 @@
$SETUP_NOTEBOOK->set_current_page ($SETUP_SERVER);
$SETUP_DIALOG->show;
$PL_WINDOW->hide;
- $SPELL_PAGE->clear_spells;
+ $SPELL_LIST->clear_spells;
return unless $CONN;
@@ -635,6 +671,7 @@
$table->add (1, 2, new CFPlus::UI::CheckBox on_changed => sub { $ENV{CFPLUS_DEBUG} ^= 4; 0 });
$table->add (0, 3, new CFPlus::UI::Label text => "Suppress Tooltips");
$table->add (1, 3, new CFPlus::UI::CheckBox on_changed => sub { $ENV{CFPLUS_DEBUG} ^= 8; 0 });
+ $table->add (0, 4, new CFPlus::UI::Button text => "die on click(tm)", on_activate => sub { die "violator" } );
my @default_smooth = (0.05, 0.13, 0.05, 0.13, 0.30, 0.13, 0.05, 0.13, 0.05);
@@ -826,27 +863,15 @@
$table->clear;
$table->add (0, 0, my $label = new CFPlus::UI::Label max_w => $WIDTH * 0.8, text => "fetching server list...");
- my $buf;
-
- my $fh = new IO::Socket::INET PeerHost => $META_SERVER, Blocking => 0;
-
- unless ($fh) {
- $label->set_text ("unable to contact metaserver: $!");
- return;
- }
+ my $ok = 0;
- Event->io (fd => $fh, poll => 'r', cb => sub {
- my $res = sysread $fh, $buf, 8192, length $buf;
-
- if (!defined $res) {
- $_[0]->w->cancel;
- $label->set_text ("error while retrieving server list: $!");
- } elsif ($res == 0) {
- $_[0]->w->cancel;
- status "server list retrieved";
-
- utf8::decode $buf if utf8::valid $buf;
+ CFPlus::background {
+ my $ua = CFPlus::lwp_useragent;
+ CFPlus::background_msg CFPlus::from_json +(CFPlus::lwp_check $ua->get ($META_SERVER))->decoded_content;
+ } sub {
+ my ($msg) = @_;
+ if ($msg) {
$table->clear;
my @tip = (
@@ -866,23 +891,30 @@
my @align = qw(1 0 1 1 -1);
my $y = 0;
- for my $m (sort { $b->[3] <=> $a->[3] } map [split /\|/], split /\015?\012/, $buf) {
- my ($ip, $last, $host, $users, $version, $desc, $ibytes, $obytes, $uptime) = @$m;
+ for my $m (
+ sort {
+ $b->{version} <=> $a->{version}
+ or $b->{users} <=> $a->{users}
+ }
+ @{ $msg->{servers} }
+ ) {
+ my ($ip, $last, $host, $users, $version, $desc, $ibytes, $obytes, $uptime) =
+ @$m{qw(ip age hostname users version description ibytes obytes uptime)};
for ($desc) {
s/
/\n/gi;
s/
/\n· /gi;
s/<.*?>//sgi;
- s/&/&/g;
- s/</g;
- s/>/>/g;
+ s/&/&/g;
+ s/<//g;
}
$uptime = sprintf "%dd %02d:%02d:%02d",
- (int $m->[8] / 86400),
- (int $m->[8] / 3600) % 24,
- (int $m->[8] / 60) % 60,
- $m->[8] % 60;
+ (int $uptime / 86400),
+ (int $uptime / 3600) % 24,
+ (int $uptime / 60) % 60,
+ $uptime % 60;
$m = [$users, $host, $uptime, $version, $desc];
@@ -902,17 +934,22 @@
]);
$table->add ($_, $y, new CFPlus::UI::Label
+ max_w => $::WIDTH * 0.4,
ellipsise => 0,
align => $align[$_],
text => $m->[$_],
tooltip => $tip[$_],
+ fg => ($m->[3] =~ /\+$/ ? [1, 1, 1] : [.7, .7, .7]),
can_hover => 1,
can_events => 1,
fontsize => 0.8)
for 0 .. $#$m;
}
+ } else {
+ $ok or $label->set_text ("error while contacting metaserver");
}
- });
+ };
+
}
sub metaserver_dialog {
@@ -926,7 +963,8 @@
x => 'center',
y => 'center',
z => 3,
- force_h => $::HEIGHT * 0.4,
+ force_w => $::WIDTH * 0.9,
+ force_h => $::HEIGHT * 0.7,
child => $vbox,
has_close_button => 1,
table => $table,
@@ -1056,7 +1094,7 @@
tooltip => "Show the Tip of the day window at startup?",
on_changed => sub {
my ($self, $value) = @_;
- $CFG->{shop_tips} = $value;
+ $CFG->{show_tips} = $value;
0
}
);
@@ -1157,12 +1195,12 @@
["Cloaks" => PICKUP_CLOAK],
],
- ["Readables", 2, 2,
+ ["Readables", 2, 0,
["Spellbooks" => PICKUP_SPELLBOOK],
["Skillscrolls" => PICKUP_SKILLSCROLL],
["Normal Books/Scrolls" => PICKUP_READABLES],
],
- ["Misc", 2, 7,
+ ["Misc", 2, 5,
["Food" => PICKUP_FOOD],
["Drinks" => PICKUP_DRINK],
["Valuables (Money, Gems)" => PICKUP_VALUABLES],
@@ -1172,6 +1210,7 @@
["Magic Devices" => PICKUP_MAGIC_DEVICE],
["Ignore cursed" => PICKUP_NOT_CURSED],
["Jewelery" => PICKUP_JEWELS],
+ ["Flesh" => PICKUP_FLESH],
],
["Weight/Value ratio", 2, 17]
)
@@ -1231,11 +1270,17 @@
my %SORT_ORDER = (
type => undef,
- mtime => sub { sort {
- ($a->{flags} & F_LOCKED) <=> ($b->{flags} & F_LOCKED)
- or $b->{mtime} <=> $a->{mtime}
- or $a->{type} <=> $b->{type}
- } @_ },
+ mtime => sub {
+ my $NOW = time;
+ sort {
+ my $atime = $a->{mtime} - $NOW; $atime = $atime < 5 * 60 ? int $atime / 60 : 6;
+ my $btime = $b->{mtime} - $NOW; $btime = $btime < 5 * 60 ? int $btime / 60 : 6;
+
+ ($a->{flags} & F_LOCKED) <=> ($b->{flags} & F_LOCKED)
+ or $btime <=> $atime
+ or $a->{type} <=> $b->{type}
+ } @_
+ },
weight => sub { sort {
$a->{weight} * ($a->{nrof} || 1) <=> $b->{weight} * ($b->{nrof} || 1)
or $a->{type} <=> $b->{type}
@@ -1270,6 +1315,7 @@
$vb1->add (my $sw1 = new CFPlus::UI::ScrolledWindow expand => 1, scroll_y => 1);
$sw1->add ($INV = new CFPlus::UI::Inventory);
+ $INV->set_sort_order ($SORT_ORDER{$::CFG->{inv_sort}});
$hb->add (my $vb2 = new CFPlus::UI::VBox);
@@ -1319,8 +1365,8 @@
"Shows all your Skills."
);
- my $spellsw = new CFPlus::UI::ScrolledWindow (expand => 1, scroll_y => 1);
- $spellsw->add ($SPELL_PAGE = new CFPlus::UI::SpellList);
+ my $spellsw = $SPELL_PAGE = new CFPlus::UI::ScrolledWindow (expand => 1, scroll_y => 1);
+ $spellsw->add ($SPELL_LIST = new CFPlus::UI::SpellList);
$ntb->add (
"Spellbook (F4)" => $spellsw,
"Displays all spells you have and lets you edit keyboard shortcuts for them."
@@ -1348,9 +1394,11 @@
$refresh = $BIND_UPD_CB = sub {
$binding_list->clear ();
- for my $mod (keys %{$::CFG->{profile}{default}{bindings}}) {
- for my $sym (keys %{$::CFG->{profile}{default}{bindings}{$mod}}) {
- my $cmds = $::CFG->{profile}{default}{bindings}{$mod}{$sym};
+ return unless $PROFILE;
+
+ for my $mod (keys %{$PROFILE->{bindings}}) {
+ for my $sym (keys %{$PROFILE->{bindings}{$mod}}) {
+ my $cmds = $PROFILE->{bindings}{$mod}{$sym};
next unless ref $cmds eq 'ARRAY' and @$cmds > 0;
my $lbl = join "; ", @$cmds;
@@ -1361,7 +1409,7 @@
tooltip => "Deletes the binding",
on_activate => sub {
$binding_list->remove ($hb);
- delete $::CFG->{profile}{default}{bindings}{$mod}{$sym};
+ delete $PROFILE->{bindings}{$mod}{$sym};
0
});
@@ -1370,7 +1418,7 @@
tooltip => "Edits the binding",
on_activate => sub {
$::BIND_EDITOR->set_binding (
- $mod, $sym, $::CFG->{profile}{default}{bindings}{$mod}{$sym},
+ $mod, $sym, $PROFILE->{bindings}{$mod}{$sym},
sub {
my ($nmod, $nsym, $ncmds) = @_;
$::BIND_EDITOR->cfg_unbind ($mod, $sym);
@@ -1819,6 +1867,7 @@
$BUTTONBAR->add (new CFPlus::UI::Flopper text => "Help!", other => $HELP_WINDOW = help_window,
tooltip => "View Documentation");
+
$BUTTONBAR->add (new CFPlus::UI::Button
text => "Quit",
tooltip => "Terminates the program",
@@ -1839,6 +1888,124 @@
$STATUSBOX->add ("Set video mode $WIDTH×$HEIGHT", timeout => 10, fg => [1, 1, 1, 0.5]);
}
+sub setup_build_button {
+ my ($enabled) = @_;
+ if ($enabled) {
+ $BUILD_BUTTON ||= new CFPlus::UI::Button
+ text => "Build",
+ tooltip => "Opens the ingame builder",
+ on_activate => sub {
+ if ($CONN) {
+ $CONN->send_ext_req (builder_player_items => sub {
+ open_ingame_editor ($_[0]) if exists $_[0]->{items};
+ });
+ }
+ 0
+ };
+ $BUTTONBAR->add ($BUILD_BUTTON);
+ } else {
+ $BUILD_BUTTON->hide if $BUILD_BUTTON;
+ }
+}
+
+sub open_ingame_editor {
+ my ($msg) = @_;
+
+ my $win = new CFPlus::UI::Toplevel
+ x => 0,
+ y => 'center',
+ z => 4,
+ name => 'builder_window',
+ force_w => int $WIDTH * 1/4,
+ force_h => int $HEIGHT * 3/4,
+ title => "In game builder",
+ has_close_button => 1;
+
+ my $r = new CFPlus::UI::ScrolledWindow (
+ expand => 1,
+ scroll_y => 1
+ );
+ $r->add (my $vb = new CFPlus::UI::VBox);
+ $win->add ($r);
+
+
+ $vb->add (
+ new CFPlus::UI::Button
+ text => "Disable build mode",
+ on_activate => sub { $::IN_BUILD_MODE = undef }
+ );
+ $vb->add (
+ new CFPlus::UI::Button
+ text => "ERASE",
+ on_activate => sub { $::IN_BUILD_MODE = { do_erase => 1 } }
+ );
+
+ for my $itemarchname (
+ sort {
+ $msg->{items}->{$a}->{build_arch_name}
+ cmp $msg->{items}->{$b}->{build_arch_name}
+ } keys %{$msg->{items}}
+ ) {
+ my $info = $msg->{items}->{$itemarchname};
+ $vb->add (
+ new CFPlus::UI::Button text => $info->{build_arch_name},
+ on_activate => sub {
+ $::IN_BUILD_MODE = { item => $itemarchname, info => $info };
+
+ if (grep { $msg->{items}->{$itemarchname}->{$_} } qw/has_connection has_name has_text/) {
+ build_mode_query_arch_info ();
+ }
+ }
+ );
+ }
+
+ $win->show;
+}
+
+sub build_mode_query_arch_info {
+ my ($iteminfo) = $::IN_BUILD_MODE;
+ my $itemarchname = $iteminfo->{item};
+ my $info = $iteminfo->{info};
+
+ my $dialog = new CFPlus::UI::Toplevel
+ x => "center",
+ y => "center",
+ z => 50,
+ force_w => int $WIDTH * 1/2,
+ title => "Enter information for placement of '$itemarchname'",
+ has_close_button => 1;
+
+ $dialog->add (my $vb = new CFPlus::UI::VBox expand => 1);
+
+ $vb->add (my $table = new CFPlus::UI::Table expand => 1);
+ my $row = 0;
+ if ($info->{has_name}) {
+ $table->add (0, $row, new CFPlus::UI::Label text => "Name:");
+ $table->add (1, $row++, new CFPlus::UI::Entry expand => 1, on_changed => sub { $::IN_BUILD_MODE->{name} = $_[1]; 0 });
+ }
+ if ($info->{has_text}) {
+ $table->add (0, $row, new CFPlus::UI::Label text => "Text:");
+ $table->add (1, $row++, new CFPlus::UI::Entry expand => 1, on_changed => sub { $::IN_BUILD_MODE->{text} = $_[1]; 0 });
+ }
+ if ($info->{has_connection}) {
+ $table->add (0, $row, new CFPlus::UI::Label text => "Connection ID:");
+ $table->add (1, $row++,
+ new CFPlus::UI::Entry
+ expand => 1,
+ on_changed => sub { $::IN_BUILD_MODE->{connection} = $_[1]; 0 },
+ tooltip => "Enter the connection ID here. The connection ID connects actors like a lever to a gate or a magic ear to a gate"
+ );
+ }
+
+ $vb->add (my $hb = new CFPlus::UI::HBox expand => 1);
+ $hb->add (new CFPlus::UI::Button
+ text => "Close",
+ expand => 1,
+ on_activate => sub { $dialog->hide; 0 },
+ );
+ $dialog->show;
+}
+
sub video_shutdown {
CFPlus::OpenGL::shutdown;
@@ -1879,6 +2046,7 @@
audio_music_finished;
+ local $_;
while (<$fh>) {
next if /^\s*#/;
next if /^\s*$/;
@@ -2022,7 +2190,7 @@
gauge_size => 0.35,
stat_fontsize => 0.7,
mapsize => 100,
- say_command => 'say',
+ say_command => 'chat',
audio_enable => 1,
bgm_enable => 1,
bgm_volume => 0.25,
@@ -2086,6 +2254,8 @@
# warn $t2-$t1;
# }
+ $startup_done->();
+
video_init;
audio_init;
}