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
================================================
<!-- You DON'T have to delete the comments (<!- Text ->), they won't be shown in the final issue -->
### Brief description
<!-- Why its it an issue? -->
### Steps to reproduce
<!-- How can anyone reproduce the issue? -->
1. ...
2. ...
3. ...
### Expected result
<!-- What do you want to happen? -->
### Actual result
<!-- What actually happens: -->
### Server Information
* CommandShop Version: <!-- Commit number or the link to where you got your .phar -->
* Software Version: <!-- e.g. PMMP Jenkins build #123 -->
* Server OS: <!-- e.g. Debian 8 -->
### 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
[](https://poggit.pmmp.io/ci/BoxOfDevs/CommandShop/CommandShop)
[](https://travis-ci.org/BoxOfDevs/CommandShop)
[Come chat with us on Discord!](https://discord.me/bod)
[<img src="https://discordapp.com/assets/fc0b01fe10a0b8c602fb0106d8189d9b.png" width="162" height= "55">](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).<br>
**This plugin requires [EconomyAPI](https://github.com/onebone/EconomyS) by onebone to enable buying commands via money!**
<br>
By BoxOfDevs:

## 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 <add|remove|setprice|sign|buycmd|addcmd|list|info|help> <args>"
permission: cshop.command.manage
buycmd:
description: "'Buy' a command"
usage: "/buycmd <command>"
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
================================================
<?php
namespace BoxOfDevs\CommandShop;
use pocketmine\block\Block;
use pocketmine\event\block\BlockBreakEvent;
use pocketmine\event\Listener;
use pocketmine\event\player\PlayerInteractEvent;
use pocketmine\tile\Sign;
use pocketmine\utils\TextFormat as TF;
class CShopListener implements Listener {
/**
* @var CommandShop
*/
private $cs;
/**
* @var int[]
*/
public $confirms = [];
/**
* @var float[]
*/
private $interactCooldowns = [];
public function __construct(CommandShop $cs) {
$this->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
================================================
<?php
namespace BoxOfDevs\CommandShop;
use onebone\economyapi\EconomyAPI;
use pocketmine\command\Command;
use pocketmine\command\CommandSender;
use pocketmine\command\ConsoleCommandSender;
use pocketmine\event\Listener;
use pocketmine\inventory\BaseInventory;
use pocketmine\item\Item;
use pocketmine\Player;
use pocketmine\plugin\PluginBase;
use pocketmine\utils\TextFormat as TF;
class CommandShop extends PluginBase implements Listener {
const PREFIX = TF::YELLOW . "[CommandShop]" . TF::WHITE . " ";
const ERROR = TF::YELLOW . "[CommandShop]" . TF::RED . " [ERROR]" . TF::WHITE . " ";
/**
* @var EconomyAPI|null
*/
private $economy;
private $usages = [
"add" => "<name> <command>",
"remove" => "<name>",
"setprice" => "<name> <money|item> <money-amount|item-id>",
"sign" => "<name>",
"buycmd" => "<name> <false|true>",
"addcmd" => "<name> <command>",
"list" => "",
"info" => "<name>",
"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 <command>\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;
}
}
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
SYMBOL INDEX (13 symbols across 2 files)
FILE: src/BoxOfDevs/CommandShop/CShopListener.php
class CShopListener (line 12) | class CShopListener implements Listener {
method __construct (line 27) | public function __construct(CommandShop $cs) {
method onSignTouch (line 36) | public function onSignTouch(PlayerInteractEvent $event) {
method onBlockBreak (line 108) | public function onBlockBreak(BlockBreakEvent $event) {
FILE: src/BoxOfDevs/CommandShop/CommandShop.php
class CommandShop (line 16) | class CommandShop extends PluginBase implements Listener {
method onEnable (line 46) | public function onEnable() {
method getMessage (line 65) | public function getMessage(string $msg, array $replacers = []): string {
method sendUsage (line 83) | public function sendUsage(string $cmd, CommandSender $p) {
method getItem (line 93) | public function getItem(string $name): Item {
method executeCommands (line 123) | public function executeCommands(array $cmds, Player $p) {
method remove (line 141) | private function remove(Item $item, BaseInventory $inventory) {
method buyCmd (line 170) | public function buyCmd(string $cmd, Player $p): bool {
method onCommand (line 237) | public function onCommand(CommandSender $sender, Command $command, str...
Condensed preview — 10 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (46K chars).
[
{
"path": ".github/ISSUE_TEMPLATE.md",
"chars": 672,
"preview": "<!-- You DON'T have to delete the comments (<!- Text ->), they won't be shown in the final issue -->\n\n### Brief descript"
},
{
"path": ".gitignore",
"chars": 2794,
"preview": "#################\n## PMMP\n#################\n\nconfig.yml\n!resources/config.yml\n\n#################\n## PhpStorm\n###########"
},
{
"path": ".poggit.yml",
"chars": 131,
"preview": "--- # Poggit-CI Manifest. Open the CI at https://poggit.pmmp.io/ci/BoxOfDevs/CommandShop\nprojects:\n CommandShop:\n pa"
},
{
"path": ".travis.yml",
"chars": 308,
"preview": "#Travis CI\n\ndist: xenial\nsudo: false\n\nlanguage: php\n\nphp:\n - 7.0\n\nscript:\n - curl -o Travis.sh 'https://cloud.himbeer.me"
},
{
"path": "LICENSE",
"chars": 13147,
"preview": "BoxOfDevs General Software License 1.1.3\n=========================================\nThis license is designed to be used w"
},
{
"path": "README.md",
"chars": 1505,
"preview": "# CommandShop\n\n[](https://poggit.pmmp.io"
},
{
"path": "plugin.yml",
"chars": 1237,
"preview": "---\nname: CommandShop\nauthor: BoxOfDevs Team\nversion: 1.0.0\nmain: BoxOfDevs\\CommandShop\\CommandShop\napi: [3.0.0-ALPHA7, "
},
{
"path": "resources/config.yml",
"chars": 1351,
"preview": "---\n# Config and command/sign-database for CommandShop by BoxOfDevs:\n\n# Messages:\n\nbuy.money.success: \"{prefix}You succe"
},
{
"path": "src/BoxOfDevs/CommandShop/CShopListener.php",
"chars": 4134,
"preview": "<?php\n\nnamespace BoxOfDevs\\CommandShop;\n\nuse pocketmine\\block\\Block;\nuse pocketmine\\event\\block\\BlockBreakEvent;\nuse poc"
},
{
"path": "src/BoxOfDevs/CommandShop/CommandShop.php",
"chars": 16616,
"preview": "<?php\n\nnamespace BoxOfDevs\\CommandShop;\n\nuse onebone\\economyapi\\EconomyAPI;\nuse pocketmine\\command\\Command;\nuse pocketmi"
}
]
About this extraction
This page contains the full source code of the BoxOfDevs/CommandShop GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 10 files (40.9 KB), approximately 11.4k tokens, and a symbol index with 13 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.