diff --git a/plugin.yml b/plugin.yml index b2df9b7..2979050 100644 --- a/plugin.yml +++ b/plugin.yml @@ -3,5 +3,8 @@ version: "2.0pre-release" api: 4.2.3 main: BedWars\BedWars author: boi1216 +dependencies: ["FormAPI"] -dependencies: ["FormAPI"] \ No newline at end of file +permissions: + bedwars.command.start: + default: op diff --git a/src/BedWars/command/DefaultCommand.php b/src/BedWars/command/DefaultCommand.php index da31e10..125e64f 100644 --- a/src/BedWars/command/DefaultCommand.php +++ b/src/BedWars/command/DefaultCommand.php @@ -28,38 +28,35 @@ class DefaultCommand extends \pocketmine\command\Command { - - private $owner; - - private $commandInfo = [ - 'create' => ['desc' => "Create new game", 'usage' => " "], - 'delete' => ['desc' => "Delete game", 'usage' => ""], - 'setlobby' => ['desc' => "Set lobby of a game", 'usage' => ""], - 'addteam' => ['desc' => "Add team to a game", 'usage' => " "], - 'setpos' => ['desc' => "Set spawn & shop positions", 'usage' => " <1|2|3> - 3 = Player Spawn, 2 = Upgrade Shop, 1 = Item Shop"], - 'addgenerator' => ['desc' => "Add generator", 'usage' => " "], - 'setbed' => ['desc' => "Set team's bed", 'usage' => " "], - 'addsafearea' => ['desc' => "Add area restricted for placing blocks", 'usage' => ""], - 'load' => ['desc' => "Load arena after finishing setup", 'usage' => ''], - 'join' => ['desc' => "Join arena by id", 'usage' => ''] - ]; - + private $commandInfo = [ + 'create' => ['desc' => "Create new game", 'usage' => " "], + 'delete' => ['desc' => "Delete game", 'usage' => ""], + 'setlobby' => ['desc' => "Set lobby of a game", 'usage' => ""], + 'addteam' => ['desc' => "Add team to a game", 'usage' => " "], + 'setpos' => ['desc' => "Set spawn & shop positions", 'usage' => " <1|2|3> - 3 = Player Spawn, 2 = Upgrade Shop, 1 = Item Shop"], + 'addgenerator' => ['desc' => "Add generator", 'usage' => " "], + 'setbed' => ['desc' => "Set team's bed", 'usage' => " "], + 'addsafearea' => ['desc' => "Add area restricted for placing blocks", 'usage' => ""], + 'load' => ['desc' => "Load arena after finishing setup", 'usage' => ''], + 'join' => ['desc' => "Join arena by id", 'usage' => ''], + 'random' => ['desc' => "Join random arena", 'usage' => ''], + 'start' => ['desc' => "force start the game", 'usage' => ''] + ]; + /** * DefaultCommand constructor. * @param BedWars $owner */ - public function __construct(BedWars $owner) - { - parent::__construct("bedwars", "BedWars", null, ["bw"]); - parent::setDescription("BedWars command"); - - $this->owner = $owner; - - } - - private function getPlugin() : BedWars{ - return $this->owner; + public function __construct( + private BedWars $owner + ){ + parent::__construct("bedwars", "BedWars", null, ["bw"]); + parent::setDescription("BedWars command"); } + + private function getPlugin() : BedWars{ + return $this->owner; + } /** * @param CommandSender $sender @@ -67,354 +64,441 @@ private function getPlugin() : BedWars{ * @param array $args * @return bool|mixed|void */ - public function execute(CommandSender $sender, string $commandLabel, array $args){ - if(empty($args)){ - $this->sendHelp($sender); - return; - } - - switch($args[0]){ - case 'create'; - if(count($args) < 7){ - $sender->sendMessage($this->getSubUsage('create')); - return; - } - $game_id = $args[1]; - $min_players = $args[2]; - $players_per_team = $args[3]; - $start_time = $args[4]; - $map_name = $args[5]; - $world_name = $args[6]; - - if($this->getPlugin()->gameExists($game_id)){ - $sender->sendMessage(TextFormat::RED . $game_id . " - game already exists!"); - return; - } - - if(!is_int(intval($min_players))){ - $sender->sendMessage(TextFormat::RED . "min_players - must be a number!"); - return; - } - - if(!is_int(intval($players_per_team))){ - $sender->sendMessage(TextFormat::RED . "players_per_team - must be a number!"); - return; - } - - if(!is_int(intval($start_time))){ - $sender->sendMessage(TextFormat::RED . "start_time - must be a number!"); - return; - } - - if(strlen($map_name) < 1){ - $sender->sendMessage(TextFormat::RED . "map_name - name too short!"); - } - - $world = $this->getPlugin()->getServer()->getWorldManager()->getWorldByName($world_name); - if(!$world instanceof World){ - $sender->sendMessage(TextFormat::RED . "World " . $world_name . " does not exist"); - return; - } - $sender->sendMessage(TextFormat::GREEN . "Game created"); - $this->getPlugin()->createGame($game_id, $min_players, $players_per_team, $start_time, $map_name, $world_name); - break; - case 'delete'; - if(count($args) < 2){ - $sender->sendMessage($this->getSubUsage('delete')); - return; - } - $game_id = $args[1]; - if($this->getPlugin()->gameExists($game_id)){ - $this->getPlugin()->deleteGame($game_id); - $sender->sendMessage(TextFormat::GREEN . "Game deleted"); - return; - } - - $sender->sendMessage(TextFormat::RED . $game_id . " - game not found"); - break; - case 'setlobby'; - if(!$sender instanceof Player){ - $sender->sendMessage(TextFormat::GREEN . "This command can be used only in-game"); - return; - } - if(count($args) < 2){ - $sender->sendMessage($this->getSubUsage('setlobby')); - return; - } - - $game_id = $args[1]; - if($this->getPlugin()->gameExists($game_id)){ - $pos = $sender->getPosition(); - $this->getPlugin()->setLobby($game_id, $pos->getX(), $pos->getY(), $pos->getZ(), $pos->getWorld()->getFolderName()); - $sender->sendMessage(TextFormat::GREEN . "Lobby set"); - } - break; - case 'setposition'; - case 'setpos'; - if(!$sender instanceof Player){ - $sender->sendMessage(TextFormat::GREEN . "This command can be used only in-game"); - return; - } - - if(count($args) < 4){ - $sender->sendMessage($this->getSubUsage('setpos')); - return; - } - - $game_id = $args[1]; - if(!$this->getPlugin()->gameExists($game_id)){ - $sender->sendMessage(TextFormat::RED . $game_id . " - Invalid game id"); - return; - } - $team = $args[2]; - - if(!$this->getPlugin()->teamExists($game_id, $team)){ - $sender->sendMessage(TextFormat::RED . "Invalid team - " . $team); - return; - } - - $positionType = array(1 => 'Shop', 2 => 'Upgrade', 3 => 'Spawn')[intval($args[3])]; - if($positionType == null){ - $sender->sendMessage(TextFormat::RED . "Invalid position"); - return; - } - $pos = $sender->getPosition(); - $this->getPlugin()->setTeamPosition($game_id, $team, $positionType, $pos->getX(), $pos->getY(), $pos->getZ(), $sender->getLocation()->getYaw()); - $sender->sendMessage(TextFormat::GREEN . "Position set"); - break; - case 'setbed'; - if(!$sender instanceof Player){ - $sender->sendMessage(TextFormat::GREEN . "This command can be used only in-game"); - return; - } - - if(count($args) < 2){ - $sender->sendMessage($this->getSubUsage('setbed')); - return; - } - - $game_id = $args[1]; - if(!$this->getPlugin()->gameExists($game_id)){ - $sender->sendMessage(TextFormat::RED . $game_id . " - Invalid game id"); - return; - } - - $team = strtolower($args[2]); - if(!$this->getPlugin()->teamExists($game_id, $team)){ - $sender->sendMessage(TextFormat::RED . "Invalid team - " . $team); - return; - } - $this->getPlugin()->bedSetup[$sender->getName()] = ['game' => $game_id, 'team' => $team , 'step' => 1]; - $sender->sendMessage(TextFormat::GREEN . "Please touch the 1st part of the bed"); - break; - case 'addteam'; - if(count($args) < 2){ - $sender->sendMessage($this->getSubUsage('addteam')); - return; - } - $game_id = $args[1]; - if(!$this->getPlugin()->gameExists($game_id)){ - $sender->sendMessage(TextFormat::RED . $game_id . " - Invalid game id"); - return; - } - $team = strtolower($args[2]); - if(!isset(BedWars::TEAMS[$team])){ - $sender->sendMessage(TextFormat::RED . $team . " - Invalid team"); - $sender->sendMessage(TextFormat::RED . "Available: " . implode(" ", array_keys(BedWars::TEAMS))); - return; - } - $this->getPlugin()->addTeam($game_id, $team); - break; - case 'addgenerator'; - if(!$sender instanceof Player){ - $sender->sendMessage(TextFormat::GREEN . "This command can be used only in-game"); - return; - } - if(count($args) < 3){ - $sender->sendMessage($this->getSubUsage('addgenerator')); - return; - } - - $game_id = $args[1]; - if(!$this->getPlugin()->gameExists($game_id)){ - $sender->sendMessage(TextFormat::RED . $game_id . " - Invalid game id"); - return; - } - - $generatorTypes = array('iron', 'gold', 'diamond', 'emerald'); - if(!in_array($args[2], $generatorTypes)){ - $sender->sendMessage(TextFormat::RED . $args[2] . " - Invalid generator type"); - return; - } - $generatorType = $args[2]; - $pos = $sender->getPosition(); - $team = isset($args[3]) ? $args[3] : ""; - if(!$this->getPlugin()->teamExists($game_id, $team) && $team !== ""){ - $sender->sendMessage(TextFormat::RED . "Invalid team - " . $team); - return; - } - $this->getPlugin()->addGenerator($game_id, $team, $generatorType, $pos->getX(), $pos->getY(), $pos->getZ()); - $sender->sendMessage(TextFormat::GREEN . "Added"); - //NON-SETUP - break; - case 'addsafearea'; - if(!$sender instanceof Player){ - $sender->sendMessage(TextFormat::GREEN . "This command can be used only in-game"); - return; - } - - if(count($args) < 2){ - $sender->sendMessage($this->getSubUsage('addsafearea')); - return; - } - - $game_id = $args[1]; - if(!$this->getPlugin()->gameExists($game_id)){ - $sender->sendMessage(TextFormat::RED . $game_id . " - Invalid game id"); - return; - } - - $ignored = array(); - str_replace(" ", "", $args[2]); - if(isset($args[2])){ - if(!strpos($args[2], ',')){ - if(is_numeric($args[2])){ - $ignored[] = intval($args[2]); - }else{ - if(!strpos($args[2], ':')){ - err: - $sender->sendMessage(TextFormat::RED . "Invalid format of ignored blocks!"); - $sender->sendMessage(TextFormat::YELLOW . "Example: 365:2,13,1:0"); - return; - } - $e = explode(":", $args[2]); - $ignored[] = $e[0] . ":" . $e[1]; - } - }else{ - foreach(explode(",", $args[2]) as $id) { - if(is_numeric($id)){ - $ignored[] = intval($id); - }else{ - if(!strpos($args[2], ':')){ - goto err; - return; - } - $e = explode(":", $id); - if(!isset($e[0]) || !isset($e[1])){ - goto err; - } - $ignored[] = $e[0] . ":" . $e[1]; - } - } - } - } - $block = null; - - foreach($ignored as $blockID){ - if(strpos($blockID, ':')){ - $idMeta = explode(":", $blockID); - - try{ - $block = BlockFactory::getInstance()->get(intval($idMeta[0]), intval($idMeta[1])); - }catch(\InvalidArgumentException $e){ - goto invalid; - } - - if(!$block instanceof Block){ - goto invalid; - } - }else{ - try{ - $block = BlockFactory::getInstance()->get($blockID, 0); - }catch(\InvalidArgumentException $e){ - goto invalid; - } - - if(!$block instanceof Block){ - invalid: - $sender->sendMessage(TextFormat::RED . $blockID . " is not a valid block id"); - return; - } - } - } - $this->getPlugin()->saSetup[$sender->getName()] = ['step' => 1, 'pos1' => null, 'pos2' => null, 'ignoredIds' => implode(",", $ignored), 'game_id' => $game_id]; - $sender->sendMessage(TextFormat::GREEN . "Break a block to set the 1st position"); - break; - case 'load'; - if(count($args) < 2){ - $sender->sendMessage($this->getSubUsage('load')); - return; - } - - $gameData = $this->getPlugin()->getGameData($args[1]); - if($gameData == null){ - return; - } - - if(!$this->getPlugin()->validateGame($gameData)){ - $sender->sendMessage(TextFormat::RED . "Setup not finished for game - " . $args[1]); - return; - } - - $this->getPlugin()->loadGame($args[1]); - $sender->sendMessage(TextFormat::GREEN . "Done"); - break; - case 'list'; - if(empty($this->getPlugin()->games)){ - $sender->sendMessage(TextFormat::RED . "There are no games loaded"); - return; - } - - $status = array(0 => TextFormat::GREEN . 'LOBBY', 1 => TextFormat::RED . 'IN-GAME', 2 => TextFormat::DARK_RED . 'RESTARTING'); - - foreach($this->getPlugin()->games as $game){ - $sender->sendMessage(TextFormat::GREEN . "Game id - " . $game->getId()); - $sender->sendMessage(TextFormat::YELLOW . "Status: " . $status[$game->getState()]); - $sender->sendMessage(TextFormat::YELLOW . "Players: " . count($game->getPlayers()) . " / " . $game->getMaxPlayers()); - $sender->sendMessage(TextFormat::GREEN . "---"); - } - break; - case 'join'; - if(!$sender instanceof Player){ - $sender->sendMessage(TextFormat::GREEN . "This command can be used only in-game"); - return; - } - if(count($args) < 2){ - $sender->sendMessage($this->getSubUsage('join')); - return; - } - - if(!$this->getPlugin()->gameExists($args[1])){ - $sender->sendMessage(TextFormat::RED . $args[1] . " - Invalid game id"); - return; - } - $this->getPlugin()->games[$args[1]]->join($sender); - break; - case 'random'; - /* if(!$sender instanceof Player){ - $sender->sendMessage("in-game command"); - } - $random = array_rand($this->getPlugin()->games, 1); - $this->getPlugin()->games[$random]->join($sender);*/ - break; - } - } - - private function getSubUsage($command){ - return TextFormat::RED . "Usage: " . $this->commandInfo[$command]['usage']; - } - + public function execute(CommandSender $sender, string $commandLabel, array $args){ + if(empty($args)){ + $this->sendHelp($sender); + return; + } + + switch($args[0]){ + case 'create'; + if(count($args) < 7){ + $sender->sendMessage($this->getSubUsage('create')); + return; + } + + $game_id = $args[1]; + $min_players = $args[2]; + $players_per_team = $args[3]; + $start_time = $args[4]; + $map_name = $args[5]; + $world_name = $args[6]; + + if($this->getPlugin()->gameExists($game_id)){ + $sender->sendMessage(TextFormat::RED . $game_id . " - game already exists!"); + return; + } + + if(!is_int(intval($min_players))){ + $sender->sendMessage(TextFormat::RED . "min_players - must be a number!"); + return; + } + + if(!is_int(intval($players_per_team))){ + $sender->sendMessage(TextFormat::RED . "players_per_team - must be a number!"); + return; + } + + if(!is_int(intval($start_time))){ + $sender->sendMessage(TextFormat::RED . "start_time - must be a number!"); + return; + } + + if(strlen($map_name) < 1){ + $sender->sendMessage(TextFormat::RED . "map_name - name too short!"); + } + + $world = $this->getPlugin()->getServer()->getWorldManager()->getWorldByName($world_name); + if(!$world instanceof World){ + $sender->sendMessage(TextFormat::RED . "World " . $world_name . " does not exist"); + return; + } + + $sender->sendMessage(TextFormat::GREEN . "Game created"); + $this->getPlugin()->createGame($game_id, $min_players, $players_per_team, $start_time, $map_name, $world_name); + break; + + case 'delete'; + if(count($args) < 2){ + $sender->sendMessage($this->getSubUsage('delete')); + return; + } + + $game_id = $args[1]; + if($this->getPlugin()->gameExists($game_id)){ + $this->getPlugin()->deleteGame($game_id); + $sender->sendMessage(TextFormat::GREEN . "Game deleted"); + return; + } + + $sender->sendMessage(TextFormat::RED . $game_id . " - game not found"); + break; + + case 'setlobby'; + if(!$sender instanceof Player){ + $sender->sendMessage(TextFormat::GREEN . "This command can be used only in-game"); + return; + } + + if(count($args) < 2){ + $sender->sendMessage($this->getSubUsage('setlobby')); + return; + } + + $game_id = $args[1]; + if($this->getPlugin()->gameExists($game_id)){ + $pos = $sender->getPosition(); + $this->getPlugin()->setLobby($game_id, intval($pos->getX()) + 0.5, $pos->getY(), intval($pos->getZ()) + 0.5, $pos->getWorld()->getFolderName()); + $sender->sendMessage(TextFormat::GREEN . "Lobby set"); + } + break; + + case 'setposition'; + case 'setpos'; + if(!$sender instanceof Player){ + $sender->sendMessage(TextFormat::GREEN . "This command can be used only in-game"); + return; + } + + if(count($args) < 4){ + $sender->sendMessage($this->getSubUsage('setpos')); + return; + } + + $game_id = $args[1]; + if(!$this->getPlugin()->gameExists($game_id)){ + $sender->sendMessage(TextFormat::RED . $game_id . " - Invalid game id"); + return; + } + + $team = $args[2]; + if(!$this->getPlugin()->teamExists($game_id, $team)){ + $sender->sendMessage(TextFormat::RED . "Invalid team - " . $team); + return; + } + + $positionType = array(1 => 'Shop', 2 => 'Upgrade', 3 => 'Spawn')[intval($args[3])]; + if($positionType == null){ + $sender->sendMessage(TextFormat::RED . "Invalid position"); + return; + } + + $pos = $sender->getPosition(); + $this->getPlugin()->setTeamPosition($game_id, $team, $positionType, intval($pos->getX()), $pos->getY(), intval($pos->getZ()), $sender->getLocation()->getYaw()); + $sender->sendMessage(TextFormat::GREEN . "Position set"); + break; + + case 'setbed'; + if(!$sender instanceof Player){ + $sender->sendMessage(TextFormat::GREEN . "This command can be used only in-game"); + return; + } + + if(count($args) < 2){ + $sender->sendMessage($this->getSubUsage('setbed')); + return; + } + + $game_id = $args[1]; + if(!$this->getPlugin()->gameExists($game_id)){ + $sender->sendMessage(TextFormat::RED . $game_id . " - Invalid game id"); + return; + } + + $team = strtolower($args[2]); + if(!$this->getPlugin()->teamExists($game_id, $team)){ + $sender->sendMessage(TextFormat::RED . "Invalid team - " . $team); + return; + } + + $this->getPlugin()->bedSetup[$sender->getName()] = ['game' => $game_id, 'team' => $team , 'step' => 1]; + $sender->sendMessage(TextFormat::GREEN . "Please touch the 1st part of the bed"); + break; + + case 'addteam'; + if(count($args) < 2){ + $sender->sendMessage($this->getSubUsage('addteam')); + return; + } + + $game_id = $args[1]; + if(!$this->getPlugin()->gameExists($game_id)){ + $sender->sendMessage(TextFormat::RED . $game_id . " - Invalid game id"); + return; + } + + $team = strtolower($args[2]); + if(!isset(BedWars::TEAMS[$team])){ + $sender->sendMessage(TextFormat::RED . $team . " - Invalid team"); + $sender->sendMessage(TextFormat::RED . "Available: " . implode(" ", array_keys(BedWars::TEAMS))); + return; + } + + $this->getPlugin()->addTeam($game_id, $team); + $sender->sendMessage(TextFormat::GREEN . "Team added!"); + break; + + case 'addgenerator'; + case 'setgenerator'; + + if(!$sender instanceof Player){ + $sender->sendMessage(TextFormat::GREEN . "This command can be used only in-game"); + return; + } + + if(count($args) < 3){ + $sender->sendMessage($this->getSubUsage('addgenerator')); + return; + } + + $game_id = $args[1]; + if(!$this->getPlugin()->gameExists($game_id)){ + $sender->sendMessage(TextFormat::RED . $game_id . " - Invalid game id"); + return; + } + + $generatorTypes = array('iron', 'gold', 'diamond', 'emerald'); + if(!in_array($args[2], $generatorTypes)){ + $sender->sendMessage(TextFormat::RED . $args[2] . " - Invalid generator type"); + return; + } + + $generatorType = $args[2]; + $pos = $sender->getPosition(); + $team = isset($args[3]) ? $args[3] : ""; + if(!$this->getPlugin()->teamExists($game_id, $team) && $team !== ""){ + $sender->sendMessage(TextFormat::RED . "Invalid team - " . $team); + return; + } + + $this->getPlugin()->addGenerator($game_id, $team, $generatorType, intval($pos->getX()), $pos->getY(), intval($pos->getZ())); + $sender->sendMessage(TextFormat::GREEN . "Added"); + break; + + case 'addsafearea'; + if(!$sender instanceof Player){ + $sender->sendMessage(TextFormat::GREEN . "This command can be used only in-game"); + return; + } + + if(count($args) < 2){ + $sender->sendMessage($this->getSubUsage('addsafearea')); + return; + } + + $game_id = $args[1]; + if(!$this->getPlugin()->gameExists($game_id)){ + $sender->sendMessage(TextFormat::RED . $game_id . " - Invalid game id"); + return; + } + + $ignored = array(); + str_replace(" ", "", $args[2]); + if(isset($args[2])){ + if(!strpos($args[2], ',')){ + if(is_numeric($args[2])){ + $ignored[] = intval($args[2]); + } else { + if(!strpos($args[2], ':')){ + err: + $sender->sendMessage(TextFormat::RED . "Invalid format of ignored blocks!"); + $sender->sendMessage(TextFormat::YELLOW . "Example: 365:2,13,1:0"); + return; + } + + $e = explode(":", $args[2]); + $ignored[] = $e[0] . ":" . $e[1]; + } + } else { + foreach(explode(",", $args[2]) as $id) { + if(is_numeric($id)){ + $ignored[] = intval($id); + } else { + if(!strpos($args[2], ':')){ + goto err; + return; + } + + $e = explode(":", $id); + if(!isset($e[0]) || !isset($e[1])){ + goto err; + } + + $ignored[] = $e[0] . ":" . $e[1]; + } + } + } + } + + $block = null; + foreach($ignored as $blockID){ + if(strpos($blockID, ':')){ + $idMeta = explode(":", $blockID); + try { + $block = BlockFactory::getInstance()->get(intval($idMeta[0]), intval($idMeta[1])); + } catch (\InvalidArgumentException $e){ + goto invalid; + } + + if(!$block instanceof Block){ + goto invalid; + } + } else { + try { + $block = BlockFactory::getInstance()->get($blockID, 0); + } catch (\InvalidArgumentException $e){ + goto invalid; + } + + if(!$block instanceof Block){ + invalid: + $sender->sendMessage(TextFormat::RED . $blockID . " is not a valid block id"); + return; + } + } + } + + $this->getPlugin()->saSetup[$sender->getName()] = ['step' => 1, 'pos1' => null, 'pos2' => null, 'ignoredIds' => implode(",", $ignored), 'game_id' => $game_id]; + $sender->sendMessage(TextFormat::GREEN . "Break a block to set the 1st position"); + break; + + case 'load'; + if(count($args) < 2){ + $sender->sendMessage($this->getSubUsage('load')); + return; + } + + $gameData = $this->getPlugin()->getGameData($args[1]); + if($gameData == null){ + return; + } + + if(!$this->getPlugin()->validateGame($gameData)){ + $sender->sendMessage(TextFormat::RED . "Setup not finished for game - " . $args[1]); + return; + } + + $this->getPlugin()->loadGame($args[1]); + $sender->sendMessage(TextFormat::GREEN . "Done"); + break; + + case 'list'; + if(empty($this->getPlugin()->games)){ + $sender->sendMessage(TextFormat::RED . "There are no games loaded"); + return; + } + + $status = array(0 => TextFormat::GREEN . 'LOBBY', 1 => TextFormat::RED . 'IN-GAME', 2 => TextFormat::DARK_RED . 'RESTARTING'); + foreach($this->getPlugin()->games as $game){ + $sender->sendMessage(TextFormat::GREEN . "Game id - " . $game->getId()); + $sender->sendMessage(TextFormat::YELLOW . "Status: " . $status[$game->getState()]); + $sender->sendMessage(TextFormat::YELLOW . "Players: " . count($game->getPlayers()) . " / " . $game->getMaxPlayers()); + $sender->sendMessage(TextFormat::GREEN . "---"); + } + break; + + case 'join'; + if(!$sender instanceof Player){ + $sender->sendMessage(TextFormat::GREEN . "This command can be used only in-game"); + return; + } + + if(count($args) < 2){ + $sender->sendMessage($this->getSubUsage('join')); + return; + } + + if(!$this->getPlugin()->gameExists($args[1])){ + $sender->sendMessage(TextFormat::RED . $args[1] . " - Invalid game id"); + return; + } + + $this->getPlugin()->games[$args[1]]->join($sender); + + break; + case 'random'; + if($sender instanceof Player){ + $sender->sendMessage(TextFormat::YELLOW . "Searching for avillable arena for you!"); + $avillableArenas = []; + + $index = []; + foreach ($this->getPlugin()->games as $arena){ + if($arena->getState() == $arena::STATE_LOBBY){ + $index[$arena->getName()] = $arena->getPlayers(); + } + } + + arsort($index); + + if(count($index) > 0){ + foreach ($index as $key => $val){ + if(count($avillableArenas) < 3){ + $avillableArenas[] = $key; + } + } + } + + if(count($avillableArenas) == 0){ + $sender->sendMessage(TextFormat::RED . "No arenas found!"); + return; + } + + $random = $avillableArenas[array_rand($avillableArenas)]; + $this->getPlugin()->games[$random]->join($sender); + $sender->sendMessage(TextFormat::YELLOW . "You send to " . $random . "!"); + } else { + $sender->sendMessage("run command in-game only!"); + } + break; + + case "start"; + if($sender instanceof Player){ + if($sender->hasPermission("bedwars.command.start")){ + if(($arena = $this->owner->getPlayerGame($sender)) !== null){ + + if(count($arena->getPlayers()) < 2){ + $sender->sendMessage(TextFormat::RED . "Need more players to start the game!"); + return; + } + + if($arena->getState() == $arena::STATE_LOBBY){ + if($arena->getStartTime() > 10){ + $arena->setForcedStart(true); + $arena->setStartTime(5); + $sender->sendMessage(TextFormat::YELLOW . "Starting in 5s"); + } else { + $sender->sendMessage(TextFormat::RED . "cannot start the game right now!"); + } + } else { + $sender->sendMessage(TextFormat::RED . "Game already started!"); + } + } else { + $sender->sendMessage(TextFormat::RED . "You're not in arena!"); + } + } else { + $sender->sendMessage(TextFormat::RED . "You don't have permission to use this command!"); + } + } else { + $sender->sendMessage("run command in-game only!"); + } + break; + } + } + + private function getSubUsage($command){ + return TextFormat::RED . "Usage: " . $this->commandInfo[$command]['usage']; + } + /** * @param CommandSender $sender */ - private function sendHelp(CommandSender $sender) { - $sender->sendMessage(TextFormat::BOLD . TextFormat::YELLOW . "BedWars Commands"); - $sender->sendMessage(TextFormat::GRAY . "Type the sub-command for usage info"); - $sender->sendMessage(TextFormat::BOLD . TextFormat::WHITE . "[] - required parameters"); - $sender->sendMessage(TextFormat::BOLD . TextFormat::WHITE . "[] - optional parameters"); - foreach($this->commandInfo as $command => $info){ - $sender->sendMessage(TextFormat::RED . $command . TextFormat::GRAY . " - " . $info['desc']); - } - - } + private function sendHelp(CommandSender $sender) { + $sender->sendMessage(TextFormat::BOLD . TextFormat::YELLOW . "BedWars Commands"); + $sender->sendMessage(TextFormat::GRAY . "Type the sub-command for usage info"); + $sender->sendMessage(TextFormat::BOLD . TextFormat::WHITE . "[] - required parameters"); + $sender->sendMessage(TextFormat::BOLD . TextFormat::WHITE . "[] - optional parameters"); + foreach($this->commandInfo as $command => $info){ + $sender->sendMessage(TextFormat::RED . $command . TextFormat::GRAY . " - " . $info['desc']); + } + } } \ No newline at end of file diff --git a/src/BedWars/game/Game.php b/src/BedWars/game/Game.php index e330263..2b92caf 100644 --- a/src/BedWars/game/Game.php +++ b/src/BedWars/game/Game.php @@ -129,6 +129,9 @@ class Game /** @var array $safeAreas */ private $safeAreas = array(); + /** @var bool $forceStart */ + private $forceStart = false; + /** * Game constructor. * @param BedWars $plugin @@ -201,6 +204,24 @@ public function getMapName() : string{ return $this->mapName; } + public function getStartTime(): int{ + return $this->startTime; + } + + public function setStartTime(int $newVal){ + if($this->startTime > $newVal){ + $this->startTime = $newVal; + } + } + + public function isForcedStart(): bool{ + return $this->forceStart; + } + + public function setForcedStart(bool $newVal){ + $this->forceStart = $newVal; + } + /** * @return int */ @@ -298,6 +319,7 @@ public function stop() : void{ $this->cachedPlayers = array(); $this->state = self::STATE_LOBBY; $this->starting = false; + $this->forceStart = false; $this->plugin->getServer()->getWorldManager()->unloadWorld($this->plugin->getServer()->getWorldManager()->getWorldByName($this->worldName)); $this->reload(); @@ -357,7 +379,7 @@ private function initGenerators() : void{ $delay = $generatorData['refreshRate']; $vector = Utils::stringToVector(":", $generator['position']); - $position = new Position($vector->x, $vector->y, $vector->z,$this->plugin->getServer()->getWorldManager()->getWorldByName($this->worldName)); + $position = new Position($vector->x + 0.5, $vector->y, $vector->z + 0.5, $this->plugin->getServer()->getWorldManager()->getWorldByName($this->worldName)); $this->generators[] = new Generator($item, $delay,$position, $spawnText, $spawnBlock, $generator['team'] == "" ? null : $this->teams[$generator['team']]); } @@ -409,8 +431,14 @@ public function join(Player $player) : void{ $this->broadcastMessage(TextFormat::GRAY . $player->getName() . " " . TextFormat::YELLOW . "has joined the game " . TextFormat::GOLD . "(" . TextFormat::AQUA . count($this->players) . TextFormat::YELLOW . "/" . TextFormat::AQUA . $this->maxPlayers . TextFormat::YELLOW . ")"); $player->getInventory()->clearAll(); + $player->getArmorInventory()->clearAll(); + $player->getCraftingGrid()->clearAll(); + $player->getOffHandInventory()->clearAll(); foreach($this->teams as $team){ - $player->getInventory()->addItem($i =new Item(new ItemIdentifier(ItemIds::WOOL, Utils::colorIntoWool($team->getColor())))); + // $player->getInventory()->addItem($i = new Item(new ItemIdentifier(ItemIds::WOOL, Utils::colorIntoWool($team->getColor())))); + $item = ItemFactory::getInstance()->get(ItemIds::WOOL, Utils::colorIntoWool($team->getColor())); + $item->setCustomName($team->getColor() . ucfirst($team->getName()) . "'s " . TextFormat::WHITE . "Team"); + $player->getInventory()->addItem($item); } $player->getInventory()->setItem(8, ItemFactory::getInstance()->get(ItemIds::COMPASS)->setCustomName(TextFormat::YELLOW . "Leave")); $player->setGamemode(GameMode::ADVENTURE()); @@ -427,7 +455,7 @@ public function join(Player $player) : void{ Scoreboard::setLine($player, 7, " " . TextFormat::WHITE . "Mode: " . TextFormat::GREEN . substr(str_repeat($this->playersPerTeam . "v", count($this->teams)), 0, -1) . str_repeat(" ", 3)); Scoreboard::setLine($player, 8, " " . TextFormat::WHITE . "Version: " . TextFormat::GRAY . "v1.0" . str_repeat(" ", 3)); Scoreboard::setLine($player, 9, " "); - Scoreboard::setLine($player, 10, " " . TextFormat::YELLOW . "www.example.net"); + Scoreboard::setLine($player, 10, " " . TextFormat::YELLOW . $this->plugin->serverWebsite); } /** @@ -516,7 +544,7 @@ public function quit(Player $player) : void{ } private function checkLobby() : void{ - if(!$this->starting && count($this->players) >= $this->minPlayers) { + if(!$this->starting && count($this->players) >= $this->minPlayers && !$this->isForcedStart()) { $this->starting = true; $this->broadcastMessage(TextFormat::GREEN . "Countdown started"); } @@ -543,21 +571,22 @@ public function killPlayer(Player $player) : void{ $this->deadQueue[$player->getName()] = 5; } + $playerGame = $this->plugin->getPlayerTeam($player); $cause = $player->getLastDamageCause(); - if($cause == null)return; + if($cause == null || $playerGame == null) return; switch($cause->getCause()){ case EntityDamageEvent::CAUSE_ENTITY_ATTACK; if($cause instanceof EntityDamageByEntityEvent){ $damager = $cause->getDamager(); - if($damager instanceof Player){ - $this->broadcastMessage($this->plugin->getPlayerTeam($player)->getColor() . $player->getName() . " " . TextFormat::GRAY . "was killed by " . $this->plugin->getPlayerTeam($damager)->getColor() . $damager->getName()); + if($damager instanceof Player && $this->plugin->getPlayerTeam($damager) !== null){ + $this->broadcastMessage($this->plugin->getPlayerTeam($player)->getColor() . $player->getName() . " " . TextFormat::GRAY . "was killed by " . $this->plugin->getPlayerTeam($damager)->getColor() . $damager->getName()); } } break; case EntityDamageEvent::CAUSE_PROJECTILE; if($cause instanceof EntityDamageByChildEntityEvent){ $damager = $cause->getDamager(); - if($damager instanceof Player){ + if($damager instanceof Player && $this->plugin->getPlayerTeam($damager) !== null){ $this->broadcastMessage($this->plugin->getPlayerTeam($player)->getColor() . $player->getName() . " " . TextFormat::GRAY . "was shot by " . $this->plugin->getPlayerTeam($damager)->getColor() . $damager->getName()); } } @@ -663,8 +692,8 @@ public function respawnPlayer(Player $player) : void{ public function tick() : void{ switch($this->state) { case self::STATE_LOBBY; - if ($this->starting) { - if(count($this->players) < $this->minPlayers) { + if ($this->starting || $this->isForcedStart()) { + if(count($this->players) < $this->minPlayers && !$this->isForcedStart()) { $this->starting = false; $this->broadcastMessage(TextFormat::YELLOW . "Countdown stopped"); $this->startTime = $this->startTimeStatic; @@ -710,12 +739,12 @@ public function tick() : void{ \BedWars\utils\Scoreboard::setLine($player, 2, " " . TextFormat::WHITE . "Map: " . TextFormat::GREEN . $this->mapName . str_repeat(" ", 3)); \BedWars\utils\Scoreboard::setLine($player, 3, " " . TextFormat::WHITE . "Players: " . TextFormat::GREEN . count($this->players) . "/" . $this->maxPlayers . str_repeat(" ", 3)); \BedWars\utils\Scoreboard::setLine($player, 4, " "); - \BedWars\utils\Scoreboard::setLine($player, 5, " " . ($this->starting ? TextFormat::WHITE . "Starting in " . TextFormat::GREEN . $this->startTime . str_repeat(" ", 3) : TextFormat::GREEN . "Waiting for players..." . str_repeat(" ", 3))); + \BedWars\utils\Scoreboard::setLine($player, 5, " " . ($this->starting || $this->isForcedStart() ? TextFormat::WHITE . "Starting in " . TextFormat::GREEN . $this->startTime . str_repeat(" ", 3) : TextFormat::GREEN . "Waiting for players..." . str_repeat(" ", 3))); \BedWars\utils\Scoreboard::setLine($player, 6, " "); \BedWars\utils\Scoreboard::setLine($player, 7, " " . TextFormat::WHITE . "Mode: " . TextFormat::GREEN . substr(str_repeat($this->playersPerTeam . "v", count($this->teams)), 0, -1) . str_repeat(" ", 3)); \BedWars\utils\Scoreboard::setLine($player, 8, " " . TextFormat::WHITE . "Version: " . TextFormat::GRAY . "v1.0" . str_repeat(" ", 3)); \BedWars\utils\Scoreboard::setLine($player, 9, " "); - \BedWars\utils\Scoreboard::setLine($player, 10, " " . TextFormat::YELLOW . "www.example.net"); + \BedWars\utils\Scoreboard::setLine($player, 10, " " . TextFormat::YELLOW . $this->plugin->serverWebsite); } break; @@ -773,7 +802,7 @@ public function tick() : void{ } \BedWars\utils\Scoreboard::setLine($player, " " . $currentLine, " "); $currentLine++; - \BedWars\utils\Scoreboard::setLine($player, " " . $currentLine, " " . TextFormat::YELLOW . "www.example.net"); + \BedWars\utils\Scoreboard::setLine($player, " " . $currentLine, " " . TextFormat::YELLOW . $this->plugin->serverWebsite); } @@ -811,11 +840,12 @@ public function tick() : void{ Scoreboard::new($player, 'bedwars', TextFormat::BOLD . TextFormat::YELLOW . "Bed Wars"); Scoreboard::setLine($player, 1, " "); Scoreboard::setLine($player, 2, "Winner team: " . TextFormat::GREEN . $this->winnerTeam->getName()); - Scoreboard::setLine($player, 3, "Thanks for playing!"); - Scoreboard::setLine($player, 4, " "); - Scoreboard::setLine($player, 5, "Restart in " . TextFormat::GREEN . $this->rebootTime); - Scoreboard::setLine($player, 6, " "); - Scoreboard::setLine($player, 7, " " . TextFormat::YELLOW . "www.example.net"); + Scoreboard::setLine($player, 3, " "); + Scoreboard::setLine($player, 4, "Thanks for playing!"); + Scoreboard::setLine($player, 5, " "); + Scoreboard::setLine($player, 6, "Restart in " . TextFormat::GREEN . $this->rebootTime); + Scoreboard::setLine($player, 7, " "); + Scoreboard::setLine($player, 8, " " . TextFormat::YELLOW . $this->plugin->serverWebsite); } diff --git a/src/BedWars/game/GameListener.php b/src/BedWars/game/GameListener.php index d5ac686..e4498ee 100644 --- a/src/BedWars/game/GameListener.php +++ b/src/BedWars/game/GameListener.php @@ -40,7 +40,9 @@ use pocketmine\entity\effect\VanillaEffects; use pocketmine\entity\effect\EffectInstance; use pocketmine\event\player\PlayerCommandPreprocessEvent; - +use pocketmine\event\player\PlayerDropItemEvent; +use pocketmine\item\enchantment\ItemFlags; +use pocketmine\item\ItemFactory; class GameListener implements Listener { @@ -69,6 +71,14 @@ public function onSignChange(SignChangeEvent $event) : void{ return; } $pos = $sign->getPosition(); + $pos_ = $pos->getX() . ":" . $pos->getY() . ":" . $pos->getZ() . ":" . $player->getWorld()->getFolderName(); + + foreach ($this->signs[$text->getLine(1)] as $key => $val){ + if($val == $pos_){ + return; + } + } + $this->plugin->createSign($text->getLine(1), $pos->getX(), $pos->getY(), $pos->getZ(), $player->getWorld()->getFolderName()); $player->sendMessage(BedWars::PREFIX . TextFormat::GREEN . "Sign created"); @@ -329,7 +339,7 @@ public function onBreak(BlockBreakEvent $event) : void if($teamName !== ""){ $teamObject = $game->teams[$name]; - if($name == $this->plugin->getPlayerTeam($player)->getName()){ + if($teamName == $this->plugin->getPlayerTeam($player)->getName()){ $player->sendMessage(TextFormat::RED . "You can't break your bed!"); $event->cancel(); return; @@ -347,6 +357,15 @@ public function onBreak(BlockBreakEvent $event) : void } } } + } else { + foreach ($this->plugin->games as $arena){ + if($arena->worldName == $player->getWorld()->getFolderName()){ + if(!isset($arena->getPlayers()[$player->getName()])){ + $event->cancel(); + return; + } + } + } } } @@ -386,8 +405,18 @@ public function onPlace(BlockPlaceEvent $event) : void{ } if($event->getBlock()->getId() == BlockLegacyIds::CHEST && !$isCancelled && $player->getInventory()->getItemInHand()->getCustomName() == TextFormat::AQUA . "Popup Tower"){ + $player->getInventory()->removeItem(ItemFactory::getInstance()->get(BlockLegacyIds::CHEST, 0, 1)); $event->cancel(); - new PopupTower($event->getBlock(), $playerGame, $player, $this->plugin->getPlayerTeam($player)); + (new PopupTower($event->getBlock(), $playerGame, $player, $this->plugin->getPlayerTeam($player))); + } + } + } else { + foreach ($this->plugin->games as $arena){ + if($arena->worldName == $player->getWorld()->getFolderName()){ + if(!isset($arena->getPlayers()[$player->getName()])){ + $event->cancel(); + return; + } } } } @@ -474,6 +503,16 @@ public function onCommandPreprocess(PlayerCommandPreprocessEvent $event) : void{ } } + public function onDrop(PlayerDropItemEvent $event){ + $player = $event->getPlayer(); + if(!$player instanceof Player) return; + if(($arena = $this->plugin->getPlayerGame($player)) !== null){ + if($arena->getState() == Game::STATE_LOBBY || $arena->getState() == Game::STATE_REBOOT){ + $event->cancel(); + } + } + } + /** diff --git a/src/BedWars/game/Generator.php b/src/BedWars/game/Generator.php index 82a8d63..2b8c6d2 100644 --- a/src/BedWars/game/Generator.php +++ b/src/BedWars/game/Generator.php @@ -97,12 +97,17 @@ public function __construct(int $itemID, int $repeatRate, Position $position, bo if($this->spawnBlock){ $path = BedWars::getInstance()->getDataFolder() . "/skins/" . $itemID . ".png"; $skin = Utils::getSkinFromFile($path, 'geometry.player_head', FakeItemEntity::GEOMETRY); - $position->add(0.5, 2.3, 0.5); - $fakeItem = new FakeItemEntity(new Location($position->getX() + 0.5, $position->getY() + 2.3, $position->getZ() + 0.5, $position->getWorld(), 0, 0), $skin); - $fakeItem->setScale(1.4); - $fakeItem->spawnToAll(); - $this->blockEntity = $fakeItem; + if($skin == null){ + BedWars::getInstance()->getLogger()->error("'" . $path . "' not exist!"); + } else { + $position->add(0.5, 2.3, 0.5); + $fakeItem = new FakeItemEntity(new Location($position->getX() + 0.5, $position->getY() + 2.3, $position->getZ() + 0.5, $position->getWorld(), 0, 0), $skin); + $fakeItem->setScale(1.4); + $fakeItem->spawnToAll(); + + $this->blockEntity = $fakeItem; + } } } diff --git a/src/BedWars/game/entity/BridgeEgg.php b/src/BedWars/game/entity/BridgeEgg.php index bb5e2e7..e01ed1a 100644 --- a/src/BedWars/game/entity/BridgeEgg.php +++ b/src/BedWars/game/entity/BridgeEgg.php @@ -19,6 +19,7 @@ use pocketmine\entity\Location; use BedWars\BedWars; +use BedWars\game\Game; use BedWars\game\Team; use BedWars\utils\Utils; @@ -59,11 +60,13 @@ protected function move(float $dx, float $dy, float $dz) : void{ parent::move($dx, $dy, $dz); return; } + $game = BedWars::getInstance()->getPlayerGame($this->getOwningEntity()); $team = BedWars::getInstance()->getPlayerTeam($this->getOwningEntity()); - if(!$team instanceof Team){ + if(!$team instanceof Team || !$game instanceof Game){ parent::move($dx, $dy, $dz); return; } + $world = $this->getWorld(); $pos = $this->getPosition(); $placePos = $pos->asVector3()->subtract(0, 1, 0); @@ -79,11 +82,18 @@ protected function move(float $dx, float $dy, float $dz) : void{ parent::move($dx, $dy, $dz); if($this->skippedFirst){ //simple skip for players position - $world->setBlock($placePos, BlockFactory::getInstance()->get(BlockLegacyIds::WOOL, Utils::colorIntoWool($team->getColor()))); - $world->setBlock($placePos->subtract(0, 0, 1), BlockFactory::getInstance()->get(BlockLegacyIds::WOOL, Utils::colorIntoWool($team->getColor()))); - $world->setBlock($placePos->subtract(1, 0, 0), BlockFactory::getInstance()->get(BlockLegacyIds::WOOL, Utils::colorIntoWool($team->getColor()))); - $world->setBlock($placePos->add(1, 0, 0), BlockFactory::getInstance()->get(BlockLegacyIds::WOOL, Utils::colorIntoWool($team->getColor()))); - $world->setBlock($placePos->add(0, 0, 1), BlockFactory::getInstance()->get(BlockLegacyIds::WOOL, Utils::colorIntoWool($team->getColor()))); + foreach ([ + $placePos, + $placePos->subtract(0, 0, 1), + $placePos->subtract(1, 0, 0), + $placePos->add(1, 0, 0), + $placePos->add(0, 0, 1) + ] as $pos){ + if($world->getBlock($pos)->getId() !== BlockLegacyIds::BED_BLOCK){ + $world->setBlock($pos, BlockFactory::getInstance()->get(BlockLegacyIds::WOOL, Utils::colorIntoWool($team->getColor()))); + $game->placedBlocks[] = Utils::vectorToString(":", $world->getBlock($pos)->getPosition()->asVector3()); + } + } } $this->skippedFirst = true; } diff --git a/src/BedWars/game/entity/FakeItemEntity.php b/src/BedWars/game/entity/FakeItemEntity.php index 350eefe..1696629 100644 --- a/src/BedWars/game/entity/FakeItemEntity.php +++ b/src/BedWars/game/entity/FakeItemEntity.php @@ -29,9 +29,12 @@ public function onUpdate(int $currentTick): bool if($this->getLocation()->yaw >= 360){ $this->getLocation()->yaw = 0; } - $this->getLocation()->yaw+=5.5; + + $this->getLocation()->yaw+=5.5; + $this->updateMovement(); $this->scheduleUpdate(); + //TODO: Add bouncing $this->move($this->motion->x, $this->motion->y, $this->motion->z); diff --git a/src/BedWars/utils/Utils.php b/src/BedWars/utils/Utils.php index ecc3ec0..f8a418b 100644 --- a/src/BedWars/utils/Utils.php +++ b/src/BedWars/utils/Utils.php @@ -15,13 +15,13 @@ class Utils { const WOOL_COLOR = [ - '§a' => 5, - '§c' => 14, - '§e' => 4, - '§6' => 1, - '§f' => 0, - '§b' => 3, - '§1' => 11 + TextFormat::GREEN => 5, + TextFormat::RED => 14, + TextFormat::YELLOW => 4, + TextFormat::GOLD => 1, + TextFormat::WHITE => 0, + TextFormat::AQUA => 3, + TextFormat::DARK_BLUE => 11 ]; public static function colorIntoWool(string $color) : int{ @@ -128,7 +128,8 @@ public static function rome($number){ * @return Skin|null */ public static function getSkinFromFile(string $path, $geometryName = null, $geometryData = null) : ?Skin{ - + if(!file_exists($path)) + return null; $img = @imagecreatefrompng($path); $bytes = ''; $l = (int) @getimagesize($path)[1];