#!/opt/bin/perl use strict; use Glib; use Gtk2 -init; use SDL; use SDL::App; use SDL::Event; use SDL::Surface; use SDL::OpenGL; use SDL::OpenGL::Constants; use Crossfire; use Crossfire::Client; use Crossfire::Protocol; use Client::Util; use Client::Widget; our $FACECACHE; our $VERSION = '0.1'; our $CFG; our $CONN; our $SDL_TIMER; our $SDL_APP; our $SDL_EV = new SDL::Event; our %SDL_CB; our @GL_INIT; # hooks called on every gl init sub init_screen { $SDL_APP = new SDL::App -flags => SDL_ANYFORMAT | SDL_HWSURFACE, -title => "Crossfire+ Client", -width => $CFG->{width}, -height => $CFG->{height}, -opengl => 1, -red_size => 8, -green_size => 8, -blue_size => 8, -double_buffer => 1, -fullscreen => $CFG->{fullscreen}, -resizeable => 0; glClearColor 0, 0, 0, 0; glEnable GL_TEXTURE_2D; glTexEnv GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE; glShadeModel GL_FLAT; glDisable GL_DEPTH_TEST; glBlendFunc GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA; glEnable GL_BLEND; glMatrixMode GL_PROJECTION; glLoadIdentity; glOrtho 0, $CFG->{width} / 32, $CFG->{height} / 32, 0, -100 , 100; glMatrixMode GL_MODELVIEW; $_->() for @GL_INIT; } sub start_game { $SDL_TIMER = add Glib::Timeout 1000/20, sub { while ($SDL_EV->poll) { ($SDL_CB{$SDL_EV->type} || sub { warn "unhandled event ", $SDL_EV->type })->(); } 1 }; init_screen; $CONN = new conn host => $CFG->{host}, port => $CFG->{port}; } sub stop_game { remove Glib::Source $SDL_TIMER; undef $SDL_APP; SDL::Quit; } sub refresh { glClear GL_COLOR_BUFFER_BIT; for (values %Client::Widget::ACTIVE_WIDGETS) { $_->draw } SDL::GLSwapBuffers; } %SDL_CB = ( SDL_QUIT() => sub { warn "sdl quit\n";#d# main_quit Gtk2; }, SDL_VIDEORESIZE() => sub { }, SDL_VIDEOEXPOSE() => sub { refresh; }, SDL_KEYDOWN() => sub { if ($SDL_EV->key_mod & KMOD_ALT && $SDL_EV->key_sym == SDLK_RETURN) { # alt-enter $CFG->{fullscreen} = !$CFG->{fullscreen}; init_screen; } else { Client::Widget::feed_sdl_key_down_event ($SDL_EV); } }, SDL_KEYUP() => sub { Client::Widget::feed_sdl_key_up_event ($SDL_EV); }, SDL_MOUSEMOTION() => sub { warn "sdl motion\n";#d# }, SDL_MOUSEBUTTONDOWN() => sub { Client::Widget::feed_sdl_button_down_event ($SDL_EV); }, SDL_MOUSEBUTTONUP() => sub { Client::Widget::feed_sdl_button_up_event ($SDL_EV); }, SDL_ACTIVEEVENT() => sub { warn "active\n";#d# }, ); @conn::ISA = Crossfire::Protocol::; sub conn::map_update { my ($self, $dirty) = @_; refresh; } sub conn::map_scroll { my ($self, $dx, $dy) = @_; refresh; } sub conn::map_clear { my ($self) = @_; refresh; } sub conn::face_find { my ($self, $face) = @_; $FACECACHE->{"$face->{chksum},$face->{name}"} } sub conn::face_update { my ($self, $face) = @_; $FACECACHE->{"$face->{chksum},$face->{name}"} = $face->{image}; $face->{texture} = new_from_image Crossfire::Client::Texture delete $face->{image}; } ############################################################################# my $mapwidget = Client::MapWidget->new; $mapwidget->activate; $mapwidget->focus_in; Client::Util::read_cfg "$Crossfire::VARDIR/pclientrc"; $FACECACHE = eval { Crossfire::load_ref "$Crossfire::VARDIR/pclient.faces" } || {}; $CFG ||= { width => 640, height => 480, fullscreen => 0, host => "crossfire.schmorp.de", port => 13327, }; Client::Util::run_config_dialog login => sub { start_game }, logout => sub { stop_game }; main Gtk2; Crossfire::save_ref $FACECACHE, "$Crossfire::VARDIR/pclient.faces";