Games-Construder

 view release on metacpan or  search on metacpan

lib/Games/Construder/Server/Player.pm  view on Meta::CPAN

         if ($ov) {
            $self->{uis}->{status}->show ([@$item]);
            $self->refill_bio ($item->[1]);
            return 1;
         }
      }

   } else {
      my ($ov) = $self->{inv}->remove ($item->[0]);
      if ($ov) {
         $self->{uis}->{status}->show ([@$item]);
         $self->refill_bio ($item->[1]);
         return 1;
      }
   }

   return 0;
}

sub refill_bio {
   my ($self, $amount) = @_;

   $self->{data}->{bio} += $amount;
   $self->{data}->{bio} = 100
      if $self->{data}->{bio} > 100;

   if ($self->{data}->{bio} > 0) {
      $self->starvation (0); # make sure we don't starve anymore
   }
}

sub kill_player {
   my ($self, $reason) = @_;
   my $pp = $self->{data}->{pos};
   my ($new_pos, $dist, $secdist) = world_find_random_teleport_destination_at_dist ($pp, 780);
   $self->teleport ($new_pos);
   $self->msg (1, "You died of $reason, your stats and inventory were reset and you have been teleported $secdist sectors away!");
   $self->{inv}->remove ('all');
   my $inv = $Games::Construder::Server::RES->get_initial_inventory;
   $self->{data}->{inv}->{$_} = $inv->{$_} for keys %$inv;
   $self->{data}->{happyness} = 100;
   $self->{data}->{bio}       = 100;
   $self->{data}->{score}     = 0;
   $self->update_score;
}

sub logout {
   my ($self) = @_;
   $self->save;
   delete $self->{uis};
   delete $self->{upd_score_hl_tmout};
   delete $self->{death_timer};
   delete $self->{tick_timer};

   ctr_log (info => "Player %s logged out", $self->{name});
   #d# print Devel::FindRef::track $self;
}

my $world_c = 0;

sub update_pos {
   my ($self, $pos, $lv) = @_;

   if ($self->{freeze_update_pos} ne '') {
      ctr_log (debug => "update_pos thrown away, awaiting teleport confirmation!");
      return;
   }

   my $opos = $self->{data}->{pos};
   $self->{data}->{pos} = $pos;
   my $olv = $self->{data}->{look_vec} || [0,0,0];
   $self->{data}->{look_vec} = vnorm ($lv);

   my $oblk = vfloor ($opos);
   my $nblk = vfloor ($pos);

   my $new_pos = vlength (vsub ($oblk, $nblk)) > 0;
   my $new_lv  = vlength (vsub ($olv, $lv)) > 0.05;
   my $dnew_lv = vlength (vsub ($olv, $lv));

   if ($new_pos || $new_lv) {
      if ($self->{uis}->{navigator}->{shown}) {
         $self->{uis}->{navigator}->show;
      }
   }

   return unless $new_pos;

   $self->upd_visible_chunks;
}

sub upd_visible_chunks {
   my ($self) = @_;
   $self->calc_visible_sectors;
   world_load_at_player ($self, sub { });
}

sub get_pos_normalized {
   my ($self) = @_;
   vfloor ($self->{data}->{pos})
}

sub get_pos_chnk {
   my ($self) = @_;
   world_pos2chnkpos ($self->{data}->{pos})
}

sub get_pos_sector {
   my ($self) = @_;
   world_chnkpos2secpos (world_pos2chnkpos ($self->{data}->{pos}))
}

sub set_vis_rad {
   my ($self, $rad) = @_;
   $self->{vis_rad} = $rad || $PL_VIS_RAD;
}

sub set_visible_chunks {
   my ($self, $new, $old, $req) = @_;

   for (@$old) {

lib/Games/Construder/Server/Player.pm  view on Meta::CPAN

         delete $self->{sent_chunks}->{$id};
      }
   }
   #delete $self->{chunk_uptodate}->{world_pos2id ($chnk)};
}

sub push_chunk_to_network {
   my ($self) = @_;

   my (@upds) = values %{$self->{to_send_chunks}};

   my $plpos = $self->{data}->{pos};
   my $plchnk = world_pos2chnkpos ($self->{data}->{pos});
   (@upds) = grep {
      $self->{visible_chunk_ids}->{world_pos2id ($_)}
   } @upds;
   (@upds) = sort {
      vlength (vsub ($plchnk, $a))
      <=>
      vlength (vsub ($plchnk, $b))
   } @upds;

   splice @upds, $PL_MAX_QUEUE_SIZE;

   my $cnt = scalar @upds;
   ctr_log (debug => "player %s: %d chunk updates in queue", $self->{name}, $cnt)
      if $cnt;
   for (my $i = 0; $i < 5; $i++) {
      my $q = shift @upds
         or return;
      $self->send_chunk ($q);
   }
}

sub send_chunk {
   my ($self, $chnk) = @_;

   # only send chunk when allcoated, in all other cases the chunk will
   # be sent by the chunk_changed-callback by the server (when it checks
   # whether any player might be interested in that chunk).
   my $id = world_pos2id ($chnk);
   my $data = Games::Construder::World::get_chunk_data (@$chnk);
   unless (defined $data) {
      #d# warn "send_chunk: @$chnk was not yet allocated!\n";
      delete $self->{to_send_chunks}->{$id};
      return;
   }

   my $buf = compress ($data);

   $self->send_client ({ cmd => "chunk", pos => $chnk }, \$buf);
   $self->{sent_chunks}->{$id} = $chnk;
   delete $self->{to_send_chunks}->{$id};
}

