--- deliantra/Deliantra-Client/bin/pclient 2006/04/11 13:38:22 1.68
+++ deliantra/Deliantra-Client/bin/pclient 2006/04/24 03:19:42 1.170
@@ -3,449 +3,1351 @@
use strict;
use utf8;
-use Glib;
-use Gtk2 -init;
-
-use SDL;
-use SDL::App;
-use SDL::Event;
-use SDL::Surface;
-use SDL::OpenGL;
-use SDL::OpenGL::Constants;
+use Time::HiRes 'time';
+use Event;
use Crossfire;
use Crossfire::Protocol;
+use Compress::LZF;
+
use CFClient;
-use CFClient::Widget;
+use CFClient::UI;
+use CFClient::MapWidget;
our $VERSION = '0.1';
-my $MAX_FPS = 30;
-my $TICKS_PER_FRAME = int 1000 / $MAX_FPS - 1; # min ticks per frame
+my $MAX_FPS = 60;
+my $MIN_FPS = 5; # unused as of yet
+
+our $META_SERVER = "crossfire.real-time.com:13326";
-our $FACECACHE;
+our $FACEMAP;
+our $TILECACHE;
+our $MAPCACHE;
+
+our $LAST_REFRESH;
+our $NOW;
our $CFG;
our $CONN;
+our $FAST; # fast, low-quality mode, possibly useful for software-rendering
+our @SDL_MODES;
our $WIDTH;
our $HEIGHT;
our $FULLSCREEN;
-
our $FONTSIZE;
-our $SDL_TIMER;
-our $SDL_APP;
-our $SDL_EV;
+our $FONT_PROP;
+our $FONT_FIXED;
+
+our $MAP;
+our $MAPWIDGET;
+our $BUTTONBAR;
+our $LOGVIEW;
+our $CONSOLE;
+our $METASERVER;
+
+our $GAUGES;
+our $STATWIDS;
+
+our $SDL_ACTIVE;
our %SDL_CB;
+our $SDL_MIXER;
+our @SOUNDS; # event => file mapping
+our %AUDIO_CHUNKS; # audio files
+
our $ALT_ENTER_MESSAGE;
our $STATUS_LINE;
our $DEBUG_STATUS;
-my $last_refresh;
-my %ANIMATE;
-my $refresh_handler;
-
-our ($tw, $te); # Test widget #d#
-
-sub init_screen {
- $SDL_APP = new SDL::App
- -flags => SDL_ANYFORMAT | SDL_HWSURFACE,
- -title => "Crossfire+ Client",
- -width => $WIDTH,
- -height => $HEIGHT,
- -opengl => 1,
- -red_size => 5,
- -green_size => 5,
- -blue_size => 5,
- -alpha_size => 0,
- -double_buffer => 1,
- -fullscreen => $FULLSCREEN,
- -resizeable => 0;
-
- $SDL_EV = new SDL::Event;
- $SDL_EV->set_unicode (1);
-
- $SDL_TIMER = add Glib::Timeout 1000/50, sub {
- ($SDL_CB{$SDL_EV->type} || sub { warn "unhandled event ", $SDL_EV->type })->()
- while $SDL_EV->poll;
+sub status {
+ $STATUS_LINE->set_text ($_[0]);
+ $STATUS_LINE->move (0, $HEIGHT - $ALT_ENTER_MESSAGE->{h} - $STATUS_LINE->{h});
+}
- 1
- };
+sub debug {
+ $DEBUG_STATUS->set_text ($_[0]);
+ $DEBUG_STATUS->move ($WIDTH - $DEBUG_STATUS->{w}, 0, $DEBUG_STATUS->{w}, $DEBUG_STATUS->{h});
+}
- $last_refresh = SDL::GetTicks;
+sub start_game {
+ status "logging in...";
- CFClient::gl_init;
+ my $mapsize = List::Util::min 32, List::Util::max 11, int $WIDTH * $CFG->{mapsize} * 0.01 / 32;
- $FONTSIZE = int $HEIGHT / 50;
+ $MAPCACHE = CFClient::db_table "mapcache_$CFG->{host}";
- #############################################################################
+ $MAP = new CFClient::Map $mapsize, $mapsize;
+
+ my ($host, $port) = split /:/, $CFG->{host};
+
+ $CONN = new conn
+ host => $host,
+ port => $port || 13327,
+ user => $CFG->{user},
+ pass => $CFG->{password},
+ mapw => $mapsize,
+ maph => $mapsize,
+ ;
- glClearColor 0.45, 0.45, 0.45, 1;
+ status "login successful";
- glEnable GL_TEXTURE_2D;
- glEnable GL_COLOR_MATERIAL;
- glShadeModel GL_FLAT;
- glDisable GL_DEPTH_TEST;
- glBlendFunc GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA;
+ CFClient::lowdelay fileno $CONN->{fh};
+}
- #############################################################################
+sub stop_game {
+ undef $CONN;
+}
- $DEBUG_STATUS = new CFClient::Widget::Label;
- $CFClient::Widget::TOPLEVEL->add ($DEBUG_STATUS);
-
- $STATUS_LINE = new CFClient::Widget::Label
- y => $HEIGHT * 59 / 60 - $FONTSIZE;
- $CFClient::Widget::TOPLEVEL->add ($STATUS_LINE);
-
- $ALT_ENTER_MESSAGE = new CFClient::Widget::Label
- y => $HEIGHT * 59 / 60,
- height => $HEIGHT / 60,
- text => "Use Alt-Enter to toggle fullscreen mode";
- $CFClient::Widget::TOPLEVEL->add ($ALT_ENTER_MESSAGE);
-
- # Test code #d#
- unless ($tw) { # haha...
- $te = new CFClient::Widget::FancyFrame x => 300, z => 1;
- $te->add (new CFClient::Widget::Entry);
- $CFClient::Widget::TOPLEVEL->add ($te);
-
- $tw = new CFClient::Widget::Animator x => $WIDTH - 200, w => 400, h => 300;
- my $lbl1 = new CFClient::Widget::Label text => "This is a\nTEST!\nOf a themed\nFrame!";
- my $lbl2 = new CFClient::Widget::Label text => "LBL2";
- my $vb = new CFClient::Widget::VBox;
- my $f = new CFClient::Widget::FancyFrame;
- my $f2 = new CFClient::Widget::FancyFrame;
- $f->add ($lbl1);
- $f2->add ($lbl2);
- $vb->add ($f);
- $vb->add ($f2, 1);
-
- $tw->add ($vb);
- $tw->moveto (0, 0);
- $CFClient::Widget::TOPLEVEL->add ($tw);
-
-# $f->move ($WIDTH - 200, 0);
-# $CFClient::Widget::TOPLEVEL->add ($f);
+sub client_setup {
+ my $dialog = new CFClient::UI::FancyFrame
+ title => "Client Setup",
+ child => (my $vbox = new CFClient::UI::VBox);
+ $vbox->add (my $table = new CFClient::UI::Table expand => 1, col_expand => [0, 1]);
+
+ $table->add (0, 0, new CFClient::UI::Label valign => 0, align => 1, text => "Video Mode");
+ $table->add (1, 0, my $hbox = new CFClient::UI::HBox);
+
+ $hbox->add (my $mode_slider = new CFClient::UI::Slider expand => 1, req_w => 100, range => [$CFG->{sdl_mode}, 0, scalar @SDL_MODES, 1]);
+ $hbox->add (my $mode_label = new CFClient::UI::Label align => 0, valign => 0, height => 0.8, template => "9999x9999");
+
+ $mode_slider->connect (changed => sub {
+ my ($self, $value) = @_;
+
+ $CFG->{sdl_mode} = $self->{range}[0] = $value = int $value;
+ $mode_label->set_text (sprintf "%dx%d", @{$SDL_MODES[$value]});
+ });
+ $mode_slider->emit (changed => $mode_slider->{range}[0]);
+
+ my $row = 1;
+
+ $table->add (0, $row, new CFClient::UI::Label valign => 0, align => 1, text => "Fullscreen");
+ $table->add (1, $row++, new CFClient::UI::CheckBox
+ state => $CFG->{fullscreen},
+ tooltip => "Bring the client into fullscreen mode",
+ connect_changed => sub {
+ my ($self, $value) = @_;
+ $CFG->{fullscreen} = $value;
+ }
+ );
+
+ $table->add (0, $row, new CFClient::UI::Label valign => 0, align => 1, text => "Fast & Ugly");
+ $table->add (1, $row++, new CFClient::UI::CheckBox
+ state => $CFG->{fast},
+ tooltip => "Lower the visual quality considerably to speed up rendering.",
+ connect_changed => sub {
+ my ($self, $value) = @_;
+ $CFG->{fast} = $value;
+ }
+ );
+
+ $table->add (0, $row, new CFClient::UI::Label valign => 0, align => 1, text => "Map Scale");
+ $table->add (1, $row++, new CFClient::UI::Slider
+ range => [$CFG->{map_scale}, 0.25, 2, 0.05],
+ tooltip => "Enlarge or shrink the displayed map",
+ connect_changed => sub {
+ my ($self, $value) = @_;
+ $CFG->{map_scale} = 0.05 * int $value / 0.05;
+ }
+ );
+
+ $table->add (0, $row, new CFClient::UI::Label valign => 0, align => 1, text => "Fog of War");
+ $table->add (1, $row++, new CFClient::UI::CheckBox
+ state => $CFG->{fow_enable},
+ tooltip => "Fog-of-War marks areas that cannot be seen by the player",
+ connect_changed => sub {
+ my ($self, $value) = @_;
+ $CFG->{fow_enable} = $value;
+ }
+ );
+
+ $table->add (0, $row, new CFClient::UI::Label valign => 0, align => 1, text => "FoW Intensity");
+ $table->add (1, $row++, new CFClient::UI::Slider
+ range => [$CFG->{fow_intensity}, 0, 1 + 0.001, 0.001],
+ tooltip => "The higher the intensity, the lighter the Fog-of-War color",
+ connect_changed => sub {
+ my ($self, $value) = @_;
+ $CFG->{fow_intensity} = $value;
+ }
+ );
+
+ $table->add (0, $row, new CFClient::UI::Label valign => 0, align => 1, text => "FoW Smooth");
+ $table->add (1, $row++, new CFClient::UI::CheckBox
+ state => $CFG->{fow_smooth},
+ tooltip => "Smooth the Fog-of-War a bit to make it more realistic",
+ connect_changed => sub {
+ my ($self, $value) = @_;
+ $CFG->{fow_smooth} = $value;
+ status "Fog of War smoothing requires OpenGL 1.2 or higher" if $CFClient::GL_VERSION < 1.2;
+ }
+ );
+
+ $table->add (0, $row, new CFClient::UI::Label valign => 0, align => 1, text => "GUI Fontsize");
+ $table->add (1, $row++, new CFClient::UI::Slider
+ range => [$CFG->{gui_fontsize}, 0.5, 2, 0.1],
+ tooltip => "The font size used by most GUI elements",
+ connect_changed => sub {
+ $CFG->{gui_fontsize} = 0.1 * int $_[1] * 10;
+# $FONTSIZE = int $HEIGHT / 40 * $CFG->{gui_fontsize};
+ }
+ );
+
+ $table->add (0, $row, new CFClient::UI::Label valign => 0, align => 1, text => "Server Log Fontsize");
+ $table->add (1, $row++, new CFClient::UI::Slider
+ range => [$CFG->{log_fontsize}, 0.5, 2, 0.1],
+ tooltip => "The font size used by the server log window only",
+ connect_changed => sub {
+ $LOGVIEW->set_fontsize ($CFG->{log_fontsize} = 0.1 * int $_[1] * 10);
+ }
+ );
+
+ $table->add (0, $row, new CFClient::UI::Label valign => 0, align => 1, text => "Stats Fontsize");
+
+ $table->add (1, $row++, new CFClient::UI::Slider
+ range => [$CFG->{stat_fontsize}, 0.5, 2, 0.1],
+ tooltip => "The font size used by the statistics window only",
+ connect_changed => sub {
+ $CFG->{stat_fontsize} = 0.1 * int $_[1] * 10;
+ &set_stats_window_fontsize;
+ }
+ );
+
+ $table->add (0, $row, new CFClient::UI::Label valign => 0, align => 1, text => "Gauge size");
+ $table->add (1, $row++, new CFClient::UI::Slider
+ range => [$CFG->{gauge_size}, 0.2, 0.8, 0.02],
+ tooltip => "Adjust the size of the stats gauges at the bottom right",
+ connect_changed => sub {
+ $CFG->{gauge_size} = $_[1];
+ my $h = int $HEIGHT * $CFG->{gauge_size};
+ $GAUGES->{win}->set_size ($WIDTH, $h);
+ $GAUGES->{win}->move (0, $HEIGHT - $h);
+ }
+ );
+
+ $table->add (0, $row, new CFClient::UI::Label valign => 0, align => 1, text => "Gauge fontsize");
+ $table->add (1, $row++, new CFClient::UI::Slider
+ range => [$CFG->{gauge_fontsize}, 0.5, 2.0, 0.1],
+ tooltip => "Adjusts the fontsize of the gauges at the bottom right",
+ connect_changed => sub {
+ $CFG->{gauge_fontsize} = 0.1 * int $_[1] * 10;
+ &set_gauge_window_fontsize;
+ }
+ );
+
+ $table->add (1, $row++, new CFClient::UI::Button
+ expand => 1, align => 0, text => "Apply",
+ tooltip => "Apply the video settings",
+ connect_activate => sub {
+ video_shutdown ();
+ video_init ();
+ }
+ );
+
+ $table->add (0, $row, new CFClient::UI::Label valign => 0, align => 1, text => "Audio Enable");
+ $table->add (1, $row++, new CFClient::UI::CheckBox
+ state => $CFG->{audio_enable},
+ tooltip => "If enabled, sound effects and music will be played. If disabled, no audio will be used and the soundcard will not be opened.",
+ connect_changed => sub {
+ $CFG->{audio_enable} = $_[1];
+ }
+ );
+# $table->add (0, 9, new CFClient::UI::Label valign => 0, align => 1, text => "Effects Volume");
+# $table->add (1, 8, new CFClient::UI::Slider range => [$CFG->{effects_volume}, 0, 128, 1], connect_changed => sub {
+# $CFG->{effects_volume} = $_[1];
+# });
+ $table->add (0, $row, new CFClient::UI::Label valign => 0, align => 1, text => "Background Music");
+ $table->add (1, $row++, my $hbox = new CFClient::UI::HBox);
+ $hbox->add (new CFClient::UI::CheckBox
+ expand => 1, state => $CFG->{bgm_enable},
+ tooltip => "Enable background music playing",
+ connect_changed => sub {
+ $CFG->{bgm_enable} = $_[1];
+ }
+ );
+ $hbox->add (new CFClient::UI::Slider
+ expand => 1, range => [$CFG->{bgm_volume}, 0, 1, 0.1],
+ tooltip => "The volume of the background music",
+ connect_changed => sub {
+ $CFG->{bgm_volume} = $_[1];
+ CFClient::MixMusic::volume $_[1] * 128;
+ }
+ );
+
+ $table->add (1, $row++, new CFClient::UI::Button
+ expand => 1, align => 0, text => "Apply",
+ tooltip => "Apply the audio settings",
+ connect_activate => sub {
+ audio_shutdown ();
+ audio_init ();
+ }
+ );
+
+ $dialog
+}
+
+sub set_stats_window_fontsize {
+ for (values %{$STATWIDS}) {
+ $_->set_fontsize ($::CFG->{stat_fontsize});
}
}
-sub destroy_screen {
- remove Glib::Source $SDL_TIMER;
- undef $SDL_APP;
- undef $SDL_EV;
- SDL::Quit;
+sub set_gauge_window_fontsize {
+ for (map { $GAUGES->{$_} } grep { $_ ne 'win' } keys %{$GAUGES}) {
+ $_->set_fontsize ($::CFG->{gauge_fontsize});
+ }
+
+# local $GAUGES->{win}{parent};#d#
+# use PApp::Util; open D, ">:utf8", "d"; print D PApp::Util::dumpval $GAUGES->{win}; close D;
}
-sub start_game {
- $WIDTH = $CFG->{width};
- $HEIGHT = $CFG->{height};
- $FULLSCREEN = 0;
+sub make_gauge_window {
+ my $gh = int ($HEIGHT * $CFG->{gauge_size});
+# my $gw = int ($WIDTH * $CFG->{gauge_w_size});
- init_screen;
+ my $win = new CFClient::UI::Frame (
+ y => $HEIGHT - $gh, x => 0, user_w => $WIDTH, user_h => $gh
+ );
+ $win->add (my $vb = new CFClient::UI::VBox);
- my $mapsize = List::Util::min 64, List::Util::max 11, int $WIDTH * $CFG->{mapsize} * 0.01 / 32;
+ $vb->add (my $hbg = new CFClient::UI::HBox expand => 1);
- $CONN = new conn
- host => $CFG->{host},
- port => $CFG->{port},
- user => $CFG->{user},
- pass => $CFG->{password},
- mapw => $mapsize,
- maph => $mapsize,
- ;
+ $hbg->add (new CFClient::UI::Empty expand => 1);
+ $hbg->add (my $hb = new CFClient::UI::HBox);
+ $hb->add (my $hg = new CFClient::UI::Gauge type => 'hp', tooltip => "Health points");
+ $hb->add (my $mg = new CFClient::UI::Gauge type => 'mana', tooltip => "Spellpoints");
+ $hb->add (my $gg = new CFClient::UI::Gauge type => 'grace', tooltip => "Grace");
+ $hb->add (my $fg = new CFClient::UI::Gauge type => 'food', tooltip => "Food");
+
+ $vb->add (my $exp = new CFClient::UI::Label valign => 0, align => 1, text => "XP: 0 LVL: 0");
+ $vb->add (my $rng = new CFClient::UI::Label valign => 0, align => 1, text => "Rng:");
+
+ $GAUGES = {
+ exp => $exp, win => $win, range => $rng,
+ food => $fg, mana => $mg, hp => $hg, grace => $gg
+ };
- CFClient::lowdelay fileno $CONN->{fh};
+ &set_gauge_window_fontsize;
+
+ $win
}
-sub stop_game {
- remove Glib::Source $refresh_handler if $refresh_handler;
- undef $refresh_handler;
+sub make_stats_window {
+ my $tgw = new CFClient::UI::FancyFrame (x => $WIDTH * 2/5, y => 0, title => "Stats");
- undef $CONN;
- destroy_screen;
+ $tgw->add (my $vb = new CFClient::UI::VBox);
+ $vb->add ($STATWIDS->{title} = new CFClient::UI::Label valign => 0, align => -1, text => "Title:", expand => 1);
+ $vb->add ($STATWIDS->{map} = new CFClient::UI::Label valign => 0, align => -1, text => "Map:", expand => 1);
+
+ $vb->add (my $hb = new CFClient::UI::HBox expand => 1);
+
+ $hb->add (my $tbl = new CFClient::UI::Table expand => 1);
+
+ $tbl->add (0, 0, $STATWIDS->{st_str} = new CFClient::UI::Label valign => 0, align => +1, template => "30");
+ $tbl->add (0, 1, $STATWIDS->{st_dex} = new CFClient::UI::Label valign => 0, align => +1, template => "30");
+ $tbl->add (0, 2, $STATWIDS->{st_con} = new CFClient::UI::Label valign => 0, align => +1, template => "30");
+ $tbl->add (0, 3, $STATWIDS->{st_int} = new CFClient::UI::Label valign => 0, align => +1, template => "30");
+ $tbl->add (0, 4, $STATWIDS->{st_wis} = new CFClient::UI::Label valign => 0, align => +1, template => "30");
+ $tbl->add (0, 5, $STATWIDS->{st_pow} = new CFClient::UI::Label valign => 0, align => +1, template => "30");
+ $tbl->add (0, 6, $STATWIDS->{st_cha} = new CFClient::UI::Label valign => 0, align => +1, template => "30");
+
+ $tbl->add (1, 0, $STATWIDS->{st_str_lbl} = new CFClient::UI::Label valign => 0, align => -1, text => "Str");
+ $tbl->add (1, 1, $STATWIDS->{st_dex_lbl} = new CFClient::UI::Label valign => 0, align => -1, text => "Dex");
+ $tbl->add (1, 2, $STATWIDS->{st_con_lbl} = new CFClient::UI::Label valign => 0, align => -1, text => "Con");
+ $tbl->add (1, 3, $STATWIDS->{st_int_lbl} = new CFClient::UI::Label valign => 0, align => -1, text => "Int");
+ $tbl->add (1, 4, $STATWIDS->{st_wis_lbl} = new CFClient::UI::Label valign => 0, align => -1, text => "Wis");
+ $tbl->add (1, 5, $STATWIDS->{st_pow_lbl} = new CFClient::UI::Label valign => 0, align => -1, text => "Pow");
+ $tbl->add (1, 6, $STATWIDS->{st_cha_lbl} = new CFClient::UI::Label valign => 0, align => -1, text => "Cha");
+
+ $tbl->add (2, 0, $STATWIDS->{st_wc} = new CFClient::UI::Label valign => 0, align => +1, template => "-120");
+ $tbl->add (2, 1, $STATWIDS->{st_ac} = new CFClient::UI::Label valign => 0, align => +1, template => "-120");
+ $tbl->add (2, 2, $STATWIDS->{st_dam} = new CFClient::UI::Label valign => 0, align => +1, template => "120");
+ $tbl->add (2, 3, $STATWIDS->{st_arm} = new CFClient::UI::Label valign => 0, align => +1, template => "120");
+ $tbl->add (2, 4, $STATWIDS->{st_spd} = new CFClient::UI::Label valign => 0, align => +1, template => "10.54");
+ $tbl->add (2, 5, $STATWIDS->{st_wspd} = new CFClient::UI::Label valign => 0, align => +1, template => "9");
+
+ $tbl->add (3, 0, $STATWIDS->{st_wc_lbl} = new CFClient::UI::Label valign => 0, align => -1, text => "Wc");
+ $tbl->add (3, 1, $STATWIDS->{st_ac_lbl} = new CFClient::UI::Label valign => 0, align => -1, text => "Ac");
+ $tbl->add (3, 2, $STATWIDS->{st_dam_lbl} = new CFClient::UI::Label valign => 0, align => -1, text => "Dam");
+ $tbl->add (3, 3, $STATWIDS->{st_arm_lbl} = new CFClient::UI::Label valign => 0, align => -1, text => "Arm");
+ $tbl->add (3, 4, $STATWIDS->{st_spd_lbl} = new CFClient::UI::Label valign => 0, align => -1, text => "Sp");
+ $tbl->add (3, 5, $STATWIDS->{st_wspd_lbl} = new CFClient::UI::Label valign => 0, align => -1, text => "WSp");
+
+ $hb->add (my $tbl2 = new CFClient::UI::Table expand => 1);
+
+ my $row = 0;
+ my $col = 0;
+
+ my %resist_names = (
+ slow => "Slow",
+ holyw => "Holy Word",
+ conf => "Confusion",
+ fire => "Fire",
+ depl => "Depletion",
+ magic => "Magic",
+ drain => "Draining",
+ acid => "Acid",
+ pois => "Poison",
+ para => "Paralysation",
+ deat => "Death",
+ phys => "Physical",
+ blind => "Blind",
+ fear => "Fear",
+ tund => "Turn undead",
+ elec => "Electricity",
+ cold => "Cold",
+ ghit => "Ghost hit",
+ );
+ for (qw/slow holyw conf fire depl magic
+ drain acid pois para deat phys
+ blind fear tund elec cold ghit/)
+ {
+ $tbl2->add ($col, $row,
+ $STATWIDS->{"res_$_"} =
+ new CFClient::UI::Label
+ template => "-100%",
+ align => +1,
+ valign => 0,
+ tooltip => $resist_names{$_}
+ );
+ $tbl2->add ($col + 1, $row, new CFClient::UI::Image
+ can_hover => 1,
+ can_events => 1,
+ image => "ui/resist/resist_$_.png",
+ tooltip => $resist_names{$_}
+ );
+
+ $row++;
+ if ($row % 6 == 0) {
+ $col += 2;
+ $row = 0;
+ }
+ }
+
+ &set_stats_window_fontsize;
+ update_stats_window ({});
+
+ $tgw
}
-sub force_refresh {
- glViewport 0, 0, $WIDTH, $HEIGHT;
+sub formsep {
+ reverse join ",", grep length, split /(...)/, reverse $_[0] * 1
+}
- glMatrixMode GL_PROJECTION;
- glLoadIdentity;
- glOrtho 0, $WIDTH, $HEIGHT, 0, -10000 , 10000;
- glMatrixMode GL_MODELVIEW;
+sub update_stats_window {
+ my ($stats) = @_;
- glClear GL_COLOR_BUFFER_BIT;
+ # i love text protocols!!!
+ my $hp = $stats->{Crossfire::Protocol::CS_STAT_HP} * 1;
+ my $hp_m = $stats->{Crossfire::Protocol::CS_STAT_MAXHP} * 1;
+ my $sp = $stats->{Crossfire::Protocol::CS_STAT_SP} * 1;
+ my $sp_m = $stats->{Crossfire::Protocol::CS_STAT_MAXSP} * 1;
+ my $fo = $stats->{Crossfire::Protocol::CS_STAT_FOOD} * 1;
+ my $fo_m = 999;
+ my $gr = $stats->{Crossfire::Protocol::CS_STAT_GRACE} * 1;
+ my $gr_m = $stats->{Crossfire::Protocol::CS_STAT_MAXGRACE} * 1;
+
+ $GAUGES->{hp} ->set_value ($hp, $hp_m);
+ $GAUGES->{mana} ->set_value ($sp, $sp_m);
+ $GAUGES->{food} ->set_value ($fo, $fo_m);
+ $GAUGES->{grace} ->set_value ($gr, $gr_m);
+ $GAUGES->{exp} ->set_text ("Exp: " . (formsep $stats->{Crossfire::Protocol::CS_STAT_EXP64})
+ . " (lvl " . ($stats->{Crossfire::Protocol::CS_STAT_LEVEL} * 1) . ")");
+ my $rng = $stats->{Crossfire::Protocol::CS_STAT_RANGE};
+ $rng =~ s/^Range: //; # thank you so much dear server
+ $GAUGES->{range} ->set_text ("Rng: " . $rng);
+ my $title = $stats->{Crossfire::Protocol::CS_STAT_TITLE};
+ $title =~ s/^Player: //;
+ $STATWIDS->{title} ->set_text ("Title: " . $title);
+
+ $STATWIDS->{st_str} ->set_text (sprintf "%d", $stats->{5});
+ $STATWIDS->{st_dex} ->set_text (sprintf "%d", $stats->{8});
+ $STATWIDS->{st_con} ->set_text (sprintf "%d", $stats->{9});
+ $STATWIDS->{st_int} ->set_text (sprintf "%d", $stats->{6});
+ $STATWIDS->{st_wis} ->set_text (sprintf "%d", $stats->{7});
+ $STATWIDS->{st_pow} ->set_text (sprintf "%d", $stats->{22});
+ $STATWIDS->{st_cha} ->set_text (sprintf "%d", $stats->{10});
+ $STATWIDS->{st_wc} ->set_text (sprintf "%d", $stats->{13});
+ $STATWIDS->{st_ac} ->set_text (sprintf "%d", $stats->{14});
+ $STATWIDS->{st_dam} ->set_text (sprintf "%d", $stats->{15});
+ $STATWIDS->{st_arm} ->set_text (sprintf "%d", $stats->{16});
+ $STATWIDS->{st_spd} ->set_text (sprintf "%.1f", $stats->{Crossfire::Protocol::CS_STAT_SPEED});
+ $STATWIDS->{st_wspd}->set_text (sprintf "%.1f", $stats->{Crossfire::Protocol::CS_STAT_WEAP_SP});
+
+ my %tbl = (
+ phys => 100,
+ magic => 101,
+ fire => 102,
+ elec => 103,
+ cold => 104,
+ conf => 105,
+ acid => 106,
+ drain => 107,
+ ghit => 108,
+ pois => 109,
+ slow => 110,
+ para => 111,
+ tund => 112,
+ fear => 113,
+ depl => 113,
+ deat => 115,
+ holyw => 116,
+ blind => 117
+ );
- $CFClient::Widget::TOPLEVEL->draw;
+ for (keys %tbl) {
+ $STATWIDS->{"res_$_"}->set_text (sprintf "%d%", $stats->{$tbl{$_}});
+ }
- SDL::GLSwapBuffers;
}
-sub debug {
- $DEBUG_STATUS->set_text ($_[0]);
- $DEBUG_STATUS->size_allocate ($DEBUG_STATUS->size_request);
- $DEBUG_STATUS->move ($WIDTH - $DEBUG_STATUS->{w}, 0);
+sub metaserver_dialog {
+ my $dialog = new CFClient::UI::FancyFrame
+ title => "Metaserver",
+ child => (my $vbox = new CFClient::UI::VBox);
+
+ $vbox->add ($dialog->{table} = new CFClient::UI::Table);
+
+ $dialog
}
-my $FPS;
+sub update_metaserver {
+ my ($HOST) = @_;
-sub refresh {
- $refresh_handler ||= add Glib::Idle sub {
- if ($SDL_APP) {
- my $next_refresh = SDL::GetTicks;
-
- if ($next_refresh - $last_refresh < $TICKS_PER_FRAME) {
- SDL::Delay $TICKS_PER_FRAME - ($next_refresh - $last_refresh);
- $next_refresh = SDL::GetTicks;
+ status "fetching metaserver list...";
+
+ my $buf;
+
+ my $fh = new IO::Socket::INET PeerHost => $META_SERVER, Blocking => 0;
+
+ Event->io (fd => $fh, poll => 'r', cb => sub {
+ my $res = sysread $fh, $buf, 8192, length $buf;
+
+ if (!defined $res) {
+ $_[0]->w->cancel;
+ status "metaserver: $!";
+ } elsif ($res == 0) {
+ $_[0]->w->cancel;
+ status "server list retrieved";
+
+ my $table = $METASERVER->{table};
+
+ $table->clear;
+
+ my @col = qw(Use #Users Host Uptime Version Description);
+ $table->add ($_, 0, new CFClient::UI::Label align => 0, fg => [1, 1, 0], text => $col[$_])
+ for 0 .. $#col;
+
+ 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 ($desc) {
+ s/
/\n/gi;
+ s/