├── .gitignore ├── .poggit.yml ├── README.md ├── plugin.yml ├── resources ├── KillCounterLogo.png └── config.yml └── src └── BlockHorizons └── KillCounter ├── KillingSpree.php ├── Loader.php ├── achievements ├── AchievementManager.php └── KillCounterAchievement.php ├── commands ├── BaseCommand.php ├── CommandOverloads.php ├── KillStatsCommand.php └── KillsTopCommand.php ├── events ├── BaseEvent.php └── player │ ├── PlayerEvent.php │ ├── PlayerKillCounterAchievementGainEvent.php │ ├── PlayerPointsChangeEvent.php │ └── killingspree │ ├── PlayerKillingSpreeEndEvent.php │ └── PlayerKillingSpreeStartEvent.php ├── handlers ├── BaseHandler.php └── KillingSpreeHandler.php ├── listeners ├── BaseListener.php └── PlayerEventListener.php └── providers ├── BaseProvider.php ├── IProvider.php ├── MySQLProvider.php └── SQLiteProvider.php /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | config.yml 3 | -------------------------------------------------------------------------------- /.poggit.yml: -------------------------------------------------------------------------------- 1 | --- # Poggit-CI Manifest. Open the CI at https://poggit.pmmp.io/ci/Sandertv/KillCounter 2 | projects: 3 | KillCounter: 4 | path: "" 5 | icon: resources/KillCounterLogo.png 6 | ... 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # KillCounter 2 | A Plugin for PocketMine-MP, aiming to give a better and more fun PvP experience. 3 |

4 | Another plugin that keeps track of kills?! There are already plenty! Why would I choose this plugin above other plugins like KillRate, that provider me with the same kind of features? 5 | 6 | ### Features 7 | KillCounter has a more advanced kill tracking system than other kill tracking plugins on several points. 8 | - [x] Kill tracking when the actual damage cause was not a player, but something else, using the last player attacker. 9 | - [x] Lots of configuration allowing you to modify the plugin in whichever way you want, such as point amounts. 10 | - [x] Economy support, requiring the Economizer library by @Chris-Prime. 11 | - [x] Killing sprees, which will give you increasingly higher points for each kills, and shut downs. 12 | - [x] Assists feature, giving points to every player that assisted in killing a player. 13 | - [x] Custom PvP achievements, which can be created in the configuration. 14 | 15 | ... I'm convinced. How do I download this? 16 | 17 | ### Installation 18 | It is mostly recommended to use released versions of the plugin, which can be found in the released version on Poggit. (once there is one)
19 | If you do decide you want the latest version of the plugin, it is recommended you fetch a pre-compiled phar file from Poggit-CI, which can be found below. 20 |