sub msg {
   my ($self, $error, $msg) = @_;
   $self->{uis}->{msgbox}->show ($error, $msg);
}

sub update_score {
   my ($self, $hl) = @_;
   $self->{uis}->{score}->show ($hl);
}

sub query {
   my ($self, $pos) = @_;
   return unless @$pos;

   world_mutate_at ($pos, sub {
      my ($data) = @_;
      if ($data->[0]) {
         $self->{uis}->{material_view}->show ($data->[0], $data->[5]);
      }
      return 0;
   }, need_entity => 1);
}

sub interact {
   my ($self, $pos) = @_;

   world_at ($pos, sub {
      my ($pos, $cell) = @_;
      Games::Construder::Server::Objects::interact ($self, $pos, $cell->[0], $cell->[5]);
   });
}

sub highlight {
   my ($self, $pos, $time, $color) = @_;
   $self->send_client ({
      cmd   => "highlight",
      pos   => $pos,
      color => $color,
      fade  => -$time
   });
}

sub debug_at {
   my ($self, $pos) = @_;
   $self->send_client ({
      cmd => "model_highlight",
      pos => $pos,
      model => [
         map {
            my $x = $_;
            map {
               my $y = $_;
               map { [[$x, $y, $_], [1, 0, rand (100) / 100, 0.2]] } 0..10
            } 0..10
         } 0..10
      ],
      id => "debug"
   });
   world_mutate_at ($pos, sub {
      my ($data) = @_;
      ctr_log (debug => "player %s: debug position @$pos: @$data", $self->{name});
      if ($data->[0] == 1) {
         $data->[0] = 0;
         return 1;
      }
      return 0;

lib/Games/Construder/Server/Player.pm  view on Meta::CPAN

   my ($self) = @_;

   my $t      = time;
   my $assign = $self->{data}->{assignment};
   my $lpos   = { %{$assign->{pos_types}} };
   my $typ    =
      Games::Construder::World::get_types_in_cube (@{$assign->{pos}}, $assign->{size});

   #d#printf "CHECK TIME 1 %f\n", time - $t;

   for (my $x = 0; $x < $assign->{size}; $x++) {
      for (my $y = 0; $y < $assign->{size}; $y++) {
         for (my $z = 0; $z < $assign->{size}; $z++) {
            my $t = shift @$typ;
            my $pid = join (",", @{vaddd ($assign->{pos}, $x, $y, $z)});

            if ($assign->{pos_types}->{$pid}) {
               if ($assign->{pos_types}->{$pid} == $t) {
                  delete $lpos->{$pid};
               }
            }
         }
      }
   }

   my %tleft;
   for (keys %$lpos) {
      $tleft{$lpos->{$_}}++;
   }
   $assign->{left} = \%tleft;

   #d#printf "CHECK TIME 2 %f\n", time - $t;

   $self->update_assignment_highlight;

   unless (grep { $_ != 0 } values %tleft) {
      $self->finished_assignmenet;
   }
}

sub assignment_select_next {
   my ($self) = @_;
   my $assign = $self->{data}->{assignment};
   my @left = grep {
      $assign->{left}->{$_} > 0
   } keys %{$assign->{left}};

   push @left, @left;
   for (my $i = 0; $i < (@left / 2); $i++) {
      if ($left[$i] == $assign->{sel_mat}) {
         $assign->{sel_mat} = $left[$i + 1];
         last;
      }
   }

   delete $self->{assign_ment_hl};
   $self->update_assignment_highlight;
   $self->{uis}->{assignment_time}->show;
}

sub update_assignment_highlight {
   my ($self) = @_;

   my $assign = $self->{data}->{assignment};
   my $selected = $assign->{sel_mat};
   if ($assign->{left}->{$selected} <= 0) {
      ($assign->{sel_mat}) = grep {
         $assign->{left}->{$_} > 0
      } keys %{$assign->{left}};
      delete $self->{assign_ment_hl};
   }

   unless ($self->{assign_ment_hl}) {
      $self->{assign_ment_hl} = 1;
      my $mat = $assign->{sel_mat};

      $self->send_client ({
         cmd   => "model_highlight",
         pos   => $assign->{pos},
         model => $assign->{mat_models}->{$mat},
         id    => "assignment",
      });
   }
}

sub check_assignment {
   my ($self) = @_;

   my $assign = $self->{data}->{assignment};
   unless ($assign) {
      $self->{uis}->{assignment_time}->hide;
      $self->send_client ({
         cmd => "model_highlight",
         id => "assignment"
      });
      return;
   }

   $self->check_assignment_positions;
   # was it finished?!
   return unless $self->{data}->{assignment};

   $self->{uis}->{assignment_time}->show;
   my $wself = $self;
   weaken $wself;
   $self->{assign_timer} = AE::timer 1, 1, sub {
      $wself->check_assignment_positions;
      # was it finished?!
      return unless $self->{data}->{assignment};

      $wself->{data}->{assignment}->{time} -= 1;
      $wself->{uis}->{assignment_time}->show;
      if ($wself->{data}->{assignment}->{time} <= 0) {
         $wself->cancel_assignment;
      }
   };
}

sub finished_assignmenet {
   my ($self) = @_;
   my $score = $self->{data}->{assignment}->{score};



( run in 1.372 second using v1.01-cache-2.11-cpan-39bf76dae61 )