Repository: BoxOfDevs/CommandShop Branch: master Commit: 73577b695b2d Files: 10 Total size: 40.9 KB Directory structure: gitextract_iem1l3se/ ├── .github/ │ └── ISSUE_TEMPLATE.md ├── .gitignore ├── .poggit.yml ├── .travis.yml ├── LICENSE ├── README.md ├── plugin.yml ├── resources/ │ └── config.yml └── src/ └── BoxOfDevs/ └── CommandShop/ ├── CShopListener.php └── CommandShop.php ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/ISSUE_TEMPLATE.md ================================================ ### Brief description ### Steps to reproduce 1. ... 2. ... 3. ... ### Expected result ### Actual result ### Server Information * CommandShop Version: * Software Version: * Server OS: ### CrashDumps/Errors ``` Paste your CrashDump or error by replacing this text (DON'T delete the backticks!) ``` ================================================ FILE: .gitignore ================================================ ################# ## PMMP ################# config.yml !resources/config.yml ################# ## PhpStorm ################# .idea/ ################# ## Eclipse ################# *.pydevproject .project .metadata bin/ tmp/ *.tmp *.bak *.swp *~.nib local.properties .classpath .settings/ .loadpath # External tool builders .externalToolBuilders/ # Locally stored "Eclipse launch configurations" *.launch # CDT-specific .cproject # PDT-specific .buildpath ################# ## Visual Studio ################# ## Ignore Visual Studio temporary files, build results, and ## files generated by popular Visual Studio add-ons. # User-specific files *.suo *.user *.sln.docstates # Build results [Dd]ebug/ [Rr]elease/ x64/ build/ [Bb]in/ [Oo]bj/ # MSTest test Results [Tt]est[Rr]esult*/ [Bb]uild[Ll]og.* *_i.c *_p.c *.ilk *.meta *.obj *.pch *.pdb *.pgc *.pgd *.rsp *.sbr *.tlb *.tli *.tlh *.tmp *.tmp_proj *.log *.vspscc *.vssscc .builds *.pidb *.log *.scc # Visual C++ cache files ipch/ *.aps *.ncb *.opensdf *.sdf *.cachefile # Visual Studio profiler *.psess *.vsp *.vspx # Guidance Automation Toolkit *.gpState # ReSharper is a .NET coding add-in _ReSharper*/ *.[Rr]e[Ss]harper # TeamCity is a build add-in _TeamCity* # DotCover is a Code Coverage Tool *.dotCover # NCrunch *.ncrunch* .*crunch*.local.xml # Installshield output folder [Ee]xpress/ # DocProject is a documentation generator add-in DocProject/buildhelp/ DocProject/Help/*.HxT DocProject/Help/*.HxC DocProject/Help/*.hhc DocProject/Help/*.hhk DocProject/Help/*.hhp DocProject/Help/Html2 DocProject/Help/html # Click-Once directory publish/ # Publish Web Output *.Publish.xml *.pubxml *.publishproj # NuGet Packages Directory ## TODO: If you have NuGet Package Restore enabled, uncomment the next line #packages/ # Windows Azure Build Output csx *.build.csdef # Windows Store app package directory AppPackages/ # Others sql/ *.Cache ClientBin/ [Ss]tyle[Cc]op.* ~$* *~ *.dbmdl *.[Pp]ublish.xml *.pfx *.publishsettings # RIA/Silverlight projects Generated_Code/ # Backup & report files from converting an old project file to a newer # Visual Studio version. Backup files are not needed, because we have git ;-) _UpgradeReport_Files/ Backup*/ UpgradeLog*.XML UpgradeLog*.htm # SQL Server files App_Data/*.mdf App_Data/*.ldf ############# ## Windows detritus ############# # Windows image file caches Thumbs.db ehthumbs.db # Folder config file Desktop.ini # Recycle Bin used on file shares $RECYCLE.BIN/ # Mac crap .DS_Store ############# ## Python ############# *.py[cod] # Packages *.egg *.egg-info dist/ build/ eggs/ parts/ var/ sdist/ develop-eggs/ .installed.cfg # Installer logs pip-log.txt # Unit test / coverage reports .coverage .tox #Translations *.mo #Mr Developer .mr.developer.cfg ================================================ FILE: .poggit.yml ================================================ --- # Poggit-CI Manifest. Open the CI at https://poggit.pmmp.io/ci/BoxOfDevs/CommandShop projects: CommandShop: path: "" ... ================================================ FILE: .travis.yml ================================================ #Travis CI dist: xenial sudo: false language: php php: - 7.0 script: - curl -o Travis.sh 'https://cloud.himbeer.me/bod/travisgen.php?slug='$TRAVIS_REPO_SLUG'&type=shell' - chmod +x Travis.sh - ./Travis.sh notifications: webhooks: https://cloud.himbeer.me/bod/travis-to-discord.php email: false ================================================ FILE: LICENSE ================================================ BoxOfDevs General Software License 1.1.3 ========================================= This license is designed to be used with any software which would like to have no selling for profits, nor any public redistribution without giving the original author credits. -------------------------------------------------------------------------------------------------------------------------------------- The License: refers to the BoxOfDevs International Software License 1.1.3 The Software: refers to any works licensed under The License. The Modification: refers to any modified version of The Software. The Redistribution: refers to any redistributions of The Software/The Modification. The User: refers to any user of The Software licensed under The License. The Author: refers to any developer, organisation, legal owner, or creator of The Software that has been licensed under the The License. -------------------------------------------------------------------------------------------------------------------------------------- Section 1 - Allowances: 1. Both The User & The Author Can: a. Modify private copies of The Software and use in any way they wish. b. Change which license The Software/The Modification is licensed under. 2. The User Can: a. Request new features, support, or more rights from The Author. b. Redistribute The Software/The Modification, ensuring The User gives all appropriate credit to The Author and alerting The Author to The Redistribution. 3. The Author Can: a. Change or update The Software in any way they wish, ensuring they follow the other terms of The License. b. Grant extra rights to The User who has requested them. c. Reserve the right to request The User to take down their instance of The Software/The Modification/The Redistribution. Section 2 - Restrictions: 1. Both The User & The Author Cannot: a. Introduce any malicious code into The Software/The Modification. b. Sell any part of The Software/The Modification for profit. 2. The User Cannot: a. Hold The Author responsible for any unknown errors. b. Claim The Software/The Modification/The Redistribution as entirely The User's product. c. Use the software without crediting the Author. 3. The Author Cannot: a. Restrict The User in any way not specified by The License. b. Distribute any form of The Software without proper documentation. Term. The term of this Public License is specified in Section 6(a). Media and formats; technical modifications allowed. The Licensor authorizes You to exercise the Licensed Rights in all media and formats whether now known or hereafter created, and to make technical modifications necessary to do so. The Licensor waives and/or agrees not to assert any right or authority to forbid You from making technical modifications necessary to exercise the Licensed Rights, including technical modifications necessary to circumvent Effective Technological Measures. For purposes of this Public License, simply making modifications authorized by this Section 2(a)(4) never produces Modification. Downstream recipients. Offer from the Licensor – Licensed Material. Every recipient of the Licensed Material automatically receives an offer from the Licensor to exercise the Licensed Rights under the terms and conditions of this Public License. Additional offer from the Licensor – the Modification. Every recipient of the Modification from You automatically receives an offer from the Licensor to exercise the Licensed Rights in the Modification under the conditions of the Adapter’s License You apply. No downstream restrictions. You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, the Licensed Material if doing so restricts exercise of the Licensed Rights by any recipient of the Licensed Material. No endorsement. Nothing in this Public License constitutes or may be construed as permission to assert or imply that You are, or that Your use of the Licensed Material is, connected with, or sponsored, endorsed, or granted official status by, the Licensor or others designated to receive attribution as provided in Section 3(a)(1)(A)(i). Other rights. Moral rights, such as the right of integrity, are not licensed under this Public License, nor are publicity, privacy, and/or other similar personality rights; however, to the extent possible, the Licensor waives and/or agrees not to assert any such rights held by the Licensor to the limited extent necessary to allow You to exercise the Licensed Rights, but not otherwise. Patent and trademark rights are not licensed under this Public License. To the extent possible, the Licensor waives any right to collect royalties from You for the exercise of the Licensed Rights, whether directly or through a collecting society under any voluntary or waivable statutory or compulsory licensing scheme. In all other cases the Licensor expressly reserves any right to collect such royalties. Section 3 – License Conditions. Your exercise of the Licensed Rights is expressly made subject to the following conditions. a) Attribution. If You Share the Licensed Material (including in modified form), You must: retain the following if it is supplied by the Licensor with the Licensed Material: identification of the creator(s) of the Licensed Material and any others designated to receive attribution, in any reasonable manner requested by the Licensor (including by pseudonym if designated); a copyright notice; a notice that refers to this Public License; a notice that refers to the disclaimer of warranties; a URI or hyperlink to the Licensed Material to the extent reasonably practicable; indicate if You modified the Licensed Material and retain an indication of any previous modifications; and indicate the Licensed Material is licensed under this Public License, and include the text of, or the URI or hyperlink to, this Public License. You may satisfy the conditions in Section 3(a)(1) in any reasonable manner based on the medium, means, and context in which You Share the Licensed Material. For example, it may be reasonable to satisfy the conditions by providing a URI or hyperlink to a resource that includes the required information. If requested by the Licensor, You must remove any of the information required by Section 3(a)(1)(A) to the extent reasonably practicable. b) ShareAlike. In addition to the conditions in Section 3(a), if You Share the Modification You produce, the following conditions also apply. The Adapter’s License You apply must be a BoxOfDevs General License with the same License Elements, this version or later, or a BY-SA Compatible License. You must include the text of, or the URI or hyperlink to, the Adapter's License You apply. You may satisfy this condition in any reasonable manner based on the medium, means, and context in which You Share the Modification. You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, Modification that restrict exercise of the rights granted under the Adapter's License You apply. c) Forever Open Source. In addition to the conditions in Section 3(a) and Section 3(b), if You Share the Modification You produce, the following conditions also apply. The Adapted work must have an open source existing repertory, accessible by anyone anytime linked in the Redistribution Description/Documentation. You may not restrict anyone from accessing the source code, use it, and redistribute it under anything not explicily specified by the License. d) Free. In addition to the conditions in Section 3(a), Section 3(b) and Section 3(c), if You Share by any way Modification and/or the Software You produce, the following conditions also apply. The Work must be redistributed entirely free, under this license. You may not impose fees to anyone that gets the Modification/The Software. Section 4 – Sui Generis Database Rights. Where the Licensed Rights include Sui Generis Database Rights that apply to Your use of the Licensed Material: for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, reuse, reproduce, and Share all or a substantial portion of the contents of the database; if You include all or a substantial portion of the database contents in a database in which You have Sui Generis Database Rights, then the database in which You have Sui Generis Database Rights (but not its individual contents) is Modification, including for purposes of Section 3(b); and You must comply with the conditions in Section 3(a) if You Share all or a substantial portion of the contents of the database. For the avoidance of doubt, this Section 4 supplements and does not replace Your obligations under this Public License where the Licensed Rights include other Copyright and Similar Rights. Section 5 – Disclaimer of Warranties and Limitation of Liability. Unless otherwise separately undertaken by the Licensor, to the extent possible, the Licensor offers the Licensed Material as-is and as-available, and makes no representations or warranties of any kind concerning the Licensed Material, whether express, implied, statutory, or other. This includes, without limitation, warranties of title, merchantability, fitness for a particular purpose, non-infringement, absence of latent or other defects, accuracy, or the presence or absence of errors, whether or not known or discoverable. Where disclaimers of warranties are not allowed in full or in part, this disclaimer may not apply to You. To the extent possible, in no event will the Licensor be liable to You on any legal theory (including, without limitation, negligence) or otherwise for any direct, special, indirect, incidental, consequential, punitive, exemplary, or other losses, costs, expenses, or damages arising out of this Public License or use of the Licensed Material, even if the Licensor has been advised of the possibility of such losses, costs, expenses, or damages. Where a limitation of liability is not allowed in full or in part, this limitation may not apply to You. The disclaimer of warranties and limitation of liability provided above shall be interpreted in a manner that, to the extent possible, most closely approximates an absolute disclaimer and waiver of all liability. Section 6 – Term and Termination. This Public License applies for the term of the Copyright and Similar Rights licensed here. However, if You fail to comply with this Public License, then Your rights under this Public License terminate automatically. Where Your right to use the Licensed Material has terminated under Section 6(a), it reinstates: automatically as of the date the violation is cured, provided it is cured within 30 days of Your discovery of the violation; or upon express reinstatement by the Licensor. For the avoidance of doubt, this Section 6(b) does not affect any right the Licensor may have to seek remedies for Your violations of this Public License. For the avoidance of doubt, the Licensor may also offer the Licensed Material under separate terms or conditions or stop distributing the Licensed Material at any time; however, doing so will not terminate this Public License. Sections 1, 5, 6, 7, and 8 survive termination of this Public License. Section 7 – Other Terms and Conditions. The Licensor shall not be bound by any additional or different terms or conditions communicated by You unless expressly agreed. Any arrangements, understandings, or agreements regarding the Licensed Material not stated herein are separate from and independent of the terms and conditions of this Public License. In the event that The License is updated/changed on the official github repository/on the official website, you automatically agree. The Author is not required to notify The User that The License has been updated/changed. Section 8 – Interpretation. For the avoidance of doubt, this Public License does not, and shall not be interpreted to, reduce, limit, restrict, or impose conditions on any use of the Licensed Material that could lawfully be made without permission under this Public License. To the extent possible, if any provision of this Public License is deemed unenforceable, it shall be automatically reformed to the minimum extent necessary to make it enforceable. If the provision cannot be reformed, it shall be severed from this Public License without affecting the enforceability of the remaining terms and conditions. No term or condition of this Public License will be waived and no failure to comply consented to unless expressly agreed to by the Licensor. Nothing in this Public License constitutes or may be interpreted as a limitation upon, or waiver of, any privileges and immunities that apply to the Licensor or You, including from the legal processes of any jurisdiction or authority. ================================================ FILE: README.md ================================================ # CommandShop [![Poggit-CI](https://poggit.pmmp.io/ci.shield/BoxOfDevs/CommandShop/CommandShop)](https://poggit.pmmp.io/ci/BoxOfDevs/CommandShop/CommandShop) [![Build Status](https://travis-ci.org/BoxOfDevs/CommandShop.svg?branch=master)](https://travis-ci.org/BoxOfDevs/CommandShop) [Come chat with us on Discord!](https://discord.me/bod) [](https://discord.me/bod) Players have to pay items or money to use specific commands! A PocketMine plugin. ### Please read the [wiki](https://github.com/BoxOfDevs/CommandShop/wiki) if you want to know how this plugin works! ###### This plugin was made for and is only tested on PocketMine-MP, you may want to report issues you have when using another variant of it (a so called spoon), but if they don't occur on standard PocketMine-MP too, fixing them won't be at a high priority. Feel free to always make a Pull Request though. ## Download this plugin! You may grab the plugin from [source](https://github.com/BoxOfDevs/CommandShop/archive/master.zip), or download the latest .phar from [Poggit](https://poggit.pmmp.io/ci/BoxOfDevs/CommandShop/CommandShop).
**This plugin requires [EconomyAPI](https://github.com/onebone/EconomyS) by onebone to enable buying commands via money!**
By BoxOfDevs: ![BoxOfDevs Banner](http://files.himbeer.me/bod-banner.gif) ## License This work is licensed under the BoxOfDevs General Software License 1.1.3 ================================================ FILE: plugin.yml ================================================ --- name: CommandShop author: BoxOfDevs Team version: 1.0.0 main: BoxOfDevs\CommandShop\CommandShop api: [3.0.0-ALPHA7, 3.0.0-ALPHA8, 3.0.0-ALPHA9, 3.0.0-ALPHA10, 3.0.0-ALPHA11, 3.0.0-ALPHA12, 3.0.0] softdepend: EconomyAPI commands: cshop: description: "Create, manage and remove 'buyable' commands" usage: "/cshop " permission: cshop.command.manage buycmd: description: "'Buy' a command" usage: "/buycmd " permission: cshop.buy.command permissions: cshop: default: op description: "Main permission for CommandShop" children: cshop.command.manage: default: op description: "Permission for '/cshop'" cshop.breaksign: default: op description: "Permission for breaking CommandShop signs" cshop.buy: default: op description: "Permission for 'buying' commands via '/buycmd' AND via signs" children: cshop.buy.command: default: true description: "Permission for 'buying' commands via '/buycmd'" cshop.buy.sign: default: true description: "Permission for 'buying' commands via signs" ... ================================================ FILE: resources/config.yml ================================================ --- # Config and command/sign-database for CommandShop by BoxOfDevs: # Messages: buy.money.success: "{prefix}You successfully bought the command {cmd} for {amount} {unit}!{line}{prefix}The command has already been executed." buy.money.miss: "{error}You don't have enough money to buy this command. You would need {amount} {unit}!" buy.item.success: "{prefix}You successfully bought the command {cmd} with the item {item}!{line}{prefix}The command has already been executed." buy.item.miss: "{error}You don't have enough items to buy this command, items needed:{line}Item: {item} Amount: {amount}" buy.contactadmin: "{line}If you are a normal user, please contact your server administrator!" command.notfound: "{error}Command {cmd} wasn't found in the list of buyable commands!" sign.confirm: "{prefix}Tap the sign again to confirm that you want to buy the command {cmd}!" sign.noperm: "{error}You don't have the permission to buy commands via signs!" sign.nobreak: "{error}You don't have the permission to break CommandShop signs!" buycmd.disabled: "{error}/buycmd is disabled for this buyable command!" # List and database of buyable commands: commands: example: cmds: - "tp {player} 123 123 123" buycmd: "true" price: paytype: "item" item: "1:0:64" # List and database for CommandShop signs: signs: [] ... ================================================ FILE: src/BoxOfDevs/CommandShop/CShopListener.php ================================================ cs = $cs; } /** * When a player touches a sign * * @param PlayerInteractEvent $event */ public function onSignTouch(PlayerInteractEvent $event) { if ($event->getBlock()->getId() != Block::SIGN_POST && $event->getBlock()->getId() != Block::WALL_SIGN) return; $p = $event->getPlayer(); // Hack for fixing MC's interact packet spam using a cooldown (Part 1) $pName = $p->getName(); if (isset($this->interactCooldowns[$pName]) && $this->interactCooldowns[$pName] + 0.5 > microtime(true)) { return; } $this->interactCooldowns[$pName] = microtime(true); $sign = $p->getLevel()->getTile($event->getBlock()); $level = $p->getLevel()->getName(); if (!($sign instanceof Sign)) return; $x = $sign->getBlock()->getX(); $y = $sign->getBlock()->getY(); $z = $sign->getBlock()->getZ(); $signs = $this->cs->getConfig()->get("signs", []); if (isset($this->cs->signsetters[$p->getName()])) { foreach ($signs as $i => $s) { if ($s["posx"] === $x && $s["posy"] === $y && $s["posz"] === $z && $s["level"] === $level) { unset($signs[$i]); $this->cs->getConfig()->set("signs", $signs); $this->cs->getConfig()->save(); } } $signs = $this->cs->getConfig()->get("signs", []); $index = 0; while (isset($signs[$index])) { $index++; } $signs[$index]["posx"] = $x; $signs[$index]["posy"] = $y; $signs[$index]["posz"] = $z; $signs[$index]["level"] = $level; $signs[$index]["cmd"] = $this->cs->signsetters[$p->getName()]; $this->cs->getConfig()->set("signs", $signs); $this->cs->getConfig()->save(); unset($this->cs->signsetters[$p->getName()]); $p->sendMessage(CommandShop::PREFIX . TF::GREEN . "Sign has been successfully created!"); return; } else { foreach ($signs as $index => $s) { if ($s["posx"] === $x && $s["posy"] === $y && $s["posz"] === $z && $s["level"] === $level) { if ($p->hasPermission("cshop.buy.sign")) { if (isset($this->confirms[$p->getName()])) { if ($this->confirms[$p->getName()] === $index) { $this->cs->buyCmd($s["cmd"], $p); unset($this->confirms[$p->getName()]); return; } else { unset($this->confirms[$p->getName()]); } } $this->confirms[$p->getName()] = $index; $replacers = ["{cmd}" => $s["cmd"]]; $p->sendMessage($this->cs->getMessage("sign.confirm", $replacers)); } else { $p->sendMessage($this->cs->getMessage("sign.noperm")); } return; } } } return; } /** * When a player breaks a sign * * @param BlockBreakEvent $event */ public function onBlockBreak(BlockBreakEvent $event) { if ($event->getBlock()->getId() != Block::SIGN_POST && $event->getBlock()->getId() != Block::WALL_SIGN) return; $p = $event->getPlayer(); $sign = $p->getLevel()->getTile($event->getBlock()); $level = $p->getLevel()->getName(); if (!($sign instanceof Sign)) return; $x = $sign->getBlock()->getX(); $y = $sign->getBlock()->getY(); $z = $sign->getBlock()->getZ(); $signs = $this->cs->getConfig()->get("signs", []); foreach ($signs as $i => $s) { if ($s["posx"] === $x && $s["posy"] === $y && $s["posz"] === $z && $s["level"] === $level) { if ($p->hasPermission("cshop.breaksign")) { unset($signs[$i]); $p->sendMessage(CommandShop::PREFIX . TF::RED . "Sign has been successfully removed!"); $this->cs->getConfig()->set("signs", $signs); $this->cs->getConfig()->save(); return; } else { $p->sendMessage($this->cs->getMessage("sign.nobreak")); $event->setCancelled(true); return; } } } return; } } ================================================ FILE: src/BoxOfDevs/CommandShop/CommandShop.php ================================================ " ", "remove" => "", "setprice" => " ", "sign" => "", "buycmd" => " ", "addcmd" => " ", "list" => "", "info" => "", "help" => "" ]; /** * @var string[] */ public $signsetters = []; /** * When the plugin enables */ public function onEnable() { $this->getServer()->getPluginManager()->registerEvents(new CShopListener($this), $this); $this->saveDefaultConfig(); if ($this->getServer()->getPluginManager()->getPlugin("EconomyAPI") != null) { $this->economy = EconomyAPI::getInstance(); $this->getLogger()->notice("EconomyAPI successfully detected!"); } else { $this->economy = null; $this->getLogger()->notice("Failed to load EconomyAPI! Only item-pay mode is avaiable."); } } /** * Translates a message from config * * @param string $msg * @param array $replacers * @return string */ public function getMessage(string $msg, array $replacers = []): string { $msg = $this->getConfig()->get($msg); $msg = str_ireplace(array_keys($replacers), array_values($replacers), $msg); $values = [ "{prefix}" => self::PREFIX, "{error}" => self::ERROR, "{line}" => "\n" ]; $msg = str_ireplace(array_keys($values), array_values($values), $msg); return $msg; } /** * Send the usage of a Command to a Player * * @param string $cmd * @param CommandSender $p */ public function sendUsage(string $cmd, CommandSender $p) { $p->sendMessage(self::ERROR . "Usage: /cshop $cmd " . $this->usages[$cmd]); } /** * Get an item from a string (used to parse count) * * @param string $name * @return Item */ public function getItem(string $name): Item { if (strpos($name, ":") != false) { $arr = explode(":", $name); $name = $arr[0]; $dmg = (int)$arr[1]; if (isset($arr[2])) { $count = (int)$arr[2]; } else { $count = 1; } } else { $dmg = 0; $count = 1; } if (!is_numeric($name)) { $item = Item::fromString($name); } else { $item = Item::get((int)$name); } $item->setDamage($dmg); $item->setCount($count); return $item; } /** * Execute command as console * * @param array $cmds * @param Player $p */ public function executeCommands(array $cmds, Player $p) { $cmds = str_replace("{player}", '"' . $p->getName() . '"', $cmds); $cmds = str_replace("{level}", $p->getLevel()->getName(), $cmds); $cmds = str_replace("{x}", (string)round($p->x, 0), $cmds); $cmds = str_replace("{y}", (string)round($p->y, 0), $cmds); $cmds = str_replace("{z}", (string)round($p->z, 0), $cmds); foreach ($cmds as $cmd) { $this->getServer()->dispatchCommand(new ConsoleCommandSender(), $cmd); } return; } /** * Removes an item from a player's inventory (solving count issues with soft) * * @param Item $item * @param BaseInventory $inventory */ private function remove(Item $item, BaseInventory $inventory) { $checkDamage = !$item->hasAnyDamageValue(); $checkTags = $item->hasCompoundTag(); $count = $item->getCount(); foreach ($inventory->getContents() as $index => $i) { if ($item->equals($i, $checkDamage, $checkTags)) { if ($i->getCount() > $count) { $i->setCount($i->getCount() - $count); $inventory->setItem($index, $i); return; } elseif ($i->getCount() < $count) { $count -= $i->getCount(); $inventory->clear($index); } else { $inventory->clear($index); return; } } } } /** * Buy a command * * @param string $cmd * @param Player $p * @return bool */ public function buyCmd(string $cmd, Player $p): bool { if ($p instanceof Player) { $name = $p->getName(); $cmd = strtolower($cmd); $cmds = $this->getConfig()->get("commands", []); if (isset($cmds[$cmd])) { $cmda = $cmds[$cmd]; if (!isset($cmda["price"])) { $msg = self::ERROR . "Command couldn't be bought because the price isn't set!"; $this->getLogger()->warning($msg); $p->sendMessage($msg . $this->getMessage("buy.contactadmin")); return false; } $price = $cmda["price"]; $commands = $cmda["cmds"]; if ($price["paytype"] === "money") { if ($this->economy != null) { $amount = $price["amount"]; if ($this->economy->reduceMoney($p, $amount) === 1) { $this->executeCommands($commands, $p); $unit = $this->economy->getMonetaryUnit(); $replacers = ["{cmd}" => $cmd, "{amount}" => $amount, "{unit}" => $unit]; $p->sendMessage($this->getMessage("buy.money.success", $replacers)); $this->getLogger()->debug("The player $name has bought the command $cmd for $amount $unit via EconomyAPI."); return true; } else { $replacers = ["{amount}" => $amount, "{unit}" => $this->economy->getMonetaryUnit()]; $p->sendMessage($this->getMessage("buy.money.miss", $replacers)); } } else { $msg = self::ERROR . "Command couldn't be bought because EconomyAPI isn't loaded."; $this->getLogger()->warning($msg); $p->sendMessage($msg . $this->getMessage("buy.contactadmin")); } } elseif ($price["paytype"] === "item") { $item = $this->getItem($price["item"]); if (!$p->getInventory()->contains($item)) { $replacers = ["{item}" => $item->getName(), "{amount}" => $item->getCount()]; $p->sendMessage($this->getMessage("buy.item.miss", $replacers)); } else { $this->remove($item, $p->getInventory()); $this->executeCommands($commands, $p); $replacers = ["{cmd}" => $cmd, "{item}" => $item->getName()]; $p->sendMessage($this->getMessage("buy.item.success", $replacers)); $this->getLogger()->debug("The player $name has bought the command $cmd with the item $item."); return true; } } } else { $replacers = ["{cmd}" => $cmd]; $p->sendMessage($this->getMessage("command.notfound", $replacers) . $this->getMessage("buy.contactadmin")); } } else { $this->getLogger()->warning(self::ERROR . "The following error happened while trying to execute the function buyCmd(): The variable \$p wasn't a Player Object. If you think you didn't cause this problem, please open an issue on the GitHub repository: https://github.com/BoxOfDevs/CommandShop"); } return false; } /** * Called when one of the defined commands of the plugin has been called * * @param CommandSender $sender * @param Command $command * @param string $label * @param array $args * @return bool */ public function onCommand(CommandSender $sender, Command $command, string $label, array $args): bool { switch ($command->getName()) { case "cshop": $subcmd = strtolower(array_shift($args)); switch ($subcmd) { case "add": if (count($args) < 2) { $this->sendUsage($subcmd, $sender); return true; } $name = strtolower(array_shift($args)); $cmd = strtolower(implode(" ", $args)); $cmds = $this->getConfig()->get("commands", []); if (!isset($cmds[$name])) { $cmds[$name]["cmds"] = [$cmd]; $cmds[$name]["buycmd"] = "true"; $this->getConfig()->set("commands", $cmds); $this->getConfig()->save(); $sender->sendMessage(self::PREFIX . TF::GREEN . "Command $name has been successfully added to the list of buyable commands!"); $sender->sendMessage(self::PREFIX . TF::AQUA . "Infos:"); $sender->sendMessage(self::PREFIX . "Name: " . $name); $sender->sendMessage(self::PREFIX . "Command: " . $cmd); $sender->sendMessage(self::PREFIX . "Please set a price now using " . TF::AQUA . "/cshop setprice" . TF::WHITE . ". Or add more commands to be executed using " . TF::AQUA . "/cshop addcmd" . TF::WHITE . "."); } else { $sender->sendMessage(self::ERROR . "That command does already exist!"); } break; case "remove": if (count($args) < 1) { $this->sendUsage($subcmd, $sender); return true; } $name = strtolower(array_shift($args)); $cmds = $this->getConfig()->get("commands", []); if (isset($cmds[$name])) { unset($cmds[$name]); $this->getConfig()->set("commands", $cmds); $this->getConfig()->save(); $sender->sendMessage(self::PREFIX . TF::GREEN . "Command $name has been successfully removed from the list of buyable commands!"); } else { $replacers = ["{cmd}" => $name]; $sender->sendMessage($this->getMessage("command.notfound", $replacers)); } break; case "setprice": if (count($args) < 3) { $this->sendUsage($subcmd, $sender); return true; } $cmd = strtolower(array_shift($args)); $type = strtolower(array_shift($args)); if ($type === "money") { if ($this->economy != null) { $amount = array_shift($args); if (!is_numeric($amount)) { $this->sendUsage($subcmd, $sender); return true; } $cmds = $this->getConfig()->get("commands", []); if (isset($cmds[$cmd])) { $cmds[$cmd]["price"]["paytype"] = "money"; $cmds[$cmd]["price"]["amount"] = $amount; $this->getConfig()->set("commands", $cmds); $this->getConfig()->save(); $unit = $this->economy->getMonetaryUnit(); $sender->sendMessage(self::PREFIX . TF::GREEN . "The price of $amount $unit has successfully been set to the command $cmd!"); } else { $replacers = ["{cmd}" => $cmd]; $sender->sendMessage($this->getMessage("command.notfound", $replacers)); } } else { $sender->sendMessage(self::ERROR . "Please install EconomyAPI by onebone in order to be able to pay for commands with money!"); } } elseif ($type === "item") { $item = array_shift($args); $cmds = $this->getConfig()->get("commands", []); if (isset($cmds[$cmd])) { $cmds[$cmd]["price"]["paytype"] = "item"; $cmds[$cmd]["price"]["item"] = $item; $this->getConfig()->set("commands", $cmds); $this->getConfig()->save(); $sender->sendMessage(self::PREFIX . TF::GREEN . "The item-price of $item has successfully been set to the command $cmd!"); } else { $replacers = ["{cmd}" => $cmd]; $sender->sendMessage($this->getMessage("command.notfound", $replacers)); } } else { $this->sendUsage($subcmd, $sender); return true; } break; case "sign": if (!$sender instanceof Player) { $sender->sendMessage(self::ERROR . "Please use this command in-game!"); break; } if (count($args) < 1) { $this->sendUsage($subcmd, $sender); return true; } $cmd = strtolower(array_shift($args)); $cmds = $this->getConfig()->get("commands", []); if (isset($cmds[$cmd])) { $this->signsetters[$sender->getName()] = $cmd; $sender->sendMessage(self::PREFIX . "Please tap a sign now!"); } else { $replacers = ["{cmd}" => $cmd]; $sender->sendMessage($this->getMessage("command.notfound", $replacers)); } break; case "buycmd": if (count($args) < 2 || ($args[1] !== "true" && $args[1] !== "false")) { $this->sendUsage($subcmd, $sender); return true; } $cmds = $this->getConfig()->get("commands", []); $cmd = strtolower(array_shift($args)); $bool = strtolower(array_shift($args)); if (isset($cmds[$cmd])) { $cmds[$cmd]["buycmd"] = $bool; $this->getConfig()->set("commands", $cmds); $this->getConfig()->save(); $sender->sendMessage(self::PREFIX . "/buycmd has been successfully " . ($bool === "true" ? "enabled" : "disabled") . " for $cmd"); } else { $replacers = ["{cmd}" => $cmd]; $sender->sendMessage($this->getMessage("command.notfound", $replacers)); } break; case "addcmd": $cmds = $this->getConfig()->get("commands", []); if (count($args) < 2) { $this->sendUsage($subcmd, $sender); return true; } $cmd = strtolower(array_shift($args)); $command = strtolower(implode(" ", $args)); if (isset($cmds[$cmd])) { $cmds[$cmd]["cmds"][] = $command; $this->getConfig()->set("commands", $cmds); $this->getConfig()->save(); $sender->sendMessage(self::PREFIX . TF::GREEN . "Successfully added the command to $cmd!"); $sender->sendMessage(self::PREFIX . TF::AQUA . "Command that was added: " . TF::WHITE . "/" . $command); } else { $replacers = ["{cmd}" => $cmd]; $sender->sendMessage($this->getMessage("command.notfound", $replacers)); } break; case "list": $cmds = $this->getConfig()->get("commands", []); if ($cmds != []) { $msg = implode(", ", array_keys($cmds)); $sender->sendMessage(self::PREFIX . "List of all buyable commands:"); $sender->sendMessage($msg); } else { $sender->sendMessage(self::ERROR . "You haven't created any buyable commands yet, please create one using " . TF::AQUA . "/cshop add" . TF::WHITE . "."); } break; case "info": if (count($args) < 1) { $this->sendUsage($subcmd, $sender); return true; } $cmdn = strtolower(array_shift($args)); $cmds = $this->getConfig()->get("commands", []); if (isset($cmds[$cmdn])) { $cmd = $cmds[$cmdn]; $sender->sendMessage(self::PREFIX . "Information for the command $cmdn:"); $commands = "Commands: \n- " . implode("\n- ", $cmd["cmds"]); $sender->sendMessage($commands); $sender->sendMessage("/buycmd: " . $cmd["buycmd"]); if (isset($cmd["price"])) { $paytype = $cmd["price"]["paytype"]; if ($paytype === "money") { $amount = $cmd["price"]["amount"]; $sender->sendMessage("Paytype: Money (EconomyAPI)"); $sender->sendMessage("Amount: $amount"); } elseif ($paytype === "item") { $item = $cmd["price"]["item"]; $item = $this->getItem($item); $sender->sendMessage("Paytype: Items"); $sender->sendMessage("Item: " . $item->getName() . " Damage: " . $item->getDamage() . " Amount: " . $item->getCount()); } else { $sender->sendMessage(self::ERROR . "Invalid paytype, please use " . TF::AQUA . "/cshop setprice" . TF::WHITE . " to set the price for this command!"); } } else { $sender->sendMessage(self::ERROR . "No price has been set for this command, please use " . TF::AQUA . "/cshop setprice" . TF::WHITE . " to set the price for this command!"); } } else { $replacers = ["{cmd}" => $cmdn]; $sender->sendMessage($this->getMessage("command.notfound", $replacers)); } break; case "help": $sender->sendMessage(self::PREFIX . "CommandShop Commands:"); foreach ($this->usages as $cmd => $usage) { $sender->sendMessage("/cshop $cmd $usage"); } $sender->sendMessage("/buycmd \nPlease visit the wiki for this plugin here: https://github.com/BoxOfDevs/CommandShop/wiki for further information."); break; default: return false; } break; case "buycmd": if (!$sender instanceof Player) { $sender->sendMessage(self::ERROR . "Please use this command in-game!"); break; } if (count($args) < 1) return false; $cmd = strtolower(array_shift($args)); $cmds = $this->getConfig()->get("commands", []); if (isset($cmds[$cmd])) { if ($cmds[$cmd]["buycmd"] === "true") { $this->buyCmd($cmd, $sender); } else { $replacers = ["{cmd}" => $cmd]; $sender->sendMessage($this->getMessage("buycmd.disabled", $replacers)); } } else { $replacers = ["{cmd}" => $cmd]; $sender->sendMessage($this->getMessage("command.notfound", $replacers)); } break; } return true; } }