diff --git a/src/pocketmine/inventory/BigShapedRecipe.php b/src/pocketmine/inventory/BigShapedRecipe.php new file mode 100644 index 000000000..927023ed2 --- /dev/null +++ b/src/pocketmine/inventory/BigShapedRecipe.php @@ -0,0 +1,26 @@ +registerRecipe((new ShapelessRecipe(Item::get(Item::SNOW_LAYER, 0, 6)))->addIngredient(Item::get(Item::SNOW_BLOCK, 0, 3))); $this->registerRecipe((new ShapelessRecipe(Item::get(Item::STICK, 0, 4)))->addIngredient(Item::get(Item::WOODEN_PLANK, null, 2))); $this->registerRecipe((new ShapelessRecipe(Item::get(Item::STONECUTTER, 0, 1)))->addIngredient(Item::get(Item::COBBLESTONE, 0, 4))); - $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, 4))); + + $this->registerRecipe((new ShapedRecipe(Item::get(Item::WOODEN_PLANK, Planks::OAK, 4), + "X" + ))->setIngredient("X", Item::get(Item::WOOD, Wood::OAK, 1))); + + $this->registerRecipe((new ShapedRecipe(Item::get(Item::WOODEN_PLANK, Planks::SPRUCE, 4), + "X" + ))->setIngredient("X", Item::get(Item::WOOD, Wood::SPRUCE, 1))); + + $this->registerRecipe((new ShapedRecipe(Item::get(Item::WOODEN_PLANK, Planks::BIRCH, 4), + "X" + ))->setIngredient("X", Item::get(Item::WOOD, Wood::BIRCH, 1))); + + $this->registerRecipe((new ShapedRecipe(Item::get(Item::WOODEN_PLANK, Planks::JUNGLE, 4), + "X" + ))->setIngredient("X", Item::get(Item::WOOD, Wood::JUNGLE, 1))); + + $this->registerRecipe((new ShapedRecipe(Item::get(Item::WOODEN_PLANK, Planks::ACACIA, 4), + "X" + ))->setIngredient("X", Item::get(Item::WOOD2, Wood2::ACACIA, 1))); + + $this->registerRecipe((new ShapedRecipe(Item::get(Item::WOODEN_PLANK, Planks::DARK_OAK, 4), + "X" + ))->setIngredient("X", Item::get(Item::WOOD2, Wood2::DARK_OAK, 1))); + + $this->registerRecipe((new ShapedRecipe(Item::get(Item::WOOL, 0, 1), + "XX", + "XX" + ))->setIngredient("X", Item::get(Item::STRING, 0, 4))); + $this->registerRecipe((new ShapelessRecipe(Item::get(Item::TORCH, 0, 4)))->addIngredient(Item::get(Item::COAL, 0, 1))->addIngredient(Item::get(Item::STICK, 0, 1))); $this->registerRecipe((new ShapelessRecipe(Item::get(Item::TORCH, 0, 4)))->addIngredient(Item::get(Item::COAL, 1, 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))); @@ -351,7 +374,20 @@ class CraftingManager{ * @param ShapedRecipe $recipe */ public function registerShapedRecipe(ShapedRecipe $recipe){ + $result = $recipe->getResult(); + $this->recipes[spl_object_hash($recipe)] = $recipe; + $ingredients = $recipe->getIngredientMap(); + $hash = ""; + foreach($ingredients as $v){ + foreach($v as $item){ + /** @var Item $item */ + $hash .= $item->getId() . ":" . ($item->getDamage() === null ? "?" : $item->getDamage()) . "x" . $item->getCount() . ","; + } + $hash .= ";"; + } + + $this->recipeLookup[$result->getId() . ":" . $result->getDamage()][$hash] = $recipe; } /** diff --git a/src/pocketmine/inventory/ShapedRecipe.php b/src/pocketmine/inventory/ShapedRecipe.php index 1dea57c79..18638bc1c 100644 --- a/src/pocketmine/inventory/ShapedRecipe.php +++ b/src/pocketmine/inventory/ShapedRecipe.php @@ -24,6 +24,7 @@ namespace pocketmine\inventory; use pocketmine\item\Item; use pocketmine\Server; use pocketmine\utils\UUID; +use pocketmine\math\Vector2; class ShapedRecipe implements Recipe{ /** @var Item */ @@ -32,10 +33,12 @@ class ShapedRecipe implements Recipe{ private $id = null; /** @var string[] */ - private $rows = []; + private $shape = []; - /** @var Item[] */ + /** @var Item[][] */ private $ingredients = []; + /** @var Vector2[][] */ + private $shapeItems = []; /** * @param Item $result @@ -43,27 +46,41 @@ class ShapedRecipe implements Recipe{ * * @throws \Exception */ - public function __construct(Item $result, array $shape = []){ + public function __construct(Item $result, ...$shape){ if(count($shape) === 0){ throw new \InvalidArgumentException("Must provide a shape"); } if(count($shape) > 3){ throw new \InvalidStateException("Crafting recipes should be 1, 2, 3 rows, not " . count($shape)); } - foreach($shape as $row){ + foreach($shape as $z => $row){ if(strlen($row) === 0 or strlen($row) > 3){ throw new \InvalidStateException("Crafting rows should be 1, 2, 3 characters, not " . count($row)); } - $this->rows[] = $row; + $this->ingredients[] = array_fill(0, strlen($row), null); $len = strlen($row); for($i = 0; $i < $len; ++$i){ - $this->ingredients[$row{$i}] = null; + $this->shape[$row{$i}] = null; + + if(!isset($this->shapeItems[$row{$i}])){ + $this->shapeItems[$row{$i}] = [new Vector2($i, $z)]; + }else{ + $this->shapeItems[$row{$i}][] = new Vector2($i, $z); + } } } $this->output = clone $result; } + public function getWidth(){ + return count($this->ingredients[0]); + } + + public function getHeight(){ + return count($this->ingredients); + } + public function getResult(){ return $this->output; } @@ -88,36 +105,54 @@ class ShapedRecipe implements Recipe{ * @throws \Exception */ public function setIngredient($key, Item $item){ - if(!isset($this->ingredients[$key])){ + if(!array_key_exists($key, $this->shape)){ throw new \Exception("Symbol does not appear in the shape: " . $key); } - $this->ingredients[$key] = $item; + $this->fixRecipe($key, $item); return $this; } + protected function fixRecipe($key, $item){ + foreach($this->shapeItems[$key] as $entry){ + $this->ingredients[$entry->y][$entry->x] = clone $item; + } + } + /** - * @return Item[] + * @return Item[][] */ public function getIngredientMap(){ $ingredients = []; - foreach($this->ingredients as $key => $ingredient){ - if($ingredient instanceof Item){ - $ingredients[$key] = clone $ingredient; - }else{ - $ingredients[$key] = $ingredient; + foreach($this->ingredients as $z => $row){ + $ingredients[$z] = []; + foreach($row as $x => $ingredient){ + if($ingredient !== null){ + $ingredients[$z][$x] = clone $ingredient; + }else{ + $ingredients[$z][$x] = null; + } } } return $ingredients; } + /** + * @param $x + * @param $z + * @return null|Item + */ + public function getIngredient($x, $z){ + return isset($this->ingredients[$z][$x]) ? $this->ingredients[$z][$x] : null; + } + /** * @return string[] */ public function getShape(){ - return $this->rows; + return $this->shape; } public function registerToCraftingManager(){ diff --git a/src/pocketmine/network/protocol/CraftingDataPacket.php b/src/pocketmine/network/protocol/CraftingDataPacket.php index 9f71e0484..64c65270f 100644 --- a/src/pocketmine/network/protocol/CraftingDataPacket.php +++ b/src/pocketmine/network/protocol/CraftingDataPacket.php @@ -27,7 +27,6 @@ namespace pocketmine\network\protocol; use pocketmine\inventory\FurnaceRecipe; use pocketmine\inventory\ShapedRecipe; use pocketmine\inventory\ShapelessRecipe; -use pocketmine\utils\Binary; use pocketmine\utils\BinaryStream; class CraftingDataPacket extends DataPacket{ @@ -64,11 +63,26 @@ class CraftingDataPacket extends DataPacket{ $stream->putInt(1); $stream->putSlot($recipe->getResult()); + $stream->putUUID($recipe->getId()); + return CraftingDataPacket::ENTRY_SHAPELESS; } private static function writeShapedRecipe(ShapedRecipe $recipe, BinaryStream $stream){ - //TODO + $stream->putInt($recipe->getWidth()); + $stream->putInt($recipe->getHeight()); + + for($z = 0; $z < $recipe->getWidth(); ++$z){ + for($x = 0; $x < $recipe->getHeight(); ++$x){ + $stream->putSlot($recipe->getIngredient($x, $z)); + } + } + + $stream->putInt(1); + $stream->putSlot($recipe->getResult()); + + $stream->putUUID($recipe->getId()); + return CraftingDataPacket::ENTRY_SHAPED; }