├── README.md ├── resources ├── athletic_position.json ├── config.yml ├── WEBHOOK_URL.sample └── skins │ ├── MazaiNPC │ └── GameMaster ├── CONTRIBUTING.md ├── .gitignore ├── src └── Core │ ├── Game │ ├── Game.php │ ├── Duel │ │ ├── stages │ │ │ └── Stage1.php │ │ └── DuelCore.php │ ├── FFAPvP │ │ └── FFAPvPCore.php │ ├── Athletic │ │ └── AthleticCore.php │ └── Survival │ │ └── SurvivalCore.php │ ├── Commands │ ├── MessagesEnum.php │ ├── SetMoneyCommand.php │ ├── PingCommand.php │ ├── DebugCommand.php │ ├── AddTagCommand.php │ ├── GameStatusCommand.php │ ├── KillSoundCommand.php │ ├── SetTagCommand.php │ ├── RankShopCommand.php │ ├── StatusCommand.php │ └── SelectGameCommand.php │ ├── Event │ ├── PlayerMove.php │ ├── PlayerRespawn.php │ ├── EntityShootBow.php │ ├── EntityInventoryChange.php │ ├── PlayerExhaust.php │ ├── BlockBreak.php │ ├── PlayerInteract.php │ ├── BlockPlace.php │ ├── PlayerPreLogin.php │ ├── PlayerQuit.php │ ├── EntityDamage.php │ ├── PlayerJoin.php │ ├── PlayerCommandPreprocess.php │ ├── PlayerLogin.php │ └── PlayerDeath.php │ ├── Task │ ├── RemoveArmorTask.php │ ├── PluginTask.php │ ├── RemoveItemTask.php │ ├── LevelCheckingTask.php │ ├── AutoSavingTask.php │ ├── AutosetBlockTask.php │ ├── Teleport │ │ ├── TeleportDuelStageTask.php │ │ ├── TeleportSurvivalSpawnTask.php │ │ ├── TeleportSpeedCorePvPTask.php │ │ ├── TeleportDuelTask.php │ │ ├── TeleportSurvivalTask.php │ │ ├── TeleportLobbyTask.php │ │ ├── TeleportAthleticTask.php │ │ └── TeleportFFAPvPTask.php │ ├── MOTDTip.php │ ├── JoinTitle.php │ └── Tip.php │ ├── Player │ ├── MazaiPoint.php │ ├── Money.php │ ├── Rank.php │ ├── KD.php │ ├── Tag.php │ ├── KillSound.php │ └── Level.php │ ├── Entity │ ├── Mazai.php │ ├── MazaiMaster.php │ ├── EntityBase.php │ ├── Bossbar.php │ └── GameMaster.php │ ├── DataFile.php │ ├── Main.php │ └── EventListener.php ├── .poggit.yml ├── .github └── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── .editorconfig ├── plugin.yml ├── LICENSE └── composer.json /README.md: -------------------------------------------------------------------------------- 1 | # 新しく作り直します。 2 | -------------------------------------------------------------------------------- /resources/athletic_position.json: -------------------------------------------------------------------------------- 1 | { 2 | 3 | } -------------------------------------------------------------------------------- /resources/config.yml: -------------------------------------------------------------------------------- 1 | #config.yml 2 | 3 | #test: true -------------------------------------------------------------------------------- /resources/WEBHOOK_URL.sample: -------------------------------------------------------------------------------- 1 | https://discordapp.com/api/webhooks/123456789/fgaenguiobl -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Issueする場合は細かく書いて下さい 2 | 1. タイトルは分かりやすく書きましょう 3 | 1. 一つのIssueに複数の問題を書くのはやめて下さい 4 | 1. 使用しているOS、phpバージョン、 PocketMine-MPバージョンも書いて下さい 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # JetBrains IDE 2 | /.idea/* 3 | 4 | # Composer 5 | /vendor/* 6 | composer.phar 7 | composer.lock 8 | 9 | # Config 10 | resources/WEBHOOK_URL -------------------------------------------------------------------------------- /src/Core/Game/Game.php: -------------------------------------------------------------------------------- 1 | plugin = $plugin; 22 | } 23 | 24 | public function event(PlayerMoveEvent $event): void 25 | { 26 | // なにもしない 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Core/Event/PlayerRespawn.php: -------------------------------------------------------------------------------- 1 | plugin = $plugin; 22 | } 23 | 24 | public function event(PlayerRespawnEvent $event): void 25 | { 26 | // なにもしない 27 | } 28 | } -------------------------------------------------------------------------------- /src/Core/Event/EntityShootBow.php: -------------------------------------------------------------------------------- 1 | plugin = $plugin; 23 | } 24 | 25 | public function event(EntityShootBowEvent $event): void 26 | { 27 | $event->setForce($event->getForce() + 0.5); 28 | } 29 | } -------------------------------------------------------------------------------- /src/Core/Event/EntityInventoryChange.php: -------------------------------------------------------------------------------- 1 | plugin = $plugin; 23 | } 24 | 25 | public function event(EntityInventoryChangeEvent $event): void 26 | { 27 | 28 | } 29 | } -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | 5 | --- 6 | 7 | **Is your feature request related to a problem? Please describe.** 8 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 9 | 10 | **Describe the solution you'd like** 11 | A clear and concise description of what you want to happen. 12 | 13 | **Describe alternatives you've considered** 14 | A clear and concise description of any alternative solutions or features you've considered. 15 | 16 | **Additional context** 17 | Add any other context or screenshots about the feature request here. 18 | -------------------------------------------------------------------------------- /src/Core/Event/PlayerExhaust.php: -------------------------------------------------------------------------------- 1 | plugin = $plugin; 22 | } 23 | 24 | public function event(PlayerExhaustEvent $event): void 25 | { 26 | if ($event->getPlayer()->getLevel()->getName() === 'lobby') { 27 | $event->setCancelled(true); 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /src/Core/Task/RemoveArmorTask.php: -------------------------------------------------------------------------------- 1 | player = $player; 23 | } 24 | 25 | public function onRun(int $currentTick) 26 | { 27 | $this->player->getArmorInventory()->clearAll(true); 28 | $this->player->getInventory()->clearAll(true); 29 | } 30 | } -------------------------------------------------------------------------------- /src/Core/Task/PluginTask.php: -------------------------------------------------------------------------------- 1 | owner = $plugin; 26 | } 27 | 28 | /** 29 | * @return Plugin 30 | */ 31 | final public function getOwner(): Plugin 32 | { 33 | return $this->owner; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Core/Task/RemoveItemTask.php: -------------------------------------------------------------------------------- 1 | owner->getServer()->getLevelByName("corepvp")->getEntities() as $entity) { 25 | if ($entity instanceof ItemEntity) { 26 | $entity->kill(); 27 | } 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /src/Core/Task/LevelCheckingTask.php: -------------------------------------------------------------------------------- 1 | level = new Level(); 24 | $this->player = $player; 25 | } 26 | 27 | public function onRun(int $currentTick) 28 | { 29 | $this->level->Checking($this->player); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Core/Task/AutoSavingTask.php: -------------------------------------------------------------------------------- 1 | owner->getServer()->getLevelByName("ffapvp")->save(true); 23 | $this->owner->getServer()->getLevelByName("lobby")->save(true); 24 | $this->owner->getServer()->getLevelByName("Survival")->save(true); 25 | $this->owner->getServer()->getLevelByName("duel")->save(true); 26 | } 27 | } -------------------------------------------------------------------------------- /src/Core/Task/AutosetBlockTask.php: -------------------------------------------------------------------------------- 1 | block = $block; 23 | } 24 | public function onRun(int $currentTick) 25 | { 26 | $this->block->getLevel()->setBlock(new Position($this->block->getX(), $this->block->getY(), $this->block->getZ(), $this->block->getLevel()), $this->block); 27 | } 28 | } -------------------------------------------------------------------------------- /src/Core/Task/Teleport/TeleportDuelStageTask.php: -------------------------------------------------------------------------------- 1 | game = $game; 24 | $this->gameId = $gameId; 25 | } 26 | public function onRun(int $currentTick) 27 | { 28 | $this->game->startGame($this->gameId, $currentTick); 29 | } 30 | } -------------------------------------------------------------------------------- /src/Core/Event/BlockBreak.php: -------------------------------------------------------------------------------- 1 | plugin = $plugin; 26 | // TODO: Rewrite 27 | $this->survival = new SurvivalCore($this->plugin); 28 | } 29 | 30 | public function event(BlockBreakEvent $event): void 31 | { 32 | $this->survival->AddBreakCount($event->getPlayer()); 33 | } 34 | } -------------------------------------------------------------------------------- /src/Core/Event/PlayerInteract.php: -------------------------------------------------------------------------------- 1 | plugin = $plugin; 24 | $this->ffapvp = new FFAPvPCore($this->plugin); 25 | } 26 | 27 | public function event(PlayerInteractEvent $event): void 28 | { 29 | $player = $event->getPlayer(); 30 | $block = $event->getBlock(); 31 | $this->ffapvp->FFAPvPKit($player, $block); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Core/Event/BlockPlace.php: -------------------------------------------------------------------------------- 1 | plugin = $plugin; 26 | // TODO: Rewrite 27 | $this->survival = new SurvivalCore($this->plugin); 28 | } 29 | 30 | public function event(BlockPlaceEvent $event): void 31 | { 32 | $this->survival->AddPlaceCount($event->getPlayer()); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /plugin.yml: -------------------------------------------------------------------------------- 1 | name: Games_Core 2 | main: Core\Main 3 | api: 4.0.0 4 | version: 3.0.0 5 | author: VectorNetworkDevelopmentTeam 6 | authors: 7 | - InkoHX 8 | - MazaiCrafty 9 | - yuko fuyutsuki 10 | - DusKong 11 | permissions: 12 | vnp.command.ping: 13 | default: true 14 | vnp.command.stats: 15 | default: true 16 | vnp.command.rankshop: 17 | default: true 18 | vnp.command.setmoney: 19 | default: op 20 | vnp.command.settag: 21 | default: op 22 | vnp.command.selectgame: 23 | default: true 24 | vnp.command.debug: 25 | default: op 26 | vnp.command.killsound: 27 | default: true 28 | vnp.command.addtag: 29 | default: op 30 | vnp.command.gamestatus: 31 | default: true 32 | vector.network.player: 33 | default: true 34 | vector.network.admin: 35 | default: op -------------------------------------------------------------------------------- /src/Core/Task/Teleport/TeleportSurvivalSpawnTask.php: -------------------------------------------------------------------------------- 1 | teleport(new Position(self::$x, self::$y, self::$z, Main::$instance->getServer()->getLevelByName('Survival'))); 34 | } 35 | } -------------------------------------------------------------------------------- /src/Core/Event/PlayerPreLogin.php: -------------------------------------------------------------------------------- 1 | plugin = $plugin; 22 | } 23 | 24 | public function event(PlayerPreLoginEvent $event): void 25 | { 26 | $player = $event->getPlayer(); 27 | if ($this->plugin->getServer()->hasWhitelist()) { 28 | if (!$this->plugin->getServer()->isWhitelisted(strtolower($player->getName()))) { 29 | $player->close($player->getLeaveMessage(), " §6Vector §bNetwork\n§7現在ホワイトリストです。\n§7詳しい情報はLobiまたはDiscordから得ることができます。\n§7Discord: https://hxbot.tk/VNP-D\n§7Lobi: https://hxbot.tk/VNP-L"); 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Core/Event/PlayerQuit.php: -------------------------------------------------------------------------------- 1 | plugin = $plugin; 24 | } 25 | 26 | public function event(PlayerQuitEvent $event): void 27 | { 28 | $player = $event->getPlayer(); 29 | $name = $player->getName(); 30 | //$event->setQuitMessage("§b[§c退出§b] §7$name が退出しました。"); 31 | $event->setQuitMessage(null); 32 | $bossbar = new Bossbar(); 33 | $bossbar->RemoveBar($player); 34 | $data = new DataFile($player->getName()); 35 | $user = $data->get("USERDATA"); 36 | $user["lastlogin"] = date("Y年m月d日 H時i分s秒"); 37 | $data->write("USERDATA", $user); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Core/Task/Teleport/TeleportSpeedCorePvPTask.php: -------------------------------------------------------------------------------- 1 | player = $player; 25 | } 26 | 27 | public function onRun(int $currentTick) 28 | { 29 | $level = $this->owner->getServer()->getLevelByName("corepvp"); 30 | $this->player->teleport(new Position(255, 8, 257, $level)); 31 | $this->player->setHealth(20); 32 | $this->player->setMaxHealth(20); 33 | $this->player->setFood(20); 34 | $this->player->getArmorInventory()->clearAll(true); 35 | $this->player->removeAllEffects(); 36 | $this->player->getInventory()->clearAll(true); 37 | $this->player->sendMessage("§aテレポートしました。"); 38 | } 39 | } -------------------------------------------------------------------------------- /src/Core/Task/MOTDTip.php: -------------------------------------------------------------------------------- 1 | owner->getServer()->getNetwork()->setName("§l§6>§e>§6> §a3GAMES §6<§e<§6<§7"); 27 | break; 28 | case 2: 29 | $this->owner->getServer()->getNetwork()->setName("§l§6>§e>§6> §aSURVIVAL §6<§e<§6<§7"); 30 | break; 31 | case 3: 32 | $this->owner->getServer()->getNetwork()->setName("§l§6>§e>§6> §bSpeed§aCore§cPvP §6<§e<§6<§7"); 33 | break; 34 | case 4: 35 | $this->owner->getServer()->getNetwork()->setName("§l§6>§e>§6> §6FFA§cPvP §6<§e<§6<§7"); 36 | break; 37 | default: 38 | $this->owner->getServer()->getNetwork()->setName("§l§6Vector §bNetwork §eProject§7"); 39 | break; 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 VectorNetworkProject 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/Core/Task/Teleport/TeleportDuelTask.php: -------------------------------------------------------------------------------- 1 | player = $player; 24 | } 25 | 26 | public function onRun(int $currentTick) 27 | { 28 | $this->player->teleport(new Position(254, 4, 254, $this->owner->getServer()->getLevelByName("duel"))); 29 | $this->player->setSpawn(new Position(254, 4, 254, $this->owner->getServer()->getLevelByName("duel"))); 30 | $this->player->setHealth(20); 31 | $this->player->getArmorInventory()->clearAll(true); 32 | $this->player->setMaxHealth(20); 33 | $this->player->setFood(20); 34 | $this->player->removeAllEffects(); 35 | $this->player->getInventory()->clearAll(true); 36 | $this->player->sendMessage("§aテレポートしました。"); 37 | } 38 | } -------------------------------------------------------------------------------- /src/Core/Task/Teleport/TeleportSurvivalTask.php: -------------------------------------------------------------------------------- 1 | player = $player; 26 | } 27 | 28 | public function onRun(int $currentTick) 29 | { 30 | $level = $this->owner->getServer()->getLevelByName("Survival"); 31 | SurvivalCore::Teleport($this->player); 32 | $this->player->setSpawn(new Position(225, 243, 256, $level)); 33 | $this->player->setHealth(20); 34 | $this->player->setMaxHealth(20); 35 | $this->player->setFood(20); 36 | $this->player->getArmorInventory()->clearAll(true); 37 | $this->player->removeAllEffects(); 38 | $this->player->getInventory()->clearAll(true); 39 | $this->player->sendMessage("§aテレポートしました。"); 40 | } 41 | } -------------------------------------------------------------------------------- /src/Core/Task/Teleport/TeleportLobbyTask.php: -------------------------------------------------------------------------------- 1 | plugin = $plugin; 24 | $this->player = $player; 25 | } 26 | 27 | public function onRun(int $currentTick) 28 | { 29 | $level = $this->owner->getServer()->getLevelByName("lobby"); 30 | $this->player->teleport(new Position(257, 8, 257, $level)); 31 | $this->player->setSpawn(new Position(257, 8, 257, $level)); 32 | $this->player->setHealth(20); 33 | $this->player->getArmorInventory()->clearAll(true); 34 | $this->player->setMaxHealth(20); 35 | $this->player->setFood(20); 36 | $this->player->removeAllEffects(); 37 | $this->player->getInventory()->clearAll(true); 38 | $this->player->sendMessage("§aテレポートしました。"); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Core/Task/Teleport/TeleportAthleticTask.php: -------------------------------------------------------------------------------- 1 | player = $player; 25 | } 26 | 27 | public function onRun(int $currentTick) 28 | { 29 | $this->player->teleport(new Position(254, 4, 254, $this->owner->getServer()->getLevelByName("athletic"))); 30 | $this->player->setSpawn(new Position(254, 4, 254, $this->owner->getServer()->getLevelByName("athletic"))); 31 | $this->player->setHealth(20); 32 | $this->player->getArmorInventory()->clearAll(true); 33 | $this->player->setMaxHealth(20); 34 | $this->player->setFood(20); 35 | $this->player->removeAllEffects(); 36 | $this->player->getInventory()->clearAll(true); 37 | $this->player->sendMessage("§aテレポートしました。"); 38 | } 39 | } -------------------------------------------------------------------------------- /src/Core/Event/EntityDamage.php: -------------------------------------------------------------------------------- 1 | plugin = $plugin; 24 | } 25 | 26 | public function event(EntityDamageEvent $event) 27 | { 28 | $entity = $event->getEntity(); 29 | if ($entity->getLevel()->getName() === "ffapvp" or $entity->getLevel()->getName() === "corepvp") { 30 | if ($event->getCause() === EntityDamageEvent::CAUSE_FALL) { 31 | $event->setCancelled(true); 32 | } 33 | } 34 | if ($event instanceof EntityDamageByEntityEvent and $entity instanceof Player) { 35 | $damager = $event->getDamager(); 36 | if ($damager instanceof Player) { 37 | if ($damager->getName() === $entity->getName()) { 38 | $event->setCancelled(true); 39 | } 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Core/Commands/SetMoneyCommand.php: -------------------------------------------------------------------------------- 1 | setPermission("vnp.command.setmoney"); 27 | $this->setDescription("Admin Command"); 28 | $this->plugin = $plugin; 29 | $this->money = new Money(); 30 | } 31 | 32 | public function execute(CommandSender $sender, string $commandLabel, array $args) 33 | { 34 | if (!$this->plugin->isEnabled()) { 35 | return false; 36 | } 37 | 38 | if (!$this->testPermission($sender)) { 39 | return false; 40 | } 41 | 42 | if (!isset($args[0]) || !isset($args[0])) { 43 | return false; 44 | } 45 | $this->money->setMoney($args[0], $args[1]); 46 | return true; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/Core/Task/Teleport/TeleportFFAPvPTask.php: -------------------------------------------------------------------------------- 1 | plugin = $plugin; 24 | $this->player = $player; 25 | } 26 | 27 | public function onRun(int $currentTick) 28 | { 29 | $this->player->teleport(new Position(254, 107, 254, $this->owner->getServer()->getLevelByName("ffapvp"))); 30 | $this->player->setSpawn(new Position(254, 107, 254, $this->owner->getServer()->getLevelByName("ffapvp"))); 31 | $this->player->setHealth(20); 32 | $this->player->getArmorInventory()->clearAll(true); 33 | $this->player->setMaxHealth(20); 34 | $this->player->setFood(20); 35 | $this->player->removeAllEffects(); 36 | $this->player->getInventory()->clearAll(true); 37 | $this->player->sendMessage("§aテレポートしました。"); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Core/Player/MazaiPoint.php: -------------------------------------------------------------------------------- 1 | get('USERDATA'); 24 | return $data['mazaipoint']; 25 | } 26 | 27 | /** 28 | * @param string $name 29 | * @param int $point 30 | */ 31 | public function addMazai(string $name, int $point) 32 | { 33 | $datafile = new DataFile($name); 34 | $data = $datafile->get('USERDATA'); 35 | $data['mazaipoint'] += $point; 36 | $datafile->write('USERDATA', $data); 37 | } 38 | 39 | /** 40 | * @param string $name 41 | * @param int $point 42 | * @return bool 43 | */ 44 | public function reduceMazai(string $name, int $point): bool 45 | { 46 | $datafile = new DataFile($name); 47 | $data = $datafile->get('USERDATA'); 48 | if ($data['mazaipoint'] < $point) { 49 | return false; 50 | } else { 51 | $data['mazaipoint'] = $data['mazaipoint'] - $point; 52 | $datafile->write('USERDATA', $data); 53 | return true; 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /src/Core/Commands/PingCommand.php: -------------------------------------------------------------------------------- 1 | setPermission("vnp.command.ping"); 24 | $this->setDescription("応答速度を計測します。"); 25 | $this->plugin = $plugin; 26 | } 27 | public function execute(CommandSender $sender, string $commandLabel, array $args) 28 | { 29 | if (!$this->plugin->isEnabled()) { 30 | return false; 31 | } 32 | if (!$this->testPermission($sender)) { 33 | return false; 34 | } 35 | if ($sender instanceof Player) { 36 | $ping = $sender->getPing(); 37 | $color = ($ping < 150 ? TextFormat::GREEN : ($ping < 250 ? TextFormat::GOLD : TextFormat::RED)); 38 | $sender->sendMessage(TextFormat::YELLOW."Pong! $color".$ping."§ems"); 39 | return true; 40 | } 41 | $sender->sendMessage(TextFormat::RED."このコマンドはプレイヤーのみが実行できます。"); 42 | return true; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Core/Event/PlayerJoin.php: -------------------------------------------------------------------------------- 1 | plugin = $plugin; 30 | $this->level = new Level(); 31 | $this->rank = new Rank($this->plugin); 32 | $this->tag = new Tag(); 33 | } 34 | 35 | public function event(PlayerJoinEvent $event): void 36 | { 37 | $player = $event->getPlayer(); 38 | $name = $player->getName(); 39 | $level = $this->level->getLevel($name); 40 | $rank = $this->rank->getRank($name); 41 | $tag = $this->tag->getTag($player); 42 | $event->setJoinMessage("§b[§a参加§b] §7$name が参加しました。"); 43 | $bossbar = new Bossbar(); 44 | $bossbar->sendBar($player, true, 16752128); 45 | $player->setNameTag("§7[§r $rank §7] §r$name"); 46 | $player->setDisplayName("§7[§r $rank §7][ §rLv.$level §7][§r $tag §7] §r$name"); 47 | $this->plugin->getScheduler()->scheduleDelayedTask(new JoinTitle($this->plugin, $player), 100); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Core/Commands/DebugCommand.php: -------------------------------------------------------------------------------- 1 | setPermission("vnp.command.debug"); 25 | $this->setDescription("Admin Command"); 26 | $this->plugin = $plugin; 27 | } 28 | 29 | public function execute(CommandSender $sender, string $commandLabel, array $args) 30 | { 31 | if (!$this->plugin->isEnabled()) { 32 | return false; 33 | } 34 | if (!$this->testPermission($sender)) { 35 | return false; 36 | } 37 | if (!$sender instanceof Player) { 38 | $sender->sendMessage(TextFormat::RED . "このコマンドはプレイヤーのみが実行できます。"); 39 | return true; 40 | } 41 | $x = $sender->getFloorX(); 42 | $y = $sender->getFloorY(); 43 | $z = $sender->getFloorZ(); 44 | $levelname = $sender->getLevel()->getName(); 45 | $itemid = $sender->getInventory()->getItemInHand()->getId(); 46 | $meta = $sender->getInventory()->getItemInHand()->getDamage(); 47 | $sender->sendMessage("X: $x\nY: $y\nZ: $z\nLevelName: $levelname\nBlockID: $itemid:$meta"); 48 | return true; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Core/Event/PlayerCommandPreprocess.php: -------------------------------------------------------------------------------- 1 | plugin = $plugin; 30 | $this->rank = new Rank($this->plugin); 31 | $this->level = new Level(); 32 | $this->tag = new Tag(); 33 | } 34 | 35 | public function event(PlayerCommandPreprocessEvent $event): void 36 | { 37 | $player = $event->getPlayer(); 38 | $name = $player->getName(); 39 | $level = $this->level->getLevel($name); 40 | $rank = $this->rank->getRank($name); 41 | $tag = $this->tag->getTag($player); 42 | $player->setDisplayName("§7[§r $rank §7][ §rLv.$level §7][§r $tag §7] §r$name"); 43 | switch ($event->getMessage()) { 44 | case '/whitelist on': 45 | if (!$player->isOp()) return; 46 | Discord::SendEmbed("SERVER STATUS", "WHITELIST ON", "メンテナンスが開始されました。", 16776960); 47 | break; 48 | case '/whitelist off': 49 | if (!$player->isOp()) return; 50 | Discord::SendEmbed("SERVER STATUS", "WHITELIST OFF", "メンテナンスが終了しました。", 8847104); 51 | break; 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /src/Core/Player/Money.php: -------------------------------------------------------------------------------- 1 | get('USERDATA'); 23 | return $data['money']; 24 | } 25 | 26 | /** 27 | * @param string $name 28 | * @param int $money 29 | */ 30 | public function setMoney(string $name, int $money) 31 | { 32 | $datafile = new DataFile($name); 33 | $data = $datafile->get('USERDATA'); 34 | $data['money'] = $money; 35 | $datafile->write('USERDATA', $data); 36 | } 37 | 38 | /** 39 | * @param string $name 40 | * @param int $money 41 | * @return bool 42 | */ 43 | public function reduceMoney(string $name, int $money): bool 44 | { 45 | $datafile = new DataFile($name); 46 | $data = $datafile->get('USERDATA'); 47 | if ($data['money'] < $money) { 48 | return false; 49 | } else { 50 | $data['money'] = $data['money'] - $money; 51 | $datafile->write('USERDATA', $data); 52 | return true; 53 | } 54 | } 55 | 56 | /** 57 | * @param string $name 58 | * @param int $money 59 | */ 60 | public function addMoney(string $name, int $money) 61 | { 62 | $datafile = new DataFile($name); 63 | $data = $datafile->get('USERDATA'); 64 | $data['money'] += $money; 65 | $datafile->write('USERDATA', $data); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/Core/Player/Rank.php: -------------------------------------------------------------------------------- 1 | plugin = $plugin; 25 | } 26 | 27 | /** 28 | * @param string $name 29 | * @return mixed 30 | */ 31 | public function getRank(string $name) 32 | { 33 | $datafile = new DataFile($name); 34 | $data = $datafile->get('USERDATA'); 35 | $rank = $data['rank']; 36 | return $rank; 37 | } 38 | 39 | /** 40 | * @param string $name 41 | * @param int $rankid 42 | */ 43 | public function setRank(string $name, int $rankid) 44 | { 45 | $datafile = new DataFile($name); 46 | $data = $datafile->get('USERDATA'); 47 | switch ($rankid) { 48 | case 1: 49 | $data['rank'] = "§6V§bN§r"; 50 | break; 51 | case 2: 52 | $data['rank'] = "§5S§r"; 53 | break; 54 | case 3: 55 | $data['rank'] = "§eA§r"; 56 | break; 57 | case 4: 58 | $data['rank'] = "§cB§r"; 59 | break; 60 | case 5: 61 | $data['rank'] = "§aC§r"; 62 | break; 63 | case 6: 64 | $data['rank'] = "§3D§r"; 65 | break; 66 | case 7: 67 | $data['rank'] = "§7E§r"; 68 | break; 69 | default: 70 | $this->plugin->getLogger()->error("ランクIDが違います RankID: " . $rankid); 71 | break; 72 | } 73 | $datafile->write('USERDATA', $data); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/Core/Player/KD.php: -------------------------------------------------------------------------------- 1 | get('FFAPVP'); 23 | $kill = $data['kill']; 24 | $death = $data['death']; 25 | if (empty($kill)) { 26 | return 0; 27 | } elseif (empty($death)) { 28 | return 0; 29 | } else { 30 | $int = $kill / $death; 31 | $kd = floor($int * pow(10, 2)) / pow(10, 2); 32 | return $kd; 33 | } 34 | } 35 | 36 | /** 37 | * @param string $name 38 | * @return float|int 39 | */ 40 | public function SCPKD(string $name) 41 | { 42 | $datafile = new DataFile($name); 43 | $data = $datafile->get('COREPVP'); 44 | $kill = $data['kill']; 45 | $death = $data['death']; 46 | if (empty($kill)) { 47 | return 0; 48 | } elseif (empty($death)) { 49 | return 0; 50 | } else { 51 | $int = $kill / $death; 52 | $kd = floor($int * pow(10, 2)) / pow(10, 2); 53 | return $kd; 54 | } 55 | } 56 | 57 | /** 58 | * @param string $name 59 | * @return float|int 60 | */ 61 | public function SCPWL(string $name) 62 | { 63 | $datafile = new DataFile($name); 64 | $data = $datafile->get('COREPVP'); 65 | $win = $data['win']; 66 | $lose = $data['lose']; 67 | if (empty($win)) { 68 | return 0; 69 | } elseif (empty($lose)) { 70 | return 0; 71 | } else { 72 | $int = $win / $lose; 73 | $kd = floor($int * pow(10, 2)) / pow(10, 2); 74 | return $kd; 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/Core/Commands/AddTagCommand.php: -------------------------------------------------------------------------------- 1 | setDescription("Admin Command"); 26 | $this->setPermission("vnp.command.addTag"); 27 | $this->tag = new Tag(); 28 | } 29 | 30 | public function execute(CommandSender $sender, string $commandLabel, array $args) 31 | { 32 | if (!$this->getPlugin()->isEnabled()) { 33 | return false; 34 | } 35 | 36 | if (!$this->testPermission($sender)) { 37 | return false; 38 | } 39 | 40 | if (!isset($args[0]) || !isset($args[0])) { 41 | return false; 42 | } 43 | foreach ($this->getPlugin()->getServer()->getOnlinePlayers() as $player) { 44 | if ($player->getName() === $args[0]) { 45 | $this->tag->setTag($player); 46 | if (isset($args[1])) { 47 | $this->tag->setTag($player, $args[1]); 48 | if (isset($args[2])) { 49 | $this->tag->setTag($player, $args[1], $args[2]); 50 | } else { 51 | $sender->sendMessage(TextFormat::GREEN."完了しました。"); 52 | } 53 | } else { 54 | $sender->sendMessage(TextFormat::GREEN."完了しました。"); 55 | } 56 | } else { 57 | $sender->sendMessage(TextFormat::RED."そのようなユーザーは現在居ません。"); 58 | } 59 | } 60 | return true; 61 | } 62 | 63 | public function getPlugin(): Plugin 64 | { 65 | return parent::getPlugin(); 66 | } 67 | } -------------------------------------------------------------------------------- /src/Core/Task/JoinTitle.php: -------------------------------------------------------------------------------- 1 | player = $player; 30 | } 31 | 32 | /** 33 | * Actions to execute when run 34 | * 35 | * @param int $currentTick 36 | * 37 | * @return void 38 | */ 39 | public function onRun(int $currentTick) 40 | { 41 | $player = $this->player; 42 | $player->addTitle("§6Vector §bNetwork", "§eDeveloped by InkoHX MazaiCrafty", 40, 100, 40); 43 | $player->sendMessage("§a---===< §6Vector §bNetwork §eProject §a>===---\n§bDeveloped by InkoHX MazaiCrafty\n§bGitHub: §7https://github.com/InkoHX/Vector-Network-Project\n§bTwitter: §7https://twitter.com/InkoHX\n§9Discord: §7https://discord.gg/EF2G5dh\n§a---=============================---"); 44 | $custom = FormApi::makeCustomForm(function ($response) { 45 | if (!FormApi::formCancelled($response)) { 46 | } 47 | }); 48 | $custom->setTitle("変更内容") 49 | ->addElement(new Label("ゲームバージョン: " . self::getVersion() . "\n" . self::getChange())) 50 | ->setId(mt_rand(111111, 999999)) 51 | ->sendToPlayer($player); 52 | } 53 | 54 | /** 55 | * @return bool|mixed 56 | */ 57 | private static function getChange() 58 | { 59 | return Internet::getURL('https://vnp.inkohx.xyz/log/change.txt'); 60 | } 61 | 62 | /** 63 | * @return bool|mixed 64 | */ 65 | private static function getVersion() 66 | { 67 | return Internet::getURL('https://vnp.inkohx.xyz/log/game_version.txt'); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/Core/Commands/GameStatusCommand.php: -------------------------------------------------------------------------------- 1 | setPermission("vector.network.player"); 27 | $this->setDescription("どのゲームに何人居るか表示します。"); 28 | } 29 | 30 | public function execute(CommandSender $sender, string $commandLabel, array $args) 31 | { 32 | if (!$this->getPlugin()->isEnabled()) { 33 | return false; 34 | } 35 | if (!$this->testPermission($sender)) { 36 | return false; 37 | } 38 | if (!$sender instanceof Player) { 39 | $sender->sendMessage(TextFormat::RED . "このコマンドはプレイヤーのみが実行できます。"); 40 | return true; 41 | } 42 | $survival = count($this->getPlugin()->getServer()->getLevelByName('Survival')->getPlayers()); 43 | $speedcorepvp = count($this->getPlugin()->getServer()->getLevelByName('corepvp')->getPlayers()); 44 | $ffapvp = count($this->getPlugin()->getServer()->getLevelByName('ffapvp')->getPlayers()); 45 | $lobby = count($this->getPlugin()->getServer()->getLevelByName('lobby')->getPlayers()); 46 | $custom = FormApi::makeCustomForm(function (?array $response) { 47 | if (!FormApi::formCancelled($response)) { 48 | } 49 | }); 50 | $custom->setTitle("ゲームステータス") 51 | ->addElement(new Label("§6ロビー§r: $lobby 人\n§6FFA§cPvP§r: $ffapvp 人\n§bSpeed§aCore§cPvP§r: $speedcorepvp 人\n§aSurvival§r: $survival 人")) 52 | ->setId(mt_rand(111111, 9999999)) 53 | ->sendToPlayer($sender); 54 | return true; 55 | } 56 | 57 | public function getPlugin(): Plugin 58 | { 59 | return parent::getPlugin(); 60 | } 61 | } -------------------------------------------------------------------------------- /src/Core/Event/PlayerLogin.php: -------------------------------------------------------------------------------- 1 | plugin = $plugin; 23 | } 24 | 25 | public function event(PlayerLoginEvent $event): void 26 | { 27 | $player = $event->getPlayer(); 28 | $name = $player->getName(); 29 | $data = new DataFile($name); 30 | if (($user = $data->get("USERDATA")) === null) { 31 | $user = [ 32 | "name" => $name, 33 | "money" => 1000, 34 | "networklevel" => 1, 35 | "exp" => 0, 36 | "maxexp" => 50, 37 | "rank" => "§rNoRank", 38 | "tag" => "§rNoTag", 39 | "mazaipoint" => 0, 40 | "killsound" => 0, 41 | "firstlogin" => date("Y年m月d日 H時i分s秒"), 42 | "lastlogin" => date("Y年m月d日 H時i分s秒") 43 | ]; 44 | $data->write("USERDATA", $user); 45 | $this->plugin->getServer()->broadcastMessage("§7[§b情報§7] $name は初参加です。"); 46 | } 47 | if (($ffapvp = $data->get("FFAPVP")) === null) { 48 | $ffapvp = [ 49 | "name" => $name, 50 | "kill" => 0, 51 | "death" => 0 52 | ]; 53 | $data->write('FFAPVP', $ffapvp); 54 | } 55 | if (($corepvp = $data->get("COREPVP")) === null) { 56 | $corepvp = [ 57 | "name" => $name, 58 | "kill" => 0, 59 | "death" => 0, 60 | "breakcore" => 0, 61 | "win" => 0, 62 | "lose" => 0 63 | ]; 64 | $data->write('COREPVP', $corepvp); 65 | } 66 | if (($inventory = $data->get('SURVIVAL')) === null) { 67 | $inventory = [ 68 | "breakblock" => 0, 69 | "placeblock" => 0, 70 | "kill" => 0, 71 | "death" => 0, 72 | "breakdiamond" => 0, 73 | "breakgold" => 0, 74 | "breakcoal" => 0, 75 | "breakiron" => 0, 76 | "health" => 20, 77 | "food" => 20, 78 | "items" => array(), 79 | "x" => 225, 80 | "y" => 243, 81 | "z" => 256 82 | ]; 83 | $data->write('SURVIVAL', $inventory); 84 | } 85 | if (($duel = $data->get('DUEL')) === null) { 86 | $duel = [ 87 | "win" => 0, 88 | "lose" => 0 89 | ]; 90 | $data->write('DUEL', $duel); 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "inkohx/vector-network-project", 3 | "description": "Vector Network Server plugin", 4 | "type": "project", 5 | "homepage": "https://vnp.inkohx.xyz/", 6 | "license": "MIT", 7 | "authors": [ 8 | { 9 | "name": "InkoHX", 10 | "homepage": "https://twitter.com/InkoHX" 11 | }, 12 | { 13 | "name": "yuko fuyutsuki" 14 | }, 15 | { 16 | "name": "MazaiCrafty" 17 | }, 18 | { 19 | "name": "DusKong" 20 | } 21 | ], 22 | "require": { 23 | "php": ">=7.2.0", 24 | "ext-bcmath": "*", 25 | "ext-curl": "*", 26 | "ext-hash": "*", 27 | "ext-json": "*", 28 | "ext-mbstring": "*", 29 | "ext-openssl": "*", 30 | "ext-pcre": "*", 31 | "ext-phar": "*", 32 | "ext-pthreads": ">=3.1.7dev", 33 | "ext-reflection": "*", 34 | "ext-sockets": "*", 35 | "ext-spl": "*", 36 | "ext-yaml": ">=2.0.0", 37 | "ext-zip": "*", 38 | "ext-zlib": ">=1.2.11", 39 | "pocketmine/pocketmine-mp": "dev-master as 3.1.3", 40 | "pocketmine/raklib": "^0.12.0", 41 | "pocketmine/spl": "^0.3.0", 42 | "pocketmine/binaryutils": "^0.1.0", 43 | "pocketmine/nbt": "^0.2.0", 44 | "pocketmine/math": "^0.2.0", 45 | "pocketmine/snooze": "^0.1.0", 46 | "fuyutsuki/libform": "^0.3.1", 47 | "vectornetworkproject/discord-pmmp": "^1.0.0" 48 | }, 49 | "autoload": { 50 | "psr-4": { 51 | "": ["src"] 52 | } 53 | }, 54 | "repositories": [ 55 | { 56 | "type": "git", 57 | "url": "https://github.com/VectorNetworkProject/PocketMine-MP" 58 | }, 59 | { 60 | "type": "git", 61 | "url": "https://github.com/pmmp/RakLib" 62 | }, 63 | { 64 | "type": "git", 65 | "url": "https://github.com/pmmp/SPL" 66 | }, 67 | { 68 | "type": "git", 69 | "url": "https://github.com/pmmp/BinaryUtils" 70 | }, 71 | { 72 | "type": "git", 73 | "url": "https://github.com/pmmp/NBT" 74 | }, 75 | { 76 | "type": "git", 77 | "url": "https://github.com/pmmp/Math" 78 | }, 79 | { 80 | "type": "git", 81 | "url": "https://github.com/pmmp/Snooze" 82 | }, 83 | { 84 | "type": "git", 85 | "url": "https://github.com/fuyutsuki/libform" 86 | }, 87 | { 88 | "type": "git", 89 | "url": "https://github.com/VectorNetworkProject/Discord-pmmp.git" 90 | } 91 | ] 92 | } -------------------------------------------------------------------------------- /src/Core/Entity/Mazai.php: -------------------------------------------------------------------------------- 1 | money = new Money(); 34 | $this->mazai = new MazaiPoint(); 35 | } 36 | 37 | /** 38 | * @param EntityLevelChangeEvent $event 39 | */ 40 | public function Check(EntityLevelChangeEvent $event): void 41 | { 42 | $entity = $event->getEntity(); 43 | if ($entity instanceof Player) { 44 | if ($event->getTarget()->getName() === 'lobby') { 45 | $this->Create($entity, "§a魔剤§e売りの§a魔剤§eさん", "MazaiNPC", new Vector3(260, 4, 265), Item::get(Item::POTION, 11, 1), self::ENTITY_ID); 46 | } else { 47 | $this->Remove($entity, self::ENTITY_ID); 48 | } 49 | } 50 | } 51 | 52 | public function ClickEntity(DataPacketReceiveEvent $event): void 53 | { 54 | $packet = $event->getPacket(); 55 | $player = $event->getPlayer(); 56 | if ($packet instanceof InventoryTransactionPacket) { 57 | if ($packet->transactionType === $packet::TYPE_USE_ITEM_ON_ENTITY) { 58 | if ($packet->trData->entityRuntimeId === self::getEid($player, self::ENTITY_ID)) { 59 | FormApi::makeListForm(function (Player $player, ?int $key) { 60 | if (!FormApi::formCancelled($key)) { 61 | switch ($key) { 62 | case 0: 63 | if ($this->money->reduceMoney($player->getName(), 10000)) { 64 | $player->sendMessage(MessagesEnum::BUY_SUCCESS); 65 | $this->mazai->addMazai($player->getName(), 1); 66 | } else { 67 | $player->sendMessage(MessagesEnum::BUY_ERROR); 68 | } 69 | break; 70 | } 71 | } 72 | })->setTitle("§a魔剤さんの§e変換所") 73 | ->setContent("§6V§bN§eCoin§rを§aMAZAI§rにします。") 74 | ->addButton(new Button("§e1§aMAZAI\n§e10000§6V§bN§eCoin")) 75 | ->sendToPlayer($player); 76 | } 77 | } 78 | } 79 | } 80 | } -------------------------------------------------------------------------------- /src/Core/Player/Tag.php: -------------------------------------------------------------------------------- 1 | getName()); 64 | $data = $datafile->get('USERDATA'); 65 | return $data['tag']; 66 | } 67 | 68 | /** 69 | * @param Player $player 70 | * @param string $tag 71 | * @param int $colorid 72 | */ 73 | public function setTag(Player $player, string $tag = "NoTag", int $colorid = 16) 74 | { 75 | $datafile = new DataFile($player->getName()); 76 | $data = $datafile->get('USERDATA'); 77 | if (mb_strlen($tag) >= 9) { 78 | $player->sendMessage("§7[§c失敗§7] §cタグは8文字以内にして下さい"); 79 | return; 80 | } 81 | 82 | if ((0 <= $colorid) && ($colorid <= 16)) { 83 | $data['tag'] = Tag::$colors[$colorid] . $tag . "§r"; 84 | $usertag = $data['tag']; 85 | $message = "§7[§a成功§7] §7あなたのタグを【 $usertag §7】に設定しました。"; 86 | } else { 87 | $data['tag'] = "§r$tag"; 88 | $message = "§7[§cエラー§7] §c指定したカラーIDが見つからなかった為デフォルトの色にしました。"; 89 | } 90 | $datafile->write('USERDATA', $data); 91 | $player->sendMessage($message); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/Core/DataFile.php: -------------------------------------------------------------------------------- 1 | owner->getServer()->broadcastMessage("§b[§7TIP§b] §7このゲームはまだ未完成です。"); 26 | break; 27 | case 2: 28 | $this->owner->getServer()->broadcastMessage("§b[§7TIP§b] §7/statsで自分のステータスを確認出来ます。"); 29 | break; 30 | case 3: 31 | $this->owner->getServer()->broadcastMessage("§b[§7TIP§b] §7/pingで応答速度を計測出来ます。"); 32 | break; 33 | case 4: 34 | $this->owner->getServer()->broadcastMessage("§b[§7TIP§b] §7/rankshopでランクを買う事が出来ます。"); 35 | break; 36 | case 5: 37 | $this->owner->getServer()->broadcastMessage("§b[§7TIP§b] §7/settagでタグを設定できます。"); 38 | break; 39 | case 6: 40 | $this->owner->getServer()->broadcastMessage("§b[§7TIP§b] §7このサーバーはInkoHXとMazaiCraftyによって開発されています。"); 41 | break; 42 | case 7: 43 | $this->owner->getServer()->broadcastMessage("§b[§7TIP§b] §7まだ開発中でありまだまだ機能追加を予定しています!!"); 44 | break; 45 | case 8: 46 | $this->owner->getServer()->broadcastMessage("§b[§7TIP§b] §7運営チームのなりすましにご注意ください。"); 47 | break; 48 | case 9: 49 | $this->owner->getServer()->broadcastMessage("§b[§7TIP§b] §7Hackerなどの報告はDiscordからお願いします。"); 50 | break; 51 | case 10: 52 | $this->owner->getServer()->broadcastMessage("§b[§7TIP§b] §7/selectgameでゲームを選択できます。"); 53 | break; 54 | case 11: 55 | $this->owner->getServer()->broadcastMessage("§b[§7TIP§b] §7よく過疎過疎うんこサーバーって言われます。"); 56 | break; 57 | case 12: 58 | $this->owner->getServer()->broadcastMessage("§b[§7TIP§b] §7SpeedCorePvPは二つチームに分かれてコアを削り合うゲームだよ!!"); 59 | break; 60 | case 13: 61 | $this->owner->getServer()->broadcastMessage("§b[§7TIP§b] §7FFAPvPはただのPvP"); 62 | break; 63 | case 14: 64 | $this->owner->getServer()->broadcastMessage("§b[§7TIP§b] §7Survivalはサバイバルだよ自分の好きなようにできる事が可能です。(重いけどね)"); 65 | break; 66 | case 15: 67 | $this->owner->getServer()->broadcastMessage("§b[§7TIP§b] §7Athleticはまだ開発中なんだ!!"); 68 | break; 69 | case 16: 70 | $this->owner->getServer()->broadcastMessage("§b[§7TIP§b] §7この鯖には魔剤要素があります。"); 71 | break; 72 | case 17: 73 | $this->owner->getServer()->broadcastMessage("§b[§7TIP§b] §7人が少ないときはサバイバルで遊びましょう()"); 74 | break; 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/Core/Game/FFAPvP/FFAPvPCore.php: -------------------------------------------------------------------------------- 1 | plugin = $plugin; 31 | $this->money = new Money(); 32 | $this->level = new Level(); 33 | } 34 | 35 | public function AddDeathCount(Player $player) 36 | { 37 | if ($player->getLevel()->getName() !== $this->worldname) return; 38 | $datafile = new DataFile($player->getName()); 39 | $data = $datafile->get('FFAPVP'); 40 | $data['death'] += 1; 41 | $datafile->write('FFAPVP', $data); 42 | $player->addTitle("§cYou are dead", "§cあなたは死んでしまった", 20, 40, 20); 43 | } 44 | 45 | public function AddKillCount(Player $player) 46 | { 47 | if ($player->getLevel()->getName() !== $this->worldname) return; 48 | $datafile = new DataFile($player->getName()); 49 | $data = $datafile->get('FFAPVP'); 50 | $data['kill'] += 1; 51 | $datafile->write('FFAPVP', $data); 52 | $rand = mt_rand(1, 50); 53 | $this->money->addMoney($player->getName(), $rand); 54 | $player->sendMessage("§a+$rand §6V§bN§eCoin"); 55 | $this->level->LevelSystem($player); 56 | $this->plugin->getScheduler()->scheduleDelayedTask(new LevelCheckingTask($this->plugin, $player), 20); 57 | } 58 | 59 | public function FFAPvPKit(Player $player, Block $block) 60 | { 61 | if ($player->getLevel()->getName() !== $this->worldname) return; 62 | if ($block->getId() !== 133) return; 63 | 64 | $player->getInventory()->clearAll(true); 65 | $player->setMaxHealth(20); 66 | $player->setHealth(20); 67 | $player->setFood(20); 68 | $items = [ 69 | "leather_cap" => Item::get(Item::LEATHER_CAP, 0, 1), 70 | "chain_tunic" => Item::get(Item::CHAIN_CHESTPLATE, 0, 1), 71 | "chain_leggings" => Item::get(Item::CHAIN_LEGGINGS, 0, 1), 72 | "leather_boots" => Item::get(Item::LEATHER_BOOTS, 0, 1), 73 | "wooden_sword" => Item::get(Item::WOODEN_SWORD, 0, 1), 74 | "bow" => Item::get(Item::BOW, 0, 1) 75 | ]; 76 | foreach ($items as $item) { 77 | if ($item instanceof Durable) { 78 | $item->setUnbreakable(true); 79 | } 80 | } 81 | $armor = $player->getArmorInventory(); 82 | $armor->setHelmet($items["leather_cap"]); 83 | $armor->setChestplate($items["chain_tunic"]); 84 | $armor->setLeggings($items["chain_leggings"]); 85 | $armor->setBoots($items["leather_boots"]); 86 | $player->getInventory()->addItem($items["wooden_sword"]); 87 | $player->getInventory()->addItem($items["bow"]); 88 | $player->getInventory()->addItem(Item::get(Item::STEAK, 0, 64)); 89 | $player->getInventory()->addItem(Item::get(Item::ARROW, 0, 64)); 90 | $player->sendMessage("§a初期装備を与えました。"); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/Core/Entity/MazaiMaster.php: -------------------------------------------------------------------------------- 1 | money = new Money(); 38 | $this->level = new Level(); 39 | $this->mazai = new MazaiPoint(); 40 | } 41 | 42 | /** 43 | * @param EntityLevelChangeEvent $event 44 | */ 45 | public function Check(EntityLevelChangeEvent $event): void 46 | { 47 | $entity = $event->getEntity(); 48 | if ($entity instanceof Player) { 49 | if ($event->getTarget()->getName() === 'lobby') { 50 | $this->Create($entity, "§a魔剤§7マスター", "MazaiNPC", new Vector3(287, 10, 270), Item::get(Item::POTION, 11, 1), self::ENTITY_ID); 51 | } else { 52 | $this->Remove($entity, self::ENTITY_ID); 53 | } 54 | } 55 | } 56 | 57 | public function ClickEntity(DataPacketReceiveEvent $event): void 58 | { 59 | $packet = $event->getPacket(); 60 | $player = $event->getPlayer(); 61 | if ($packet instanceof InventoryTransactionPacket) { 62 | if ($packet->transactionType === $packet::TYPE_USE_ITEM_ON_ENTITY) { 63 | if ($packet->trData->entityRuntimeId === self::getEid($player, self::ENTITY_ID)) { 64 | FormApi::makeListForm(function (Player $player, ?int $key) { 65 | if (!FormApi::formCancelled($key)) { 66 | switch ($key) { 67 | case 0: 68 | if ($this->mazai->reduceMazai($player->getName(), 1)) { 69 | $player->sendMessage(MessagesEnum::MAZAI_SUCCESS); 70 | $this->level->addExp($player->getName(), 300); 71 | Main::$instance->getScheduler()->scheduleDelayedTask(new LevelCheckingTask(Main::$instance, $player), 20); 72 | } else { 73 | $player->sendMessage(MessagesEnum::MAZAI_ERROR); 74 | } 75 | break; 76 | case 1: 77 | if ($this->mazai->reduceMazai($player->getName(), 1)) { 78 | $player->sendMessage(MessagesEnum::MAZAI_SUCCESS); 79 | $this->money->addMoney($player->getName(), 10000); 80 | } else { 81 | $player->sendMessage(MessagesEnum::MAZAI_ERROR); 82 | } 83 | break; 84 | } 85 | } 86 | })->setTitle("§aMAZAI§e変換所") 87 | ->setContent("§aMAZAI§rを色んなものに変換します。") 88 | ->addButton(new Button("§e300§aXP\n§e1§aMAZAI")) 89 | ->addButton(new Button("§e10000§6V§bN§eCoin\n§e1§aMAZAI\"")) 90 | ->sendToPlayer($player); 91 | } 92 | } 93 | } 94 | } 95 | } -------------------------------------------------------------------------------- /src/Core/Commands/KillSoundCommand.php: -------------------------------------------------------------------------------- 1 | setPermission("vnp.command.killsound"); 39 | $this->setDescription("敵を倒した時のサウンドを設定します。"); 40 | $this->plugin = $plugin; 41 | $this->killsound = new \Core\Player\KillSound($plugin); 42 | } 43 | 44 | public function execute(CommandSender $sender, string $commandLabel, array $args) 45 | { 46 | if (!$this->plugin->isEnabled()) { 47 | return false; 48 | } 49 | if (!$this->testPermission($sender)) { 50 | return false; 51 | } 52 | if (!$sender instanceof Player) { 53 | $sender->sendMessage(TextFormat::RED . "このコマンドはプレイヤーのみが実行できます。"); 54 | return true; 55 | } 56 | FormApi::makeCustomForm(function (Player $player, ?array $response) { 57 | if (!FormApi::formCancelled($response)) { 58 | switch ($response[0]) { 59 | case self::$sounds[0]: 60 | $this->killsound->setKillSound($player, 0); 61 | $player->sendMessage("§7[§a成功§7] §aキルサウンドを無効にしました。"); 62 | break; 63 | case self::$sounds[1]: 64 | $this->killsound->setKillSound($player, 1); 65 | $player->sendMessage("§7[§a成功§7] §aキルサウンドを【チーン】に設定しました。"); 66 | break; 67 | case self::$sounds[2]: 68 | $this->killsound->setKillSound($player, 2); 69 | $player->sendMessage("§7[§a成功§7] §aキルサウンドを【1UP】に設定しました。"); 70 | break; 71 | case self::$sounds[3]: 72 | $this->killsound->setKillSound($player, 3); 73 | $player->sendMessage("§7[§a成功§7] §aキルサウンドを【骨が折れる音】に設定しました。"); 74 | break; 75 | case self::$sounds[4]: 76 | $this->killsound->setKillSound($player, 4); 77 | $player->sendMessage("§7[§a成功§7] §aキルサウンドを【デデドン】に設定しました。"); 78 | break; 79 | case self::$sounds[5]: 80 | $this->killsound->setKillSound($player, 5); 81 | $player->sendMessage("§7[§a成功§7] §aキルサウンドを【ピチューン】に設定しました。"); 82 | break; 83 | case self::$sounds[6]: 84 | $this->killsound->setKillSound($player, 6); 85 | $player->sendMessage("§7[§a成功§7] §aキルサウンドを【ブスッ】に設定しました。"); 86 | break; 87 | case self::$sounds[7]: 88 | $this->killsound->setKillSound($player, 7); 89 | $player->sendMessage("§7[§a成功§7] §aキルサウンドを【許してくれたまえ】に設定しました。"); 90 | break; 91 | case self::$sounds[8]: 92 | $this->killsound->setKillSound($player, 8); 93 | $player->sendMessage("§7[§a成功§7] §aキルサウンドを【さっさと逃げればいいものを】に設定しました。"); 94 | break; 95 | } 96 | } 97 | })->setTitle("キルサウンド選択") 98 | ->addElement(new Dropdown("敵を倒したときに出るサウンドを設定します。", self::$sounds)) 99 | ->sendToPlayer($sender); 100 | return true; 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/Core/Game/Athletic/AthleticCore.php: -------------------------------------------------------------------------------- 1 | getPlayer(); 35 | if ($player->getLevel()->getName() === "athletic") { 36 | if ($event->getBlock() === 133) { 37 | $array_data = self::$json->get($this->getAthleticData($event)); 38 | $this->player_data[$player->getName()] = [ 39 | "Athletic" => $this->getAthleticData($event), 40 | "X" => $array_data["SpawnX"], 41 | "Y" => $array_data["SpawnY"], 42 | "Z" => $array_data["SpawnZ"], 43 | "StartTime" => microtime(true) 44 | ]; 45 | if ($this->isAthleticFinish($event, $player)) { 46 | $time = microtime(true) - $this->player_data[$player->getName()]["StartTime"]; 47 | $player->sendMessage($time); 48 | unset($this->player_data[$player->getName()]); 49 | return; 50 | } 51 | } 52 | } 53 | } 54 | 55 | public function getAthleticData(PlayerInteractEvent $event): string 56 | { 57 | return array_search($event->getTouchVector(), self::$json->getAll(true)); 58 | } 59 | 60 | public function isAthleticFinish(PlayerInteractEvent $event, Player $player): bool 61 | { 62 | if (!isset($this->player_data)) return false; 63 | if ($event->getTouchVector() == $this->getAthleticFinishPos($player)) { 64 | return true; 65 | } 66 | return false; 67 | } 68 | 69 | public function getAthleticFinishPos(Player $player) 70 | { 71 | return self::$json->get($this->player_data[$player->getName()]["Athletic"])["Finish"]; 72 | } 73 | 74 | public static function setAthletic(string $athle_name, string $author, $x, $y, $z, Vector3 $startPos, Vector3 $finishPos, int $prize): bool 75 | { 76 | if (self::$json->exists($athle_name)) { 77 | return false; 78 | } 79 | self::$json->set($athle_name, [ 80 | "Author" => $author, 81 | "SpawnX" => $x, 82 | "SpawnY" => $y, 83 | "SpawnZ" => $z, 84 | "StartPos" => $startPos, 85 | "FinishPos" => $finishPos, 86 | "Prize" => $prize 87 | ]); 88 | return true; 89 | } 90 | 91 | public function loop(PlayerMoveEvent $event): void 92 | { 93 | $player = $event->getPlayer(); 94 | if ($player->getLevel()->getName() === "athletic") { 95 | if ($event->getTo()->getFloorY() < 4) { 96 | if (isset($this->player_data[$player->getName()])) { 97 | $pos = $this->player_data[$player->getName()]; 98 | $player->teleport(new Position($pos["X"], $pos["Y"], $pos["Z"], $player->getLevel()->getName())); 99 | $player->sendMessage("失敗"); 100 | unset($this->player_data[$player->getName()]); 101 | } 102 | } 103 | } 104 | } 105 | 106 | public function onQuit(PlayerQuitEvent $event): void 107 | { 108 | $player = $event->getPlayer(); 109 | if (isset($this->player_data[$player->getName()])) { 110 | unset($this->player_data[$player->getName()]); 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/Core/Commands/SetTagCommand.php: -------------------------------------------------------------------------------- 1 | setPermission("vector.network.player"); 35 | $this->setDescription("§6V§bN§eCoin§rを使ってタグを設定します。"); 36 | $this->plugin = $plugin; 37 | $this->money = new Money(); 38 | $this->tag = new Tag(); 39 | } 40 | 41 | public function execute(CommandSender $sender, string $commandLabel, array $args) 42 | { 43 | if (!$this->plugin->isEnabled()) { 44 | return false; 45 | } 46 | if (!$this->testPermission($sender)) { 47 | return false; 48 | } 49 | if (!$sender instanceof Player) { 50 | $sender->sendMessage(TextFormat::RED . "このコマンドはプレイヤーのみが実行できます。"); 51 | return true; 52 | } 53 | FormApi::makeCustomForm(function (Player $player, ?array $response) { 54 | if (!FormApi::formCancelled($response)) { 55 | if (empty($response[2])) { 56 | $player->sendMessage("§7[§c失敗§7] §cタグ名を記入して下さい。"); 57 | } else { 58 | if ($this->money->reduceMoney($player->getName(), 1000)) { 59 | $player->sendMessage("§7[§b情報§7] §6V§bN§eCoin§7を§61000§7消費しました。"); 60 | $this->tag->setTag($player, $response[2], self::getColor($response[1])); 61 | } else { 62 | $player->sendMessage(MessagesEnum::BUY_ERROR); 63 | } 64 | } 65 | } 66 | })->setTitle("Tag設定メニュー") 67 | ->addElement(new Label("§6V§bN§eCoin§rを§61000§r消費してタグを設定します。")) 68 | ->addElement(new Dropdown("タグの色を選択して下さい(選択してない場合は色なしになります。)", ["§0黒色", "§1濃い青色", "§2濃い緑色", "§3濃い水色", "§4濃い赤色", "§5紫色", "§6金色", "§7灰色", "§8灰色", "§9青色", "§a緑色", "§b水色", "§c赤色", "§d桃色", "§e黄色", "§f白色", "色無し"])) 69 | ->addElement(new Input("設定するタグの名前を入力してください。", "最大8文字")) 70 | ->sendToPlayer($sender); 71 | return true; 72 | } 73 | 74 | private static function getColor(string $color = null): int 75 | { 76 | switch ($color) { 77 | case "§0黒色": 78 | return 0; 79 | break; 80 | case "§1濃い青色": 81 | return 1; 82 | break; 83 | case "§2濃い緑色": 84 | return 2; 85 | break; 86 | case "§3濃い水色": 87 | return 3; 88 | break; 89 | case "§4濃い赤色": 90 | return 4; 91 | break; 92 | case "§5紫色": 93 | return 5; 94 | break; 95 | case "§6金色": 96 | return 6; 97 | break; 98 | case "§7灰色": 99 | return 7; 100 | break; 101 | case "§8灰色": 102 | return 8; 103 | break; 104 | case "§9青色": 105 | return 9; 106 | break; 107 | case "§a緑色": 108 | return 10; 109 | break; 110 | case "§b水色": 111 | return 11; 112 | break; 113 | case "§c赤色": 114 | return 12; 115 | break; 116 | case "§d桃色": 117 | return 13; 118 | break; 119 | case "§e黄色": 120 | return 14; 121 | break; 122 | case "§f白色": 123 | return 15; 124 | break; 125 | case "色無し": 126 | return 16; 127 | break; 128 | default: 129 | return 16; 130 | break; 131 | } 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /src/Core/Player/KillSound.php: -------------------------------------------------------------------------------- 1 | plugin = $plugin; 23 | } 24 | 25 | /** 26 | * @param string $name 27 | * @return int 28 | */ 29 | public function getKillSound(string $name): int 30 | { 31 | $datafile = new DataFile($name); 32 | $data = $datafile->get('USERDATA'); 33 | return $data['killsound']; 34 | } 35 | 36 | /** 37 | * @param Player $player 38 | * @param int $soundid 39 | */ 40 | public function setKillSound(Player $player, int $soundid) 41 | { 42 | $datafile = new DataFile($player->getName()); 43 | $data = $datafile->get('USERDATA'); 44 | switch ($soundid) { 45 | case 0: 46 | $data['killsound'] = 0; 47 | break; 48 | case 1: 49 | $data['killsound'] = 1; 50 | break; 51 | case 2: 52 | $data['killsound'] = 2; 53 | break; 54 | case 3: 55 | $data['killsound'] = 3; 56 | break; 57 | case 4: 58 | $data['killsound'] = 4; 59 | break; 60 | case 5: 61 | $data['killsound'] = 5; 62 | break; 63 | case 6: 64 | $data['killsound'] = 6; 65 | break; 66 | case 7: 67 | $data['killsound'] = 7; 68 | break; 69 | case 8: 70 | $data['killsound'] = 8; 71 | break; 72 | default: 73 | $this->plugin->getLogger()->error("指定されたSoundIDが見つかりませんでした。"); 74 | break; 75 | } 76 | $datafile->write('USERDATA', $data); 77 | } 78 | 79 | /** 80 | * @param Player $player 81 | */ 82 | public function PlaySound(Player $player) 83 | { 84 | $datafile = new DataFile($player->getName()); 85 | $data = $datafile->get('USERDATA'); 86 | switch ($data['killsound']) { 87 | case 0: 88 | return; 89 | break; 90 | case 1: 91 | $this->PlaySoundPacket($player, "music.tin", $player->getX(), $player->getY(), $player->getZ()); 92 | break; 93 | case 2: 94 | $this->PlaySoundPacket($player, "music.1up", $player->getX(), $player->getY(), $player->getZ()); 95 | break; 96 | case 3: 97 | $this->PlaySoundPacket($player, "music.guki", $player->getX(), $player->getY(), $player->getZ()); 98 | break; 99 | case 4: 100 | $this->PlaySoundPacket($player, "music.dededon", $player->getX(), $player->getY(), $player->getZ()); 101 | break; 102 | case 5: 103 | $this->PlaySoundPacket($player, "music.picyun", $player->getX(), $player->getY(), $player->getZ()); 104 | break; 105 | case 6: 106 | $this->PlaySoundPacket($player, "music.busu", $player->getX(), $player->getY(), $player->getZ()); 107 | break; 108 | case 7: 109 | $this->PlaySoundPacket($player, "music.musuka1", $player->getX(), $player->getY(), $player->getZ()); 110 | break; 111 | case 8: 112 | $this->PlaySoundPacket($player, "music.musuka2", $player->getX(), $player->getY(), $player->getZ()); 113 | break; 114 | } 115 | } 116 | 117 | /** 118 | * @param Player $player 119 | * @param string $soundname 120 | * @param int $x 121 | * @param int $y 122 | * @param int $z 123 | * @param int $volume 124 | * @param float $pitch 125 | */ 126 | public function PlaySoundPacket(Player $player, string $soundname, int $x, int $y, int $z, int $volume = 1, float $pitch = 1) 127 | { 128 | $sound = new PlaySoundPacket(); 129 | $sound->soundName = $soundname; 130 | $sound->volume = $volume; 131 | $sound->pitch = $pitch; 132 | $sound->x = $x; 133 | $sound->y = $y; 134 | $sound->z = $z; 135 | $player->sendDataPacket($sound, false); 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /src/Core/Entity/EntityBase.php: -------------------------------------------------------------------------------- 1 | uuid = ($uuid = UUID::fromRandom()); 48 | $addPlayerPacket->username = $username; 49 | $addPlayerPacket->entityRuntimeId = ($eid = Entity::$entityCount++); 50 | $addPlayerPacket->position = $pos; 51 | $addPlayerPacket->yaw = $yaw; 52 | $addPlayerPacket->headYaw = $headyaw; 53 | $addPlayerPacket->item = $item; 54 | $flags = ( 55 | (1 << Entity::DATA_FLAG_CAN_SHOW_NAMETAG) | 56 | (1 << Entity::DATA_FLAG_ALWAYS_SHOW_NAMETAG) | 57 | (1 << Entity::DATA_FLAG_IMMOBILE) 58 | ); 59 | $addPlayerPacket->metadata = [ 60 | Entity::DATA_FLAGS => [Entity::DATA_TYPE_LONG, $flags], 61 | Entity::DATA_NAMETAG => [Entity::DATA_TYPE_STRING, $username] 62 | ]; 63 | $player->sendDataPacket($addPlayerPacket); 64 | for ($type = 0; $type <= 1; $type++) { 65 | $playerListPacket = new PlayerListPacket(); 66 | $playerListPacket->entries[] = PlayerListEntry::createAdditionEntry 67 | ( 68 | $uuid, 69 | $eid, 70 | "", 71 | "", 72 | 0, 73 | new Skin("Standard_Custom", base64_decode(file_get_contents("plugins/Games_Core/resources/skins/$skin"))) 74 | ); 75 | $playerListPacket->type = $type; 76 | $player->sendDataPacket($playerListPacket); 77 | } 78 | static::$players[$player->getName()][$id] = $eid; 79 | } 80 | 81 | 82 | /** 83 | * @param Player $player 84 | * @param int $id 85 | */ 86 | public function Remove(Player $player, int $id): void 87 | { 88 | if (isset(static::$players[$player->getName()][$id])) { 89 | $eid = static::$players[$player->getName()][$id]; 90 | $removeEntityPacket = new RemoveEntityPacket(); 91 | $removeEntityPacket->entityUniqueId = $eid; 92 | $player->sendDataPacket($removeEntityPacket); 93 | unset(static::$players[$player->getName()][$id]); 94 | } 95 | } 96 | 97 | /** 98 | * @param Player $player 99 | * @param int $id 100 | * @return int 101 | */ 102 | public static function getEid(Player $player, int $id): int 103 | { 104 | if (isset(static::$players[$player->getName()][$id])) { 105 | $eid = static::$players[$player->getName()][$id]; 106 | return $eid; 107 | } else { 108 | return 0; 109 | } 110 | } 111 | 112 | /** 113 | * @param EntityLevelChangeEvent $event 114 | * @return mixed 115 | */ 116 | abstract public function Check(EntityLevelChangeEvent $event): void; 117 | 118 | /** 119 | * @param DataPacketReceiveEvent $event 120 | * @return mixed 121 | */ 122 | abstract public function ClickEntity(DataPacketReceiveEvent $event): void; 123 | } -------------------------------------------------------------------------------- /src/Core/Commands/RankShopCommand.php: -------------------------------------------------------------------------------- 1 | setPermission("vnp.command.rankshop"); 41 | $this->setDescription("§6V§bN§eCoin§rでランク買います。"); 42 | $this->plugin = $plugin; 43 | $this->money = new Money(); 44 | $this->rank = new Rank($plugin); 45 | } 46 | 47 | public function execute(CommandSender $sender, string $commandLabel, array $args) 48 | { 49 | if (!$this->plugin->isEnabled()) { 50 | return false; 51 | } 52 | if (!$this->testPermission($sender)) { 53 | return false; 54 | } 55 | if ($sender instanceof Player) { 56 | FormApi::makeCustomForm(function(Player $player, ?array $response) { 57 | if (!FormApi::formCancelled($response)) { 58 | switch ($response[0]) { 59 | case self::$ranks[0]: 60 | if ($this->money->reduceMoney($player->getName(), 1500000)) { 61 | $player->sendMessage(MessagesEnum::BUY_SUCCESS); 62 | $this->rank->setRank($player->getName(), 1); 63 | } else { 64 | $player->sendMessage(MessagesEnum::BUY_ERROR); 65 | } 66 | break; 67 | case self::$ranks[1]: 68 | if ($this->money->reduceMoney($player->getName(), 1000000)) { 69 | $player->sendMessage(MessagesEnum::BUY_SUCCESS); 70 | $this->rank->setRank($player->getName(), 2); 71 | } else { 72 | $player->sendMessage(MessagesEnum::BUY_ERROR); 73 | } 74 | break; 75 | case self::$ranks[2]: 76 | if ($this->money->reduceMoney($player->getName(), 700000)) { 77 | $player->sendMessage(MessagesEnum::BUY_SUCCESS); 78 | $this->rank->setRank($player->getName(), 3); 79 | } else { 80 | $player->sendMessage(MessagesEnum::BUY_ERROR); 81 | } 82 | break; 83 | case self::$ranks[3]: 84 | if ($this->money->reduceMoney($player->getName(), 500000)) { 85 | $player->sendMessage(MessagesEnum::BUY_SUCCESS); 86 | $this->rank->setRank($player->getName(), 4); 87 | } else { 88 | $player->sendMessage(MessagesEnum::BUY_ERROR); 89 | } 90 | break; 91 | case self::$ranks[4]: 92 | if ($this->money->reduceMoney($player->getName(), 300000)) { 93 | $player->sendMessage(MessagesEnum::BUY_SUCCESS); 94 | $this->rank->setRank($player->getName(), 5); 95 | } else { 96 | $player->sendMessage(MessagesEnum::BUY_ERROR); 97 | } 98 | break; 99 | case self::$ranks[5]: 100 | if ($this->money->reduceMoney($player->getName(), 100000)) { 101 | $player->sendMessage(MessagesEnum::BUY_SUCCESS); 102 | $this->rank->setRank($player->getName(), 6); 103 | } else { 104 | $player->sendMessage(MessagesEnum::BUY_ERROR); 105 | } 106 | break; 107 | case self::$ranks[6]: 108 | if ($this->money->reduceMoney($player->getName(), 50000)) { 109 | $player->sendMessage(MessagesEnum::BUY_SUCCESS); 110 | $this->rank->setRank($player->getName(), 7); 111 | } else { 112 | $player->sendMessage(MessagesEnum::BUY_ERROR); 113 | } 114 | break; 115 | default: 116 | $player->sendMessage("§7[§c失敗§7] §c購入をキャンセルしました。"); 117 | break; 118 | } 119 | } 120 | })->setTitle("RankShop") 121 | ->addElement(new Dropdown("§6V§bN§eCoin§rを消費してランクを買う事が出来ます。", self::$ranks)) 122 | ->addElement(new Label("§6V§bN §61500000 §eCoin\n§5S §61000000 §eCoin\n§eA §6700000 §eCoin\n§cB §6500000 §eCoin\n§aC §6300000 §eCoin\n§3D §6100000 §eCoin\n§7E §650000 §eCoin")) 123 | ->sendToPlayer($sender); 124 | return true; 125 | } 126 | $sender->sendMessage(TextFormat::RED . "このコマンドはプレイヤーのみが実行できます。"); 127 | return true; 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /src/Core/Commands/StatusCommand.php: -------------------------------------------------------------------------------- 1 | setPermission("vector.network.player"); 40 | $this->setDescription("自分のステータスを表示します。"); 41 | $this->plugin = $plugin; 42 | $this->level = new Level(); 43 | $this->money = new Money(); 44 | $this->rank = new Rank($this->plugin); 45 | $this->kd = new KD(); 46 | $this->mazai = new MazaiPoint(); 47 | } 48 | 49 | public function execute(CommandSender $sender, string $commandLabel, array $args) 50 | { 51 | if (!$this->plugin->isEnabled()) { 52 | return false; 53 | } 54 | if (!$this->testPermission($sender)) { 55 | return false; 56 | } 57 | if ($sender instanceof Player) { 58 | $name = $sender->getName(); 59 | $datafile = new DataFile($name); 60 | $userdata = $datafile->get('USERDATA'); 61 | $ffapvp = $datafile->get('FFAPVP'); 62 | $speedcorepvp = $datafile->get('COREPVP'); 63 | $level = $this->level->getLevel($name); 64 | $money = $this->money->getMoney($name); 65 | $exp = $this->level->getExp($name); 66 | $firstlogin = $userdata['firstlogin']; 67 | $lastlogin = $userdata['lastlogin']; 68 | $maxexp = $userdata['maxexp'] - $exp; 69 | $mazai = $this->mazai->getMazai($sender->getName()); 70 | $ffapvp_kill = $ffapvp['kill']; 71 | $ffapvp_death = $ffapvp['death']; 72 | $ffapvp_kd = $this->kd->FFAKD($name); 73 | $rank = $this->rank->getRank($name); 74 | $tag = $userdata['tag']; 75 | $speedcorepvp_kill = $speedcorepvp['kill']; 76 | $speedcorepvp_death = $speedcorepvp['death']; 77 | $speedcorepvp_breakcore = $speedcorepvp['breakcore']; 78 | $speedcorepvp_win = $speedcorepvp['win']; 79 | $speedcorepvp_lose = $speedcorepvp['lose']; 80 | $speedcorepvp_kd = $this->kd->SCPKD($sender->getName()); 81 | $speedcorepvp_wl = $this->kd->SCPWL($sender->getName()); 82 | $survival_kill = SurvivalCore::getKillCount($name); 83 | $survival_death = SurvivalCore::getDeathCount($name); 84 | $survival_place = SurvivalCore::getPlaceCount($name); 85 | $survival_breakblock = SurvivalCore::getBreakBlock($name); 86 | $survival_breakdiamond = SurvivalCore::getBreakDiamond($name); 87 | $survival_breakiron = SurvivalCore::getBreakIron($name); 88 | $survival_breakgold = SurvivalCore::getBreakGold($name); 89 | $survival_breakcoal = SurvivalCore::getBreakCoal($name); 90 | 91 | $custom = FormApi::makeCustomForm(function ($response) { 92 | if (!FormApi::formCancelled($response)) { 93 | } 94 | }); 95 | $custom->setTitle("§l$name のステータス") 96 | ->addElement(new Label(" 97 | 現在の§bレベル§r: $level 98 | 現在の§e経験値§r: $exp XP (次のレベルアップまで: $maxexp xp必要です。) 99 | §6V§bN§eCoin§r: $money 100 | §aMAZAI§r: $mazai 101 | Rank: $rank 102 | タグ: $tag 103 | 参加した日: $firstlogin 104 | 最終ログイン日: $lastlogin")) 105 | ->addElement(new Label(" 106 | ---=== §6FFA§cPvP §r===---\n 107 | §eキル数§r: $ffapvp_kill 108 | §cデス数§r: $ffapvp_death 109 | §eK§7/§cD§r: $ffapvp_kd")) 110 | ->addElement(new Label(" 111 | ---=== §bSpeed§aCore§cPvP §r===---\n 112 | §eキル数§r: $speedcorepvp_kill 113 | §cデス数§r: $speedcorepvp_death 114 | §aコア§c破壊回数§r: $speedcorepvp_breakcore 115 | §aWin§r: $speedcorepvp_win 116 | §cLose§r: $speedcorepvp_lose 117 | §eK§7/§cD§r: $speedcorepvp_kd 118 | §aW§7/§cL§r: $speedcorepvp_wl")) 119 | ->addElement(new Label(" 120 | ---=== §aSurvival §r===---\n 121 | §eキル数§r: $survival_kill 122 | §cデス数§r: $survival_death 123 | §aブロック§c破壊数§r: §s$survival_breakblock 124 | §aブロック§e設置数§r: $survival_place 125 | §a採掘した§bダイヤモンド§aの数§r: $survival_breakdiamond 126 | §a採掘した§e金鉱石§aの数§r: $survival_breakgold 127 | §a採掘した§7鉄鉱石§aの数§r: $survival_breakiron 128 | §a採掘した§0石炭鉱石§aの数§r: $survival_breakcoal")) 129 | ->sendToPlayer($sender); 130 | return true; 131 | } 132 | $sender->sendMessage(TextFormat::RED . "このコマンドはプレイヤーのみが実行できます。"); 133 | return true; 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /src/Core/Entity/Bossbar.php: -------------------------------------------------------------------------------- 1 | metadata = [ 38 | Entity::DATA_FLAGS => [Entity::DATA_TYPE_LONG, $flags], 39 | Entity::DATA_NAMETAG => [Entity::DATA_TYPE_STRING, $title]]; 40 | $this->setHealthPercent($hp, $maxHp); 41 | $this->entityId = Entity::$entityCount++; 42 | } 43 | 44 | /** 45 | * @param float|null $hp 46 | * @param float|null $maxHp 47 | * @param bool $update 48 | */ 49 | public function setHealthPercent(float $hp = null, float $maxHp = null, bool $update = true) 50 | { 51 | if ($maxHp !== null) { 52 | $this->maxHealthPercent = $maxHp; 53 | } 54 | if ($hp !== null) { 55 | if ($hp > $this->maxHealthPercent) { 56 | $this->maxHealthPercent = $hp; 57 | } 58 | $this->healthPercent = $hp; 59 | } 60 | if ($update) { 61 | $this->BossbarUpdateAll(); 62 | } 63 | } 64 | 65 | /** 66 | * @param Player $player 67 | */ 68 | public function RemoveBar(Player $player) 69 | { 70 | $pk = new BossEventPacket(); 71 | $pk->bossEid = $this->entityId; 72 | $pk->eventType = BossEventPacket::TYPE_HIDE; 73 | $player->sendDataPacket($pk); 74 | $pk2 = new RemoveEntityPacket(); 75 | $pk2->entityUniqueId = $this->entityId; 76 | $player->sendDataPacket($pk2); 77 | if (isset($this->viewers[$player->getLoaderId()])) { 78 | unset($this->viewers[$player->getLoaderId()]); 79 | } 80 | } 81 | 82 | /** 83 | * @param Player $player 84 | * @param bool $isViewer 85 | * @param int $color 86 | * @param int $overlay 87 | * @param int $unknownShort 88 | */ 89 | public function sendBar(Player $player, bool $isViewer = true, int $color = 0, int $overlay = 0, int $unknownShort = 0) 90 | { 91 | $pk = new AddEntityPacket; 92 | $pk->entityRuntimeId = $this->entityId; 93 | $pk->type = EntityIds::SHULKER; 94 | $pk->metadata = $this->metadata; 95 | $pk->position = $this; 96 | $player->sendDataPacket($pk); 97 | $player->sendDataPacket($this->getHealthPacket()); 98 | $pk2 = new BossEventPacket; 99 | $pk2->bossEid = $this->entityId; 100 | $pk2->eventType = BossEventPacket::TYPE_SHOW; 101 | $pk2->title = $this->getMetadata(Entity::DATA_NAMETAG); 102 | $pk2->healthPercent = $this->healthPercent; 103 | $pk2->overlay = $overlay; 104 | $pk2->unknownShort = $unknownShort; 105 | $pk2->color = $color; 106 | $player->sendDataPacket($pk2); 107 | if ($isViewer) { 108 | $this->viewers[$player->getLoaderId()] = $player; 109 | } 110 | } 111 | 112 | /** 113 | * @param Player $player 114 | */ 115 | public function BossbarUpdate(Player $player) 116 | { 117 | $pk = new BossEventPacket; 118 | $pk->bossEid = $this->entityId; 119 | $pk->eventType = BossEventPacket::TYPE_TITLE; 120 | $pk->healthPercent = $this->healthPercent; 121 | $pk->title = $this->getMetadata(Entity::DATA_NAMETAG); 122 | $player->sendDataPacket($pk); 123 | } 124 | 125 | public function BossbarUpdateAll(): void 126 | { 127 | foreach ($this->viewers as $player) { 128 | $this->BossbarUpdate($player); 129 | } 130 | } 131 | 132 | protected function getHealthPacket(): UpdateAttributesPacket 133 | { 134 | $attr = Attribute::getAttribute(Attribute::HEALTH); 135 | $attr->setMaxValue($this->maxHealthPercent); 136 | $attr->setValue($this->healthPercent); 137 | $pk = new UpdateAttributesPacket; 138 | $pk->entityRuntimeId = $this->entityId; 139 | $pk->entries = [$attr]; 140 | return $pk; 141 | } 142 | 143 | public function getMetadata(int $key) 144 | { 145 | return isset($this->metadata[$key]) ? $this->metadata[$key][1] : null; 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /src/Core/Event/PlayerDeath.php: -------------------------------------------------------------------------------- 1 | plugin = $plugin; 34 | $this->ffapvp = new FFAPvPCore($this->plugin); 35 | $this->speedcorepvp = new SpeedCorePvPCore($this->plugin); 36 | $this->survival = new SurvivalCore($this->plugin); 37 | $this->killsound = new KillSound($this->plugin); 38 | } 39 | 40 | public function event(PlayerDeathEvent $event): void 41 | { 42 | $event->setDeathMessage(null); 43 | $player = $event->getPlayer(); 44 | $cause = $player->getLastDamageCause(); 45 | if ($player->getLevel()->getName() === "ffapvp") { 46 | $event->setDrops([Item::get(0, 0, 0)]); 47 | $player->setMaxHealth(20); 48 | if ($cause instanceof EntityDamageByEntityEvent) { 49 | $damager = $cause->getDamager(); 50 | if ($damager instanceof Player) { 51 | $this->ffapvp->AddKillCount($damager); 52 | $this->ffapvp->AddDeathCount($player); 53 | $this->DeathMessage('ffapvp', $player->getName(), $damager->getName()); 54 | if ($damager->getMaxHealth() < 40) { 55 | $damager->setMaxHealth($damager->getMaxHealth() + 1); 56 | } 57 | $damager->getInventory()->addItem(Item::get(Item::GOLDEN_APPLE, 0, 1)); 58 | $this->killsound->PlaySound($damager); 59 | } 60 | } else { 61 | $this->DeathMessage('ffapvp', $player->getName()); 62 | $this->ffapvp->AddDeathCount($player); 63 | } 64 | } elseif ($player->getLevel()->getName() === "corepvp") { 65 | $drops = $event->getDrops(); 66 | foreach ($drops as $slot => $item) { 67 | switch ($item->getId()) { 68 | case Item::LEATHER_CAP: 69 | unset($drops[$slot]); 70 | break; 71 | case Item::LEATHER_CHESTPLATE: 72 | unset($drops[$slot]); 73 | break; 74 | case Item::LEATHER_LEGGINGS: 75 | unset($drops[$slot]); 76 | break; 77 | case Item::LEATHER_BOOTS: 78 | unset($drops[$slot]); 79 | break; 80 | case Item::GOLD_PICKAXE: 81 | unset($drops[$slot]); 82 | break; 83 | case Item::WOODEN_SWORD: 84 | unset($drops[$slot]); 85 | break; 86 | case Item::STONE_AXE: 87 | unset($drops[$slot]); 88 | break; 89 | case Item::STONE_SHOVEL: 90 | unset($drops[$slot]); 91 | break; 92 | } 93 | } 94 | $event->setDrops($drops); 95 | if ($cause instanceof EntityDamageByEntityEvent) { 96 | $damager = $cause->getDamager(); 97 | if ($damager instanceof Player) { 98 | $this->speedcorepvp->AddKillCount($damager); 99 | $this->speedcorepvp->addDeathCount($player); 100 | $this->killsound->PlaySound($damager); 101 | $this->DeathMessage('corepvp', $player->getName(), $damager->getName()); 102 | } 103 | } else { 104 | $this->DeathMessage('corepvp', $player->getName()); 105 | $this->speedcorepvp->addDeathCount($player); 106 | } 107 | } elseif ($player->getLevel()->getName() === "Survival") { 108 | if ($cause instanceof EntityDamageByEntityEvent) { 109 | $damager = $cause->getDamager(); 110 | if ($damager instanceof Player) { 111 | $this->survival->AddKillCount($damager); 112 | $this->survival->AddDeathCount($player); 113 | $this->killsound->PlaySound($damager); 114 | $this->DeathMessage("Survival", $player->getName(), $damager->getName()); 115 | } 116 | } else { 117 | $this->DeathMessage("Survival", $player->getName()); 118 | $this->survival->AddDeathCount($player); 119 | } 120 | } elseif ($player->getLevel()->getName() === "duel") { 121 | $duel = new DuelCore(); 122 | $duel->endGame($player); 123 | } 124 | } 125 | 126 | public function DeathMessage(string $levelname, string $killed = null, string $killer = null): void 127 | { 128 | foreach ($this->plugin->getServer()->getOnlinePlayers() as $player) { 129 | if ($player->getLevel()->getName() === $levelname) { 130 | if ($killer === null) { 131 | $player->sendMessage("§7[§b情報§7] §c✖ §7$killed"); 132 | } else { 133 | $player->sendMessage("§7[§b情報§7] §7$killer §c➡ §7$killed"); 134 | } 135 | } 136 | } 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /src/Core/Player/Level.php: -------------------------------------------------------------------------------- 1 | server = Server::getInstance(); 21 | } 22 | 23 | /** 24 | * @param string $name 25 | * @param int $level 26 | */ 27 | public function setLevel(string $name, int $level) 28 | { 29 | $datafile = new DataFile($name); 30 | $data = $datafile->get('USERDATA'); 31 | $data['networklevel'] = $level; 32 | $datafile->write('USERDATA', $data); 33 | } 34 | 35 | /** 36 | * @param string $name 37 | * @param int $maxexp 38 | */ 39 | public function setMaxExp(string $name, int $maxexp) 40 | { 41 | $datafile = new DataFile($name); 42 | $data = $datafile->get('USERDATA'); 43 | $data['maxexp'] = $maxexp; 44 | $datafile->write('USERDATA', $data); 45 | } 46 | 47 | /** 48 | * @param Player $player 49 | */ 50 | public function LevelSystem(Player $player) 51 | { 52 | $exp = $this->getExp($player->getName()); 53 | $maxexp = $this->getMaxExp($player->getName()); 54 | if ($exp >= $maxexp) { 55 | $this->addMaxExp($player->getName(), 50); 56 | $this->addLevel($player->getName(), 1); 57 | $this->setExp($player->getName(), 0); 58 | $level = $this->getLevel($player->getName()); 59 | $name = $player->getName(); 60 | $this->server->broadcastMessage("§7[§b情報§7] $name が Lv.$level になりました。"); 61 | } else { 62 | $rand = mt_rand(1, 10); 63 | $this->addExp($player->getName(), $rand); 64 | $player->sendMessage("§a+$rand EXP"); 65 | } 66 | } 67 | 68 | /** 69 | * @param string $name 70 | * @return int 71 | */ 72 | public function getExp(string $name) : int 73 | { 74 | $datafile = new DataFile($name); 75 | $data = $datafile->get('USERDATA'); 76 | return $data['exp']; 77 | } 78 | 79 | /** 80 | * @param string $name 81 | * @return int 82 | */ 83 | public function getMaxExp(string $name) : int 84 | { 85 | $datafile = new DataFile($name); 86 | $data = $datafile->get('USERDATA'); 87 | return $data['maxexp']; 88 | } 89 | 90 | /** 91 | * @param string $name 92 | * @param int $maxexp 93 | */ 94 | public function addMaxExp(string $name, int $maxexp) 95 | { 96 | $datafile = new DataFile($name); 97 | $data = $datafile->get('USERDATA'); 98 | $data['maxexp'] += $maxexp; 99 | $datafile->write('USERDATA', $data); 100 | } 101 | 102 | /** 103 | * @param string $name 104 | * @param int $level 105 | */ 106 | public function addLevel(string $name, int $level) 107 | { 108 | $datafile = new DataFile($name); 109 | $data = $datafile->get('USERDATA'); 110 | $data['networklevel'] += $level; 111 | $datafile->write('USERDATA', $data); 112 | } 113 | 114 | /** 115 | * @param string $name 116 | * @param int $exp 117 | */ 118 | public function setExp(string $name, int $exp) 119 | { 120 | $datafile = new DataFile($name); 121 | $data = $datafile->get('USERDATA'); 122 | $data['exp'] = $exp; 123 | $datafile->write('USERDATA', $data); 124 | } 125 | 126 | /** 127 | * @param string $name 128 | * @return int 129 | */ 130 | public function getLevel(string $name) : int 131 | { 132 | $datafile = new DataFile($name); 133 | $data = $datafile->get('USERDATA'); 134 | return $data['networklevel']; 135 | } 136 | 137 | /** 138 | * @param string $name 139 | * @param int $exp 140 | */ 141 | public function addExp(string $name, int $exp) 142 | { 143 | $datafile = new DataFile($name); 144 | $data = $datafile->get('USERDATA'); 145 | $data['exp'] += $exp; 146 | $datafile->write('USERDATA', $data); 147 | } 148 | 149 | public function Checking(Player $player) 150 | { 151 | $exp = $this->getExp($player->getName()); 152 | $maxexp = $this->getMaxExp($player->getName()); 153 | if ($exp >= $maxexp) { 154 | $this->addMaxExp($player->getName(), 50); 155 | $this->addLevel($player->getName(), 1); 156 | $this->setExp($player->getName(), 0); 157 | $level = $this->getLevel($player->getName()); 158 | $name = $player->getName(); 159 | $this->server->broadcastMessage("§7[§b情報§7] $name が Lv.$level になりました。"); 160 | } 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /src/Core/Commands/SelectGameCommand.php: -------------------------------------------------------------------------------- 1 | setPermission("vnp.command.selectgame"); 35 | $this->setDescription("遊びたいゲームを選択できます。"); 36 | $this->plugin = $plugin; 37 | } 38 | 39 | public function execute(CommandSender $sender, string $commandLabel, array $args) 40 | { 41 | if (!$this->plugin->isEnabled()) { 42 | return false; 43 | } 44 | if (!$this->testPermission($sender)) { 45 | return false; 46 | } 47 | if (!$sender instanceof Player) { 48 | $sender->sendMessage(TextFormat::RED . "このコマンドはプレイヤーのみが実行できます。"); 49 | return true; 50 | } 51 | FormApi::makeListForm(function (Player $player, ?int $key) { 52 | if (!FormApi::formCancelled($key)) { 53 | $level = $player->getLevel(); 54 | switch ($key) { 55 | case 0: 56 | if ($level->getName() === "lobby") { 57 | $player->sendMessage("§c既にロビーに居ます。"); 58 | } else { 59 | $player->sendMessage("§e10秒後テレポートします。"); 60 | $this->plugin->getScheduler()->scheduleDelayedTask(new TeleportLobbyTask($this->plugin, $player), 10 * 20); 61 | } 62 | break; 63 | case 1: 64 | if ($level->getName() === "ffapvp") { 65 | $player->sendMessage("§c既にFFAPvPに居ます"); 66 | } else { 67 | if ($level->getName() === "lobby") { 68 | $player->teleport(new Position(254, 107, 254, $this->plugin->getServer()->getLevelByName("ffapvp"))); 69 | $player->setSpawn(new Position(254, 107, 254, $this->plugin->getServer()->getLevelByName("ffapvp"))); 70 | $player->sendMessage("§aテレポートしました。"); 71 | } else { 72 | $player->sendMessage("§e10秒後テレポートします。"); 73 | $this->plugin->getScheduler()->scheduleDelayedTask(new TeleportFFAPvPTask($this->plugin, $player), 10 * 20); 74 | } 75 | } 76 | break; 77 | case 2: 78 | if ($level->getName() === "corepvp") { 79 | $player->sendMessage("§c既にCorePvPに居ます"); 80 | } else { 81 | if ($level->getName() === "lobby") { 82 | $player->teleport(new Position(255, 8, 257, $this->plugin->getServer()->getLevelByName("corepvp"))); 83 | $player->sendMessage("§aテレポートしました。"); 84 | } else { 85 | $player->sendMessage("§e10秒後テレポートします。"); 86 | $this->plugin->getScheduler()->scheduleDelayedTask(new TeleportSpeedCorePvPTask($this->plugin, $player), 10 * 20); 87 | } 88 | } 89 | break; 90 | case 3: 91 | if ($player->isOp()) { 92 | if ($level->getName() === "athletic") { 93 | $player->sendMessage("§c既にAthleticに居ます"); 94 | } else { 95 | if ($level->getName() === "lobby") { 96 | $player->teleport(new Position(254, 4, 254, $this->plugin->getServer()->getLevelByName("athletic"))); 97 | $player->sendMessage("§aテレポートしました。"); 98 | } else { 99 | $player->sendMessage("§e10秒後テレポートします。"); 100 | $this->plugin->getScheduler()->scheduleDelayedTask(new TeleportAthleticTask($this->plugin, $player), 10 * 20); 101 | } 102 | } 103 | } else { 104 | $player->sendMessage("現在開発者のみがテレポートする事が出来ます。"); 105 | } 106 | break; 107 | case 4: 108 | FormApi::makeModalForm(function (Player $player, ?bool $bool) { 109 | if (!FormApi::formCancelled($bool)) { 110 | if ($bool) { 111 | $level = $player->getLevel(); 112 | if ($level->getName() === "Survival") { 113 | $player->sendMessage("§c既にSurvivalに居ます"); 114 | } else { 115 | if ($level->getName() === "lobby") { 116 | SurvivalCore::Teleport($player); 117 | $player->setSpawn(new Position(225, 243, 256, $this->plugin->getServer()->getLevelByName("Survival"))); 118 | $player->sendMessage("§aテレポートしました。"); 119 | } else { 120 | $player->sendMessage("§e10秒後テレポートします。"); 121 | $this->plugin->getScheduler()->scheduleDelayedTask(new TeleportSurvivalTask($this->plugin, $player), 10 * 20); 122 | } 123 | } 124 | } 125 | } 126 | })->setTitle("注意") 127 | ->setContent("このゲームのステージはかなり重くアプリがクラッシュする事があります。\nそれでも参加したい方は諦めずに参加を繰り返して下さい。") 128 | ->setButtonText(true, "俺の端末にクラッシュなんてねぇ") 129 | ->setButtonText(false, "いや俺の端末はクソだから...") 130 | ->sendToPlayer($player); 131 | break; 132 | case 5: 133 | if ($player->isOp()) { 134 | if ($level->getName() === "duel") { 135 | $player->sendMessage("§c既にDuelに居ます"); 136 | } else { 137 | if ($level->getName() === "lobby") { 138 | $player->teleport(new Position(254, 4, 254, $this->plugin->getServer()->getLevelByName("duel"))); 139 | $player->sendMessage("§aテレポートしました。"); 140 | } else { 141 | $player->sendMessage("§e10秒後テレポートします。"); 142 | $this->plugin->getScheduler()->scheduleDelayedTask(new TeleportDuelTask($this->plugin, $player), 10 * 20); 143 | } 144 | } 145 | } else { 146 | $player->sendMessage("現在開発者のみがテレポートする事が出来ます。"); 147 | } 148 | break; 149 | } 150 | } 151 | })->setTitle("ゲーム選択") 152 | ->setContent("遊びたいゲームを選択してください") 153 | ->addButton(new Button("§eロビー")) 154 | ->addButton(new Button("§6FFA§cPvP")) 155 | ->addButton(new Button("§bSpeed§aCore§cPvP")) 156 | ->addButton(new Button("§dAthletic")) 157 | ->addButton(new Button("§aSurvival")) 158 | ->addButton(new Button("§7Duel")) 159 | ->sendToPlayer($sender); 160 | return true; 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /src/Core/Entity/GameMaster.php: -------------------------------------------------------------------------------- 1 | plugin = $plugin; 37 | } 38 | 39 | /** 40 | * @param EntityLevelChangeEvent $event 41 | */ 42 | public function Check(EntityLevelChangeEvent $event): void 43 | { 44 | $entity = $event->getEntity(); 45 | if ($entity instanceof Player) { 46 | if ($event->getTarget()->getName() === 'lobby') { 47 | $this->Create($entity, "§aGame§7Master", "GameMaster", new Vector3(252, 4, 265), Item::get(Item::COMPASS, 0, 1), self::ENTITY_ID); 48 | } else { 49 | $this->Remove($entity, self::ENTITY_ID); 50 | } 51 | } 52 | } 53 | 54 | public function ClickEntity(DataPacketReceiveEvent $event): void 55 | { 56 | $packet = $event->getPacket(); 57 | $player = $event->getPlayer(); 58 | if ($packet instanceof InventoryTransactionPacket) { 59 | if ($packet->transactionType === $packet::TYPE_USE_ITEM_ON_ENTITY) { 60 | if ($packet->trData->entityRuntimeId === self::getEid($player, self::ENTITY_ID)) { 61 | FormApi::makeListForm(function (Player $player, ?int $key) { 62 | if (!FormApi::formCancelled($key)) { 63 | $level = $player->getLevel(); 64 | switch ($key) { 65 | case 0: 66 | if ($level->getName() === "lobby") { 67 | $player->sendMessage("§c既にロビーに居ます。"); 68 | } else { 69 | $player->sendMessage("§e10秒後テレポートします。"); 70 | $this->plugin->getScheduler()->scheduleDelayedTask(new TeleportLobbyTask($this->plugin, $player), 10 * 20); 71 | } 72 | break; 73 | case 1: 74 | if ($level->getName() === "ffapvp") { 75 | $player->sendMessage("§c既にFFAPvPに居ます"); 76 | } else { 77 | if ($level->getName() === "lobby") { 78 | $player->teleport(new Position(254, 107, 254, $this->plugin->getServer()->getLevelByName("ffapvp"))); 79 | $player->setSpawn(new Position(254, 107, 254, $this->plugin->getServer()->getLevelByName("ffapvp"))); 80 | $player->sendMessage("§aテレポートしました。"); 81 | } else { 82 | $player->sendMessage("§e10秒後テレポートします。"); 83 | $this->plugin->getScheduler()->scheduleDelayedTask(new TeleportFFAPvPTask($this->plugin, $player), 10 * 20); 84 | } 85 | } 86 | break; 87 | case 2: 88 | if ($level->getName() === "corepvp") { 89 | $player->sendMessage("§c既にCorePvPに居ます"); 90 | } else { 91 | if ($level->getName() === "lobby") { 92 | $player->teleport(new Position(255, 8, 257, $this->plugin->getServer()->getLevelByName("corepvp"))); 93 | $player->sendMessage("§aテレポートしました。"); 94 | } else { 95 | $player->sendMessage("§e10秒後テレポートします。"); 96 | $this->plugin->getScheduler()->scheduleDelayedTask(new TeleportSpeedCorePvPTask($this->plugin, $player), 10 * 20); 97 | } 98 | } 99 | break; 100 | case 3: 101 | if ($player->isOp()) { 102 | if ($level->getName() === "athletic") { 103 | $player->sendMessage("§c既にAthleticに居ます"); 104 | } else { 105 | if ($level->getName() === "lobby") { 106 | $player->teleport(new Position(254, 4, 254, $this->plugin->getServer()->getLevelByName("athletic"))); 107 | $player->sendMessage("§aテレポートしました。"); 108 | } else { 109 | $player->sendMessage("§e10秒後テレポートします。"); 110 | $this->plugin->getScheduler()->scheduleDelayedTask(new TeleportAthleticTask($this->plugin, $player), 10 * 20); 111 | } 112 | } 113 | } else { 114 | $player->sendMessage("現在開発者のみがテレポートする事が出来ます。"); 115 | } 116 | break; 117 | case 4: 118 | FormApi::makeModalForm(function (Player $player, ?bool $bool) { 119 | if (!FormApi::formCancelled($bool)) { 120 | if ($bool) { 121 | $level = $player->getLevel(); 122 | if ($level->getName() === "Survival") { 123 | $player->sendMessage("§c既にSurvivalに居ます"); 124 | } else { 125 | if ($level->getName() === "lobby") { 126 | $player->teleport(new Position(225, 243, 256, $this->plugin->getServer()->getLevelByName("Survival"))); 127 | $player->setSpawn(new Position(225, 243, 256, $this->plugin->getServer()->getLevelByName("Survival"))); 128 | $player->sendMessage("§aテレポートしました。"); 129 | } else { 130 | $player->sendMessage("§e10秒後テレポートします。"); 131 | $this->plugin->getScheduler()->scheduleDelayedTask(new TeleportSurvivalTask($this->plugin, $player), 10 * 20); 132 | } 133 | } 134 | } 135 | } 136 | })->setTitle("注意") 137 | ->setContent("このゲームのステージはかなり重くアプリがクラッシュする事があります。\nそれでも参加したい方は諦めずに参加を繰り返して下さい。") 138 | ->setButtonText(true, "俺の端末にクラッシュなんてねぇ") 139 | ->setButtonText(false, "いや俺の端末はクソだから...") 140 | ->sendToPlayer($player); 141 | break; 142 | case 5: 143 | if ($player->isOp()) { 144 | if ($level->getName() === "duel") { 145 | $player->sendMessage("§c既にDuelに居ます"); 146 | } else { 147 | if ($level->getName() === "lobby") { 148 | $player->teleport(new Position(254, 4, 254, $this->plugin->getServer()->getLevelByName("duel"))); 149 | $player->sendMessage("§aテレポートしました。"); 150 | } else { 151 | $player->sendMessage("§e10秒後テレポートします。"); 152 | $this->plugin->getScheduler()->scheduleDelayedTask(new TeleportDuelTask($this->plugin, $player), 10 * 20); 153 | } 154 | } 155 | } else { 156 | $player->sendMessage("現在開発者のみがテレポートする事が出来ます。"); 157 | } 158 | break; 159 | } 160 | } 161 | })->setTitle("ゲーム選択") 162 | ->setContent("遊びたいゲームを選択してください") 163 | ->addButton(new Button("§eロビー")) 164 | ->addButton(new Button("§6FFA§cPvP")) 165 | ->addButton(new Button("§bSpeed§aCore§cPvP")) 166 | ->addButton(new Button("§dAthletic")) 167 | ->addButton(new Button("§aSurvival")) 168 | ->addButton(new Button("§7Duel")) 169 | ->sendToPlayer($player); 170 | } 171 | } 172 | } 173 | } 174 | } -------------------------------------------------------------------------------- /src/Core/Main.php: -------------------------------------------------------------------------------- 1 | registerCommands(); 82 | } 83 | 84 | protected function onEnable(): void 85 | { 86 | $this->init(); 87 | $this->getLogger()->info(self::START_MESSAGE); 88 | Discord::SendEmbed("SERVER STATUS", "ONLINE", "サーバーがオンラインになりました。", 65280); 89 | } 90 | 91 | protected function onDisable(): void 92 | { 93 | Discord::SendEmbed("SERVER STATUS", "OFFLINE", "サーバーがオフラインになりました。", 16711680); 94 | $this->getLogger()->info(TextFormat::RED . "Games_Coreを終了しました。"); 95 | } 96 | 97 | private function init(): void 98 | { 99 | date_default_timezone_set("Asia/Tokyo"); 100 | self::$datafolder = $this->getDataFolder(); 101 | $this->getServer()->getPluginManager()->registerEvents(new EventListener($this), $this); 102 | // TODO: $this->registerEvents(); 103 | $this->saveDefaultConfig(); 104 | $this->loadLevels()->setLevelsTime()->runTasks()->registerRecipes(); 105 | Tag::registerColors(); 106 | FormApi::register($this); 107 | } 108 | 109 | private function setLevelsTime(): self 110 | { 111 | foreach ($this->getServer()->getLevels() as $level) { 112 | $level->setTime(6000); 113 | $level->stopTime(); 114 | } 115 | 116 | return $this; 117 | } 118 | 119 | private function runTasks(): self 120 | { 121 | $this->getScheduler()->scheduleRepeatingTask(new Tip($this), 180 * 20); 122 | $this->getScheduler()->scheduleRepeatingTask(new AutoSavingTask($this), 10 * 20); 123 | $this->getScheduler()->scheduleRepeatingTask(new RemoveItemTask($this), 30 * 20); 124 | $this->getScheduler()->scheduleRepeatingTask(new MOTDTip($this), 30 * 20); 125 | 126 | return $this; 127 | } 128 | 129 | private function registerRecipes(): self 130 | { 131 | $recipes = [ 132 | "豪華なベッド" => new ShapedRecipe( 133 | [ 134 | " A ", 135 | "BBB", 136 | "CCC"], 137 | [ 138 | "A" => Item::get(Item::REDSTONE_TORCH, 0, 3), 139 | "B" => Item::get(Item::DIAMOND, 0, 1), 140 | "C" => Item::get(Item::WOODEN_PLANKS, 0, 1) 141 | ], 142 | [ 143 | Item::get(Item::BED, 0, 1)->setCustomName("§l§b綺麗なベット") 144 | ] 145 | ) 146 | ]; 147 | 148 | foreach ($recipes as $recipe) { 149 | $this->getServer()->getCraftingManager()->registerRecipe($recipe); 150 | } 151 | 152 | return $this; 153 | } 154 | 155 | private function loadLevels(): self 156 | { 157 | foreach (scandir('worlds/') as $levelName) { 158 | if ($levelName === '.' or $levelName === '..' or $levelName === $this->getServer()->getDefaultLevel()->getName()) { 159 | continue; 160 | } 161 | $this->getServer()->loadLevel($levelName); 162 | } 163 | return $this; 164 | } 165 | 166 | private function registerCommands(): self 167 | { 168 | $commands = [ 169 | new PingCommand($this), 170 | new StatusCommand($this), 171 | new RankShopCommand($this), 172 | new SetMoneyCommand($this), 173 | new SetTagCommand($this), 174 | new SelectGameCommand($this), 175 | new DebugCommand($this), 176 | new KillSoundCommand($this), 177 | new AddTagCommand($this), 178 | new GameStatusCommand($this) 179 | ]; 180 | $this->getServer()->getCommandMap()->registerAll($this->getName(), $commands); 181 | return $this; 182 | } 183 | 184 | private function registerEvents(): self 185 | { 186 | $plm = $this->getServer()->getPluginManager(); 187 | $plm->registerEvents(new BlockBreak($this), $this); 188 | $plm->registerEvents(new BlockPlace($this), $this); 189 | $plm->registerEvents(new EntityDamage($this), $this); 190 | $plm->registerEvents(new EntityInventoryChange($this), $this); 191 | $plm->registerEvents(new EntityShootBow($this), $this); 192 | $plm->registerEvents(new PlayerCommandPreprocess($this), $this); 193 | $plm->registerEvents(new PlayerDeath($this), $this); 194 | $plm->registerEvents(new PlayerExhaust($this), $this); 195 | $plm->registerEvents(new PlayerJoin($this), $this); 196 | $plm->registerEvents(new PlayerLogin($this), $this); 197 | $plm->registerEvents(new PlayerMove($this), $this); 198 | $plm->registerEvents(new PlayerPreLogin($this), $this); 199 | $plm->registerEvents(new PlayerQuit($this), $this); 200 | $plm->registerEvents(new PlayerRespawn($this), $this); 201 | return $this; 202 | } 203 | 204 | public static function isDev(): bool 205 | { 206 | return self::$isDev; 207 | } 208 | } 209 | -------------------------------------------------------------------------------- /src/Core/Game/Duel/DuelCore.php: -------------------------------------------------------------------------------- 1 | stages = [ 42 | new Stage1(), 43 | //new Stage2(), 44 | //new Stage3(), 45 | //new Stage4(), 46 | //new Stage5(), 47 | //new Stage6(), 48 | ]; 49 | self::$money = new Money(); 50 | self::$level = new Level(); 51 | } 52 | 53 | public function create(int $gameId) 54 | { 55 | $this->players[$gameId] = 0; 56 | $this->playerslist[$gameId] = []; 57 | $this->status[$gameId] = false; 58 | } 59 | 60 | public function DuelJoin(Player $player, int $gameId = 0) 61 | { 62 | $name = $player->getName(); 63 | if ($player->getLevel()->getName() !== self::LEVEL_NAME) return; 64 | if (!$this->status[$gameId]) { 65 | if (empty($this->datas[$name])) { 66 | $data["gameId"] = $gameId; 67 | $this->datas[$name] = $data; 68 | $player->sendMessage("§aDuelに参加しました。"); 69 | $player->setImmobile(true); 70 | $this->players[$gameId]++; 71 | $this->playerslist[$gameId][$player->getId()] = $player; 72 | if ($this->players[$gameId] == self::DUEL_MAX_PLAYER) { 73 | $this->randStage($gameId); 74 | $this->status[$gameId] = true; 75 | $this->wattingGame($gameId); 76 | } 77 | } else { 78 | $player->sendMessage("§c既にDuelに参加しています。"); 79 | } 80 | } else { 81 | $gameId = self::$gameId++; 82 | $this->create($gameId); 83 | $this->DuelJoin($player, $gameId); 84 | } 85 | } 86 | 87 | public function DuelQuit(Player $player) 88 | { 89 | $gameId = self::getGameIdByPlayer($player); 90 | if ($gameId == null) return; 91 | if ($this->status[$gameId]) { 92 | $this->endGame($player); 93 | } else { 94 | $name = $player->getName(); 95 | unset($this->datas[$name]); 96 | unset($this->playerslist[$gameId][$name]); 97 | $this->players[$gameId]--; 98 | $player->setHealth(20); 99 | $player->setFood(20); 100 | $player->getInventory()->clearAll(); 101 | $player->teleport(new Position(257, 8, 257, Main::$instance->getServer()->getLevelByName(self::LEVEL_NAME))); 102 | } 103 | } 104 | 105 | public function wattingGame(int $gameId) 106 | { 107 | $c = 0; 108 | $spawnPosition = $this->stage[$gameId][1]->getSpawnPosition(); 109 | foreach ($this->playerslist[$gameId] as $entityId => $player) { 110 | $player->teleport($spawnPosition[$c]); 111 | $c++; 112 | } 113 | Main::$instance->getScheduler()->scheduleDelayedTask(new TeleportDuelStageTask(Main::$instance, $this, $gameId), 6 * 20); 114 | } 115 | 116 | public function startGame(int $gameId, int $count) 117 | { 118 | if ($count % 20 == 0) { 119 | $time = 5 - $count % 20; 120 | foreach ($this->playerslist[$gameId] as $entityId => $player) { 121 | switch ($time) { 122 | case 5: 123 | $player->addTitle("§a5", "", 20, 20, 20); 124 | break; 125 | case 4: 126 | $player->addTitle("§a4", "", 20, 20, 20); 127 | break; 128 | case 3: 129 | $player->addTitle("§e3", "", 20, 20, 20); 130 | break; 131 | case 2: 132 | $player->addTitle("§e2", "", 20, 20, 20); 133 | break; 134 | case 1: 135 | $player->addTitle("§c1", "", 20, 20, 20); 136 | break; 137 | case 0: 138 | $player->setImmobile(false); 139 | $player->addTitle("§cSTART", "§cMode: Duel(1v1)", 20, 20, 20); 140 | break; 141 | 142 | } 143 | } 144 | } 145 | } 146 | 147 | public function endGame(Player $player) 148 | { 149 | $gameId = self::getGameIdByPlayer($player); 150 | if ($gameId == null) return; 151 | if (!$this->status[$gameId]) return; 152 | foreach ($this->playerslist[$gameId] as $entityId => $players) { 153 | if ($player === $players) { 154 | $players->addTitle("§cYOU DIED", "§cあなたは勝負に負けてしまった。", 20, 40, 20); 155 | self::$level->LevelSystem($players); 156 | self::AddLose($players); 157 | } else { 158 | $players->addTitle("§6VICTORY", "§6あなたは勝負に買った", 20, 40, 20); 159 | $this->broatcastMessage($gameId, "§7[§cDuel§7] §e" . $player->getName() . "§aが勝利しました。"); 160 | self::$money->addMoney($players->getName(), 100); 161 | self::$level->LevelSystem($players); 162 | self::AddWin($players); 163 | } 164 | $players->setHealth(20); 165 | $players->setFood(20); 166 | $players->getInventory()->clearAll(); 167 | $players->teleport(new Position(257, 8, 257, Main::$instance->getServer()->getLevelByName(self::LEVEL_NAME))); 168 | } 169 | $this->reset($gameId); 170 | } 171 | 172 | public function Join(PlayerInteractEvent $event) 173 | { 174 | $player = $event->getPlayer(); 175 | $block = $event->getBlock(); 176 | if ($player->getLevel()->getName() !== self::LEVEL_NAME) return; 177 | if ($block->getId() === Block::IRON_BLOCK) { 178 | $this->DuelJoin($player); 179 | //$this->DuelJoin($player, self::$gameId); 180 | } 181 | } 182 | 183 | public function Quit(PlayerQuitEvent $event) 184 | { 185 | $player = $event->getPlayer(); 186 | if (isset($this->datas[$player->getName()])) { 187 | $this->DuelQuit($player); 188 | } 189 | } 190 | 191 | public function CancelCommand(PlayerCommandPreprocessEvent $event) 192 | { 193 | $player = $event->getPlayer(); 194 | if (isset($this->datas[$player->getName()])) { 195 | if ($event->getMessage() === "/selectgame") return; 196 | } 197 | } 198 | 199 | public function randStage(int $gameId) 200 | { 201 | $rand = mt_rand(0, count($this->stages) - 1); 202 | if (empty($this->usedStage[$rand])) { 203 | $this->usedStage[$rand] = $gameId; 204 | $this->stage[$gameId] = [$rand, $this->stages[$rand]]; 205 | } else { 206 | $this->randStage($gameId); 207 | } 208 | } 209 | 210 | public function reset(int $gameId) 211 | { 212 | foreach ($this->playerslist[$gameId] as $entityId => $player) { 213 | unset($this->datas[$player->getName()]); 214 | } 215 | $this->playerslist[$gameId] = []; 216 | $this->status[$gameId] = false; 217 | $this->players[$gameId] = []; 218 | 219 | $stageId = $this->stage[$gameId][0]; 220 | unset($this->usedStage[$stageId]); 221 | } 222 | 223 | public function broatcastMessage(int $gameId, string $message) 224 | { 225 | foreach ($this->playerslist[$gameId] as $entityId => $player) { 226 | $player->sendMessage($message); 227 | } 228 | } 229 | 230 | private static function AddWin(Player $player) 231 | { 232 | $name = $player->getName(); 233 | $datafile = new DataFile($name); 234 | $data = $datafile->get('DUEL'); 235 | $data['win']++; 236 | $datafile->write('DUEL', $data); 237 | } 238 | 239 | private static function AddLose(Player $player) 240 | { 241 | $name = $player->getName(); 242 | $datafile = new DataFile($name); 243 | $data = $datafile->get('DUEL'); 244 | $data['lose']++; 245 | $datafile->write('DUEL', $data); 246 | } 247 | 248 | public function getGameIdByPlayer(Player $player) 249 | { 250 | $name = $player->getName(); 251 | if (empty($this->datas[$name])) return null; 252 | return $this->datas[$name]["gameId"]; 253 | } 254 | } -------------------------------------------------------------------------------- /src/Core/EventListener.php: -------------------------------------------------------------------------------- 1 | plugin = $plugin; 89 | $this->ffapvp = new FFAPvPCore($this->plugin); 90 | $this->speedcorepvp = new SpeedCorePvPCore($this->plugin); 91 | $this->duel = new DuelCore(); 92 | $this->athletic = new AthleticCore(); 93 | $this->survival = new SurvivalCore($this->plugin); 94 | $this->mazainpc = new Mazai(); 95 | $this->gamemasternpc = new GameMaster($this->plugin); 96 | $this->mazaimasternpc = new MazaiMaster(); 97 | $this->playerjoinevent = new PlayerJoin($this->plugin); 98 | $this->playerquitevent = new PlayerQuit($this->plugin); 99 | $this->playerloginevent = new PlayerLogin($this->plugin); 100 | $this->playerdeathevent = new PlayerDeath($this->plugin); 101 | $this->playerprelogin = new PlayerPreLogin($this->plugin); 102 | $this->playermoveevent = new PlayerMove($this->plugin); 103 | $this->entitydamage = new EntityDamage($this->plugin); 104 | $this->blockbreakevent = new BlockBreak($this->plugin); 105 | $this->blockplaceevent = new BlockPlace($this->plugin); 106 | $this->playerinteractevent = new PlayerInteract($this->plugin); 107 | $this->playercommandpreprocessevent = new PlayerCommandPreprocess($this->plugin); 108 | $this->playerrespawnevent = new PlayerRespawn($this->plugin); 109 | $this->entityinventorychange = new EntityInventoryChange($this->plugin); 110 | $this->entityshootbowevent = new EntityShootBow($this->plugin); 111 | $this->playerexhaustevent = new PlayerExhaust($this->plugin); 112 | } 113 | 114 | public function onJoin(PlayerJoinEvent $event) 115 | { 116 | $this->playerjoinevent->event($event); 117 | $player = $event->getPlayer(); 118 | $this->mazainpc->Create($player, "§a魔剤§e売りの§a魔剤§eさん", "MazaiNPC", new Vector3(260, 4, 265), Item::get(Item::POTION, 11, 1), Mazai::ENTITY_ID); 119 | $this->gamemasternpc->Create($player, "§aGame§7Master", "GameMaster", new Vector3(252, 4, 265), Item::get(Item::COMPASS, 0, 1), GameMaster::ENTITY_ID); 120 | $this->mazaimasternpc->Create($player, "§a魔剤§7マスター", "MazaiNPC", new Vector3(287, 10, 270), Item::get(Item::POTION, 11, 1), MazaiMaster::ENTITY_ID); 121 | } 122 | 123 | public function onQuit(PlayerQuitEvent $event) 124 | { 125 | $this->playerquitevent->event($event); 126 | $player = $event->getPlayer(); 127 | $this->speedcorepvp->GameQuit($player); 128 | $this->survival->SaveData($player); 129 | $this->mazainpc->Remove($player, Mazai::ENTITY_ID); 130 | $this->gamemasternpc->Remove($player, GameMaster::ENTITY_ID); 131 | $this->mazaimasternpc->Remove($player, MazaiMaster::ENTITY_ID); 132 | $this->duel->Quit($event); 133 | // $this->athletic->onQuit($event); 134 | } 135 | 136 | public function onLogin(PlayerLoginEvent $event) 137 | { 138 | $this->playerloginevent->event($event); 139 | } 140 | 141 | public function onDeath(PlayerDeathEvent $event) 142 | { 143 | $this->playerdeathevent->event($event); 144 | } 145 | 146 | public function onReceive(DataPacketReceiveEvent $event) 147 | { 148 | $this->mazainpc->ClickEntity($event); 149 | $this->gamemasternpc->ClickEntity($event); 150 | $this->mazaimasternpc->ClickEntity($event); 151 | } 152 | 153 | public function pnPreLogin(PlayerPreLoginEvent $event) 154 | { 155 | $this->playerprelogin->event($event); 156 | } 157 | 158 | public function onMove(PlayerMoveEvent $event) 159 | { 160 | $this->playermoveevent->event($event); 161 | $this->athletic->loop($event); 162 | } 163 | 164 | public function onEntityDamage(EntityDamageEvent $event) 165 | { 166 | $this->entitydamage->event($event); 167 | $this->speedcorepvp->Damage($event); 168 | } 169 | 170 | public function onBreak(BlockBreakEvent $event) 171 | { 172 | $this->blockbreakevent->event($event); 173 | $this->speedcorepvp->BreakCore($event); 174 | $this->speedcorepvp->DropItem($event); 175 | $this->survival->BreakBlock($event); 176 | } 177 | 178 | public function onPlace(BlockPlaceEvent $event) 179 | { 180 | $this->blockplaceevent->event($event); 181 | $this->speedcorepvp->AntiPlace($event); 182 | } 183 | 184 | public function onInteract(PlayerInteractEvent $event) 185 | { 186 | $this->playerinteractevent->event($event); 187 | $this->speedcorepvp->GameJoin($event->getPlayer(), $event->getBlock()); 188 | $this->speedcorepvp->Interact($event); 189 | $this->survival->Join($event); 190 | $this->duel->Join($event); 191 | //$this->athletic->isAthleticFinish($event, $event->getPlayer()); 192 | //$this->athletic->touch($event); 193 | //$this->athletic->getAthleticData($event); 194 | } 195 | 196 | public function onPlayerCommandPreprocess(PlayerCommandPreprocessEvent $event) 197 | { 198 | $this->playercommandpreprocessevent->event($event); 199 | } 200 | 201 | public function onRespawn(PlayerRespawnEvent $event) 202 | { 203 | $this->playerrespawnevent->event($event); 204 | $this->speedcorepvp->Respawn($event->getPlayer()); 205 | } 206 | 207 | public function onEntityInventoryChange(EntityInventoryChangeEvent $event) 208 | { 209 | $this->entityinventorychange->event($event); 210 | $this->speedcorepvp->CancelChange($event); 211 | } 212 | 213 | public function onEntityShootBow(EntityShootBowEvent $event) 214 | { 215 | $this->entityshootbowevent->event($event); 216 | } 217 | 218 | public function EntityLevelChange(EntityLevelChangeEvent $event) 219 | { 220 | $this->speedcorepvp->LevelChange($event); 221 | $this->survival->LoadData($event); 222 | $this->mazainpc->Check($event); 223 | $this->gamemasternpc->Check($event); 224 | $this->mazaimasternpc->Check($event); 225 | } 226 | 227 | public function onChat(PlayerChatEvent $event) 228 | { 229 | $this->speedcorepvp->TeamChat($event); 230 | } 231 | 232 | public function onPlayerAchievementAwarded(PlayerAchievementAwardedEvent $event) 233 | { 234 | $event->setCancelled(true); 235 | } 236 | 237 | public function onSignChange(SignChangeEvent $event) 238 | { 239 | $this->survival->Sign($event); 240 | $this->speedcorepvp->Sign($event); 241 | } 242 | 243 | public function onPlayerExhaust(PlayerExhaustEvent $event) 244 | { 245 | $this->playerexhaustevent->event($event); 246 | } 247 | 248 | public function onCraftItem(CraftItemEvent $event) 249 | { 250 | $this->speedcorepvp->CancelCraft($event); 251 | } 252 | } 253 | -------------------------------------------------------------------------------- /src/Core/Game/Survival/SurvivalCore.php: -------------------------------------------------------------------------------- 1 | plugin = $plugin; 39 | $this->money = new Money(); 40 | $this->level = new Level(); 41 | } 42 | 43 | /** 44 | * @param Player $player 45 | */ 46 | public function Kit(Player $player) 47 | { 48 | $player->getInventory()->addItem(Item::get(Item::STEAK, 0, 64)); 49 | } 50 | 51 | /** 52 | * @param PlayerInteractEvent $event 53 | */ 54 | public function Join(PlayerInteractEvent $event) 55 | { 56 | $player = $event->getPlayer(); 57 | $block = $event->getBlock(); 58 | if ($player->getLevel()->getName() === self::LEVEL_NAME) { 59 | $tile = $block->getLevel()->getTile($block); 60 | if ($tile instanceof Sign) { 61 | $text = $tile->getText(); 62 | if ($text[0] === "§7[§2Survival §eJoin§7]") { 63 | $player->teleport(new Position(mt_rand(1, 999), 300, mt_rand(1, 999), $this->plugin->getServer()->getLevelByName(self::LEVEL_NAME))); 64 | $player->addEffect(new EffectInstance(Effect::getEffect(Effect::DAMAGE_RESISTANCE), 10 * 20, 256, false)); 65 | $player->addEffect(new EffectInstance(Effect::getEffect(Effect::REGENERATION), 15 * 20, 256, false)); 66 | $this->Kit($player); 67 | $player->addTitle("§aTeleport", "§eサバイバルの世界へ転送されました。", 40, 60, 40); 68 | } 69 | } 70 | } 71 | } 72 | 73 | /** 74 | * @param SignChangeEvent $event 75 | */ 76 | public function Sign(SignChangeEvent $event) 77 | { 78 | $player = $event->getPlayer(); 79 | if ($event->getLine(0) === "S1") { 80 | if ($player->isOp()) { 81 | $event->setLine(0, "§7[§2Survival §eJoin§7]"); 82 | $event->setLine(1, "§7この看板をタッチしてサバイバルに入る"); 83 | $event->setLine(2, "§cクソ重いかもしれません。"); 84 | } 85 | } 86 | } 87 | 88 | /** 89 | * @param Player $player 90 | */ 91 | public function SaveInventory(Player $player) 92 | { 93 | if ($player->getLevel()->getName() === self::LEVEL_NAME) { 94 | $datafile = new DataFile($player->getName()); 95 | $data = $datafile->get('SURVIVAL'); 96 | if (isset($data['items'])) { 97 | if (empty($player->getInventory()->getContents())) { 98 | $data['items'] = array(); 99 | $datafile->write('SURVIVAL', $data); 100 | } else { 101 | $data['items'] = $player->getInventory()->getContents(); 102 | $datafile->write('SURVIVAL', $data); 103 | } 104 | } 105 | } 106 | } 107 | 108 | /** 109 | * @param EntityLevelChangeEvent $event 110 | */ 111 | public function LoadData(EntityLevelChangeEvent $event) 112 | { 113 | $entity = $event->getEntity(); 114 | if ($entity instanceof Player) { 115 | if ($event->getTarget()->getName() === self::LEVEL_NAME) { 116 | $datafile = new DataFile($entity->getName()); 117 | $data = $datafile->get('SURVIVAL'); 118 | if (isset($data['items'])) { 119 | $items = $data['items']; 120 | foreach ($items as $item) { 121 | if (isset($item['damage'])) { 122 | $damage = $item['damage']; 123 | } else { 124 | $damage = 0; 125 | } 126 | if (isset($item['count'])) { 127 | $count = $item['count']; 128 | } else { 129 | $count = 1; 130 | } 131 | $entity->getInventory()->addItem(Item::get($item['id'], $damage, $count)); 132 | } 133 | } 134 | $entity->setHealth(self::getHealth($entity->getName())); 135 | $entity->setFood(self::getFood($entity->getName())); 136 | } elseif ($event->getOrigin()->getName() === self::LEVEL_NAME) { 137 | $this->SaveInventory($entity); 138 | $this->SaveSpawn($entity->getName(), $entity->getLevel()->getName(), $entity->getX(), $entity->getY(), $entity->getZ()); 139 | $this->SaveFood($entity); 140 | $this->SaveHeath($entity); 141 | } 142 | } 143 | } 144 | 145 | public function SaveData(Player $player) 146 | { 147 | if ($player->getLevel()->getName() === self::LEVEL_NAME) return; 148 | self::SaveFood($player); 149 | self::SaveHeath($player); 150 | self::SaveInventory($player); 151 | self::SaveSpawn($player->getName(), self::LEVEL_NAME, $player->getX(), $player->getY(), $player->getZ()); 152 | } 153 | 154 | /** 155 | * @param Player $player 156 | */ 157 | public function SaveHeath(Player $player) 158 | { 159 | if ($player->getLevel()->getName() === self::LEVEL_NAME) { 160 | $datafile = new DataFile($player->getName()); 161 | $data = $datafile->get('SURVIVAL'); 162 | $data['health'] = $player->getHealth(); 163 | $datafile->write('SURVIVAL', $data); 164 | } 165 | } 166 | 167 | /** 168 | * @param Player $player 169 | */ 170 | public function SaveFood(Player $player) 171 | { 172 | if ($player->getLevel()->getName() === self::LEVEL_NAME) { 173 | $datafile = new DataFile($player->getName()); 174 | $data = $datafile->get('SURVIVAL'); 175 | $data['food'] = $player->getFood(); 176 | $datafile->write('SURVIVAL', $data); 177 | } 178 | } 179 | 180 | /** 181 | * @param string $name 182 | * @param string $level 183 | * @param float $x 184 | * @param float $y 185 | * @param float $z 186 | */ 187 | public function SaveSpawn(string $name, string $level, float $x, float $y, float $z) 188 | { 189 | if ($level === self::LEVEL_NAME) { 190 | $datafile = new DataFile($name); 191 | $data = $datafile->get('SURVIVAL'); 192 | $data['x'] = $x; 193 | $data['y'] = $y; 194 | $data['z'] = $z; 195 | $datafile->write('SURVIVAL', $data); 196 | } 197 | } 198 | 199 | /** 200 | * @param BlockBreakEvent $event 201 | */ 202 | public function BreakBlock(BlockBreakEvent $event) 203 | { 204 | $player = $event->getPlayer(); 205 | $block = $event->getBlock(); 206 | if ($player->getLevel()->getName() === self::LEVEL_NAME) { 207 | self::RandomFood($player); 208 | $datafile = new DataFile($player->getName()); 209 | $data = $datafile->get('SURVIVAL'); 210 | switch ($block->getId()) { 211 | case Block::DIAMOND_ORE: 212 | $data['breakdiamond'] += 1; 213 | $money = mt_rand(100, 300); 214 | $exp = mt_rand(50, 100); 215 | $this->money->addMoney($player->getName(), $money); 216 | $this->level->addExp($player->getName(), $exp); 217 | $datafile->write('SURVIVAL', $data); 218 | $this->plugin->getScheduler()->scheduleDelayedTask(new LevelCheckingTask($this->plugin, $player), 20); 219 | $player->sendMessage("§a+$money §6V§bN§eCoin\n§a+$exp EXP"); 220 | break; 221 | case Block::IRON_ORE: 222 | $data['breakiron'] += 1; 223 | $money = mt_rand(30, 60); 224 | $exp = mt_rand(20, 30); 225 | $this->money->addMoney($player->getName(), $money); 226 | $this->level->addExp($player->getName(), $exp); 227 | $event->setDrops([Item::get(Item::IRON_INGOT, 0, 1)]); 228 | $datafile->write('SURVIVAL', $data); 229 | $this->plugin->getScheduler()->scheduleDelayedTask(new LevelCheckingTask($this->plugin, $player), 20); 230 | $player->sendMessage("§a+$money §6V§bN§eCoin\n§a+$exp EXP"); 231 | break; 232 | case Block::GOLD_ORE: 233 | $data['breakgold'] += 1; 234 | $money = mt_rand(40, 70); 235 | $exp = mt_rand(30, 50); 236 | $this->money->addMoney($player->getName(), $money); 237 | $this->level->addExp($player->getName(), $exp); 238 | $datafile->write('SURVIVAL', $data); 239 | $event->setDrops([Item::get(Item::GOLD_INGOT, 0, 1)]); 240 | $this->plugin->getScheduler()->scheduleDelayedTask(new LevelCheckingTask($this->plugin, $player), 20); 241 | $player->sendMessage("§a+$money §6V§bN§eCoin\n§a+$exp EXP"); 242 | break; 243 | case Block::COAL_ORE: 244 | $data['breakcoal'] += 1; 245 | $money = mt_rand(1, 10); 246 | $exp = mt_rand(1, 10); 247 | $this->money->addMoney($player->getName(), $money); 248 | $this->level->addExp($player->getName(), $exp); 249 | $datafile->write('SURVIVAL', $data); 250 | $this->plugin->getScheduler()->scheduleDelayedTask(new LevelCheckingTask($this->plugin, $player), 20); 251 | $player->sendMessage("§a+$money §6V§bN§eCoin\n§a+$exp EXP"); 252 | break; 253 | } 254 | } 255 | } 256 | 257 | /** 258 | * @param Player $player 259 | */ 260 | public function AddKillCount(Player $player) 261 | { 262 | if ($player->getLevel()->getName() === self::LEVEL_NAME) { 263 | $datafile = new DataFile($player->getName()); 264 | $data = $datafile->get('SURVIVAL'); 265 | $data['kill'] += 1; 266 | $datafile->write('SURVIVAL', $data); 267 | $rand = mt_rand(1, 50); 268 | $this->money->addMoney($player->getName(), $rand); 269 | $player->sendMessage("§a+$rand §6V§bN§eCoin"); 270 | $this->level->LevelSystem($player); 271 | $this->plugin->getScheduler()->scheduleDelayedTask(new LevelCheckingTask($this->plugin, $player), 20); 272 | } 273 | } 274 | 275 | /** 276 | * @param Player $player 277 | */ 278 | public function AddDeathCount(Player $player) 279 | { 280 | if ($player->getLevel()->getName() === self::LEVEL_NAME) { 281 | $datafile = new DataFile($player->getName()); 282 | $data = $datafile->get('SURVIVAL'); 283 | $data['death'] += 1; 284 | $data['items'] = []; 285 | $datafile->write('SURVIVAL', $data); 286 | $this->SaveSpawn($player->getName(), self::LEVEL_NAME, 225, 243, 256); 287 | $player->addTitle("§cYou are dead", "§cあなたは死んでしまった", 20, 40, 20); 288 | } 289 | } 290 | 291 | /** 292 | * @param Player $player 293 | */ 294 | public static function Teleport(Player $player) 295 | { 296 | $datafile = new DataFile($player->getName()); 297 | $data = $datafile->get('SURVIVAL'); 298 | $player->teleport(new Position($data['x'], $data['y'], $data['z'], Main::$instance->getServer()->getLevelByName(self::LEVEL_NAME))); 299 | } 300 | 301 | /** 302 | * @param Player $player 303 | */ 304 | public function AddBreakCount(Player $player) 305 | { 306 | if ($player->getLevel()->getName() === self::LEVEL_NAME) { 307 | $datafile = new DataFile($player->getName()); 308 | $data = $datafile->get('SURVIVAL'); 309 | $data['breakblock'] += 1; 310 | $datafile->write('SURVIVAL', $data); 311 | } 312 | } 313 | 314 | /** 315 | * @param Player $player 316 | */ 317 | public function AddPlaceCount(Player $player) 318 | { 319 | if ($player->getLevel()->getName() === self::LEVEL_NAME) { 320 | $datafile = new DataFile($player->getName()); 321 | $data = $datafile->get('SURVIVAL'); 322 | $data['placeblock'] += 1; 323 | $datafile->write('SURVIVAL', $data); 324 | } 325 | } 326 | 327 | /** 328 | * @param string $name 329 | * @return int 330 | */ 331 | public static function getPlaceCount(string $name): int 332 | { 333 | $datafile = new DataFile($name); 334 | $data = $datafile->get('SURVIVAL'); 335 | return $data['placeblock']; 336 | } 337 | 338 | /** 339 | * @param string $name 340 | * @return int 341 | */ 342 | public static function getBreakBlock(string $name): int 343 | { 344 | $datafile = new DataFile($name); 345 | $data = $datafile->get('SURVIVAL'); 346 | return $data['breakblock']; 347 | } 348 | 349 | /** 350 | * @param string $name 351 | * @return int 352 | */ 353 | public static function getDeathCount(string $name): int 354 | { 355 | $datafile = new DataFile($name); 356 | $data = $datafile->get('SURVIVAL'); 357 | return $data['death']; 358 | } 359 | 360 | /** 361 | * @param string $name 362 | * @return int 363 | */ 364 | public static function getKillCount(string $name): int 365 | { 366 | $datafile = new DataFile($name); 367 | $data = $datafile->get('SURVIVAL'); 368 | return $data['kill']; 369 | } 370 | 371 | /** 372 | * @param string $name 373 | * @return int 374 | */ 375 | public static function getBreakDiamond(string $name): int 376 | { 377 | $datafile = new DataFile($name); 378 | $data = $datafile->get('SURVIVAL'); 379 | return $data['breakdiamond']; 380 | } 381 | 382 | /** 383 | * @param string $name 384 | * @return int 385 | */ 386 | public static function getBreakIron(string $name): int 387 | { 388 | $datafile = new DataFile($name); 389 | $data = $datafile->get('SURVIVAL'); 390 | return $data['breakiron']; 391 | } 392 | 393 | /** 394 | * @param string $name 395 | * @return int 396 | */ 397 | public static function getBreakGold(string $name): int 398 | { 399 | $datafile = new DataFile($name); 400 | $data = $datafile->get('SURVIVAL'); 401 | return $data['breakgold']; 402 | } 403 | 404 | /** 405 | * @param string $name 406 | * @return int 407 | */ 408 | public static function getBreakCoal(string $name): int 409 | { 410 | $datafile = new DataFile($name); 411 | $data = $datafile->get('SURVIVAL'); 412 | return $data['breakcoal']; 413 | } 414 | 415 | /** 416 | * @param string $name 417 | * @return float 418 | */ 419 | public static function getHealth(string $name): float 420 | { 421 | $datafile = new DataFile($name); 422 | $data = $datafile->get('SURVIVAL'); 423 | return $data['health']; 424 | } 425 | 426 | /** 427 | * @param string $name 428 | * @return float 429 | */ 430 | public static function getFood(string $name): float 431 | { 432 | $datafile = new DataFile($name); 433 | $data = $datafile->get('SURVIVAL'); 434 | return $data['health']; 435 | } 436 | 437 | /** 438 | * @param Player $player 439 | */ 440 | private static function RandomFood(Player $player) 441 | { 442 | if (mt_rand(1, 10) === mt_rand(1, 10)) { 443 | $player->getInventory()->addItem(Item::get(Item::STEAK, 0, 1)); 444 | $player->sendMessage("§6ブロックの中からステーキが出てきた!!たまげたなぁ"); 445 | } 446 | } 447 | 448 | public function setSpawnPoint(BlockPlaceEvent $event) 449 | { 450 | $player = $event->getPlayer(); 451 | if ($player->getLevel()->getName() !== self::LEVEL_NAME) return; 452 | if ($event->getBlock()->getId() !== Block::BED_BLOCK) return; 453 | $event->setCancelled(true); 454 | $player->getInventory()->removeItem(Item::get(Item::BED, 0, 1)); 455 | // ここ思考中 456 | } 457 | } -------------------------------------------------------------------------------- /resources/skins/MazaiNPC: -------------------------------------------------------------------------------- 1 | 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+LaF//u5iP/2tIP/8rB///i2hf/ysH//8rB///u5iP/zsYD/97WE//Sygf/zsYD/8a9+//a0g//ysH//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARERE8A0W0f8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA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 -------------------------------------------------------------------------------- /resources/skins/GameMaster: -------------------------------------------------------------------------------- 1 | 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 --------------------------------------------------------------------------------