Quickly make team deathmatch plugin with PMMP
#Foreword I will make a team death match quickly using the library The plugins you create should not interfere with any other plugins
Completed is here
Contents of the plugin to be created
Create a game with /create
and join with /join
The score increases with each kill, and when the set upper limit is reached or the time limit is exceeded, the game is over
Display timer on BossBar and match status on Scoreboard
#Install library The library used is team_game_system
with the dependency of team_game_system form_builder slot_menu_system will also be introduced.
Use scoreboard_system in scoreboard API Use bossbar_system in the bossbar API
Go to the plugins folder at the command prompt
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
This is OK
#Create project
Create a folder called TeamDeathMatch
.
name: TeamDeathMatch
main: TeamDeathMatch\Main
version: 1.0.0
api: 3.0.0
depend:
-TeamGameSystem
-FormBuilder
-SlotMenuSystem
Completion with # Composer Please see only those who want to complement with Composer
{
"name": "Your name/TeamDeathMatch",
"authors": [
{
"name": "your name"
}
],
"autoload": {
"psr-4": {
"": [
"src/"
]
}
},
"repositories": [
{
"type": "git",
"name": "suinua/form_builder",
"url": "https://github.com/MineDeepRock/form_builder"
},
{
"type": "git",
"name": "suinua/slot_menu_system",
"url": "https://github.com/MineDeepRock/slot_menu_system"
},
{
"type": "git",
"name": "suinua/scoreboard_system",
"url": "https://github.com/MineDeepRock/scoreboard_system"
},
{
"type": "git",
"name": "suinua/bossbar_system",
"url": "https://github.com/MineDeepRock/bossbar_system"
},
{
"type": "git",
"name": "suinua/team_game_system",
"url": "https://github.com/MineDeepRock/team_game_system"
}
],
"require": {
"pocketmine/pocketmine-mp": "3.14.2",
"suinua/form_builder": "dev-master",
"suinua/slot_menu_system": "dev-master",
"suinua/team_game_system": "dev-master",
"suinua/scoreboard_system": "dev-master",
"suinua/bossbar_system": "dev-master"
}
}
Write code
Creating the Main class
<?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);
}
}
Create a game from Form
Create a form to create a game
Create src/tdm/GameTypeList.php
as preparation
<?php
namespace tdm;
use team_game_system\model\GameType;
class GameTypeList
{
static function TeamDeathMatch(): GameType {
return new GameType("TeamDeathMatch");
}
}
Create 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;
public function __construct(TaskScheduler $scheduler) {
$this->scheduler = $scheduler;
$this->maxScore = new Input("Victory score", "", "20");
$this->maxPlayersCount = new Input("People limit", "", "");
$this->timeLimit = new Input("Time limit (seconds)", "", "300");
parent::__construct("", [
new Label ("Please leave blank if none"),
$this->maxScore,
$this->maxPlayersCount,
$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 :inttval($maxPlayersCount);
$timeLimit = $this->timeLimit->getResult();
$timeLimit = $timeLimit === "" ?null :intval($timeLimit);
//team
$teams = [
Team::asNew("Red", TextFormat::RED),
Team::asNew("Blue", TextFormat::BLUE),
];
// Select map (we will register the map in Minecraft later)
$map = TeamGameSystem::selectMap("city", $teams);
// create a game$game = Game::asNew(GameTypeList::TeamDeathMatch(), $map, $teams, $maxScore, $maxPlayersCount, $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 * 20);
}
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
を編集します
$player = $event->getPlayer();
$gameId = $event->getGameId();
$game = TeamGameSystem::getGame($event->getGameId());
//Do not process if it is related to games other than team deathmatch
if (!$game->getType()->equals(GameTypeList::TeamDeathMatch())) return;
$level = Server::getInstance()->getLevelByName("lobby");
foreach ($level->getPlayers() as $lobbyPlayer) {
$lobbyPlayer->sendMessage($player->getName() ." joined the team deathmatch");
}
// Join halfway
if ($game->isStarted()) {
$playerData = TeamGameSystem::getPlayerData($player);
//Set spawn point
TeamGameSystem::setSpawnPoint($player);
//Teleport
$player->teleport($player->getSpawn());
//notification
$player->sendTitle("Team Deathmatch Start");
$team = TeamGameSystem::getTeam($gameId, $playerData->getTeamId());
$player->sendMessage("You are". $team->getTeamColorFormat() .$team->getName() .TextFormat::RESET. "");
//Scoreboard set
TeamDeathMatchScoreBoard::send($player, $game);
// Set the boss bar
$bossBar = new BossBar($player, BossBarTypeList::TeamDeathMatch(), "TeamDeathMatch", 0);
$bossBar->send();
// set item
$player->getInventory()->setContents([
ItemFactory::get(ItemIds::WOODEN_SWORD, 0, 1),
ItemFactory::get(ItemIds::APPLE, 0, 10),
]);
}
}
Write the process at the start of the match
Edit src/tdm/Main.php
public function onStartedGame(StartedGameEvent $event) {
$gameId = $event->getGameId();
$game = TeamGameSystem::getGame($gameId);
//Do not process if it is related to games other than team deathmatch
if (!$game->getType()->equals(GameTypeList::TeamDeathMatch())) return;
$playersData = TeamGameSystem::getGamePlayersData($gameId);
foreach ($playersData as $playerData) {
$player = $this->getServer()->getPlayer($playerData->getName());
//Set spawn point
TeamGameSystem::setSpawnPoint($player);
//Teleport
$player->teleport($player->getSpawn());
//notification
$player->sendTitle("Team Deathmatch Start");
$team = TeamGameSystem::getTeam($gameId, $playerData->getTeamId());
$player->sendMessage("You are". $team->getTeamColorFormat() .$team->getName() .TextFormat::RESET. "");
//Scoreboard set
TeamDeathMatchScoreBoard::send($player, $game);
// Set the boss bar
$bossBar = new BossBar($player, BossBarTypeList::TeamDeathMatch(), "TeamDeathMatch", 0);
$bossBar->send();
// set item
$player->getInventory()->setContents([
ItemFactory::get(ItemIds::WOODEN_SWORD, 0, 1),
ItemFactory::get(ItemIds::APPLE, 0, 10),
]);
}
}
So that the score will be included when you defeat the opponent
edit src\tdm\Main.php
public function onPlayerKilledPlayer(PlayerKilledPlayerEvent $event): void {
$attacker = $event->getAttacker();
$attackerData = TeamGameSystem::getPlayerData($attacker);
//Do not process if it is related to games other than team deathmatch
$game = TeamGameSystem::getGame($attackerData->getGameId());
if (!$game->getType()->equals(GameTypeList::TeamDeathMatch())) return;
TeamGameSystem::addScore($attackerData->getGameId(), $attackerData->getTeamId(), new Score(1));
}
Update scoreboard when adding score
edit src\tdm\Main.php
public function onAddedScore(AddedScoreEvent $event): void {
$gameId = $event->getGameId();
$game = TeamGameSystem::getGame($gameId);
//Do not process if it is related to games other than team deathmatch
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);
}
}
Set items when respawning
edit src\tdm\Main.php
public function onRespawn(PlayerRespawnEvent $event) {
$player = $event->getPlayer();
$playerData = TeamGameSystem::getPlayerData($player);
if ($playerData->getGameId() === null) return;
//Do not process if it is related to games other than team deathmatch
$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),
]);
}
Erase the item drop on death
edit src\tdm\Main.php
public function onPlayerDeath(PlayerDeathEvent $event) {$player = $event->getPlayer();
$playerData = TeamGameSystem::getPlayerData($player);
if ($playerData->getGameId() === null) return;
//Do not process if it is related to games other than team deathmatch
$game = TeamGameSystem::getGame($playerData->getGameId());
if (!$game->getType()->equals(GameTypeList::TeamDeathMatch())) return;
$event->setDrops([]);
}
Update boss bar after match time
edit src\tdm\Main.php
public function onUpdatedGameTimer(UpdatedGameTimerEvent $event): void {
$gameId = $event->getGameId();
$game = TeamGameSystem::getGame($gameId);
//Do not process if it is related to games other than team deathmatch
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 there is no time limit
if ($timeLimit === null) {
$bossBar->updateTitle("Elapsed time:" .$elapsedTime);
continue;
}
$bossBar->updatePercentage($elapsedTime / $timeLimit);
$bossBar->updateTitle($elapsedTime ."/" .$timeLimit);
}
}
Send participants to the lobby after the match
edit 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 = "Draw";
} else {
$message = $wonTeam->getTeamColorFormat() .$wonTeam->getName() .TextFormat::RESET ."Win of!";
}
$playersData = $event->getPlayersData();
// send it back to lobby
$server = Server::getInstance();
$level = $server->getLevelByName("lobby");
foreach ($playersData as $playerData) {
$player = $server->getPlayer($playerData->getName());
// erase the scoreboard
TeamDeathMatchScoreboard::delete($player);
// erase the boss bar
$bossBar = BossBar::findByType($player, BossBarTypeList::TeamDeathMatch());
$bossBar->remove();
$player->getInventory()->setContents([]);
//Teleport
$player->teleport($level->getSpawnLocation());
//Send Messege
$player->sendMessage($message);
}
}
This completes the plugin Next we will set the map
Map settings
- First, teleport to the map you want to register
2, type the
/map
command 3, selectCreate
4, enter the map name and send 5, 2 additional spawn point groups (can be 0 and 1) Select 6,0 and register some spawn points 1 Do the same 7, the end
Change mapname
in line 54 of src\tdm\CreateTeamDeathMatchForm.php
to the registered map name
$map = TeamGameSystem::selectMap("city", $teams);
that’s all
Thank you
Bye