package GameServer; =head1 NAME GameServer - Main thingie =cut use 5.010; use Moose; use Manager; use DOMTemplate; use User; use JSON::XS; use Coro; use Coro::Event; use Count; use Chat; use vars qw( $push_stream $push_group $push_sent @push_msg_queue ); use vars qw( $session_count ); with qw( Debug MooseX::Continuity::Request MooseX::Continuity::CallbackLinks ); has manager => (is => 'rw'); has tpl => (is => 'rw'); has user => (is => 'rw'); has session_num => (is => 'rw'); # sub process_msg_queue { # while(my $msg = shift @push_msg_queue) { # my $to = $msg->{to}; # push @{$push_stream->{$to}->{msg_queue}}, $msg; # $push_stream->{$to}->{push_sent} = 1; # } # } # async { # my $w = Coro::Event->var(var => \$push_sent, poll => 'w'); # while(1) { # $w->next; # process_msg_queue(); # } # }; sub main { my ($self) = @_; $self->session_num( $session_count++ ); given($self->request->uri->path) { when (/^\/user\/(\w+)/) { $self->show_user($1) } when (/^\/register/) { $self->register_user } when (/^\/game\/(\w+)/) { $self->show_game($1) } when (/^\/comet\//) { $self->comet } when (/^\/sayhi/) { $self->sayhi } default { $self->show_gamelist } } } sub comet { my ($self) = @_; my $sid = $self->request->session_id; $push_stream->{$sid}->{push_sent} = 0; $push_stream->{$sid}->{msg_queue} ||= []; my $w = Coro::Event->var(var => \($push_stream->{$sid}->{push_sent}), poll => 'w'); while(1) { print STDERR "[COMET $sid] Received HTTP connection.\n"; @{$push_stream->{$sid}->{msg_queue}} || $w->next; print STDERR "[COMET $sid] Received wakeup.\n"; $self->request->print(encode_json $push_stream->{$sid}->{msg_queue}); $push_stream->{$sid}->{msg_queue} = []; $self->request->next; } } sub send_msg { my ($self, %msg) = @_; my $sid = $self->request->session_id . "-comet"; if(!$msg{to}) { $msg{to} = $sid; } if($msg{to} eq 'ALL') { foreach my $dest (keys %$push_stream) { print STDERR "[PUSH] queue for $dest\n"; push @{$push_stream->{$dest}->{msg_queue}}, \%msg; $push_stream->{$dest}->{push_sent} = 1; } } else { push @{$push_stream->{$msg{to}}->{msg_queue}}, \%msg; $push_stream->{$msg{to}}->{push_sent} = 1; } print STDERR "[PUSH $msg{to}] Sending message\n"; } sub sayhi { my ($self) = @_; $self->request->print('hiya :)'); Coro::Event->timer( after => 5, cb => sub { $self->send_msg( cmd => 'dom-set-content', target => '#chat .chat-messages', content => 'Boogity! say HI!' ); } ); $self->request->next; } # }; # $self->request->print(encode_json $cmd); # $self->request->next; # } # sub fake { # my ($self) = @_; # $self->push( # cmd => 'dom-set-content' # target => '#chat .chat-messages', # content => 'blah' # ); # $self->broadcast_push( # cmd => 'blah' # ); # # or # $self->push( # to => 'ALL', # implicitly to => 'self'. also to => 'groupname' # cmd => 'eval', # content => 'alert("Hello!")' # ); # $self->add_push_group('game-12343'); # $self->remove_push_group('game-12343'); # } # sub add_push_group { # my ($self, @groups) = @_; # my $cid = $self->session_id; # push @{ $comet->{$cid . '-comet'}->{groups} }, @groups; # } sub output { my ($self, @text) = @_; my $content = join '',@text; my $cid = $self->request->session_id; # Infuse all links with the session ID $content =~ s/request->print($content); return $self; } sub message { my ($self, $msg) = @_; $self->show_content(qq|

Login or Register

$msg
|); $self->next; } sub show_user { my ($self, $username) = @_; $self->message("So... you want to see $username?"); } sub show_gamelist { my ($self) = @_; # $self->send_msg( # #to => $self->request->session_id, # to => 'test', # cmd => 'dom-set-content', # target => '#custom', # content => 'Boogity!' # ); my $tpl = $self->main_template; my $games = ''; foreach my $game (keys %{$self->manager->available_games}) { $games .= "
  • "; $games .= $self->cb_link( $game->display_name => sub { $self->start_new_game($game) } ); $games .= "
  • \n"; } $tpl->set('#available-games' => qq{

    Start a Game

    }); $tpl->set('#cid' => $self->request->session_id); my @kids = (); push @kids, Count->new( request => $self->request, holder => $self ); push @kids, Count->new( request => $self->request, holder => $self ); push @kids, Count->new( request => $self->request, holder => $self ); push @kids, Chat->new( request => $self->request, holder => $self ); while(1) { foreach my $kid (@kids) { $kid->process; } $self->output($tpl->as_HTML); $self->next->process_callbacks; print STDERR "HERE!!!!\n"; } } sub main_template { my ($self) = @_; return $self->tpl if $self->tpl; my $tpl = DOMTemplate->new('tpl/main.html'); $self->tpl($tpl); return $tpl; } sub start_new_game { my ($self, $game_class) = @_; my $user = $self->get_user; return unless $user; my $game = $game_class->new( owner => $self->user, ); my $game_id = int rand 1000000; $self->manager->running_games->{$game_id} = $game; $self->continue_game($game, $user); } sub continue_game { my ($self, $game, $user) = @_; my $game_controller = $game->new_controller( request => $self->request, user => $user, ); $game_controller->main; } # sub get_user { # my ($self) = @_; # return $self->user if $self->user; # my $username = $self->request->get_cookie('auth_username') || ''; # my $token = $self->request->get_cookie('auth_token') || ''; # if($self->manager->users->{$username} && $self->manager->users->{$username}->auth_token eq $token) { # $self->user($self->manager->users->{$username}); # return $self->user; # } # $self->message("You must login or register!"); # return undef; # } sub show_content { my ($self, $content) = @_; my $tpl = $self->main_template; $tpl->set('#content' => $content); $tpl->set('#cid' => $self->request->session_id); $self->output($tpl->as_HTML); $self->next; #->process_callbacks; } sub get_user { my ($self, $msg) = @_; return $self->user if $self->user; $msg //= ''; $self->show_content(qq{

    Login or Register

    $msg
    Username:
    Password:

    }); print STDERR "Here2\n"; use Data::Dumper; print STDERR "all of em: " . Dumper({ $self->params }) . "\n"; my $username = $self->param('xusername'); my $password = $self->param('xpassword'); my $action = $self->param('action'); print STDERR "Got username: <$username>, password: <$password>, action: <$action>\n"; if($action eq 'Login') { if($password ne '' && defined $self->manager->users->{$username} && $self->manager->users->{$username}->check_password($password)) { return $self->manager->users->{username}; } else { return $self->get_user("Incorrect password for user."); } } elsif($action eq 'Register') { if($password eq '') { return $self->get_user("You must enter a password."); } elsif(defined $self->manager->users->{$username}) { return $self->get_user("This user already exists!"); } else { my $user = User->new( username => $username, password => $password, ); $self->manager->users->{$username} = $user; return $user; } } return $self->get_user('Invalid input.'); } 1;