Skip to content

Commit

Permalink
ChestShop v2 UPDATE.
Browse files Browse the repository at this point in the history
* Fixed error when a player quits with the GUI open.
* Fixed plugin not detecting item to be purchased.
* Fixed unserialize error after adding item to the shop.
* NBT::$replace now uses IntArrayTag to save the replaced block's damage.
* Added /cs removebyid <itemId> <itemDamage>
* Added "default-price" option in config.yml
* Added "banned-items" (These items are banned from being /cs add ed).
* Fixed many more bugs.
  • Loading branch information
Muqsit authored Feb 16, 2017
1 parent a311856 commit c4c8957
Show file tree
Hide file tree
Showing 7 changed files with 119 additions and 31 deletions.
6 changes: 3 additions & 3 deletions plugin.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: ChestShop
main: ChestShop\Main
api: [2.0.0, 3.0.0]
version: 1.0.0
api: [2.0.0, 3.0.0, 3.0.0-ALPHA3]
version: 2.0
depend: [EconomyAPI]
commands:
chestshop:
Expand All @@ -10,4 +10,4 @@ permissions:
chestshop.command.add:
default: op
chestshop.command.remove:
default: op
default: op
7 changes: 5 additions & 2 deletions resources/config.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
---

...
default-price: 15000
banned-items:
- 35:1
- 7
...
5 changes: 3 additions & 2 deletions src/ChestShop/Chest/CustomChest.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ public function __construct(Chunk $chunk, CompoundTag $nbt){
}

