まえがき
ライブラリを使ってサーッとチームデスマッチつくります
作成するプラグインは、他のプラグインに一切干渉しないようにしています
完成品 はここに
作成するプラグインの内容
/create
でゲームを作成し、/join
で参加
1キルごとにスコアが増えていき、設定した上限に達するか制限時間を超えたら、試合終了というもの
BossBarでタイマーを、Scoreboardで試合の状況を表示します
ライブラリのインストール
使用するライブラリはteam_game_system
team_game_systemの依存関係で
form_builder
slot_menu_system も導入します。
スコアボードのAPIで scoreboard_system を使用します
ボスバーのAPIで bossbar_system を使用します
コマンドプロンプトでpluginsフォルダに移動して
git clone https://github.com/MineDeepRock/team_game_system
git clone https://github.com/MineDeepRock/form_builder
git clone https://github.com/MineDeepRock/slot_menu_system
git clone https://github.com/MineDeepRock/scoreboard_system
git clone https://github.com/MineDeepRock/bossbar_system
これでOK
プロジェクトの作成
TeamDeathMatch
というフォルダを作成します。
name: TeamDeathMatch
main: TeamDeathMatch\Main
version: 1.0.0
api: 3.0.0
depend:
- TeamGameSystem
- FormBuilder
- SlotMenuSystem
Composerでの補完
Composerで補完したい人だけ見てください
{
"name": "あなたの名前/TeamDeathMatch",
"authors": [
{
"name": "あなたの名前"
}
],
"autoload": {
"psr-4": {
"": [
"src/"
]
}
},
"repositories": [
{
"type": "git",
"name": "mine_deep_rock/form_builder",
"url": "https://github.com/MineDeepRock/form_builder"
},
{
"type": "git",
"name": "mine_deep_rock/slot_menu_system",
"url": "https://github.com/MineDeepRock/slot_menu_system"
},
{
"type": "git",
"name": "mine_deep_rock/scoreboard_system",
"url": "https://github.com/MineDeepRock/scoreboard_system"
},
{
"type": "git",
"name": "mine_deep_rock/bossbar_system",
"url": "https://github.com/MineDeepRock/bossbar_system"
},
{
"type": "git",
"name": "mine_deep_rock/team_game_system",
"url": "https://github.com/MineDeepRock/team_game_system"
}
],
"require": {
"pocketmine/pocketmine-mp": "3.14.2",
"mine_deep_rock/form_builder": "dev-master",
"mine_deep_rock/slot_menu_system": "dev-master",
"mine_deep_rock/team_game_system": "dev-master",
"mine_deep_rock/scoreboard_system": "dev-master",
"mine_deep_rock/bossbar_system": "dev-master"
}
}
コードを書く
Mainクラスの作成
<?php
namespace tdm;
use pocketmine\event\Listener;
use pocketmine\plugin\PluginBase;
class Main extends PluginBase implements Listener
{
public function onEnable() {
$this->getServer()->getPluginManager()->registerEvents($this, $this);
}
}
Formからゲームを作成する
ゲームを作成するフォームを作ります
下準備としてsrc/tdm/GameTypeList.php
を作成します
<?php
namespace tdm;
use team_game_system\model\GameType;
class GameTypeList
{
static function TeamDeathMatch(): GameType {
return new GameType("TeamDeathMatch");
}
}
src\tdm\CreateTeamDeathMatchForm
を作成します
<?php
namespace tdm;
use form_builder\models\custom_form_elements\Input;
use form_builder\models\custom_form_elements\Label;
use form_builder\models\CustomForm;
use pocketmine\Player;
use pocketmine\scheduler\ClosureTask;
use pocketmine\scheduler\TaskScheduler;
use pocketmine\utils\TextFormat;
use team_game_system\model\Game;
use team_game_system\model\Score;
use team_game_system\model\Team;
use team_game_system\TeamGameSystem;
class CreateTeamDeathMatchForm extends CustomForm
{
private $scheduler;
private $timeLimit;
private $maxPlayersCount;
private $maxScore;
private $maxPlayersDifference;
public function __construct(TaskScheduler $scheduler) {
$this->scheduler = $scheduler;
$this->maxScore = new Input("勝利判定スコア", "", "20");
$this->maxPlayersCount = new Input("人数制限", "", "");
$this->maxPlayersDifference = new Input("人数差制限", "", "1");
$this->timeLimit = new Input("制限時間(秒)", "", "300");
parent::__construct("", [
new Label("無い場合は空白でお願いします"),
$this->maxScore,
$this->maxPlayersCount,
$this->maxPlayersDifference,
$this->timeLimit,
]);
}
function onSubmit(Player $player): void {
$maxScore = $this->maxScore->getResult();
$maxScore = $maxScore === "" ? null : new Score(intval($maxScore));
$maxPlayersCount = $this->maxPlayersCount->getResult();
$maxPlayersCount = $maxPlayersCount === "" ? null : intval($maxPlayersCount);
$maxPlayersDifference = $this->maxPlayersDifference->getResult();
$maxPlayersDifference = $maxPlayersDifference === "" ? null : intval($maxPlayersDifference);
$timeLimit = $this->timeLimit->getResult();
$timeLimit = $timeLimit === "" ? null : intval($timeLimit);
//チーム
$teams = [
Team::asNew("Red", TextFormat::RED),
Team::asNew("Blue", TextFormat::BLUE),
];
//マップを選択(あとからMinecraft内でマップを登録します)
$map = TeamGameSystem::selectMap("city", $teams);
//ゲームを作成
$game = Game::asNew(GameTypeList::TeamDeathMatch(), $map, $teams);
$game->setMaxScore($maxScore);
$game->setMaxPlayersCount($maxPlayersCount);
$game->setMaxPlayersDifference($maxPlayersDifference);
$game->setTimeLimit($timeLimit);
//ゲームを登録
TeamGameSystem::registerGame($game);
//試合がひらかれてから20秒後にスタートされるように
$gameId = $game->getId();
$this->scheduler->scheduleDelayedTask(new ClosureTask(function (int $tick) use ($gameId): void {
TeamGameSystem::startGame($this->scheduler, $gameId);
}), 20 * 5);
}
function onClickCloseButton(Player $player): void { }
}
Formからゲームに参加する
<?php
namespace tdm;
use form_builder\models\simple_form_elements\SimpleFormButton;
use form_builder\models\SimpleForm;
use pocketmine\Player;
use pocketmine\utils\TextFormat;
use team_game_system\TeamGameSystem;
class TeamDeathMatchListForm extends SimpleForm
{
public function __construct() {
$buttons = [];
foreach (TeamGameSystem::findGamesByType(GameTypeList::TeamDeathMatch()) as $game) {
$gameId = $game->getId();
$map = $game->getMap();
$maxScore = $game->getMaxScore() === null ? "無し" : $game->getMaxScore()->getValue();
$timeLimit = $game->getTimeLimit() === null ? "無し" : $game->getTimeLimit() . "秒";
$participantsCount = count(TeamGameSystem::getGamePlayersData($gameId));
$participants = $game->getMaxPlayersCount() === null ? $participantsCount : "{$participantsCount}/{$game->getMaxPlayersCount()}";
$buttons[] = new SimpleFormButton(
"ゲームモード:" . TextFormat::BOLD . strval($game->getType()) . TextFormat::RESET .
",マップ:" . TextFormat::BOLD . $map->getName() . TextFormat::RESET .
"\n勝利判定:" . TextFormat::BOLD . $maxScore . TextFormat::RESET .
",時間制限:" . TextFormat::BOLD . $timeLimit . TextFormat::RESET .
",参加人数:" . TextFormat::BOLD . $participants . TextFormat::RESET,
null,
function (Player $player) use ($gameId) {
TeamGameSystem::joinGame($player, $gameId);
}
);
}
parent::__construct("チームデスマッチ一覧", "", $buttons);
}
function onClickCloseButton(Player $player): void { }
}
コマンドからフォームを呼び出す
plugin.yml
に以下を付け足します
commands:
create:
usage: "/create"
description: ""
join:
usage: "/join"
description: ""
src/tdm/Main.php
を編集します
<?php
namespace tdm;
use pocketmine\command\Command;
use pocketmine\command\CommandSender;
use pocketmine\event\Listener;
use pocketmine\Player;
use pocketmine\plugin\PluginBase;
class Main extends PluginBase implements Listener
{
public function onCommand(CommandSender $sender, Command $command, string $label, array $args): bool {
if ($sender instanceof Player) {
switch ($label) {
case "create":
$sender->sendForm(new CreateTeamDeathMatchForm($this->getScheduler()));
return true;
case "join":
$sender->sendForm(new TeamDeathMatchListForm());
return true;
}
}
return false;
}
}
スコアボードの作成
src\tdm\TeamDeathMatchScoreboard.php
を作成します
<?php
namespace tdm;
use pocketmine\Player;
use scoreboard_system\models\Score;
use scoreboard_system\models\Scoreboard;
use scoreboard_system\models\ScoreboardSlot;
use scoreboard_system\models\ScoreSortType;
use team_game_system\model\Game;
class TeamDeathMatchScoreboard extends Scoreboard
{
private static function create(Game $game): Scoreboard {
$slot = ScoreboardSlot::sideBar();
$scores = [
new Score($slot, "====TeamDeathMatch====", 0, 0),
new Score($slot, "Map:" . $game->getMap()->getName(), 1, 1),
];
$index = count($scores);
foreach ($game->getTeams() as $team) {
$scores[] = new Score($slot, $team->getTeamColorFormat() . $team->getName() . ":" . $team->getScore()->getValue(), $index, $index);
$index++;
}
return parent::__create($slot, "Server Name", $scores, ScoreSortType::smallToLarge());
}
static function send(Player $player, Game $game) {
$scoreboard = self::create($game);
parent::__send($player, $scoreboard);
}
static function update(Player $player, Game $game) {
$scoreboard = self::create($game);
parent::__update($player, $scoreboard);
}
}
ボスバーの下準備
src\tdm\BossBarTypeList.php
を作成します
<?php
namespace tdm;
use bossbar_system\model\BossBarType;
class BossBarTypeList
{
static function TeamDeathMatch(): BossBarType {
return new BossBarType("TeamDeathMatch");
}
}
ゲーム参加時にロビーにいた人に知らせる&途中参加の処理を書く
src\tdm\Main.php
を編集します
public function onJoinGame(PlayerJoinedGameEvent $event) {
$player = $event->getPlayer();
$gameId = $event->getGameId();
$game = TeamGameSystem::getGame($event->getGameId());
//チームデスマッチ以外のゲームに関するものだったら処理を行わない
if (!$game->getType()->equals(GameTypeList::TeamDeathMatch())) return;
$level = Server::getInstance()->getLevelByName("lobby");
foreach ($level->getPlayers() as $lobbyPlayer) {
$lobbyPlayer->sendMessage($player->getName() . "がチームデスマッチに参加しました");
}
//途中参加
if ($game->isStarted()) {
$playerData = TeamGameSystem::getPlayerData($player);
//スポーン地点をセット
TeamGameSystem::setSpawnPoint($player);
//テレポート
$player->teleport($player->getSpawn());
//通知
$player->sendTitle("チームデスマッチ スタート");
$team = TeamGameSystem::getTeam($gameId, $playerData->getTeamId());
$player->sendMessage("あなたは" . $team->getTeamColorFormat() . $team->getName() . TextFormat::RESET . "です");
//Scoreboardのセット
TeamDeathMatchScoreBoard::send($player, $game);
//ボスバーをセット
$bossBar = new BossBar($player, BossBarTypeList::TeamDeathMatch(), "TeamDeathMatch", 0);
$bossBar->send();
//アイテムをセット
$player->getInventory()->setContents([
ItemFactory::get(ItemIds::WOODEN_SWORD, 0, 1),
ItemFactory::get(ItemIds::APPLE, 0, 10),
]);
}
}
試合開始時の処理を書く
src/tdm/Main.php
を編集します
public function onStartedGame(StartedGameEvent $event) {
$gameId = $event->getGameId();
$game = TeamGameSystem::getGame($gameId);
//チームデスマッチ以外のゲームに関するものだったら処理を行わない
if (!$game->getType()->equals(GameTypeList::TeamDeathMatch())) return;
$playersData = TeamGameSystem::getGamePlayersData($gameId);
foreach ($playersData as $playerData) {
$player = $this->getServer()->getPlayer($playerData->getName());
//スポーン地点をセット
TeamGameSystem::setSpawnPoint($player);
//テレポート
$player->teleport($player->getSpawn());
//通知
$player->sendTitle("チームデスマッチ スタート");
$team = TeamGameSystem::getTeam($gameId, $playerData->getTeamId());
$player->sendMessage("あなたは" . $team->getTeamColorFormat() . $team->getName() . TextFormat::RESET . "です");
//Scoreboardのセット
TeamDeathMatchScoreBoard::send($player, $game);
//ボスバーをセット
$bossBar = new BossBar($player, BossBarTypeList::TeamDeathMatch(), "TeamDeathMatch", 0);
$bossBar->send();
//アイテムをセット
$player->getInventory()->setContents([
ItemFactory::get(ItemIds::WOODEN_SWORD, 0, 1),
ItemFactory::get(ItemIds::APPLE, 0, 10),
]);
}
}
相手を倒したときにスコアが入るように
src\tdm\Main.php
を編集します
public function onPlayerKilledPlayer(PlayerKilledPlayerEvent $event): void {
$attacker = $event->getAttacker();
$attackerData = TeamGameSystem::getPlayerData($attacker);
//チームデスマッチ以外のゲームに関するものだったら処理を行わない
$game = TeamGameSystem::getGame($attackerData->getGameId());
if (!$game->getType()->equals(GameTypeList::TeamDeathMatch())) return;
TeamGameSystem::addScore($attackerData->getGameId(), $attackerData->getTeamId(), new Score(1));
}
スコア追加時にスコアボードを更新するように
src\tdm\Main.php
を編集します
public function onAddedScore(AddedScoreEvent $event): void {
$gameId = $event->getGameId();
$game = TeamGameSystem::getGame($gameId);
//チームデスマッチ以外のゲームに関するものだったら処理を行わない
if (!$game->getType()->equals(GameTypeList::TeamDeathMatch())) return;
$playersData = TeamGameSystem::getGamePlayersData($gameId);
foreach ($playersData as $playerData) {
$player = $this->getServer()->getPlayer($playerData->getName());
TeamDeathMatchScoreBoard::update($player, $game);
}
}
リスポーン時にアイテムをセットする
src\tdm\Main.php
を編集します
public function onRespawn(PlayerRespawnEvent $event) {
$player = $event->getPlayer();
$playerData = TeamGameSystem::getPlayerData($player);
if ($playerData->getGameId() === null) return;
//チームデスマッチ以外のゲームに関するものだったら処理を行わない
$game = TeamGameSystem::getGame($playerData->getGameId());
if (!$game->getType()->equals(GameTypeList::TeamDeathMatch())) return;
$player->getInventory()->setContents([
ItemFactory::get(ItemIds::WOODEN_SWORD, 0, 1),
ItemFactory::get(ItemIds::APPLE, 0, 10),
]);
}
死亡時のアイテムドロップを消す
src\tdm\Main.php
を編集します
public function onPlayerDeath(PlayerDeathEvent $event) {
$player = $event->getPlayer();
$playerData = TeamGameSystem::getPlayerData($player);
if ($playerData->getGameId() === null) return;
//チームデスマッチ以外のゲームに関するものだったら処理を行わない
$game = TeamGameSystem::getGame($playerData->getGameId());
if (!$game->getType()->equals(GameTypeList::TeamDeathMatch())) return;
$event->setDrops([]);
}
試合時間経過時にボスバーを更新する
src\tdm\Main.php
を編集します
public function onUpdatedGameTimer(UpdatedGameTimerEvent $event): void {
$gameId = $event->getGameId();
$game = TeamGameSystem::getGame($gameId);
//チームデスマッチ以外のゲームに関するものだったら処理を行わない
if (!$game->getType()->equals(GameTypeList::TeamDeathMatch())) return;
$playersData = TeamGameSystem::getGamePlayersData($gameId);
$timeLimit = $event->getTimeLimit();
$elapsedTime = $event->getElapsedTime();
foreach ($playersData as $playerData) {
$player = Server::getInstance()->getPlayer($playerData->getName());
$bossBar = BossBar::findByType($player, BossBarTypeList::TeamDeathMatch());
//制限時間がなかったら
if ($timeLimit === null) {
$bossBar->updateTitle("経過時間:" . $elapsedTime);
continue;
}
$bossBar->updatePercentage($elapsedTime / $timeLimit);
$bossBar->updateTitle($elapsedTime . "/" . $timeLimit);
}
}
試合終了後に参加者をロビーに送る
src\tdm\Main.php
を編集します
public function onFinishedGame(FinishedGameEvent $event): void {
$game = $event->getGame();
if (!$game->getType()->equals(GameTypeList::TeamDeathMatch())) return;
$wonTeam = $event->getWonTeam();
if ($wonTeam === null) {
$message = "引き分け";
} else {
$message = $wonTeam->getTeamColorFormat() . $wonTeam->getName() . TextFormat::RESET . "の勝利!";
}
$playersData = $event->getPlayersData();
//lobbyに送り返す
$server = Server::getInstance();
$level = $server->getLevelByName("lobby");
foreach ($playersData as $playerData) {
$player = $server->getPlayer($playerData->getName());
//スコアボードを消す
TeamDeathMatchScoreboard::delete($player);
//ボスバーを消す
$bossBar = BossBar::findByType($player, BossBarTypeList::TeamDeathMatch());
$bossBar->remove();
$player->getInventory()->setContents([]);
//テレポート
$player->teleport($level->getSpawnLocation());
//メッセージ送信
$player->sendMessage($message);
}
}
以上でプラグインは完成です
次はマップの設定を行っていきます
Mapの設定
1,まず登録したいマップにテレポートします
2,/map
コマンドを打ちます
3,Create
を選択
4,マップ名を入力し送信
5,スポーン地点グループを2つ追加(0と1ができる)
6,0を選択しいくつかスポーン地点を登録 1も同様に行う
7,終わり
src\tdm\CreateTeamDeathMatchForm.php
の54行目のmapname
を登録したマップ名に変更
$map = TeamGameSystem::selectMap("city", $teams);
以上
お疲れさまでした
ばいばい