21 | [![Poggit-CI](https://poggit.pmmp.io/ci.shield/BlockHorizons/KillCounter/KillCounter)](https://poggit.pmmp.io/ci/BlockHorizons/KillCounter/KillCounter) 22 | 23 | ### Support 24 | I found an issue in the plugin which I would like to be fixed quickly! What do I do?
25 | > It's very much appreciated you report any bugs found in the plugin in the Issues tab from the repository in GitHub. Issues can be easily managed here. 26 | 27 |
28 | I want something to be added to the plugin. Where can I ask if this can be made?
29 | 30 | > This too is most easily managed in the Issues tab. Not every feature is guaranteed to be added, but everything will be taken in consideration. 31 | -------------------------------------------------------------------------------- /plugin.yml: -------------------------------------------------------------------------------- 1 | { 2 | "name": "KillCounter", 3 | "version": "1.0.0", 4 | "api": [ 5 | "3.0.0-ALPHA10", 6 | "3.0.0-ALPHA11" 7 | ], 8 | "author": "BlockHorizons", 9 | "authors": [ 10 | "Sandertv (@Sandertv)", 11 | "Luke (@lukeeey)" 12 | ], 13 | "main": "BlockHorizons\\KillCounter\\Loader", 14 | 15 | "permissions": { 16 | "killcounter": { 17 | "default": false, 18 | "description": "Allows access to every feature of KillCounter", 19 | "children": { 20 | "killcounter.command": { 21 | "default": false, 22 | "description": "Allows access to all KillCounter commands", 23 | "children": { 24 | "killcounter.command.killstats": { 25 | "default": true, 26 | "description": "Allows access to the killstats command" 27 | }, 28 | "killcounter.command.killstop": { 29 | "default": true, 30 | "description": "Allows access to the killstop command" 31 | } 32 | } 33 | } 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /resources/KillCounterLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlockHorizons/KillCounter/6f57d6865c22399757ce966c0a824e0ae021179e/resources/KillCounterLogo.png -------------------------------------------------------------------------------- /resources/config.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Configuration file for KillCounter plugin by BlockHorizons. 3 | 4 | # The provider to save the statistics of players in, like player kills. 5 | Provider: SQLite 6 | 7 | # Settings required if the above provider is set to MySQL. If the provider is not MySQL, these settings don't matter. 8 | Host: 127.0.0.1 9 | User: Admin 10 | Password: Admin 11 | Database: KillCounter 12 | Port: 3306 13 | 14 | # Worlds the plugin should NOT work in. 15 | Disabled-Worlds: 16 | - MyWorld3 17 | - SpawnWorld98 18 | 19 | # Whether to check if there was a last player who damaged the dead one, and reward that player with points, even though the actual cause was not the last player that damaged it. 20 | Track-Non-Player-Damage-Deaths: true 21 | 22 | # The amount of points to award for killing a player. 23 | Points-Per-Player-Kill: 100 24 | 25 | # The amount of points to award for assisting in the killing of a player. 26 | Points-Per-Player-Assist: 30 27 | 28 | # The amount of points to award for killing an entity. 29 | Points-Per-Entity-Kill: 30 30 | 31 | # The amount of points to be subtracted from a player when it dies. 32 | Points-Lost-Per-Death: 50 33 | 34 | # The amount of points to add for every kill made during a killing spree. 35 | Points-Added-Per-Spree-Kill: 10 36 | 37 | # Amount of kills required for a killing spree to be declared. 38 | Kills-For-Killing-Spree: 5 39 | 40 | # The amount of points obtained when killing a player that has a killing spree active. 41 | Points-For-Spree-Killing: 200 42 | 43 | # Whether to enable 'multi-kills' such as a double or a triple kill, or disable them. 44 | Enable-Multi-Kill: true 45 | 46 | # Maximum amount of time between to kills to be declared a 'multi-kill' in seconds. 47 | Multi-Kill-Time: 8 48 | 49 | # Economy Support 50 | # The settings below are only used if economy is enabled. 51 | # 52 | # Support for economy is done using the Economizer library by @Chris-Prime (https://github.com/Chris-Prime/Economizer) 53 | # Installation of this library is required to have economy support enabled. 54 | Economy-Support: false 55 | 56 | # Subtracts an amount of money specified below from the player killed, and adds that to the killer. 57 | Enable-Money-Leeching: true 58 | 59 | # Amount of money earned when killing a player. (and subtracted when being killed with leech enabled) 60 | Money-Per-Player-Kill: 30 61 | 62 | # Amount of money earned when assisting in the killing of a player. 63 | Money-Per-Player-Assist: 15 64 | 65 | # Amount of money earned when killing an entity. 66 | Money-Per-Entity-Kill: 15 67 | 68 | # Achievements 69 | 70 | # Whether to enable or disable achievements. 71 | Enable-Achievements: true 72 | 73 | # Achievements can be created here. An example has been made. 74 | # 75 | # Player-Kills: The required amount of kills on players. 76 | # Player-Assists: The required amount of assists on players. 77 | # Entity-Kills: The required amount of entity kills. 78 | # Deaths: The required amount of deaths. 79 | # Points-Reward: The amount of points to reward when achieving the achievement. A - can be added to subtract points. 80 | # Message: The message to send to the player when achieving the achievement. New lines can be made using '\n'. 81 | 82 | Achievements: 83 | ExampleAchievement: 84 | Player-Kills: 10 85 | Player-Assists: 10 86 | Entity-Kills: 10 87 | Deaths: 100 88 | Points-Reward: 1000 89 | Message: §bYou have died! §lAgain! \n§r§aCongratulations on achieving this achievement, you have earned 1000 points! 90 | ... -------------------------------------------------------------------------------- /src/BlockHorizons/KillCounter/KillingSpree.php: -------------------------------------------------------------------------------- 1 | player = $player->getName(); 16 | $this->kills = $kills; 17 | } 18 | 19 | /** 20 | * @return Loader 21 | */ 22 | public function getLoader(): Loader { 23 | $loader = Server::getInstance()->getPluginManager()->getPlugin("KillCounter"); 24 | if($loader instanceof Loader) { 25 | return $loader; 26 | } 27 | return null; 28 | } 29 | 30 | /** 31 | * @return Player 32 | */ 33 | public function getPlayer(): Player { 34 | return Server::getInstance()->getPlayer($this->player); 35 | } 36 | 37 | /** 38 | * @return int 39 | */ 40 | public function getKills(): int { 41 | return $this->kills; 42 | } 43 | 44 | /** 45 | * @param int $kills 46 | */ 47 | public function setKills(int $kills) { 48 | $this->kills = $kills; 49 | } 50 | 51 | /** 52 | * @return int 53 | */ 54 | public function getTotalKills(): int { 55 | return $this->kills + $this->getLoader()->getConfig()->get("Kills-For-Killing-Spree", 5) - 1; 56 | } 57 | 58 | /** 59 | * @param int $amount 60 | */ 61 | public function addKills(int $amount = 1) { 62 | $this->kills += $amount; 63 | 64 | $totalKills = $this->getTotalKills(); 65 | Server::getInstance()->broadcastMessage(TF::YELLOW . $this->getPlayer()->getDisplayName() . TF::RESET . TF::YELLOW . " is on a killing spree of " . TF::RED . TF::BOLD . $totalKills . TF::RESET . TF::YELLOW . " kills!"); 66 | } 67 | } -------------------------------------------------------------------------------- /src/BlockHorizons/KillCounter/Loader.php: -------------------------------------------------------------------------------- 1 | getDataFolder())) { 36 | mkdir($this->getDataFolder()); 37 | } 38 | $this->saveResource("config.yml"); 39 | 40 | $this->prepareEconomy(); 41 | $this->selectProvider(); 42 | $this->getServer()->getPluginManager()->registerEvents(new PlayerEventListener($this), $this); 43 | 44 | $this->registerCommands(); 45 | 46 | $this->killingSpreeHandler = new KillingSpreeHandler($this); 47 | $this->achievementManager = new AchievementManager($this); 48 | } 49 | 50 | public function onDisable() { 51 | $this->getProvider()->closeDatabase(); 52 | 53 | $this->getKillingSpreeHandler()->save(); 54 | } 55 | 56 | /** 57 | * @return bool 58 | */ 59 | public function registerCommands(): bool { 60 | $commands = [ 61 | new KillStatsCommand($this), 62 | new KillsTopCommand($this) 63 | ]; 64 | foreach($commands as $command) { 65 | $this->getServer()->getCommandMap()->register($command->getName(), $command); 66 | } 67 | return true; 68 | } 69 | 70 | /** 71 | * @return KillingSpreeHandler 72 | */ 73 | public function getKillingSpreeHandler(): KillingSpreeHandler { 74 | return $this->killingSpreeHandler; 75 | } 76 | 77 | /** 78 | * @return AchievementManager 79 | */ 80 | public function getAchievementManager(): AchievementManager { 81 | return $this->achievementManager; 82 | } 83 | 84 | /** 85 | * @return BaseProvider 86 | */ 87 | public function getProvider(): BaseProvider { 88 | return $this->provider; 89 | } 90 | 91 | /** 92 | * @return BaseProvider 93 | */ 94 | public function selectProvider(): BaseProvider { 95 | switch(strtolower($this->getConfig()->get("Provider"))) { 96 | default: 97 | case "sqlite": 98 | case "sqlite3": 99 | $this->provider = new SQLiteProvider($this); 100 | break; 101 | case "mysql": 102 | case "mysqli": 103 | $this->provider = new MySQLProvider($this); 104 | break; 105 | } 106 | return $this->provider; 107 | } 108 | 109 | public function prepareEconomy(): bool { 110 | if($this->getConfig()->get("Economy-Support") === true) { 111 | 112 | $pluginManager = $this->getServer()->getPluginManager(); 113 | /** @var Plugin $economyPlugin */ 114 | $economyPlugin = null; 115 | 116 | $economyPlugins = [ 117 | $pluginManager->getPlugin("EconomyAPI"), 118 | $pluginManager->getPlugin("MassiveEconomy"), 119 | $pluginManager->getPlugin("PocketMoney"), 120 | $pluginManager->getPlugin("EssentialsPE") 121 | ]; 122 | foreach($economyPlugins as $ecoPlugin) { 123 | if($ecoPlugin !== null) { 124 | $economyPlugin = $ecoPlugin; 125 | break; 126 | } 127 | } 128 | if($economyPlugin === null || ($transistor = Economizer::getTransistorFor($economyPlugin)) === null) { 129 | $this->getLogger()->info(TF::RED . "[Error] No supported economy plugin could be found. Disabling economy support."); 130 | return false; 131 | } 132 | $this->economizer = new Economizer($this, $transistor); 133 | if($this->economizer->ready()) { 134 | $this->getLogger()->info(TF::AQUA . "Economy support enabled, using economy API from: " . $economyPlugin->getName()); 135 | $this->economyEnabled = true; 136 | $this->economizer = $this->economizer->getTransistor(); 137 | } else { 138 | $this->getLogger()->info(TF::RED . "Oops! Something went wrong when preparing the economy support."); 139 | } 140 | return true; 141 | } 142 | return false; 143 | } 144 | 145 | /** 146 | * @return bool 147 | */ 148 | public function isEconomyEnabled(): bool { 149 | return $this->economyEnabled; 150 | } 151 | 152 | /** 153 | * @return Transistor 154 | */ 155 | public function getEconomy(): Transistor { 156 | return $this->economizer; 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /src/BlockHorizons/KillCounter/achievements/AchievementManager.php: -------------------------------------------------------------------------------- 1 | loader = $loader; 15 | 16 | $data = $loader->getConfig()->get("Achievements"); 17 | foreach($data as $name => $achievementData) { 18 | $processedData = @[ 19 | "playerKills" => $achievementData["Player-Kills"] ?? 0, 20 | "playerAssists" => $achievementData["Player-Assists"] ?? 0, 21 | "entityKills" => $achievementData["Entity-Kills"] ?? 0, 22 | "deaths" => $achievementData["Deaths"] ?? 0, 23 | "pointsReward" => $achievementData["Points-Reward"] ?? 0, 24 | "message" => $achievementData["Message"] ?? "" 25 | ]; 26 | $this->achievements[strtolower($name)] = new KillCounterAchievement($this, strtolower($name), $processedData); 27 | } 28 | } 29 | 30 | /** 31 | * @return Loader 32 | */ 33 | public function getLoader(): Loader { 34 | return $this->loader; 35 | } 36 | 37 | /** 38 | * @param string $name 39 | * 40 | * @return KillCounterAchievement 41 | */ 42 | public function getAchievement(string $name): KillCounterAchievement { 43 | $name = strtolower($name); 44 | if(!isset($this->achievements[$name])) { 45 | return new KillCounterAchievement($this, $name); 46 | } 47 | return $this->achievements[$name]; 48 | } 49 | 50 | /** 51 | * @return KillCounterAchievement[] 52 | */ 53 | public function getAchievements(): array { 54 | return $this->achievements; 55 | } 56 | } -------------------------------------------------------------------------------- /src/BlockHorizons/KillCounter/achievements/KillCounterAchievement.php: -------------------------------------------------------------------------------- 1 | manager = $manager; 22 | $this->name = $name; 23 | foreach($data as $key => $datum) { 24 | $this->{$key} = $datum; 25 | } 26 | } 27 | 28 | /** 29 | * @return string 30 | */ 31 | public function getName(): string { 32 | return $this->name; 33 | } 34 | 35 | /** 36 | * @return AchievementManager 37 | */ 38 | public function getManager(): AchievementManager { 39 | return $this->manager; 40 | } 41 | 42 | /** 43 | * @return int 44 | */ 45 | public function getPlayerKills(): int { 46 | return $this->playerKills; 47 | } 48 | 49 | /** 50 | * @return int 51 | */ 52 | public function getPlayerAssists(): int { 53 | return $this->playerAssists; 54 | } 55 | 56 | /** 57 | * @return int 58 | */ 59 | public function getEntityKills(): int { 60 | return $this->entityKills; 61 | } 62 | 63 | /** 64 | * @return int 65 | */ 66 | public function getDeaths(): int { 67 | return $this->deaths; 68 | } 69 | 70 | /** 71 | * @return int 72 | */ 73 | public function getRewardPoints(): int { 74 | return $this->pointsReward; 75 | } 76 | 77 | /** 78 | * @return string 79 | */ 80 | public function getMessage(): string { 81 | return $this->message; 82 | } 83 | 84 | /** 85 | * @param Player $player 86 | * 87 | * @return bool 88 | */ 89 | public function meetsRequirements(Player $player): bool { 90 | $provider = $this->getManager()->getLoader()->getProvider(); 91 | if(!$provider->getPlayerKills($player) >= $this->playerKills) { 92 | return false; 93 | } elseif(!$provider->getPlayerAssists($player) >= $this->playerAssists) { 94 | return false; 95 | } elseif(!$provider->getEntityKills($player) >= $this->entityKills) { 96 | return false; 97 | } elseif(!$provider->getDeaths($player) >= $this->deaths) { 98 | return false; 99 | } 100 | return true; 101 | } 102 | 103 | /** 104 | * @param Player $player 105 | * 106 | * @return bool 107 | */ 108 | public function achieve(Player $player): bool { 109 | if(!$this->meetsRequirements($player)) { 110 | return false; 111 | } 112 | $this->getManager()->getLoader()->getServer()->getPluginManager()->callEvent($ev = new PlayerKillCounterAchievementGainEvent($this->getManager()->getLoader(), $player, $this)); 113 | if($ev->isCancelled()) { 114 | return false; 115 | } 116 | $player->sendMessage($this->message); 117 | $this->getManager()->getLoader()->getProvider()->addPoints($player, $this->pointsReward); 118 | $this->getManager()->getLoader()->getProvider()->achieveAchievement($player, $this->getName()); 119 | return true; 120 | } 121 | } -------------------------------------------------------------------------------- /src/BlockHorizons/KillCounter/commands/BaseCommand.php: -------------------------------------------------------------------------------- 1 | setPermission("killcounter.command." . $this->getName()); 21 | $this->loader = $loader; 22 | } 23 | 24 | /** 25 | * @return Loader 26 | */ 27 | public function getPlugin(): plugin { 28 | return $this->loader; 29 | } 30 | 31 | /** 32 | * @return Loader 33 | */ 34 | public function getLoader(): Loader { 35 | return $this->loader; 36 | } 37 | 38 | /** 39 | * @return BaseProvider 40 | */ 41 | public function getProvider(): BaseProvider { 42 | return $this->getLoader()->getProvider(); 43 | } 44 | 45 | public function generateCustomCommandData(Player $player): array { 46 | $commandData = parent::generateCustomCommandData($player); 47 | $commandData["overloads"]["default"]["input"]["parameters"] = CommandOverloads::getOverloads($this->getName()); 48 | return $commandData; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/BlockHorizons/KillCounter/commands/CommandOverloads.php: -------------------------------------------------------------------------------- 1 | [ 21 | 0 => [ 22 | "type" => "rawtext", 23 | "name" => "player", 24 | "optional" => true 25 | ] 26 | ], 27 | "killstop" => [ 28 | 0 => [ 29 | "type" => "int", 30 | "name" => "limit", 31 | "optional" => true 32 | ] 33 | ] 34 | ]; 35 | } 36 | } -------------------------------------------------------------------------------- /src/BlockHorizons/KillCounter/commands/KillStatsCommand.php: -------------------------------------------------------------------------------- 1 | testPermission($sender)) { 25 | return false; 26 | } 27 | if(!$sender instanceof Player && !isset($args[0])) { 28 | $sender->sendMessage(TF::RED . "[Error] You can't use this command through console."); 29 | return true; 30 | } 31 | $player = $sender; 32 | if(isset($args[0])) { 33 | if(($player = $this->getLoader()->getServer()->getPlayer($args[0])) === null) { 34 | $sender->sendMessage(TF::RED . "[Error] That player could not be found."); 35 | return true; 36 | } 37 | } 38 | $data = $this->getLoader()->getProvider()->getPlayerStats($player); 39 | 40 | $sender->sendMessage(TF::GREEN . "--- " . TF::YELLOW . "KillCounter" . TF::GREEN . " ---"); 41 | $sender->sendMessage( 42 | TF::GREEN . "KDA: " . TF::YELLOW . $this->getLoader()->getProvider()->getKda($player) . "\n" . 43 | TF::GREEN . "Player Kills: " . TF::YELLOW . $data["PlayerKills"] . "\n" . 44 | TF::GREEN . "Player Assists: " . TF::YELLOW . $data["PlayerAssists"] . "\n" . 45 | TF::GREEN . "Entity Kills: " . TF::YELLOW . $data["EntityKills"] . "\n" . 46 | TF::GREEN . "Deaths: " . TF::YELLOW . $data["Deaths"] . "\n" . 47 | TF::GREEN . "Points: " . TF::YELLOW . $data["Points"]); 48 | return true; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/BlockHorizons/KillCounter/commands/KillsTopCommand.php: -------------------------------------------------------------------------------- 1 | testPermission($sender)) { 18 | return false; 19 | } 20 | $limit = 10; 21 | if(isset($args[0])) { 22 | if(!is_numeric($args[0])) { 23 | $sender->sendMessage(TF::RED . "[Error] The limit should be numeric."); 24 | return true; 25 | } 26 | $limit = $args[0]; 27 | if($limit > 20) { 28 | $sender->sendMessage(TF::RED . "[Error] Exceeded maximum limit, setting limit to 20..."); 29 | $limit = 20; 30 | } 31 | } 32 | $data = $this->getLoader()->getProvider()->getPointsTop($limit); 33 | 34 | $sender->sendMessage(TF::GREEN . "--- " . TF::YELLOW . "Kill Points Top" . TF::GREEN . " ---"); 35 | $i = 1; 36 | foreach($data as $player => $points) { 37 | $sender->sendMessage(TF::GREEN . "[" . $i . "] " . TF::YELLOW . ucfirst($player) . " : " . TF::RED . TF::BOLD . $points); 38 | $i++; 39 | } 40 | return true; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/BlockHorizons/KillCounter/events/BaseEvent.php: -------------------------------------------------------------------------------- 1 | loader; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/BlockHorizons/KillCounter/events/player/PlayerEvent.php: -------------------------------------------------------------------------------- 1 | player = $player; 16 | } 17 | 18 | /** 19 | * @return Player 20 | */ 21 | public function getPlayer(): Player { 22 | return $this->player; 23 | } 24 | } -------------------------------------------------------------------------------- /src/BlockHorizons/KillCounter/events/player/PlayerKillCounterAchievementGainEvent.php: -------------------------------------------------------------------------------- 1 | achievement = $achievement; 19 | } 20 | 21 | /** 22 | * @return KillCounterAchievement 23 | */ 24 | public function getAchievement(): KillCounterAchievement { 25 | return $this->achievement; 26 | } 27 | } -------------------------------------------------------------------------------- /src/BlockHorizons/KillCounter/events/player/PlayerPointsChangeEvent.php: -------------------------------------------------------------------------------- 1 | previousAmount = $previousAmount; 26 | $this->nextAmount = $nextAmount; 27 | } 28 | 29 | /** 30 | * @return int 31 | */ 32 | public function getPrevious(): int { 33 | return $this->previousAmount; 34 | } 35 | 36 | /** 37 | * @return int 38 | */ 39 | public function getNext(): int { 40 | return $this->nextAmount; 41 | } 42 | 43 | /** 44 | * @param int $nextAmount 45 | */ 46 | public function setNext(int $nextAmount) { 47 | $this->nextAmount = $nextAmount; 48 | } 49 | } -------------------------------------------------------------------------------- /src/BlockHorizons/KillCounter/events/player/killingspree/PlayerKillingSpreeEndEvent.php: -------------------------------------------------------------------------------- 1 | totalKills = $totalKills; 20 | $this->spreeKills = $spreeKills; 21 | } 22 | 23 | /** 24 | * Returns the total amount of kills achieved during this killing spree, and the way to it. 25 | * 26 | * @return int 27 | */ 28 | public function getTotalKills(): int { 29 | return $this->totalKills; 30 | } 31 | 32 | /** 33 | * Returns only the kills that have been achieved while the killing spree was active. 34 | * 35 | * @return int 36 | */ 37 | public function getSpreeKills(): int { 38 | return $this->spreeKills; 39 | } 40 | } -------------------------------------------------------------------------------- /src/BlockHorizons/KillCounter/events/player/killingspree/PlayerKillingSpreeStartEvent.php: -------------------------------------------------------------------------------- 1 | totalKills = $totalKills; 20 | $this->startingKills = $startingKills; 21 | } 22 | 23 | /** 24 | * Returns the total amount of kills from the kills without killing spree and with killing spree. 25 | * 26 | * @return int 27 | */ 28 | public function getTotalKills(): int { 29 | return $this->totalKills; 30 | } 31 | 32 | /** 33 | * Gets the kills the killing spree will be started with. This number is usually zero. 34 | * 35 | * @return int 36 | */ 37 | public function getStartingKills(): int { 38 | return $this->startingKills; 39 | } 40 | 41 | /** 42 | * Sets the kills the killing spree will be started with. 43 | * 44 | * @param int $amount 45 | */ 46 | public function setStartingKills(int $amount) { 47 | $originalKills = $this->totalKills - $this->startingKills; 48 | $this->startingKills = $amount; 49 | $this->totalKills = $amount + $originalKills; 50 | } 51 | } -------------------------------------------------------------------------------- /src/BlockHorizons/KillCounter/handlers/BaseHandler.php: -------------------------------------------------------------------------------- 1 | loader = $loader; 14 | } 15 | 16 | /** 17 | * @return Loader 18 | */ 19 | public function getLoader(): Loader { 20 | return $this->loader; 21 | } 22 | } -------------------------------------------------------------------------------- /src/BlockHorizons/KillCounter/handlers/KillingSpreeHandler.php: -------------------------------------------------------------------------------- 1 | getDataFolder() . "killingsprees.yml")) { 24 | return; 25 | } 26 | $killingSprees = yaml_parse_file($loader->getDataFolder() . "killingsprees.yml"); 27 | foreach($killingSprees as $name => $killingSpree) { 28 | $killingSpree = unserialize($killingSpree); 29 | $this->killingSpree[$name] = $killingSpree; 30 | } 31 | unlink($loader->getDataFolder() . "killingsprees.yml"); 32 | } 33 | 34 | public function save() { 35 | $data = []; 36 | foreach($this->killingSpree as $player => $spree) { 37 | $data[$player] = serialize($spree); 38 | } 39 | yaml_emit_file($this->getLoader()->getDataFolder() . "killingsprees.yml", $data); 40 | } 41 | 42 | /** 43 | * @param Player $player 44 | * 45 | * @return bool 46 | */ 47 | public function addPlayer(Player $player): bool { 48 | if(isset($this->currentKills[$player->getname()])) { 49 | return false; 50 | } 51 | $this->currentKills[$player->getName()] = 0; 52 | return true; 53 | } 54 | 55 | /** 56 | * @param Player $player 57 | * 58 | * @return int 59 | */ 60 | public function getCurrentKills(Player $player): int { 61 | return $this->currentKills[$player->getName()]; 62 | } 63 | 64 | /** 65 | * @param Player $player 66 | */ 67 | public function clearCurrentKills(Player $player) { 68 | unset($this->currentKills[$player->getName()]); 69 | } 70 | 71 | /** 72 | * @param Player $player 73 | * @param int $amount 74 | */ 75 | public function addKills(Player $player, Player $victim, int $amount = 1) { 76 | $this->addPlayer($player); 77 | $this->currentKills[$player->getName()] += $amount; 78 | 79 | if(isset($this->latestKill[$player->getName()]) && $this->getLoader()->getConfig()->get("Enable-Multi-Kill")) { 80 | if(time() - $this->getLatestKill($player)["time"] <= $this->getLoader()->getConfig()->get("Multi-Kill-Time")) { 81 | switch($this->getLatestKill($player)["kills"]) { 82 | default: 83 | case 1: 84 | $type = "Double Kill! "; 85 | break; 86 | case 2: 87 | $type = "Triple Kill! "; 88 | break; 89 | case 3: 90 | $type = "Quadra Kill! "; 91 | break; 92 | case 4: 93 | $type = "Penta Kill! "; 94 | break; 95 | case 5: 96 | $type = "Hexa Kill! "; 97 | unset($this->latestKill[$player->getName()]); 98 | break; 99 | } 100 | $message = TF::RED . TF::BOLD . $type . TF::RESET . TF::YELLOW . $player->getDisplayName() . TF::RESET . TF::YELLOW . " has slain " . TF::RED . $victim->getDisplayName() . TF::YELLOW . "!"; 101 | $this->getLoader()->getServer()->broadcastMessage($message); 102 | } else { 103 | unset($this->latestKill[$player->getName()]); 104 | } 105 | } 106 | $this->setLatestKill($player); 107 | 108 | if($this->getCurrentKills($player) >= $this->getRequiredKills()) { 109 | $this->startKillingSpree($player); 110 | } 111 | } 112 | 113 | /** 114 | * @param Player $player 115 | * 116 | * @return int 117 | */ 118 | public function getKills(Player $player): int { 119 | return $this->currentKills[$player->getName()]; 120 | } 121 | 122 | /** 123 | * @return int 124 | */ 125 | public function getRequiredKills(): int { 126 | return $this->getLoader()->getConfig()->get("Kills-For-Killing-Spree"); 127 | } 128 | 129 | /** 130 | * @param Player $player 131 | * @param int $kills 132 | * 133 | * @return bool 134 | */ 135 | public function startKillingSpree(Player $player, int $kills = 0): bool { 136 | if(isset($this->killingSpree[$player->getName()])) { 137 | return false; 138 | } 139 | $this->getLoader()->getServer()->getPluginManager()->callEvent($ev = new PlayerKillingSpreeStartEvent($this->getLoader(), $player, $kills + $this->getCurrentKills($player), $kills)); 140 | if($ev->isCancelled()) { 141 | return false; 142 | } 143 | 144 | $this->currentKills[$player->getName()] = $ev->getTotalKills() - $ev->getStartingKills(); 145 | $this->killingSpree[$player->getName()] = new KillingSpree($player, $ev->getStartingKills()); 146 | return true; 147 | } 148 | 149 | /** 150 | * @param Player $player 151 | * 152 | * @return KillingSpree 153 | */ 154 | public function getKillingSpree(Player $player): KillingSpree { 155 | return $this->killingSpree[$player->getName()]; 156 | } 157 | 158 | /** 159 | * @param Player $player 160 | * 161 | * @return bool 162 | */ 163 | public function hasKillingSpree(Player $player): bool { 164 | return isset($this->killingSpree[$player->getName()]); 165 | } 166 | 167 | /** 168 | * @param Player $player 169 | * @param Player $killer 170 | * 171 | * @return bool 172 | */ 173 | public function endKillingSpree(Player $player, Player $killer): bool { 174 | if($this->hasKillingSpree($player)) { 175 | $this->getLoader()->getServer()->getPluginManager()->callEvent($ev = new PlayerKillingSpreeEndEvent($this->getLoader(), $player, $this->getKillingSpree($player)->getTotalKills(), $this->getKillingSpree($player)->getKills())); 176 | if($ev->isCancelled()) { 177 | return false; 178 | } 179 | $this->getLoader()->getServer()->broadcastMessage(TF::YELLOW . TF::BOLD . "Shut down! " . TF::RESET . TF::AQUA . $player->getDisplayName() . " was killed by " . $killer->getDisplayName()); 180 | $this->getLoader()->getServer()->broadcastMessage(TF::YELLOW . "The killing spree of " . TF::RED . $player->getDisplayName() . TF::YELLOW . " has ended, with a total of " . TF::RED . $this->killingSpree[$player->getName()]->getTotalKills() . " kills!"); 181 | unset($this->killingSpree[$player->getName()]); 182 | $this->clearCurrentKills($player); 183 | return true; 184 | } 185 | return false; 186 | } 187 | 188 | /** 189 | * @param Player $player 190 | * 191 | * @return bool 192 | */ 193 | public function setLatestKill(Player $player): bool { 194 | $this->latestKill[$player->getName()] = [ 195 | "time" => time(), 196 | "kills" => (isset($this->latestKill[$player->getName()]) ? $this->latestKill[$player->getName()]["kills"] + 1 : 1) 197 | ]; 198 | return true; 199 | } 200 | 201 | /** 202 | * @param Player $player 203 | * 204 | * @return array 205 | */ 206 | public function getLatestKill(Player $player) { 207 | return $this->latestKill[$player->getName()]; 208 | } 209 | } -------------------------------------------------------------------------------- /src/BlockHorizons/KillCounter/listeners/BaseListener.php: -------------------------------------------------------------------------------- 1 | loader = $loader; 15 | } 16 | 17 | /** 18 | * @return Loader 19 | */ 20 | public function getLoader(): Loader { 21 | return $this->loader; 22 | } 23 | 24 | /** 25 | * @return BaseProvider 26 | */ 27 | public function getProvider(): BaseProvider { 28 | return $this->getLoader()->getProvider(); 29 | } 30 | } -------------------------------------------------------------------------------- /src/BlockHorizons/KillCounter/listeners/PlayerEventListener.php: -------------------------------------------------------------------------------- 1 | getProvider()->playerExists($event->getPlayer())) { 32 | $this->getProvider()->initializePlayer($event->getPlayer()); 33 | } 34 | } 35 | 36 | /** 37 | * @param EntityDamageEvent $event 38 | */ 39 | public function onPlayerDamage(EntityDamageEvent $event) { 40 | if(!$event instanceof EntityDamageByEntityEvent) { 41 | return; 42 | } 43 | $attacker = $event->getDamager(); 44 | $target = $event->getEntity(); 45 | if(!$attacker instanceof Player || !$target instanceof Player) { 46 | return; 47 | } 48 | 49 | $this->damagedBy[$target->getName()][$attacker->getName()] = $event->getFinalDamage(); 50 | $this->lastPlayerDamageCause[$target->getName()] = $attacker->getName(); 51 | } 52 | 53 | /** 54 | * @param EntityRegainHealthEvent $event 55 | */ 56 | public function onHealthRegenerate(EntityRegainHealthEvent $event) { 57 | $entity = $event->getEntity(); 58 | if(!$entity instanceof Player) { 59 | return; 60 | } 61 | $totalHealth = ($health = $entity->getHealth() + $event->getAmount()) > 20 ? 20 : $health; 62 | if($totalHealth === 20) { 63 | unset($this->damagedBy[$entity->getName()]); 64 | unset($this->lastPlayerDamageCause[$entity->getName()]); 65 | } 66 | } 67 | 68 | /** 69 | * @param EntityDeathEvent $event 70 | * 71 | * @priority MONITOR 72 | */ 73 | public function onDeath(EntityDeathEvent $event) { 74 | $entity = $event->getEntity(); 75 | if(in_array($entity->getLevel()->getName(), $this->getLoader()->getConfig()->get("Disabled-Worlds", []))) { 76 | return; 77 | } 78 | if(!$entity instanceof Player) { 79 | $cause = $entity->getLastDamageCause(); 80 | if($cause instanceof EntityDamageByEntityEvent) { 81 | $killer = $cause->getDamager(); 82 | if($killer instanceof Player && $killer->isOnline()) { 83 | $killer->sendMessage(TF::AQUA . "+" . $this->getLoader()->getConfig()->get("Points-Per-Entity-Kill") . " Points! " . TF::YELLOW . "You killed a creature!"); 84 | $this->getProvider()->addEntityKills($killer); 85 | } 86 | } 87 | return; 88 | } 89 | } 90 | 91 | /** 92 | * @param PlayerDeathEvent $event 93 | * 94 | * @priority MONITOR 95 | */ 96 | public function onPlayerDeath(PlayerDeathEvent $event) { 97 | $entity = $event->getPlayer(); 98 | $extraPoints = 0; 99 | $spreeKills = $this->getLoader()->getConfig()->get("Points-For-Spree-Killing"); 100 | $lastPlayerAttacker = null; 101 | $killer = null; 102 | if(in_array($entity->getLevel()->getName(), $this->getLoader()->getConfig()->get("Disabled-Worlds", []))) { 103 | return; 104 | } 105 | if(($cause = $entity->getLastDamageCause())->getCause() !== EntityDamageEvent::CAUSE_ENTITY_ATTACK) { 106 | if(!$this->getLoader()->getConfig()->get("Track-Non-Player-Damage-Deaths") === true) { 107 | return; 108 | } 109 | $lastPlayerAttacker = $this->getLoader()->getServer()->getPlayer($this->getLastPlayerAttacker($entity)); 110 | if($lastPlayerAttacker !== null) { 111 | $this->getProvider()->addPlayerKills($lastPlayerAttacker, 1, $this->getKillingSpreeHandler()->hasKillingSpree($entity) ? $spreeKills - 10 : -1); 112 | 113 | $this->getKillingSpreeHandler()->addKills($lastPlayerAttacker, $entity); 114 | 115 | if($this->getKillingSpreeHandler()->hasKillingSpree($lastPlayerAttacker)) { 116 | $this->getKillingSpreeHandler()->getKillingSpree($lastPlayerAttacker)->addKills(); 117 | $extraPoints = $this->getKillingSpreeHandler()->getKillingSpree($lastPlayerAttacker)->getKills() * $this->getLoader()->getConfig()->get("Points-Added-Per-Spree-Kill"); 118 | } 119 | 120 | $lastPlayerAttacker->sendMessage(TF::AQUA . "+" . (string) ($this->getKillingSpreeHandler()->hasKillingSpree($entity) ? $spreeKills - 10 : $this->getLoader()->getConfig()->get("Points-Per-Player-Kill") + $extraPoints) . " Points! " . TF::YELLOW . "You killed " . $entity->getDisplayName() . "!"); 121 | foreach($this->damagedBy[$entity->getName()] as $playerName => $damage) { 122 | if($playerName === $lastPlayerAttacker->getName()) { 123 | continue; 124 | } 125 | if(($player = $this->getLoader()->getServer()->getPlayer($playerName)) !== null) { 126 | $player->sendMessage(TF::AQUA . "+" . $this->getLoader()->getConfig()->get("Points-Per-Player-Assist") . " Points! " . TF::YELLOW . "You have assisted in killing " . $entity->getDisplayName(). "!"); 127 | $this->getProvider()->addPlayerAssists($player); 128 | } 129 | } 130 | } 131 | } 132 | 133 | elseif($cause instanceof EntityDamageByEntityEvent) { 134 | $killer = $cause->getDamager(); 135 | if($killer instanceof Player) { 136 | $this->getProvider()->addPlayerKills($killer, 1, $this->getKillingSpreeHandler()->hasKillingSpree($entity) ? $spreeKills - 10 : -1); 137 | 138 | $this->getKillingSpreeHandler()->addKills($killer, $entity); 139 | if($this->getKillingSpreeHandler()->hasKillingSpree($killer)) { 140 | $this->getKillingSpreeHandler()->getKillingSpree($killer)->addKills(); 141 | $extraPoints = $this->getKillingSpreeHandler()->getKillingSpree($killer)->getKills() * $this->getLoader()->getConfig()->get("Points-Added-Per-Spree-Kill"); 142 | } 143 | 144 | $killer->sendMessage(TF::AQUA . "+" . (string) ($this->getKillingSpreeHandler()->hasKillingSpree($entity) ? $spreeKills - 10 : $this->getLoader()->getConfig()->get("Points-Per-Player-Kill") + $extraPoints) . " Points! " . TF::YELLOW . "You killed " . $entity->getDisplayName(). "!"); 145 | foreach($this->damagedBy[$entity->getName()] as $playerName => $damage) { 146 | if($playerName === $killer->getName()) { 147 | continue; 148 | } 149 | if(($player = $this->getLoader()->getServer()->getPlayer($playerName)) !== null) { 150 | $player->sendMessage(TF::AQUA . "+" . $this->getLoader()->getConfig()->get("Points-Per-Player-Assist") . " Points! " . TF::YELLOW . "You have assisted in killing " . $entity->getDisplayName(). "!"); 151 | $this->getProvider()->addPlayerAssists($player); 152 | } 153 | } 154 | } 155 | } 156 | $this->getProvider()->addDeaths($entity); 157 | unset($this->damagedBy[$entity->getName()]); 158 | unset($this->lastPlayerDamageCause[$entity->getName()]); 159 | 160 | if(isset($killer) || isset($lastPlayerAttacker)) { 161 | $this->getKillingSpreeHandler()->clearCurrentKills($entity); 162 | $this->getKillingSpreeHandler()->endKillingSpree($entity, $killer ?? $lastPlayerAttacker); 163 | } 164 | } 165 | 166 | /** 167 | * @param PlayerPointsChangeEvent $event 168 | */ 169 | public function onPointsGain(PlayerPointsChangeEvent $event) { 170 | if($this->getLoader()->getConfig()->get("Enable-Achievements") !== true) { 171 | return; 172 | } 173 | foreach($this->getLoader()->getAchievementManager()->getAchievements() as $name => $achievement) { 174 | if($achievement->meetsRequirements($event->getPlayer())) { 175 | if($this->getLoader()->getProvider()->hasAchievement($event->getPlayer(), $name)) { 176 | return; 177 | } 178 | $achievement->achieve($event->getPlayer()); 179 | } 180 | } 181 | } 182 | 183 | /** 184 | * @param Player $player 185 | * 186 | * @return string 187 | */ 188 | public function getLastPlayerAttacker(Player $player): string { 189 | return $this->lastPlayerDamageCause[$player->getName()] ?? ""; 190 | } 191 | 192 | /** 193 | * @return KillingSpreeHandler 194 | */ 195 | public function getKillingSpreeHandler(): KillingSpreeHandler { 196 | return $this->getLoader()->getKillingSpreeHandler(); 197 | } 198 | } -------------------------------------------------------------------------------- /src/BlockHorizons/KillCounter/providers/BaseProvider.php: -------------------------------------------------------------------------------- 1 | loader = $loader; 14 | 15 | $this->initializeDatabase(); 16 | } 17 | 18 | /** 19 | * @return Loader 20 | */ 21 | public function getLoader(): Loader { 22 | return $this->loader; 23 | } 24 | 25 | /** 26 | * @param $player 27 | * 28 | * @return string 29 | */ 30 | protected function turnToPlayerName($player): string { 31 | if($player instanceof Player) { 32 | return strtolower($player->getName()); 33 | } 34 | return strtolower($player); 35 | } 36 | 37 | /** 38 | * @param $player 39 | * 40 | * @return int 41 | */ 42 | public function getPlayerKills($player): int { 43 | return $this->getPlayerStats($player)["PlayerKills"]; 44 | } 45 | 46 | /** 47 | * @param $player 48 | * 49 | * @return int 50 | */ 51 | public function getPlayerAssists($player): int { 52 | return $this->getPlayerStats($player)["PlayerAssists"]; 53 | } 54 | 55 | /** 56 | * @param $player 57 | * 58 | * @return int 59 | */ 60 | public function getEntityKills($player): int { 61 | return $this->getPlayerStats($player)["EntityKills"]; 62 | } 63 | 64 | /** 65 | * @param $player 66 | * 67 | * @return int 68 | */ 69 | public function getDeaths($player): int { 70 | return $this->getPlayerStats($player)["Deaths"]; 71 | } 72 | 73 | /** 74 | * @param $player 75 | * 76 | * @return int 77 | */ 78 | public function getPoints($player): int { 79 | return $this->getPlayerStats($player)["Points"]; 80 | } 81 | 82 | /** 83 | * @param $player 84 | * @param int $amount 85 | * 86 | * @return bool 87 | */ 88 | public function addPoints($player, int $amount): bool { 89 | return $this->setPoints($player, $this->getPoints($player) + $amount); 90 | } 91 | 92 | /** 93 | * @param $player 94 | * @param int $amount 95 | * @param int $points 96 | * @param int $money 97 | * 98 | * @return bool 99 | */ 100 | public function addPlayerKills($player, int $amount = 1, int $points = -1, int $money = -1): bool { 101 | $extraMoney = 0; 102 | $extraPoints = 0; 103 | if($this->getLoader()->getKillingSpreeHandler()->hasKillingSpree($player)) { 104 | $killingSpree = $this->getLoader()->getKillingSpreeHandler()->getKillingSpree($player); 105 | $extraPoints = $killingSpree->getKills() * $this->getLoader()->getConfig()->get("Points-Added-Per-Spree-Kill"); 106 | $extraMoney = $killingSpree->getKills() * $this->getLoader()->getConfig()->get("Money-Added-Per-Spree-Kill"); 107 | } 108 | $this->addPoints($player, $points === -1 ? $this->getLoader()->getConfig()->get("Points-Per-Player-Kill") * $amount + $extraPoints: $points * $amount); 109 | if($this->getLoader()->isEconomyEnabled()) { 110 | $this->getLoader()->getEconomy()->addMoney($this->getLoader()->getServer()->getPlayer($player), $money === -1 ? $this->getLoader()->getConfig()->get("Money-Per-Player-Kill") * $amount + $extraMoney : $money * $amount); 111 | } 112 | return $this->setPlayerKills($player, $this->getPlayerKills($player) + $amount); 113 | } 114 | 115 | /** 116 | * @param $player 117 | * @param int $amount 118 | * @param int $points 119 | * @param int $money 120 | * 121 | * @return bool 122 | */ 123 | public function addPlayerAssists($player, int $amount = 1, int $points = -1, int $money = -1): bool { 124 | $this->addPoints($player, $points === -1 ? $this->getLoader()->getConfig()->get("Points-Per-Player-Assist") * $amount : $points * $amount); 125 | if($this->getLoader()->isEconomyEnabled()) { 126 | $this->getLoader()->getEconomy()->addMoney($this->getLoader()->getServer()->getPlayer($player), $money === -1 ? $this->getLoader()->getConfig()->get("Money-Per-Player-Assist") * $amount : $money * $amount); 127 | } 128 | return $this->setPlayerAssists($player, $this->getPlayerAssists($player) + $amount); 129 | } 130 | 131 | /** 132 | * @param $player 133 | * @param int $amount 134 | * @param int $points 135 | * @param int $money 136 | * 137 | * @return bool 138 | */ 139 | public function addEntityKills($player, int $amount = 1, int $points = -1, int $money = -1): bool { 140 | $this->addPoints($player, $points === -1 ? $this->getLoader()->getConfig()->get("Points-Per-Entity-Kill") * $amount : $points * $amount); 141 | if($this->getLoader()->isEconomyEnabled()) { 142 | $this->getLoader()->getEconomy()->addMoney($this->getLoader()->getServer()->getPlayer($player), $money === -1 ? $this->getLoader()->getConfig()->get("Money-Per-Entity-Kill") * $amount : $money * $amount); 143 | } 144 | return $this->setEntityKills($player, $this->getEntityKills($player) + $amount); 145 | } 146 | 147 | /** 148 | * @param $player 149 | * @param int $amount 150 | * @param int $subtractPoints 151 | * 152 | * @return bool 153 | */ 154 | public function addDeaths($player, int $amount = 1, int $subtractPoints = -1, $subtractMoney = -1): bool { 155 | $this->addPoints($player, $subtractPoints === -1 ? -$this->getLoader()->getConfig()->get("Points-Lost-Per-Death") * $amount : -$subtractPoints * $amount); 156 | if($this->getLoader()->isEconomyEnabled() && $this->getLoader()->getConfig()->get("Enable-Money-Leeching") === true) { 157 | $this->getLoader()->getEconomy()->takeMoney($this->getLoader()->getServer()->getPlayer($player), $subtractMoney === -1 ? $this->getLoader()->getConfig()->get("Money-Per-Player-Kill") * $amount : $subtractMoney * $amount); 158 | } 159 | return $this->setDeaths($player, $this->getDeaths($player) + $amount); 160 | } 161 | 162 | /** 163 | * @param $player 164 | * 165 | * @return float 166 | */ 167 | public function getKda($player): float { 168 | $player = $this->turnToPlayerName($player); 169 | $kda = ($this->getPlayerKills($player) + $this->getPlayerAssists($player)) / $this->getDeaths($player); 170 | return $kda; 171 | } 172 | } -------------------------------------------------------------------------------- /src/BlockHorizons/KillCounter/providers/IProvider.php: -------------------------------------------------------------------------------- 1 | getLoader()->getConfig(); 23 | $this->database = new \mysqli($cfg->get("Host"), $cfg->get("User"), $cfg->get("Password"), $cfg->get("Database"), $cfg->get("Port")); 24 | if($this->database->connect_error !== null) { 25 | throw new \mysqli_sql_exception("No connection could be made to the MySQL database: " . $this->database->connect_error); 26 | } 27 | $query = "CREATE TABLE IF NOT EXISTS KillCounter( 28 | Player VARCHAR(16) PRIMARY KEY, 29 | PlayerKills INT, 30 | PlayerAssists INT, 31 | EntityKills INT, 32 | Deaths INT, 33 | Points INT)"; 34 | $this->database->query($query); 35 | 36 | $query = "CREATE TABLE IF NOT EXISTS Achievements( 37 | Player VARCHAR(16), 38 | Achievement VARCHAR(128), 39 | PRIMARY KEY(Player, Achievement))"; 40 | return $this->database->query($query); 41 | } 42 | 43 | /** 44 | * @param Player|string $player 45 | * 46 | * @return bool 47 | */ 48 | public function initializePlayer($player): bool { 49 | $player = $this->turnToPlayerName($player); 50 | 51 | $query = "INSERT INTO KillCounter(Player, PlayerKills, PlayerAssists, EntityKills, Points, Deaths) VALUES ('" . $this->escape($player) . "', 0, 0, 0, 0, 0)"; 52 | return $this->database->query($query); 53 | } 54 | 55 | /** 56 | * @param Player|string $player 57 | * 58 | * @return array 59 | */ 60 | public function getPlayerStats($player): array { 61 | $player = $this->turnToPlayerName($player); 62 | 63 | $query = "SELECT * FROM KillCounter WHERE Player = '" . $this->escape($player) . "'"; 64 | return $this->database->query($query)->fetch_assoc(); 65 | } 66 | 67 | /** 68 | * @return bool 69 | */ 70 | public function closeDatabase(): bool { 71 | if($this->database instanceof \mysqli) { 72 | $this->database->close(); 73 | return true; 74 | } 75 | return false; 76 | } 77 | 78 | /** 79 | * @param $player 80 | * @param int $amount 81 | * 82 | * @return bool 83 | */ 84 | public function setPlayerKills($player, int $amount): bool { 85 | $player = $this->turnToPlayerName($player); 86 | 87 | $query = "UPDATE KillCounter SET PlayerKills = $amount WHERE Player = '" . $this->escape($player) . "'"; 88 | return $this->database->query($query); 89 | } 90 | 91 | public function setPlayerAssists($player, int $amount): bool { 92 | $player = $this->turnToPlayerName($player); 93 | 94 | $query = "UPDATE KillCounter SET PlayerAssists = $amount WHERE Player = '" . $this->escape($player) . "'"; 95 | return $this->database->query($query); 96 | } 97 | 98 | /** 99 | * @param $player 100 | * @param int $amount 101 | * 102 | * @return bool 103 | */ 104 | public function setEntityKills($player, int $amount): bool { 105 | $player = $this->turnToPlayerName($player); 106 | 107 | $query = "UPDATE KillCounter SET EntityKills = $amount WHERE Player = '" . $this->escape($player) . "'"; 108 | return $this->database->query($query); 109 | } 110 | 111 | /** 112 | * @param $player 113 | * @param int $amount 114 | * 115 | * @return bool 116 | */ 117 | public function setPoints($player, int $amount): bool { 118 | $player = $this->turnToPlayerName($player); 119 | 120 | if(($foundPlayer = $this->getLoader()->getServer()->getPlayer($player)) !== null) { 121 | $this->getLoader()->getServer()->getPluginManager()->callEvent($ev = new PlayerPointsChangeEvent($this->getLoader(), $foundPlayer, $this->getPoints($foundPlayer), $amount)); 122 | $amount = $ev->getNext(); 123 | if($ev->isCancelled()) { 124 | return false; 125 | } 126 | } 127 | 128 | $query = "UPDATE KillCounter SET Points = $amount WHERE Player = '" . $this->escape($player) . "'"; 129 | return $this->database->query($query); 130 | } 131 | 132 | /** 133 | * @param $player 134 | * @param int $amount 135 | * 136 | * @return bool 137 | */ 138 | public function setDeaths($player, int $amount): bool { 139 | $player = $this->turnToPlayerName($player); 140 | 141 | $query = "UPDATE KillCounter SET Deaths = $amount WHERE Player = '" . $this->escape($player) . "'"; 142 | return $this->database->query($query); 143 | } 144 | 145 | /** 146 | * @param $player 147 | * 148 | * @return bool 149 | */ 150 | public function playerExists($player): bool { 151 | $player = $this->turnToPlayerName($player); 152 | 153 | $query = "SELECT * FROM KillCounter WHERE Player = '" . $this->escape($player) . "'"; 154 | return !empty($this->database->query($query)->fetch_assoc()); 155 | } 156 | 157 | /** 158 | * @param int $limit 159 | * 160 | * @return array 161 | */ 162 | public function getPointsTop(int $limit = 10): array { 163 | $query = "SELECT * FROM KillCounter ORDER BY Points DESC LIMIT $limit"; 164 | $top = []; 165 | $return = $this->database->query($query); 166 | for($i = 0; $i < $limit; $i++) { 167 | $step = $return->fetch_assoc(); 168 | if(!empty($step["Player"])){ 169 | $top[$step["Player"]] = $step["Points"]; 170 | } 171 | } 172 | return $top; 173 | } 174 | 175 | /** 176 | * @param $player 177 | * @param string $achievement 178 | * 179 | * @return bool 180 | */ 181 | public function achieveAchievement($player, string $achievement): bool { 182 | $player = $this->turnToPlayerName($player); 183 | 184 | $query = "INSERT INTO Achievements(Player, Achievement) VALUES ('" . $this->escape($player) . "', '" . $this->escape($achievement) . "')"; 185 | return $this->database->query($query); 186 | } 187 | 188 | /** 189 | * @param $player 190 | * @param string $achievement 191 | * 192 | * @return bool 193 | */ 194 | public function hasAchievement($player, string $achievement): bool { 195 | $player = $this->turnToPlayerName($player); 196 | 197 | $query = "SELECT * FROM Achievements WHERE Player = '" . $this->escape($player) . "' AND Achievement = '" . $this->escape($achievement) . "'"; 198 | return !empty($this->database->query($query)->fetch_assoc()); 199 | } 200 | 201 | /** 202 | * @param string $string 203 | * 204 | * @return string 205 | */ 206 | private function escape(string $string): string { 207 | return $this->database->real_escape_string($string); 208 | } 209 | } -------------------------------------------------------------------------------- /src/BlockHorizons/KillCounter/providers/SQLiteProvider.php: -------------------------------------------------------------------------------- 1 | getLoader()->getDataFolder() . "killcounter.sqlite3")) { 19 | file_put_contents($file, ""); 20 | } 21 | $this->database = new \SQLite3($file); 22 | $query = "CREATE TABLE IF NOT EXISTS KillCounter( 23 | Player VARCHAR(16) PRIMARY KEY, 24 | PlayerKills INT, 25 | PlayerAssists INT, 26 | EntityKills INT, 27 | Deaths INT, 28 | Points INT)"; 29 | $this->database->exec($query); 30 | 31 | $query = "CREATE TABLE IF NOT EXISTS Achievements( 32 | Player VARCHAR(16), 33 | Achievement VARCHAR(128), 34 | PRIMARY KEY(Player, Achievement))"; 35 | return $this->database->exec($query); 36 | } 37 | 38 | /** 39 | * @param $player 40 | * @param string $achievement 41 | * 42 | * @return bool 43 | */ 44 | public function achieveAchievement($player, string $achievement): bool { 45 | $player = $this->turnToPlayerName($player); 46 | 47 | $query = "INSERT INTO Achievements(Player, Achievement) VALUES ('" . $this->escape($player) . "', '" . $this->escape($achievement) . "')"; 48 | return $this->database->exec($query); 49 | } 50 | 51 | /** 52 | * @param $player 53 | * @param string $achievement 54 | * 55 | * @return bool 56 | */ 57 | public function hasAchievement($player, string $achievement): bool { 58 | $player = $this->turnToPlayerName($player); 59 | 60 | $query = "SELECT * FROM Achievements WHERE Player = '" . $this->escape($player) . "' AND Achievement = '" . $this->escape($achievement) . "'"; 61 | return !empty($this->database->query($query)->fetchArray(SQLITE3_ASSOC)); 62 | } 63 | 64 | /** 65 | * @param Player|string $player 66 | * 67 | * @return bool 68 | */ 69 | public function initializePlayer($player): bool { 70 | $player = $this->turnToPlayerName($player); 71 | 72 | $query = "INSERT INTO KillCounter(Player, PlayerKills, PlayerAssists, EntityKills, Points, Deaths) VALUES ('" . $this->escape($player) . "', 0, 0, 0, 0, 0)"; 73 | return $this->database->exec($query); 74 | } 75 | 76 | /** 77 | * @param Player|string $player 78 | * 79 | * @return array 80 | */ 81 | public function getPlayerStats($player): array { 82 | $player = $this->turnToPlayerName($player); 83 | 84 | $query = "SELECT * FROM KillCounter WHERE Player = '" . $this->escape($player) . "'"; 85 | return $this->database->query($query)->fetchArray(SQLITE3_ASSOC); 86 | } 87 | 88 | /** 89 | * @param $player 90 | * @param int $amount 91 | * 92 | * @return bool 93 | */ 94 | public function setPlayerKills($player, int $amount): bool { 95 | $player = $this->turnToPlayerName($player); 96 | 97 | $query = "UPDATE KillCounter SET PlayerKills = $amount WHERE Player = '" . $this->escape($player) . "'"; 98 | return $this->database->exec($query); 99 | } 100 | 101 | /** 102 | * @param $player 103 | * @param int $amount 104 | * 105 | * @return bool 106 | */ 107 | public function setPlayerAssists($player, int $amount): bool { 108 | $player = $this->turnToPlayerName($player); 109 | 110 | $query = "UPDATE KillCounter SET PlayerAssists = $amount WHERE Player = '" . $this->escape($player) . "'"; 111 | return $this->database->exec($query); 112 | } 113 | 114 | /** 115 | * @param $player 116 | * @param int $amount 117 | * 118 | * @return bool 119 | */ 120 | public function setPoints($player, int $amount): bool { 121 | $player = $this->turnToPlayerName($player); 122 | 123 | if(($foundPlayer = $this->getLoader()->getServer()->getPlayer($player)) !== null) { 124 | $this->getLoader()->getServer()->getPluginManager()->callEvent($ev = new PlayerPointsChangeEvent($this->getLoader(), $foundPlayer, $this->getPoints($foundPlayer), $amount)); 125 | $amount = $ev->getNext(); 126 | if($ev->isCancelled()) { 127 | return false; 128 | } 129 | } 130 | 131 | $query = "UPDATE KillCounter SET Points = $amount WHERE Player = '" . $this->escape($player) . "'"; 132 | return $this->database->exec($query); 133 | } 134 | 135 | /** 136 | * @param $player 137 | * @param int $amount 138 | * 139 | * @return bool 140 | */ 141 | public function setEntityKills($player, int $amount): bool { 142 | $player = $this->turnToPlayerName($player); 143 | 144 | $query = "UPDATE KillCounter SET EntityKills = $amount WHERE Player = '" . $this->escape($player) . "'"; 145 | return $this->database->exec($query); 146 | } 147 | 148 | /** 149 | * @param $player 150 | * @param int $amount 151 | * 152 | * @return bool 153 | */ 154 | public function setDeaths($player, int $amount): bool { 155 | $player = $this->turnToPlayerName($player); 156 | 157 | $query = "UPDATE KillCounter SET Deaths = $amount WHERE Player = '" . $this->escape($player) . "'"; 158 | return $this->database->exec($query); 159 | } 160 | 161 | /** 162 | * @return bool 163 | */ 164 | public function closeDatabase(): bool { 165 | if($this->database instanceof \SQLite3) { 166 | $this->database->close(); 167 | return true; 168 | } 169 | return false; 170 | } 171 | 172 | /** 173 | * @param $player 174 | * 175 | * @return bool 176 | */ 177 | public function playerExists($player): bool { 178 | $player = $this->turnToPlayerName($player); 179 | 180 | $query = "SELECT * FROM KillCounter WHERE Player = '" . $this->escape($player) . "'"; 181 | return !empty($this->database->query($query)->fetchArray(SQLITE3_ASSOC)); 182 | } 183 | 184 | /** 185 | * @param int $limit 186 | * 187 | * @return array 188 | */ 189 | public function getPointsTop(int $limit = 10): array { 190 | $query = "SELECT * FROM KillCounter ORDER BY Points DESC LIMIT $limit"; 191 | $top = []; 192 | $return = $this->database->query($query); 193 | for($i = 0; $i < $limit; $i++) { 194 | $step = $return->fetchArray(SQLITE3_ASSOC); 195 | if(!empty($step["Player"])){ 196 | $top[$step["Player"]] = $step["Points"]; 197 | } 198 | } 199 | return $top; 200 | } 201 | 202 | /** 203 | * @param string $string 204 | * 205 | * @return string 206 | */ 207 | private function escape(string $string): string { 208 | return \SQLite3::escapeString($string); 209 | } 210 | } 211 | --------------------------------------------------------------------------------