public function getReplacement() : Block{
return Block::get($this->namedtag->replace->getValue() ?? 0);
$replace = $this->namedtag->replace->getValue() ?? [0, 0];
return Block::get($replace[0], $replace[1]);
}
}
}
2 changes: 1 addition & 1 deletion src/ChestShop/Chest/CustomChestInventory.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public function onClose(Player $who){
$block->y = floor($pos->y);
$block->z = floor($pos->z);
$block->level = $pos->getLevel();
$block->level->sendBlocks([$who], [$block]);
if($who instanceof Player) $block->level->sendBlocks([$who], [$block]);
parent::onClose($who);
unset(\ChestShop\Main::getInstance()->clicks[$who->getId()]);
$this->holder->close();
Expand Down
23 changes: 14 additions & 9 deletions src/ChestShop/EventListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@

class EventListener implements Listener{

const DEFAULT_PRICE = 15000;
protected $plugin;

public function __construct(Main $plugin){
Expand All @@ -47,7 +46,7 @@ public function __construct(Main $plugin){
* is a Chest Shop tile where the block is.
*/
public function onBreak(BlockBreakEvent $event){
$event->setCancelled($event->getBlock()->getLevel()->getTile($event->getBlock()) instanceof CustomChest);
if($event->getBlock()->getLevel()->getTile($event->getBlock()) instanceof CustomChest) $event->setCancelled();
}

/**
Expand All @@ -67,15 +66,19 @@ public function onTransaction(InventoryTransactionEvent $event){
$player = $assumed;
$chestinv = $inv;
$action = $transaction;
break;
break 2;
}
}
}
}

if($chestinv === null) return;

/*
* $player => Player interacting with the GUI.
* $chestinv => The chest's inventory.
* $action => BaseTransaction|Transaction|SimpleTransactionGroup
*/
$event->setCancelled();
$item = $action->getTargetItem();
$item = ($item = $action->getTargetItem())->getId() === 0 ? $action->getSourceItem() : $item;

if(isset($item->getNamedTag()->turner)){
$action = $item->getNamedTag()->turner->getValue();
Expand All @@ -84,16 +87,18 @@ public function onTransaction(InventoryTransactionEvent $event){
return;
}

$data = $item->getNamedTag()->ChestShop->getValue() ?? null;
$data = isset($item->getNamedTag()->ChestShop) ? $item->getNamedTag()->ChestShop->getValue() : null;
if($data === null) return;
$price = $data[0] ?? self::DEFAULT_PRICE;

$price = $data[0] ?? $this->plugin->defaultprice;
if(!isset($this->plugin->clicks[$player->getId()][$data[1]])){
$this->plugin->clicks[$player->getId()][$data[1]] = 1;
return;
}

if(EconomyAPI::getInstance()->myMoney($player) >= $price){
$item = $this->plugin->getItemFromShop($data[1]);
$player->sendMessage(Main::PREFIX.TF::GREEN.'Purchased '.TF::BOLD.$item->getName().TF::RESET.TF::GREEN.TF::GRAY.' (x'.$item->getCount().')'.TF::GREEN.' for $'.$price);
$player->sendMessage(Main::PREFIX.TF::GREEN.'Purchased '.TF::BOLD.$item->getName().TF::RESET.TF::GREEN.TF::GRAY.' (x'.$item->getCount().')'.TF::GREEN.' for $'.$price.'.');
$player->getInventory()->addItem($item);
EconomyAPI::getInstance()->reduceMoney($player, $price);
unset($this->plugin->clicks[$player->getId()]);
Expand Down
67 changes: 53 additions & 14 deletions src/ChestShop/Main.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,12 @@ class Main extends PluginBase{

const PREFIX = TF::BOLD.TF::YELLOW.'CS '.TF::RESET;

public $defaultprice;
public $inChestShop, $clicks = [];
protected $shops = [];
private $helpcmd = [];
private static $instance = null;
public $inChestShop, $clicks = [];
private $notallowed = [];

public function onEnable(){
self::$instance = $this;
Expand All @@ -62,7 +64,7 @@ public function onEnable(){
$this->getLogger()->notice(implode("\n", $info));

if(!is_dir($this->getDataFolder())) mkdir($this->getDataFolder());
foreach(['shops.yml'] as $file){
foreach(['shops.yml', 'config.yml'] as $file){
if(!is_file($this->getDataFolder().$file)){
$openf = fopen($this->getDataFolder().$file, 'w') or die('Cannot open file: '.$file);
file_put_contents($this->getDataFolder().$file, $this->getResource($file));
Expand All @@ -72,6 +74,11 @@ public function onEnable(){

$shops = yaml_parse_file($this->getDataFolder().'shops.yml');
if(!empty($shops)) foreach($shops as $key => $val) $this->shops[$key] = $val;

$config = yaml_parse_file($this->getDataFolder().'config.yml');
$this->defaultprice = $config["default-price"] ?? 15000;
$this->notallowed = array_flip($config["banned-items"] ?? []);

$this->helpcmd = [
TF::YELLOW.TF::BOLD.'Chest Shop'.TF::RESET,
TF::YELLOW.'/{:cmd:} add [price]'.TF::GRAY.' - Add the item in your hand to the chest shop.',
Expand Down Expand Up @@ -100,7 +107,7 @@ public function sendChestShop(Player $player){
]);
/** @var Chest $tile */
$tile = Tile::createTile('CustomChest', $player->chunk, $nbt);
$tile->namedtag->replace = new IntTag("replace", $tile->getBlock()->getId());
$tile->namedtag->replace = new IntArrayTag("replace", [$tile->getBlock()->getId(), $tile->getBlock()->getDamage()]);
$block = Block::get(Block::CHEST);
$block->x = floor($tile->x);
$block->y = floor($tile->y);
Expand All @@ -117,9 +124,12 @@ public function reload(){
$this->shops = [];
$shops = yaml_parse_file($this->getDataFolder().'shops.yml');
if(!empty($shops)) foreach($shops as $key => $val) $this->shops[$key] = $val;
$config = yaml_parse_file($this->getDataFolder().'config.yml');
$this->defaultprice = $config["default-price"] ?? 15000;
$this->notallowed = array_flip($config["banned-items"] ?? []);
}

public function getItemFromShop(int $id) : Item{
public function getItemFromShop(int $id): Item {
$data = $this->shops[$id] ?? null;
$item = null;
if(is_array($data)){
Expand All @@ -139,7 +149,7 @@ public function fillInventoryWithShop($inventory, $page = 0){
$item = Item::get($data[0], $data[1], $data[2]);
if($data[3] === null) break;
$item->setNamedTag(unserialize($data[3]));
$item->setCustomName(TF::RESET.TF::YELLOW.'Tap again to purchase for $'.$item->getNamedTag()->ChestShop->getValue()[0].TF::RESET."\n".' '."\n".$item->getName());
$item->setCustomName(TF::RESET.$item->getName()."\n \n".TF::YELLOW.'Double-tap to purchase for $'.$item->getNamedTag()->ChestShop->getValue()[0].TF::RESET);
$inventory->addItem($item);
}
}
Expand All @@ -148,11 +158,12 @@ public function fillInventoryWithShop($inventory, $page = 0){
$turnleft = Item::get(Item::PAPER);
$turnright = Item::get(Item::PAPER);
$turnleft->setCustomName(TF::RESET.TF::GOLD.TF::BOLD.'<< Turn Left'.TF::RESET."\n".TF::GRAY.'Turn towards the left.');
$turnright->setCustomName(TF::RESET.TF::GOLD.TF::BOLD.' Turn Right'.TF::RESET."\n".TF::GRAY.'Turn towards the right.');
$turnright->setCustomName(TF::RESET.TF::GOLD.TF::BOLD.'Turn Right >>'.TF::RESET."\n".TF::GRAY.'Turn towards the right.');

$nbtleft = $turnleft->getNamedTag();
$nbtleft->turner = new IntArrayTag('turner', [0, $page]);
$turnleft->setNamedTag($nbtleft);

$nbtright = $turnright->getNamedTag();
$nbtright->turner = new IntArrayTag('turner', [1, $page]);
$turnright->setNamedTag($nbtright);
Expand All @@ -163,21 +174,29 @@ public function fillInventoryWithShop($inventory, $page = 0){

public function addToChestShop(Item $item, int $price){
$key = rand();
$nbt = $item->getNamedTag() !== null ? serialize($item->getNamedTag()) : null;
$nbt = $item->getNamedTag() ?? new CompoundTag("", []);
$nbt->ChestShop = new IntArrayTag ('ChestShop', [$price, $key]);
$nbt->ChestShop = new IntArrayTag('ChestShop', [$price, $key]);
$nbt->CSKey = $key;
$item->setNamedTag($nbt);
$this->shops[$key] = [$item->getId(), $item->getDamage(), $item->getCount(), $nbt];
$this->shops[$key] = [$item->getId(), $item->getDamage(), $item->getCount(), serialize($nbt)];
}

public function removeItemOffShop(int $page, int $slot){
if(empty($this->shops)) return;
$keys = array_keys($this->shops);//$shops is an associative array.
$key = (24*$page) + $slot;//array_chunks divides $shops into 24 parts in the GUI. Hope PHP follows BODMAS.
$keys = array_keys($this->shops);//$this->shops is an associative array.
$key = (24*$page) + $slot;//array_chunks divides $shops into 24 parts in the GUI.
unset($this->shops[$keys[--$key]]);//$slot - 1. Slots are counted from 0. If $slot is 1, the issuer probably (actually) is referring to slot zero.
}

private function isNotAllowed(int $itemId, int $itemDamage = 0) : bool{
if($itemDamage === 0) return isset($this->notallowed[$itemId]) || isset($this->notallowed[$itemId.':'.$itemDamage]);
else return isset($this->notallowed[$itemId.':'.$itemDamage]);
}

public function removeItemsByKey(array $keys){
foreach($keys as $key) unset($this->shops[$key]);
}

public function onCommand(CommandSender $sender, Command $cmd, $label, array $args){
if(isset($args[0])){
switch(strtolower($args[0])){
Expand All @@ -191,19 +210,39 @@ public function onCommand(CommandSender $sender, Command $cmd, $label, array $ar
if($sender->hasPermission('chestshop.command.add')){
$item = $sender->getInventory()->getItemInHand();
if($item->getId() === 0) $sender->sendMessage(self::PREFIX.TF::RED.'Please hold an item in your hand.');
elseif($this->isNotAllowed($item->getId(), $item->getDamage())) $sender->sendMessage(self::PREFIX.TF::RED.'You cannot sell '.((Item::get($item->getId(), $item->getDamage()))->getName()).' on /chestshop.');
else{
if(isset($args[1]) && is_numeric($args[1]) && $args[1] >= 0) $this->addToChestShop($item, $args[1]);
else $sender->sendMessage(TF::RED.'Please enter a valid number.');
if(isset($args[1]) && is_numeric($args[1]) && $args[1] >= 0) {
$sender->sendMessage(self::PREFIX.TF::YELLOW.'Added '.(explode("\n", $item->getName())[0]).' to '.$cmd->getName().' for $'.$args[1].'.');
$this->addToChestShop($item, $args[1]);
}else $sender->sendMessage(TF::RED.'Please enter a valid number.');
}
}
break;
case "removebyid":
if($sender->hasPermission('chestshop.command.remove')){
if(isset($args[1]) && is_numeric($args[1]) && $args[1] >= 1){
$damage = $args[2] ?? 0;
if(count($this->shops) <= 27){
$i = 0;
foreach($this->shops as $k => $item){
if($item[0] == $args[1] && $item[1] == $damage){
unset($this->shops[$k]);
++$i;
}
}
$sender->sendMessage(self::PREFIX.TF::YELLOW.$i.' items were removed off auction house (ID: '.$args[1].', DAMAGE: '.$damage.').');
}else $this->getServer()->getScheduler()->scheduleAsyncTask(new RemoveByIdTask([$sender->getName(), $args[1], $damage, &$this->shops]));
}else $sender->sendMessage(self::PREFIX.TF::YELLOW.'Usage: /'.$cmd->getName().' removebyid [item-id] [item-damage]');
}
break;
case "remove":
if($sender->hasPermission('chestshop.command.remove')){
if(isset($args[1], $args[2]) && is_numeric($args[1]) && is_numeric($args[2]) && ($args[1] >= 0) && ($args[2] >= 1)){
$sender->sendMessage(self::PREFIX.TF::YELLOW.'Removed item on page #'.$args[1].', slot #'.$args[2].'.');
$this->removeItemOffShop($args[1], $args[2]);
} else $sender->sendMessage(TF::RED.'Page number and item slot must be integers (page > -1, slot > 0).');
}
}
break;
case "reload":
if($sender->hasPermission('chestshop.command.reload')){
Expand Down
40 changes: 40 additions & 0 deletions src/ChestShop/RemoveByIdTask.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php
namespace ChestShop;

use pocketmine\{Player, Server};
use pocketmine\scheduler\AsyncTask;
use pocketmine\utils\TextFormat as TF;

class RemoveByIdTask extends AsyncTask{

/*
* $data = [
* (string) (playername)
* (int) (itemid)
* (int) (itemdamage)
* (int) (assoc array)
* ];
*/
private $data;
public function __construct(array $data){
$this->data = $data;
}

public function onRun(){
$res = [];
foreach($this->data[3] as $k => $v){
if($v[0] == $this->data[1] && $v[1] == $this->data[2]){
$res[] = $k;
}
}
$this->setResult($res);
}

public function onCompletion(Server $server){
$res = $this->getResult();
if(($player = $server->getPlayerExact($this->data[0])) instanceof Player){
$player->sendMessage(Main::PREFIX.TF::YELLOW.count($res).' items were removed off auction house (ID: '.$this->data[1].', DAMAGE: '.$this->data[2].').');
}
$server->getPluginManager()->getPlugin("ChestShop")->removeItemsByKey($res);
}
}

0 comments on commit c4c8957

Please sign in to comment.