public function onRun(Session $session, array $args)
 {
     if (!$session->getTeam() instanceof Team) {
         return TextFormat::RED . "You aren't in a team!";
     }
     if (!isset($args[0])) {
         return TextFormat::RED . "Usage: " . $this->getUsage();
     }
     $kicked = $this->getSession(array_shift($args));
     if (!$kicked instanceof Session) {
         return TextFormat::RED . "There is no player online by that name.";
     }
     if ($kicked === $session) {
         return TextFormat::RED . "You can't kick yourself from your team!\n" . TextFormat::AQUA . "Use " . TextFormat::LIGHT_PURPLE . "/team rank" . TextFormat::AQUA . " instead.";
     }
     if ($kicked->getTeam() !== $session->getTeam()) {
         return TextFormat::RED . "{$kicked} is not in your team.";
     }
     if ($session->getTeamRank() < Team::RANK_CO_LEADER) {
         return TextFormat::RED . "You must be at least a Co-Leader to kick a team member.";
     }
     if ($kicked->getTeamRank() >= $session->getTeamRank()) {
         return TextFormat::RED . "You can only kick team members of lower rank than you.";
     }
     $session->getTeam()->quit($kicked);
     $session->getPlayer()->kick(TextFormat::YELLOW . "You have been kicked from your team. You are kicked from the server to apply the changes.", false);
     return "{$session} has been kicked from the team.";
 }
 protected function onRun(Session $ses, array $args)
 {
     if (isset($args[0])) {
         $team = $this->main->getTeamManager()->getTeamByName($args[0]);
     } elseif (!($team = $ses->getTeam()) instanceof Team) {
         return TextFormat::RED . "You are not in a team! Usage: " . $this->getUsage();
     }
     $this->main->updateGameSessionData();
     $info = $team->getStats();
     $new = $info->totalMembers - $info->oldMembers;
     $ses->tell(TextFormat::DARK_BLUE . "%s team {$team} ({$info->totalMembers} / {$team->maxCapacity} members%s)", $team->open ? "Open" : "Invite-only", $new > 0 ? $new > 1 ? ", {$new} are new" : ", 1 is new" : "");
     $ses->tell("Requirements to join the team: ");
     foreach (explode("\n", $team->requires) as $line) {
         $ses->tell(TextFormat::RESET . $line);
     }
     $ses->tell("Team rules:");
     foreach (explode("\n", $team->rules) as $line) {
         $ses->tell(TextFormat::RESET . $line);
     }
     $gold = TextFormat::GOLD;
     $dg = TextFormat::DARK_GREEN;
     $kd = $info->pvpDeaths > 0 ? (string) round($info->pvpKills / $info->pvpDeaths, 3) : "N/A";
     $ses->tell($gold . "KitPvP:{$dg} {$info->pvpKills} kills, {$info->pvpDeaths} deaths, max killstreak {$info->pvpMaxStreak}, Overall K/D {$kd}");
     $ses->tell($gold . "Parkour:{$dg} {$info->parkourWins} completions, average {$info->parkourAvgFalls()} falls per completion");
     $ses->tell($gold . "Spleef:{$dg} {$info->spleefWins} wins, {$info->spleefLosses} losses, {$info->spleefDraws} draws");
     $ses->tell($gold . "Overall team points:{$dg} " . round($info->totalPoints() / $info->oldMembers, 3));
     return null;
 }
 protected function onRun(Session $ses, array $args)
 {
     if (!isset($args[0])) {
         return TextFormat::RED . "Usage: " . $this->getUsage();
     }
     if ($ses->getTeam() instanceof Team) {
         return TextFormat::RED . "You are alerady in a team!";
     }
     $name = array_shift($args);
     if (preg_match('#^[A-Za-z][A-Za-z0-9_\\-]{2,62}$#', $name) === 0) {
         $red = TextFormat::RED;
         $yellow = TextFormat::YELLOW;
         $aqua = TextFormat::AQUA;
         return $red . "A team name must{$yellow} start with an alphabet{$red}, must{$yellow} only contain{$aqua} alphabets{$red},{$aqua} numerals{$red},{$aqua} underscore{$red} and{$aqua} hyphens{$red}, must be{$yellow} at least 3 characters{$red} long and{$yellow} at most 63 characters{$red} long.";
     }
     if ($this->main->getTeamManager()->getTeamByExactName($name) instanceof Team) {
         return TextFormat::RED . "A team with this name already exists!";
     }
     $team = new Team($this->main, $this->main->getMySQLi()->nextTID(), $name, Settings::team_maxCapacity($ses->getRank()), false, [$ses->getUID() => Team::RANK_LEADER]);
     $ses->getMysqlSession()->data["tid"] = $team->tid;
     $ses->getMysqlSession()->data["teamrank"] = Team::RANK_LEADER;
     $ses->getMysqlSession()->data["teamjointime"] = time();
     $this->main->getTeamManager()->addTeam($team);
     $ses->getPlayer()->kick(TextFormat::YELLOW . "You have been kicked from the server in order to apply your changes about creating a team.", false);
     return null;
 }
 protected function onRun(Session $ses, array $args)
 {
     $team = $ses->getTeam();
     if (!$team instanceof Team) {
         return TextFormat::RED . "You are not in a team!";
     }
     if (!$ses->quitTeamConfirmed) {
         $ses->quitTeamConfirmed = true;
         return TextFormat::YELLOW . "Are you sure to quit your team? You may not be able to join the team again! If you are the leader, you are going to disband the team! Run \"/team q\" again to confirm.";
     }
     $ses->quitTeamConfirmed = false;
     if ($ses->getTeamRank() === Team::RANK_LEADER) {
         $team->tell(TextFormat::YELLOW . "Team {$team} is disbanding because the leader is quitting the team! You are going to be kicked to apply the changes.");
         /** @var Session $ses */
         foreach ($team->getSessionsOnline() as $ses) {
             $team->quit($ses);
             $ses->getPlayer()->kick(TextFormat::YELLOW . "Your team has been disbanded. You have been kicked to apply the changes", false);
         }
         $this->main->getMySQLi()->query("UPDATE PLAYERS SET tid=-1,teamrank=0,teamjointime=0 WHERE tid={$team->tid}", MysqlConnection::RAW);
         $this->main->getTeamManager()->rmTeam($team);
         return null;
     }
     $team->quit($ses);
     $ses->getPlayer()->kick(TextFormat::YELLOW . "You have quitted your team. You have been kicked to apply the changes.", false);
     return null;
 }
 protected function onRun(Session $ses, array $args)
 {
     if (!isset($args[0])) {
         return TextFormat::RED . "Usage: " . $this->getUsage();
     }
     if ($ses->getTeam() instanceof Team) {
         return TextFormat::RED . "You are already in a team!";
     }
     $team = $this->main->getTeamManager()->getTeamByName($name = array_shift($args));
     if (!$team instanceof Team) {
         return TextFormat::RED . "Team \"{$name}\" not found! Try using \"/team list\" to search discover teams.";
     }
     if ($team->isFull()) {
         return TextFormat::RED . "Team {$team} is already full!";
     }
     if (!$team->canJoin($ses)) {
         return TextFormat::RED . "You must be invited to join the team!";
     }
     $team->tell(TextFormat::AQUA . "{$ses} joined the team!");
     $team->join($ses);
     if (isset($team->invited[$ses->getUID()])) {
         unset($team->invited[$ses->getUID()]);
     }
     $ses->getPlayer()->kick(TextFormat::YELLOW . "You have joined Team {$team}. You have been kicked from the server to aply the changes.", false);
     return TextFormat::GREEN . "You have joined Team {$team}! You are going to be kicked to apply the changes.";
 }
 protected function onRun(Session $ses, array $args)
 {
     if (isset($args[0])) {
         $name = array_shift($args);
         $team = $this->main->getTeamManager()->getTeamByName($name);
     } else {
         $team = $ses->getTeam();
     }
     if (!$team instanceof Team) {
         return TextFormat::RED . "Usage: /team members [team name]";
     }
     $lightPurple = TextFormat::LIGHT_PURPLE;
     $darkBlue = TextFormat::DARK_BLUE;
     $ses->tell(TextFormat::DARK_BLUE . "Members in {$lightPurple}{$team->name}{$darkBlue}: (%d / %d)", $lightPurple . count($team->members) . $darkBlue, $lightPurple . $team->maxCapacity . $darkBlue);
     $members = array_fill_keys(array_keys(Team::$RANK_NAMES), []);
     $this->main->getTeamManager()->saveTeam($team);
     $sess = array_map(function (Session $session) {
         return $session->getMysqlSession();
     }, $this->main->getTeamManager()->getSessionsOfTeam($team));
     if (count($sess) > 0) {
         MysqlSession::saveData($sess, $this->main->getMySQLi());
     }
     $result = $this->main->getMySQLi()->query("SELECT names,teamrank FROM players WHERE tid=%d", MysqlConnection::ALL, $team->tid);
     foreach ($result as $r) {
         $members[(int) $r["teamrank"]][] = substr($r["names"], 0, -1);
     }
     foreach ($members as $rank => $group) {
         $ses->tell($lightPurple . Team::$RANK_NAMES[$rank] . $darkBlue . ": " . $lightPurple . implode(", ", $group) . $darkBlue);
     }
     return TextFormat::DARK_BLUE . "--- END OF MEMBERS LIST ---";
 }
 protected function onRun(Session $ses, array $args)
 {
     if (!($team = $ses->getTeam()) instanceof Team) {
         return TextFormat::RED . "You aren't in a team!";
     }
     $ses->setWriteToChannel($ch = $team->getChannel());
     return TextFormat::GREEN . "You are now talking on #{$ch}.";
 }
 protected function onRun(Session $ses, array $args)
 {
     if (!($team = $ses->getTeam()) instanceof Team) {
         return TextFormat::RED . "You aren't in a team!";
     }
     if ($ses->getTeamRank() < Team::RANK_CO_LEADER) {
         return TextFormat::RED . "You must be a leader or a co-leader to change the state of your team!";
     }
     if ($team->open === $this->open) {
         return TextFormat::RED . "Your team is already a " . TextFormat::LIGHT_PURPLE . ($this->open ? "open" : "closed") . TextFormat::GREEN . " team!";
     }
     $team->open = $this->open;
     return TextFormat::GREEN . "Your team is now a " . TextFormat::LIGHT_PURPLE . ($this->open ? "open" : "closed") . TextFormat::GREEN . " team.";
 }
 protected function onRun(Session $ses, array $args)
 {
     if (!($team = $ses->getTeam()) instanceof Team) {
         return TextFormat::RED . "You are not in a team!";
     }
     $value = trim(implode(" ", array_filter($args)));
     $field = $this->fieldName;
     if ($value === "") {
         return TextFormat::GREEN . ucfirst($this->humanName) . " for Team {$team}:\n" . TextFormat::RESET . str_replace("\n", "\n" . TextFormat::RESET, $team->{$field});
     }
     $value = preg_replace('/ ?\\| ?/', "\n", $value);
     $team->{$field} = $value;
     return TextFormat::GREEN . "The {$this->humanName} for Team {$team} has been changed to:\n" . TextFormat::RESET . str_replace("\n", "\n" . TextFormat::RESET, $value);
 }
 protected function onRun(Session $ses, array $args)
 {
     $team = $ses->getTeam();
     if (!$team instanceof Team) {
         return TextFormat::RED . "You are not in a team!";
     }
     if (!isset($args[0])) {
         return TextFormat::RED . "Usage: " . $this->getUsage();
     }
     $target = $this->getSession(array_shift($args));
     if (!$target instanceof Session) {
         return TextFormat::RED . "There is no player online by that name!";
     }
     if (!isset($team->members[$target->getUID()])) {
         return TextFormat::RED . $target->getRealName() . " is not in your team!";
     }
     $myRank = $ses->getTeamRank();
     $lightPurple = TextFormat::LIGHT_PURPLE;
     $red = TextFormat::RED;
     $aqua = TextFormat::AQUA;
     if ($myRank < Team::RANK_CO_LEADER) {
         return $red . "You must be{$lightPurple} a team leader or co-leader{$red} to promote/demote players!";
     }
     $hisRank = $ses->getTeamRank();
     if ($hisRank === Team::RANK_CO_LEADER and $this->promote) {
         return TextFormat::RED . "There can only be one leader per team, and the leadership cannot be transferred. \n{$aqua}" . "You can contact an{$lightPurple} admin{$aqua}, a{$lightPurple} developer{$aqua} or an{$lightPurple} owner{$aqua} if you have special reasons.";
     }
     if ($hisRank === Team::RANK_JUNIOR and !$this->promote) {
         return TextFormat::RED . "Junior-Member is already the lowest rank. \n{$aqua}" . "Use {$lightPurple}/t k{$aqua} if you wish to kick the player.";
     }
     if ($hisRank >= $myRank) {
         return TextFormat::RED . "You can only promote/demote members of lower rank than you!";
     }
     $team->members[$target->getUID()] = $target->getMysqlSession()->data["teamrank"] = $this->promote ? ++$hisRank : --$hisRank;
     $rankName = Team::$RANK_NAMES[$hisRank];
     $target->tell(TextFormat::AQUA . "You have been " . $this->getName() . "d to a{$lightPurple} {$rankName}{$aqua} by " . $ses->getRealName() . ". \n" . TextFormat::GREEN . "If you wish to have your nametag updated, please rejoin.\n{$aqua}" . "If you don't mind, you don't need to rejoin; your nametag will be updated the next time you join.");
     // TODO $session->recalculateNametag()
     return TextFormat::GREEN . $target->getRealName() . " has been " . $this->getName() . "d to a{$lightPurple} {$rankName}.";
 }