Implemented new crafting mechanism

This commit is contained in:
Shoghi Cervantes
2015-08-07 21:26:12 +02:00
parent 696edfd31f
commit d026e2ecf0
6 changed files with 112 additions and 233 deletions

View File

@ -340,6 +340,14 @@ class CraftingManager{
}
}
/**
* @param UUID $id
* @return Recipe
*/
public function getRecipe(UUID $id){
$index = $id->toBinary();
return isset($this->recipes[$index]) ? $this->recipes[$index] : null;
}
/**
* @return Recipe[]
@ -375,7 +383,7 @@ class CraftingManager{
*/
public function registerShapedRecipe(ShapedRecipe $recipe){
$result = $recipe->getResult();
$this->recipes[spl_object_hash($recipe)] = $recipe;
$this->recipes[$recipe->getId()->toBinary()] = $recipe;
$ingredients = $recipe->getIngredientMap();
$hash = "";
foreach($ingredients as $v){
@ -395,7 +403,7 @@ class CraftingManager{
*/
public function registerShapelessRecipe(ShapelessRecipe $recipe){
$result = $recipe->getResult();
$this->recipes[spl_object_hash($recipe)] = $recipe;
$this->recipes[$recipe->getId()->toBinary()] = $recipe;
$hash = "";
$ingredients = $recipe->getIngredientList();
usort($ingredients, [$this, "sort"]);
@ -471,86 +479,12 @@ class CraftingManager{
}
/**
* @param CraftingTransactionGroup $ts
*
* @return Recipe
*/
public function matchTransaction(CraftingTransactionGroup $ts){
$result = $ts->getResult();
if(!($result instanceof Item)){
return false;
}
$k = $result->getId() . ":" . $result->getDamage();
if(!isset($this->recipeLookup[$k])){
return false;
}
$hash = "";
$input = $ts->getRecipe();
usort($input, [$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])){
$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, $checkItem->getCompoundTag() === 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 = $recipe->getResult();
if($checkResult->equals($result) and $checkResult->getCount() === $result->getCount()){
return $recipe;
}
return null;
}
/**
* @param Recipe $recipe
*/
public function registerRecipe(Recipe $recipe){
$recipe->setId(UUID::fromData(++self::$RECIPE_COUNT, $recipe->getResult()->getId(), $recipe->getResult()->getDamage(), $recipe->getResult()->getCount(), $recipe->getResult()->getCompoundTag()));
if($recipe instanceof ShapedRecipe){
$this->registerShapedRecipe($recipe);
}elseif($recipe instanceof ShapelessRecipe){
@ -558,8 +492,6 @@ class CraftingManager{
}elseif($recipe instanceof FurnaceRecipe){
$this->registerFurnaceRecipe($recipe);
}
$recipe->setId(UUID::fromData(++self::$RECIPE_COUNT, $recipe->getResult()->getId(), $recipe->getResult()->getDamage(), $recipe->getResult()->getCount(), $recipe->getResult()->getCompoundTag()));
}
}

View File

@ -1,111 +0,0 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\inventory;
use pocketmine\event\inventory\CraftItemEvent;
use pocketmine\item\Item;
use pocketmine\Server;
class CraftingTransactionGroup extends SimpleTransactionGroup{
/** @var Item[] */
protected $input = [];
/** @var Item[] */
protected $output = [];
/** @var Recipe */
protected $recipe = null;
public function __construct(SimpleTransactionGroup $group){
parent::__construct();
$this->transactions = $group->getTransactions();
$this->inventories = $group->getInventories();
$this->source = $group->getSource();
$this->matchItems($this->output, $this->input);
}
public function addTransaction(Transaction $transaction){
parent::addTransaction($transaction);
$this->input = [];
$this->output = [];
$this->matchItems($this->output, $this->input);
}
/**
* Gets the Items that have been used
*
* @return Item[]
*/
public function getRecipe(){
return $this->input;
}
/**
* @return Item
*/
public function getResult(){
reset($this->output);
return current($this->output);
}
public function canExecute(){
if(count($this->output) !== 1 or count($this->input) === 0){
return false;
}
return $this->getMatchingRecipe() instanceof Recipe;
}
/**
* @return Recipe
*/
public function getMatchingRecipe(){
if($this->recipe === null){
$this->recipe = Server::getInstance()->getCraftingManager()->matchTransaction($this);
}
return $this->recipe;
}
public function execute(){
if($this->hasExecuted() or !$this->canExecute()){
return false;
}
Server::getInstance()->getPluginManager()->callEvent($ev = new CraftItemEvent($this, $this->getMatchingRecipe()));
if($ev->isCancelled()){
foreach($this->inventories as $inventory){
$inventory->sendContents($inventory->getViewers());
}
return false;
}
foreach($this->transactions as $transaction){
$transaction->getInventory()->setItem($transaction->getSlot(), $transaction->getTargetItem(), $this->getSource());
}
$this->hasExecuted = true;
return true;
}
}