From 3ac60f98601b00bcb792b1e85092c0b395e4bde7 Mon Sep 17 00:00:00 2001 From: Shoghi Cervantes Date: Tue, 27 May 2014 23:26:07 +0200 Subject: [PATCH] Added Normal and Big crafting recipes, fixed CraftingTransactionGroup count --- src/pocketmine/Player.php | 93 +++++--- src/pocketmine/block/Stonecutter.php | 5 +- src/pocketmine/block/Workbench.php | 5 +- .../inventory/BigShapelessRecipe.php | 26 ++ src/pocketmine/inventory/CraftingManager.php | 222 +++++++++++++++++- .../inventory/CraftingTransactionGroup.php | 18 +- src/pocketmine/inventory/ShapelessRecipe.php | 11 + .../inventory/SimpleTransactionGroup.php | 3 + src/pocketmine/recipes/Crafting.php | 1 - 9 files changed, 333 insertions(+), 51 deletions(-) create mode 100644 src/pocketmine/inventory/BigShapelessRecipe.php diff --git a/src/pocketmine/Player.php b/src/pocketmine/Player.php index 5f3ac5f42..822552ae4 100644 --- a/src/pocketmine/Player.php +++ b/src/pocketmine/Player.php @@ -40,6 +40,7 @@ use pocketmine\event\player\PlayerRespawnEvent; use pocketmine\event\server\DataPacketReceiveEvent; use pocketmine\event\server\DataPacketSendEvent; use pocketmine\inventory\BaseTransaction; +use pocketmine\inventory\BigShapelessRecipe; use pocketmine\inventory\CraftingTransactionGroup; use pocketmine\inventory\FurnaceInventory; use pocketmine\inventory\Inventory; @@ -117,7 +118,9 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{ public $chunksLoaded = []; public $lastCorrect; /** @var SimpleTransactionGroup */ - public $currentTransaction = null; + protected $currentTransaction = null; + public $craftingType = 0; //0 = 2x2 crafting, 1 = 3x3 crafting, 2 = stonecutter + protected $isCrafting = false; public $loginData = []; protected $lastMovement = 0; @@ -1561,6 +1564,8 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{ case ProtocolInfo::USE_ITEM_PACKET: $blockVector = new Vector3($packet->x, $packet->y, $packet->z); + $this->craftingType = 0; + if(($this->spawned === false or $this->blocked === true) and $packet->face >= 0 and $packet->face <= 5){ $target = $this->getLevel()->getBlock($blockVector); $block = $target->getSide($packet->face); @@ -1642,6 +1647,8 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{ if($this->spawned === false or $this->blocked === true){ break; } + + $this->craftingType = 0; $packet->eid = $this->id; switch($packet->action){ @@ -1716,6 +1723,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{ if($this->spawned === false or $this->blocked === true){ break; } + $this->craftingType = 0; $vector = new Vector3($packet->x, $packet->y, $packet->z); @@ -1788,6 +1796,8 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{ if($this->spawned === false){ break; } + + $this->craftingType = 0; $packet->eid = $this->id; $data = []; $data["target"] = $packet->target; @@ -1882,6 +1892,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{ if($this->spawned === false or $this->dead === false){ break; } + $this->craftingType = 0; $this->server->getPluginManager()->callEvent($ev = new PlayerRespawnEvent($this, $this->spawnPosition)); @@ -1903,6 +1914,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{ if($this->spawned === false or $this->blocked === true){ break; } + $this->craftingType = 0; $packet->eid = $this->id; if($this->entity->inAction === true){ @@ -1976,6 +1988,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{ if($this->spawned === false){ break; } + $this->craftingType = 0; $packet->message = TextFormat::clean($packet->message); if(trim($packet->message) != "" and strlen($packet->message) <= 255){ $message = $packet->message; @@ -1997,6 +2010,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{ if($this->spawned === false or $packet->windowid === 0){ break; } + $this->craftingType = 0; if(isset($this->windowIndex[$packet->windowid])){ $this->server->getPluginManager()->callEvent(new InventoryCloseEvent($this->windowIndex[$packet->windowid], $this)); $this->removeWindow($this->windowIndex[$packet->windowid]); @@ -2019,6 +2033,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{ } $transaction = new BaseTransaction($this->inventory, $packet->slot, $this->inventory->getItem($packet->slot), $packet->item); }elseif(isset($this->windowIndex[$packet->windowid])){ + $this->craftingType = 0; $inv = $this->windowIndex[$packet->windowid]; $transaction = new BaseTransaction($inv, $packet->slot, $inv->getItem($packet->slot), $packet->item); }else{ @@ -2063,40 +2078,47 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{ $this->currentTransaction = null; }elseif($packet->windowid == 0){ //Try crafting $craftingGroup = new CraftingTransactionGroup($this->currentTransaction); - if($craftingGroup->canExecute() and $craftingGroup->execute()){ //We can craft! - switch($craftingGroup->getResult()->getID()){ - case Item::WORKBENCH: - $this->awardAchievement("buildWorkBench"); - break; - case Item::WOODEN_PICKAXE: - $this->awardAchievement("buildPickaxe"); - break; - case Item::FURNACE: - $this->awardAchievement("buildFurnace"); - break; - case Item::WOODEN_HOE: - $this->awardAchievement("buildHoe"); - break; - case Item::BREAD: - $this->awardAchievement("makeBread"); - break; - case Item::CAKE: - //TODO: detect complex recipes like cake that leave remainings - $this->awardAchievement("bakeCake"); - $this->inventory->addItem(Item::get(Item::BUCKET, 0, 3)); - break; - case Item::STONE_PICKAXE: - case Item::GOLD_PICKAXE: - case Item::IRON_PICKAXE: - case Item::DIAMOND_PICKAXE: - $this->awardAchievement("buildBetterPickaxe"); - break; - case Item::WOODEN_SWORD: - $this->awardAchievement("buildSword"); - break; - case Item::DIAMOND: - $this->awardAchievement("diamond"); - break; + if($craftingGroup->canExecute()){ //We can craft! + $recipe = $craftingGroup->getMatchingRecipe(); + if($recipe instanceof BigShapelessRecipe and $this->craftingType !== 1){ + break; + }//TODO: do stonecutter + + if($craftingGroup->execute()){ + switch($craftingGroup->getResult()->getID()){ + case Item::WORKBENCH: + $this->awardAchievement("buildWorkBench"); + break; + case Item::WOODEN_PICKAXE: + $this->awardAchievement("buildPickaxe"); + break; + case Item::FURNACE: + $this->awardAchievement("buildFurnace"); + break; + case Item::WOODEN_HOE: + $this->awardAchievement("buildHoe"); + break; + case Item::BREAD: + $this->awardAchievement("makeBread"); + break; + case Item::CAKE: + //TODO: detect complex recipes like cake that leave remainings + $this->awardAchievement("bakeCake"); + $this->inventory->addItem(Item::get(Item::BUCKET, 0, 3)); + break; + case Item::STONE_PICKAXE: + case Item::GOLD_PICKAXE: + case Item::IRON_PICKAXE: + case Item::DIAMOND_PICKAXE: + $this->awardAchievement("buildBetterPickaxe"); + break; + case Item::WOODEN_SWORD: + $this->awardAchievement("buildSword"); + break; + case Item::DIAMOND: + $this->awardAchievement("diamond"); + break; + } } @@ -2119,6 +2141,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{ if($this->spawned === false or $this->blocked === true){ break; } + $this->craftingType = 0; $t = $this->getLevel()->getTile(new Vector3($packet->x, $packet->y, $packet->z)); if($t instanceof Sign){ diff --git a/src/pocketmine/block/Stonecutter.php b/src/pocketmine/block/Stonecutter.php index 31a19a9c7..17da9731e 100644 --- a/src/pocketmine/block/Stonecutter.php +++ b/src/pocketmine/block/Stonecutter.php @@ -24,6 +24,7 @@ namespace pocketmine\block; use pocketmine\item\Item; use pocketmine\Player; +//TODO: check orientation class Stonecutter extends Solid{ public function __construct($meta = 0){ parent::__construct(self::STONECUTTER, $meta, "Stonecutter"); @@ -31,7 +32,9 @@ class Stonecutter extends Solid{ } public function onActivate(Item $item, Player $player = null){ - $player->toCraft[-1] = 2; + if($player instanceof Player){ + $player->craftingType = 2; + } return true; } diff --git a/src/pocketmine/block/Workbench.php b/src/pocketmine/block/Workbench.php index da5ffda3d..f82d51bba 100644 --- a/src/pocketmine/block/Workbench.php +++ b/src/pocketmine/block/Workbench.php @@ -24,6 +24,7 @@ namespace pocketmine\block; use pocketmine\item\Item; use pocketmine\Player; +//TODO: check orientation class Workbench extends Solid{ public function __construct($meta = 0){ parent::__construct(self::WORKBENCH, $meta, "Crafting Table"); @@ -32,7 +33,9 @@ class Workbench extends Solid{ } public function onActivate(Item $item, Player $player = null){ - $player->toCraft[-1] = 1; + if($player instanceof Player){ + $player->craftingType = 1; + } return true; } diff --git a/src/pocketmine/inventory/BigShapelessRecipe.php b/src/pocketmine/inventory/BigShapelessRecipe.php new file mode 100644 index 000000000..7b565d5d4 --- /dev/null +++ b/src/pocketmine/inventory/BigShapelessRecipe.php @@ -0,0 +1,26 @@ +registerDyes(); + $this->registerIngots(); + $this->registerTools(); + $this->registerWeapons(); + $this->registerArmor(); + $this->registerFood(); + + $this->registerRecipe((new ShapelessRecipe(Item::get(Item::CLAY_BLOCK, 0, 1)))->addIngredient(Item::get(Item::CLAY, 0, 4))); + $this->registerRecipe((new ShapelessRecipe(Item::get(Item::WORKBENCH, 0, 1)))->addIngredient(Item::get(Item::WOODEN_PLANK, null, 4))); + $this->registerRecipe((new ShapelessRecipe(Item::get(Item::GLOWSTONE_BLOCK, 0, 1)))->addIngredient(Item::get(Item::GLOWSTONE_DUST, 0, 1))); + $this->registerRecipe((new ShapelessRecipe(Item::get(Item::LIT_PUMPKIN, 0, 1)))->addIngredient(Item::get(Item::PUMPKIN, 0, 1))->addIngredient(Item::get(Item::TORCH, 0, 1))); + $this->registerRecipe((new ShapelessRecipe(Item::get(Item::SNOW_BLOCK, 0, 1)))->addIngredient(Item::get(Item::SNOWBALL, 0, 1))); + $this->registerRecipe((new ShapelessRecipe(Item::get(Item::STICK, 0, 1)))->addIngredient(Item::get(Item::WOODEN_PLANK, null, 2))); + $this->registerRecipe((new ShapelessRecipe(Item::get(Item::STONECUTTER, 0, 1)))->addIngredient(Item::get(Item::COBBLESTONE, 0, 1))); $this->registerRecipe((new ShapelessRecipe(Item::get(Item::WOODEN_PLANK, Planks::OAK, 4)))->addIngredient(Item::get(Item::WOOD, Wood::OAK, 1))); $this->registerRecipe((new ShapelessRecipe(Item::get(Item::WOODEN_PLANK, Planks::SPRUCE, 4)))->addIngredient(Item::get(Item::WOOD, Wood::SPRUCE, 1))); $this->registerRecipe((new ShapelessRecipe(Item::get(Item::WOODEN_PLANK, Planks::BIRCH, 4)))->addIngredient(Item::get(Item::WOOD, Wood::BIRCH, 1))); $this->registerRecipe((new ShapelessRecipe(Item::get(Item::WOODEN_PLANK, Planks::JUNGLE, 4)))->addIngredient(Item::get(Item::WOOD, Wood::JUNGLE, 1))); //$this->registerRecipe((new ShapelessRecipe(Item::get(Item::WOODEN_PLANK, Planks::ACACIA, 4)))->addIngredient(Item::get(Item::WOOD2, Wood2::ACACIA, 1))); //$this->registerRecipe((new ShapelessRecipe(Item::get(Item::WOODEN_PLANK, Planks::DARK_OAK, 4)))->addIngredient(Item::get(Item::WOOD2, Wood2::DARK_OAK, 1))); + $this->registerRecipe((new ShapelessRecipe(Item::get(Item::WOOL, 0, 1)))->addIngredient(Item::get(Item::STRING, 0, 1))); + $this->registerRecipe((new ShapelessRecipe(Item::get(Item::TORCH, 0, 4)))->addIngredient(Item::get(Item::COAL, null, 1))->addIngredient(Item::get(Item::STICK, 0, 1))); + $this->registerRecipe((new ShapelessRecipe(Item::get(Item::SUGAR, 0, 1)))->addIngredient(Item::get(Item::SUGARCANE, 0, 1))); + + + $this->registerRecipe((new BigShapelessRecipe(Item::get(Item::BED, 0, 1)))->addIngredient(Item::get(Item::WOOL, null, 3))->addIngredient(Item::get(Item::WOODEN_PLANK, null, 3))); + $this->registerRecipe((new BigShapelessRecipe(Item::get(Item::CHEST, 0, 1)))->addIngredient(Item::get(Item::WOODEN_PLANK, null, 8))); + $this->registerRecipe((new BigShapelessRecipe(Item::get(Item::FENCE, 0, 2)))->addIngredient(Item::get(Item::STICK, 0, 6))); + $this->registerRecipe((new BigShapelessRecipe(Item::get(Item::FENCE_GATE, 0, 1)))->addIngredient(Item::get(Item::STICK, 0, 4))->addIngredient(Item::get(Item::WOODEN_PLANK, null, 2))); + $this->registerRecipe((new BigShapelessRecipe(Item::get(Item::FURNACE, 0, 1)))->addIngredient(Item::get(Item::COBBLESTONE, 0, 8))); + $this->registerRecipe((new BigShapelessRecipe(Item::get(Item::GLASS_PANE, 0, 16)))->addIngredient(Item::get(Item::GLASS, 0, 6))); + $this->registerRecipe((new BigShapelessRecipe(Item::get(Item::LADDER, 0, 2)))->addIngredient(Item::get(Item::STICK, 0, 7))); + $this->registerRecipe((new BigShapelessRecipe(Item::get(Item::NETHER_REACTOR, 0, 1)))->addIngredient(Item::get(Item::DIAMOND, 0, 3))->addIngredient(Item::get(Item::IRON_INGOT, 0, 6))); + $this->registerRecipe((new BigShapelessRecipe(Item::get(Item::TRAPDOOR, 0, 2)))->addIngredient(Item::get(Item::WOODEN_PLANK, null, 2))); + $this->registerRecipe((new BigShapelessRecipe(Item::get(Item::WOODEN_DOOR, 0, 1)))->addIngredient(Item::get(Item::WOODEN_PLANK, null, 6))); + $this->registerRecipe((new BigShapelessRecipe(Item::get(Item::WOODEN_STAIRS, 0, 4)))->addIngredient(Item::get(Item::WOODEN_PLANK, Planks::OAK, 6))); + $this->registerRecipe((new BigShapelessRecipe(Item::get(Item::WOOD_SLAB, Planks::OAK, 6)))->addIngredient(Item::get(Item::WOODEN_PLANK, Planks::OAK, 3))); + $this->registerRecipe((new BigShapelessRecipe(Item::get(Item::SPRUCE_WOOD_STAIRS, 0, 4)))->addIngredient(Item::get(Item::WOODEN_PLANK, Planks::SPRUCE, 6))); + $this->registerRecipe((new BigShapelessRecipe(Item::get(Item::WOOD_SLAB, Planks::SPRUCE, 6)))->addIngredient(Item::get(Item::WOODEN_PLANK, Planks::SPRUCE, 3))); + $this->registerRecipe((new BigShapelessRecipe(Item::get(Item::SPRUCE_WOOD_STAIRS, 0, 4)))->addIngredient(Item::get(Item::WOODEN_PLANK, Planks::BIRCH, 6))); + $this->registerRecipe((new BigShapelessRecipe(Item::get(Item::WOOD_SLAB, Planks::BIRCH, 6)))->addIngredient(Item::get(Item::WOODEN_PLANK, Planks::BIRCH, 3))); + $this->registerRecipe((new BigShapelessRecipe(Item::get(Item::JUNGLE_WOOD_STAIRS, 0, 4)))->addIngredient(Item::get(Item::WOODEN_PLANK, Planks::JUNGLE, 6))); + $this->registerRecipe((new BigShapelessRecipe(Item::get(Item::WOOD_SLAB, Planks::JUNGLE, 6)))->addIngredient(Item::get(Item::WOODEN_PLANK, Planks::JUNGLE, 3))); + //TODO: add new wood stairs, slabs + + $this->registerRecipe((new BigShapelessRecipe(Item::get(Item::BUCKET, 0, 1)))->addIngredient(Item::get(Item::IRON_INGOT, 0, 3))); + $this->registerRecipe((new BigShapelessRecipe(Item::get(Item::CLOCK, 0, 1)))->addIngredient(Item::get(Item::GOLD_INGOT, 0, 4))->addIngredient(Item::get(Item::REDSTONE_DUST, 0, 1))); + $this->registerRecipe((new BigShapelessRecipe(Item::get(Item::COMPASS, 0, 1)))->addIngredient(Item::get(Item::IRON_INGOT, 0, 4))->addIngredient(Item::get(Item::REDSTONE_DUST, 0, 1))); + $this->registerRecipe((new BigShapelessRecipe(Item::get(Item::TNT, 0, 1)))->addIngredient(Item::get(Item::GUNPOWDER, 0, 5))->addIngredient(Item::get(Item::SAND, null, 4))); //TODO: check if TNT can be crafted with red sand + $this->registerRecipe((new BigShapelessRecipe(Item::get(Item::BOWL, 0, 1)))->addIngredient(Item::get(Item::WOODEN_PLANKS, null, 3))); + $this->registerRecipe((new BigShapelessRecipe(Item::get(Item::MINECART, 0, 1)))->addIngredient(Item::get(Item::IRON_INGOT, 0, 5))); + $this->registerRecipe((new BigShapelessRecipe(Item::get(Item::BOOK, 0, 1)))->addIngredient(Item::get(Item::PAPER, 0, 3))); + $this->registerRecipe((new BigShapelessRecipe(Item::get(Item::BOOKSHELF, 0, 1)))->addIngredient(Item::get(Item::WOODEN_PLANK, null, 6))->addIngredient(Item::get(Item::BOOK, 0, 3))); + $this->registerRecipe((new BigShapelessRecipe(Item::get(Item::PAINTING, 0, 1)))->addIngredient(Item::get(Item::STICK, 0, 8))->addIngredient(Item::get(Item::WOOL, null, 1))); + $this->registerRecipe((new BigShapelessRecipe(Item::get(Item::PAPER, 0, 1)))->addIngredient(Item::get(Item::SUGARCANE, 0, 3))); + $this->registerRecipe((new BigShapelessRecipe(Item::get(Item::SIGN, 0, 1)))->addIngredient(Item::get(Item::STICK, 0, 1))->addIngredient(Item::get(Item::WOODEN_PLANKS, null, 6))); //TODO: check if it gives one sign or three + $this->registerRecipe((new BigShapelessRecipe(Item::get(Item::IRON_BARS, 0, 16)))->addIngredient(Item::get(Item::IRON_INGOT, 0, 6))); + + //$this->registerRecipe((new BigShapelessRecipe(Item::get(Item::, 0, )))->addIngredient(Item::get(Item::, 0, ))); + //TODO: Stonecutter recipes + } + + protected function registerFood(){ + //TODO: check COOKIES + $this->registerRecipe((new ShapelessRecipe(Item::get(Item::MELON_SEEDS, 0, 1)))->addIngredient(Item::get(Item::MELON_SLICE, 0, 1))); + $this->registerRecipe((new ShapelessRecipe(Item::get(Item::PUMPKIN_SEEDS, 0, 4)))->addIngredient(Item::get(Item::PUMPKIN, 0, 1))); + $this->registerRecipe((new ShapelessRecipe(Item::get(Item::PUMPKIN_PIE, 0, 1)))->addIngredient(Item::get(Item::PUMPKIN, 0, 1))->addIngredient(Item::get(Item::EGG, 0, 1))->addIngredient(Item::get(Item::SUGAR, 0, 1))); + $this->registerRecipe((new ShapelessRecipe(Item::get(Item::MUSHROOM_STEW, 0, 1)))->addIngredient(Item::get(Item::BOWL, 0, 1))->addIngredient(Item::get(Item::BROWN_MUSHROOM, 0, 1))->addIngredient(Item::get(Item::RED_MUSHROOM, 0, 1))); + $this->registerRecipe((new BigShapelessRecipe(Item::get(Item::MELON_BLOCK, 0, 1)))->addIngredient(Item::get(Item::MELON_SLICE, 0, 9))); + $this->registerRecipe((new BigShapelessRecipe(Item::get(Item::BEETROOT_SOUP, 0, 1)))->addIngredient(Item::get(Item::BEETROOT, 0, 4))->addIngredient(Item::get(Item::BOWL, 0, 1))); + $this->registerRecipe((new ShapelessRecipe(Item::get(Item::BREAD, 0, 1)))->addIngredient(Item::get(Item::WHEAT, 0, 3))); + $this->registerRecipe((new BigShapelessRecipe(Item::get(Item::CAKE, 0, 1)))->addIngredient(Item::get(Item::WHEAT, 0, 3))->addIngredient(Item::get(Item::BUCKET, 1, 3))->addIngredient(Item::get(Item::EGG, 0, 1))->addIngredient(Item::get(Item::SUGAR, 0, 2))); + } + + protected function registerArmor(){ + $cost = [5, 8, 7, 4]; + $types = [ + [Item::LEATHER, Item::FIRE, Item::IRON_INGOT, Item::DIAMOND, Item::GOLD_INGOT], + [Item::LEATHER_CAP, Item::CHAIN_HELMET, Item::IRON_HELMET, Item::DIAMOND_HELMET, Item::GOLD_HELMET], + [Item::LEATHER_TUNIC, Item::CHAIN_CHESTPLATE, Item::IRON_CHESTPLATE, Item::DIAMOND_CHESTPLATE, Item::GOLD_CHESTPLATE], + [Item::LEATHER_PANTS, Item::CHAIN_LEGGINGS, Item::IRON_LEGGINGS, Item::DIAMOND_LEGGINGS, Item::GOLD_LEGGINGS], + [Item::LEATHER_BOOTS, Item::CHAIN_BOOTS, Item::IRON_BOOTS, Item::DIAMOND_BOOTS, Item::GOLD_BOOTS], + ]; + for($i = 1; $i < 2; ++$i){ + foreach($types[$i] as $j => $type){ + $this->registerRecipe((new BigShapelessRecipe(Item::get($type, 0, 1)))->addIngredient(Item::get($types[0][$j], 0, $cost[$i - 1]))); + } + } + } + + protected function registerWeapons(){ + $cost = [2]; + $types = [ + [Item::WOODEN_PLANK, Item::COBBLESTONE, Item::IRON_INGOT, Item::DIAMOND, Item::GOLD_INGOT], + [Item::WOODEN_SWORD, Item::STONE_SWORD, Item::IRON_SWORD, Item::DIAMOND_SWORD, Item::GOLD_SWORD], + ]; + for($i = 1; $i < 2; ++$i){ + foreach($types[$i] as $j => $type){ + $this->registerRecipe((new BigShapelessRecipe(Item::get($type, 0, 1)))->addIngredient(Item::get($types[0][$j], 0, $cost[$i - 1]))->addIngredient(Item::get(Item::STICK, 0, 1))); + } + } + + $this->registerRecipe((new ShapelessRecipe(Item::get(Item::ARROW, 0, 1)))->addIngredient(Item::get(Item::STICK, 0, 1))->addIngredient(Item::get(Item::FLINT, 0, 1))->addIngredient(Item::get(Item::FEATHER, 0, 1))); + $this->registerRecipe((new ShapelessRecipe(Item::get(Item::BOW, 0, 1)))->addIngredient(Item::get(Item::STRING, 0, 3))->addIngredient(Item::get(Item::STICK, 0, 3))); + } + + protected function registerTools(){ + $cost = [3, 1, 3, 2]; + $types = [ + [Item::WOODEN_PLANK, Item::COBBLESTONE, Item::IRON_INGOT, Item::DIAMOND, Item::GOLD_INGOT], + [Item::WOODEN_PICKAXE, Item::STONE_PICKAXE, Item::IRON_PICKAXE, Item::DIAMOND_PICKAXE, Item::GOLD_PICKAXE], + [Item::WOODEN_SHOVEL, Item::STONE_SHOVEL, Item::IRON_SHOVEL, Item::DIAMOND_SHOVEL, Item::GOLD_SHOVEL], + [Item::WOODEN_AXE, Item::STONE_AXE, Item::IRON_AXE, Item::DIAMOND_AXE, Item::GOLD_AXE], + [Item::WOODEN_HOE, Item::STONE_HOE, Item::IRON_HOE, Item::DIAMOND_HOE, Item::GOLD_HOE], + ]; + for($i = 1; $i < 5; ++$i){ + foreach($types[$i] as $j => $type){ + $this->registerRecipe((new BigShapelessRecipe(Item::get($type, 0, 1)))->addIngredient(Item::get($types[0][$j], 0, $cost[$i - 1]))->addIngredient(Item::get(Item::STICK, 0, 2))); + } + } + + $this->registerRecipe((new ShapelessRecipe(Item::get(Item::FLINT_AND_STEEL, 0, 1)))->addIngredient(Item::get(Item::IRON_INGOT, 0, 1))->addIngredient(Item::get(Item::FLINT, 0, 1))); + $this->registerRecipe((new ShapelessRecipe(Item::get(Item::SHEARS, 0, 1)))->addIngredient(Item::get(Item::IRON_INGOT, 0, 2))); + } + + protected function registerDyes(){ + for($i = 0; $i < 16; ++$i){ + $this->registerRecipe((new ShapelessRecipe(Item::get(Item::WOOL, 15 - $i, 1)))->addIngredient(Item::get(Item::DYE, $i, 1))->addIngredient(Item::get(Item::WOOL, 0, 1))); + //TODO: add stained clay and glass things + //$this->registerRecipe((new ShapelessRecipe(Item::get(Item::WOOL, 15 - $i, 1)))->addIngredient(Item::get(Item::DYE, $i, 1))->addIngredient(Item::get(Item::WOOL, 0, 1))); + //$this->registerRecipe((new ShapelessRecipe(Item::get(Item::WOOL, 15 - $i, 1)))->addIngredient(Item::get(Item::DYE, $i, 1))->addIngredient(Item::get(Item::WOOL, 0, 1))); + //$this->registerRecipe((new ShapelessRecipe(Item::get(Item::WOOL, 15 - $i, 1)))->addIngredient(Item::get(Item::DYE, $i, 1))->addIngredient(Item::get(Item::WOOL, 0, 1))); + + $this->registerRecipe((new ShapelessRecipe(Item::get(Item::CARPET, $i, 3)))->addIngredient(Item::get(Item::WOOL, $i, 2))); + } + + $this->registerRecipe((new ShapelessRecipe(Item::get(Item::DYE, 11, 2)))->addIngredient(Item::get(Item::DANDELION, 0, 1))); + $this->registerRecipe((new ShapelessRecipe(Item::get(Item::DYE, 15, 1)))->addIngredient(Item::get(Item::BONE, 0, 1))); + $this->registerRecipe((new ShapelessRecipe(Item::get(Item::DYE, 3, 2)))->addIngredient(Item::get(Item::DYE, 14, 1))->addIngredient(Item::get(Item::DYE, 0, 1))); + $this->registerRecipe((new ShapelessRecipe(Item::get(Item::DYE, 3, 3)))->addIngredient(Item::get(Item::DYE, 1, 1))->addIngredient(Item::get(Item::DYE, 0, 1))->addIngredient(Item::get(Item::DYE, 11, 1))); + $this->registerRecipe((new ShapelessRecipe(Item::get(Item::DYE, 9, 2)))->addIngredient(Item::get(Item::DYE, 15, 1))->addIngredient(Item::get(Item::DYE, 1, 1))); + $this->registerRecipe((new ShapelessRecipe(Item::get(Item::DYE, 14, 2)))->addIngredient(Item::get(Item::DYE, 11, 1))->addIngredient(Item::get(Item::DYE, 1, 1))); + $this->registerRecipe((new ShapelessRecipe(Item::get(Item::DYE, 10, 2)))->addIngredient(Item::get(Item::DYE, 2, 1))->addIngredient(Item::get(Item::DYE, 15, 1))); + $this->registerRecipe((new ShapelessRecipe(Item::get(Item::DYE, 12, 2)))->addIngredient(Item::get(Item::DYE, 4, 1))->addIngredient(Item::get(Item::DYE, 15, 1))); + $this->registerRecipe((new ShapelessRecipe(Item::get(Item::DYE, 6, 2)))->addIngredient(Item::get(Item::DYE, 4, 1))->addIngredient(Item::get(Item::DYE, 2, 1))); + $this->registerRecipe((new ShapelessRecipe(Item::get(Item::DYE, 5, 2)))->addIngredient(Item::get(Item::DYE, 4, 1))->addIngredient(Item::get(Item::DYE, 1, 1))); + $this->registerRecipe((new ShapelessRecipe(Item::get(Item::DYE, 13, 3)))->addIngredient(Item::get(Item::DYE, 4, 1))->addIngredient(Item::get(Item::DYE, 1, 1))->addIngredient(Item::get(Item::DYE, 15, 1))); + $this->registerRecipe((new ShapelessRecipe(Item::get(Item::DYE, 1, 1)))->addIngredient(Item::get(Item::BEETROOT, 0, 1))); + + $this->registerRecipe((new ShapelessRecipe(Item::get(Item::DYE, 13, 4)))->addIngredient(Item::get(Item::DYE, 15, 1))->addIngredient(Item::get(Item::DYE, 1, 2))->addIngredient(Item::get(Item::DYE, 4, 1))); + $this->registerRecipe((new ShapelessRecipe(Item::get(Item::DYE, 13, 2)))->addIngredient(Item::get(Item::DYE, 5, 1))->addIngredient(Item::get(Item::DYE, 9, 1))); + $this->registerRecipe((new ShapelessRecipe(Item::get(Item::DYE, 8, 2)))->addIngredient(Item::get(Item::DYE, 0, 1))->addIngredient(Item::get(Item::DYE, 15, 1))); + $this->registerRecipe((new ShapelessRecipe(Item::get(Item::DYE, 7, 3)))->addIngredient(Item::get(Item::DYE, 0, 1))->addIngredient(Item::get(Item::DYE, 15, 2))); + $this->registerRecipe((new ShapelessRecipe(Item::get(Item::DYE, 7, 2)))->addIngredient(Item::get(Item::DYE, 0, 1))->addIngredient(Item::get(Item::DYE, 8, 1))); + + } + + protected function registerIngots(){ + $ingots = [ + Item::GOLD_BLOCK => Item::GOLD_INGOT, + Item::IRON_BLOCK => Item::IRON_INGOT, + Item::DIAMOND_BLOCK => Item::DIAMOND, + //Item::EMERALD_BLOCK => Item::EMERALD, + //Item::REDSTONE_BLOCK => Item::REDSTONE_DUST, + Item::COAL_BLOCK => Item::COAL, + Item::HAY_BALE => Item::WHEAT, + ]; + + foreach($ingots as $block => $ingot){ + $this->registerRecipe((new BigShapelessRecipe(Item::get($block, 0, 1)))->addIngredient(Item::get($ingot, 0, 9))); + $this->registerRecipe((new ShapelessRecipe(Item::get($ingot, 0, 9)))->addIngredient(Item::get($block, 0, 1))); + } + + + $this->registerRecipe((new BigShapelessRecipe(Item::get(Item::LAPIS_BLOCK, 0, 1)))->addIngredient(Item::get(Item::DYE, 4, 9))); + $this->registerRecipe((new ShapelessRecipe(Item::get(Item::DYE, 4, 9)))->addIngredient(Item::get(Item::LAPIS_BLOCK, 0, 1))); + + //$this->registerRecipe((new BigShapelessRecipe(Item::get(Item::GOLD_INGOT, 0, 1)))->addIngredient(Item::get(Item::GOLD_NUGGET, 0, 9))); + //$this->registerRecipe((new ShapelessRecipe(Item::get(Item::GOLD_NUGGET, 0, 9)))->addIngredient(Item::get(Item::GOLD_INGOT, 0, 1))); + } public function sort(Item $i1, Item $i2){ @@ -120,15 +294,57 @@ class CraftingManager{ $hash = ""; $input = $ts->getRecipe(); usort($input, array($this, "sort")); + $inputCount = 0; foreach($input as $item){ + $inputCount += $item->getCount(); $hash .= $item->getID().":".($item->getDamage() === null ? "?":$item->getDamage())."x".$item->getCount().","; } if(!isset($this->recipeLookup[$k][$hash])){ - return false; + $hasRecipe = null; + foreach($this->recipeLookup[$k] as $recipe){ + if($recipe instanceof ShapelessRecipe){ + if($recipe->getIngredientCount() !== $inputCount){ + continue; + } + $checkInput = $recipe->getIngredientList(); + foreach($input as $item){ + $amount = $item->getCount(); + foreach($checkInput as $k => $checkItem){ + if($checkItem->equals($item, $checkItem->getDamage() === null ? false : true)){ + $remove = min($checkItem->getCount(), $amount); + $checkItem->setCount($checkItem->getCount() - $remove); + if($checkItem->getCount() === 0){ + unset($checkInput[$k]); + } + $amount -= $remove; + if($amount === 0){ + break; + } + } + } + } + if(count($checkInput) === 0){ + $hasRecipe = $recipe; + break; + } + } + if($hasRecipe instanceof Recipe){ + break; + } + } + + if($hasRecipe === null){ + return false; + } + + $recipe = $hasRecipe; + }else{ + $recipe = $this->recipeLookup[$k][$hash]; } - $checkResult = $this->recipeLookup[$k][$hash]->getResult(); + + $checkResult = $recipe->getResult(); if($checkResult->equals($result, true) and $checkResult->getCount() === $result->getCount()){ - return $this->recipeLookup[$k][$hash]; + return $recipe; } return null; } diff --git a/src/pocketmine/inventory/CraftingTransactionGroup.php b/src/pocketmine/inventory/CraftingTransactionGroup.php index b3652a24f..b90665ef1 100644 --- a/src/pocketmine/inventory/CraftingTransactionGroup.php +++ b/src/pocketmine/inventory/CraftingTransactionGroup.php @@ -30,21 +30,16 @@ class CraftingTransactionGroup extends SimpleTransactionGroup{ protected $input = []; /** @var Item[] */ protected $output = []; + + /** @var Recipe */ + protected $recipe = null; + public function __construct(TransactionGroup $group){ parent::__construct(); $this->transactions = $group->getTransactions(); $this->inventories = $group->getInventories(); $this->matchItems($this->output, $this->input); - /*$input = ""; - $output = ""; - foreach($this->input as $item){ - $input .= $item->getID().":".$item->getDamage()."(".$item->getCount()."), "; - } - foreach($this->output as $item){ - $output .= $item->getID().":".$item->getDamage()."(".$item->getCount()."), "; - } - console("craft_tx#".spl_object_hash($this).": ".substr($input, 0, -2)." => ".substr($output, 0, -2));*/ } public function addTransaction(Transaction $transaction){ @@ -82,7 +77,10 @@ class CraftingTransactionGroup extends SimpleTransactionGroup{ * @return Recipe */ public function getMatchingRecipe(){ - return Server::getInstance()->getCraftingManager()->matchTransaction($this); + if($this->recipe === null){ + $this->recipe = Server::getInstance()->getCraftingManager()->matchTransaction($this); + } + return $this->recipe; } public function execute(){ diff --git a/src/pocketmine/inventory/ShapelessRecipe.php b/src/pocketmine/inventory/ShapelessRecipe.php index d446b2741..12c9aaede 100644 --- a/src/pocketmine/inventory/ShapelessRecipe.php +++ b/src/pocketmine/inventory/ShapelessRecipe.php @@ -91,6 +91,17 @@ class ShapelessRecipe implements Recipe{ return $ingredients; } + /** + * @return int + */ + public function getIngredientCount(){ + $count = 0; + foreach($this->ingredients as $ingredient){ + $count += $ingredient->getCount(); + } + return $count; + } + public function registerToCraftingManager(){ Server::getInstance()->getCraftingManager()->registerShapelessRecipe($this); } diff --git a/src/pocketmine/inventory/SimpleTransactionGroup.php b/src/pocketmine/inventory/SimpleTransactionGroup.php index 43512483d..60af227c4 100644 --- a/src/pocketmine/inventory/SimpleTransactionGroup.php +++ b/src/pocketmine/inventory/SimpleTransactionGroup.php @@ -100,6 +100,9 @@ class SimpleTransactionGroup implements TransactionGroup{ $haveItems = []; $needItems = []; $this->matchItems($haveItems, $needItems); + $input = ""; + $output = ""; + return count($haveItems) === 0 and count($needItems) === 0 and count($this->transactions) > 0; } diff --git a/src/pocketmine/recipes/Crafting.php b/src/pocketmine/recipes/Crafting.php index 438ddc589..ce335f03c 100644 --- a/src/pocketmine/recipes/Crafting.php +++ b/src/pocketmine/recipes/Crafting.php @@ -72,7 +72,6 @@ abstract class Crafting{ "PUMPKIN:?x1,EGG:?x1,SUGAR:?x1=>PUMPKIN_PIE:0x1", "BROWN_MUSHROOM:?x1,RED_MUSHROOM:?x1,BOWL:?x1=>MUSHROOM_STEW:0x1", "SUGARCANE:?x1=>SUGAR:0x1", - "MELON_SLICE:?x1=>MELON_SEEDS:0x1", "HAY_BALE:?x1=>WHEAT:0x9", //Items