#!/opt/bin/perl use strict; use Crossfire::Client; use Crossfire::Protocol; package Crossfire::Client; # uh, yeah use strict; use SDL; use SDL::App; use SDL::Event; use SDL::Surface; use SDL::OpenGL; use SDL::OpenGL::Constants; my $conn; my $app; my $WIDTH = 640; my $HEIGHT = 480; sub glinit { # nuke all gl context data $app = new SDL::App -title => "Crossfire+ Client", -width => $WIDTH, -height => $HEIGHT, -depth => 24, -opengl => 1, -double_buffer => 1, -resizeable => 0; glEnable GL_TEXTURE_2D; glShadeModel GL_FLAT; glDisable GL_DEPTH_TEST; glMatrixMode GL_PROJECTION; #glViewport 0, 0, $WIDTH, $HEIGHT; # re-bind all textures } sub refresh { glClearColor 0.5, 0.5, 0.7, 0; glClear GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT; glLoadIdentity; glOrtho 0, $WIDTH / 32, $HEIGHT / 32, 0, -1 , 1; my $map = $conn->{map}; for my $x (0 .. $conn->{mapw} - 1) { for my $y (0 .. $conn->{maph} - 1) { my $cell = $map->[$x][$y] or next; for my $num (grep $_, $cell->[0], $cell->[1], $cell->[2]) { my $tex = $conn->{face}[$num]{texture} ||= do { $conn->send ("askface $num") unless $conn->{face}[$num]{askface}++; 0 }; glBindTexture GL_TEXTURE_2D, $tex; glBegin GL_QUADS; glTexCoord 0, 0; glVertex $x, $y; glTexCoord 1, 0; glVertex $x + 1, $y; glTexCoord 1, 1; glVertex $x + 1, $y + 1; glTexCoord 0, 1; glVertex $x, $y + 1; glEnd; } } } SDL::GLSwapBuffers; } my $ev = new SDL::Event; my %ev_cb; sub event(&$) { $ev_cb{$_[0]->()} = $_[1]; } sub does(&) { shift } event {SDL_QUIT} does { exit; }; event {SDL_VIDEORESIZE} does { print "resize\n"; }; event {SDL_KEYDOWN} does { print "keypress\n"; }; event {SDL_KEYUP} does { print "keyup\n";#d# }; event {SDL_MOUSEMOTION} does { print "motion\n"; }; event {SDL_MOUSEBUTTONDOWN} does { print "button\n"; }; event {SDL_MOUSEBUTTONUP} does { print "buttup\n"; }; event {SDL_ACTIVEEVENT} does { print "active\n"; }; package Crossfire::Client; @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_update { my ($self, $num, $face) = @_; warn "up face $self,$num,$face\n";#d# #TODO open my $fh, ">:raw", "/tmp/x~"; syswrite $fh, $face->{image}; close $fh; my $surface = new SDL::Surface -name => "/tmp/x~"; unlink "/tmp/x~"; my ($tex) = @{glGenTextures 1}; glGetError(); $face->{texture} = $tex; glBindTexture GL_TEXTURE_2D, $tex; my $glerr=glGetError(); die "a: ".gluErrorString($glerr)."\n" if $glerr; # glTexParameter GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR; # glTexParameter GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR; $surface->rgba; glTexImage2D GL_TEXTURE_2D, 0, 4, # components $surface->width, $surface->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, $surface->pixels; my $glerr=glGetError(); die "Problem setting up 2d Texture (dimensions not a power of 2?)):".gluErrorString($glerr)."\n" if $glerr; } ############################################################################# use Event; glinit; $conn = new conn host => "cf.schmorp.de", port => 13327; Event->timer (after => 0, interval => 1/20, hard => 1, cb => sub { while ($ev->poll) { ($ev_cb{$ev->type} || sub { warn "unhandled event ", $ev->type })->(); } }); Event::loop;