Implemented Transactions

This commit is contained in:
Shoghi Cervantes
2014-05-27 01:20:18 +02:00
parent 160c633c08
commit 6fcd5322d0
13 changed files with 844 additions and 234 deletions

View File

@ -94,7 +94,7 @@ abstract class BaseInventory implements Inventory{
}
public function getItem($index){
return isset($this->slots[$index]) ? $this->slots[$index] : Item::get(Item::AIR, null, 0);
return isset($this->slots[$index]) ? clone $this->slots[$index] : Item::get(Item::AIR, null, 0);
}
public function getContents(){
@ -121,6 +121,7 @@ abstract class BaseInventory implements Inventory{
}
public function setItem($index, Item $item){
$item = clone $item;
if($index < 0 or $index >= $this->size){
return false;
}elseif($item->getID() === 0){

View File

@ -0,0 +1,64 @@
<?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\item\Item;
class BaseTransaction implements Transaction{
/** @var Inventory */
protected $inventory;
/** @var int */
protected $slot;
/** @var Item */
protected $sourceItem;
/** @var Item */
protected $targetItem;
/**
* @param Inventory $inventory
* @param int $slot
* @param Item $sourceItem
* @param Item $targetItem
*/
public function __construct(Inventory $inventory, $slot, Item $sourceItem, Item $targetItem){
$this->inventory = $inventory;
$this->slot = (int) $slot;
$this->sourceItem = clone $sourceItem;
$this->targetItem = clone $targetItem;
}
public function getInventory(){
return $this->inventory;
}
public function getSlot(){
return $this->slot;
}
public function getSourceItem(){
return clone $this->sourceItem;
}
public function getTargetItem(){
return clone $this->targetItem;
}
}

View File

@ -0,0 +1,60 @@
<?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;
/**
* Manages crafting operations
* This class includes future methods for shaped crafting
*
* TODO: add small matrix inventory
*/
class CraftingInventory extends BaseInventory{
/** @var Inventory */
private $resultInventory;
/**
* @param InventoryHolder $holder
* @param Inventory $resultInventory
* @param InventoryType $inventoryType
*
* @throws \Exception
*/
public function __construct(InventoryHolder $holder, Inventory $resultInventory, InventoryType $inventoryType){
if($inventoryType->getDefaultTitle() !== "Crafting"){
throw new \Exception("Invalid Inventory type, expected CRAFTING or WORKBENCH");
}
$this->resultInventory = $resultInventory;
parent::__construct($holder, $inventoryType);
}
/**
* @return Inventory
*/
public function getResultInventory(){
return $this->resultInventory;
}
public function getSize(){
return $this->getResultInventory()->getSize() + parent::getSize();
}
}

View File

@ -0,0 +1,73 @@
<?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;
class CraftingManager{
/** @var Recipe[] */
public $recipes = [];
/** @var FurnaceRecipe[] */
public $furnaceRecipes = [];
public function __construct(){
//TODO: add crafting recipes
}
public function sort(){
//TODO: recipe sort
}
/**
* @param ShapedRecipe $recipe
*/
public function registerShapedRecipe(ShapedRecipe $recipe){
}
/**
* @param ShapelessRecipe $recipe
*/
public function registerShapelessRecipe(ShapelessRecipe $recipe){
}
/**
* @param FurnaceRecipe $recipe
*/
public function registerFurnaceRecipe(FurnaceRecipe $recipe){
}
/**
* @param Recipe $recipe
*/
public function registerRecipe(Recipe $recipe){
if($recipe instanceof ShapedRecipe){
$this->registerShapedRecipe($recipe);
}elseif($recipe instanceof ShapelessRecipe){
$this->registerShapelessRecipe($recipe);
}elseif($recipe instanceof FurnaceRecipe){
$this->registerFurnaceRecipe($recipe);
}
}
}

View File

@ -0,0 +1,36 @@
<?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;
class CraftingTransactionGroup extends SimpleTransactionGroup{
public function __construct(TransactionGroup $group){
parent::__construct();
$this->transactions = $group->getTransactions();
$this->inventories = $group->getInventories();
}
public function canExecute(){
//TODO: search in crafting recipes
return false;
}
}

View File

@ -0,0 +1,114 @@
<?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\item\Item;
class FurnaceRecipe implements Recipe{
/** @var Item */
private $output;
/** @var Item */
private $ingredient;
/**
* @param Item $result
* @param Item $ingredient
*/
public function __construct(Item $result, Item $ingredient){
$this->output = clone $result;
$this->ingredient = clone $ingredient;
}
/**
* @param Item $item
*/
public function setInput(Item $item){
$this->ingredient = clone $item;
}
/**
* @return Item
*/
public function getInput(){
return clone $this->ingredient;
}
/**
* @return Item
*/
public function getResult(){
return clone $this->output;
}
/**
* @param Item $item
*
* @returns ShapelessRecipe
*
* @throws \Exception
*/
public function addIngredient(Item $item){
if(count($this->ingredients) >= 9){
throw new \Exception("Shapeless recipes cannot have more than 9 ingredients");
}
$it = clone $item;
$it->setCount(1);
while($item->getCount() > 0){
$this->ingredients[] = clone $it;
$item->setCount($item->getCount() - 1);
}
return $this;
}
/**
* @param Item $item
*
* @return $this
*/
public function removeIngredient(Item $item){
foreach($this->ingredients as $index => $ingredient){
if($item->getCount() <= 0){
break;
}
if($ingredient->equals($item, $item->getDamage() === null ? false : true)){
unset($this->ingredients[$index]);
$item->setCount($item->getCount() - 1);
}
}
return $this;
}
/**
* @return Item[]
*/
public function getIngredientList(){
$ingredients = [];
foreach($this->ingredients as $ingredient){
$ingredients[] = clone $ingredient;
}
return $ingredients;
}
}

View File

@ -0,0 +1,32 @@
<?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;
interface Recipe{
/**
* @return \pocketmine\item\Item
*/
public function getResult();
public function registerToCraftingManager();
}

View File

@ -0,0 +1,101 @@
<?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\item\Item;
class ShapedRecipe implements Recipe{
/** @var Item */
private $output;
/** @var string[] */
private $rows = [];
/** @var Item[] */
private $ingredients = [];
/**
* @param Item $result
* @param string[] $shape
*
* @throws \Exception
*/
public function __construct(Item $result, array $shape = []){
if(count($shape) === 0){
throw new \Exception("Must provide a shape");
}
if(count($shape) > 3){
throw new \Exception("Crafting recipes should be 1, 2, 3 rows, not ".count($shape));
}
foreach($shape as $row){
if(strlen($row) === 0 or strlen($row) > 3){
throw new \Exception("Crafting rows should be 1, 2, 3 characters, not ".count($row));
}
$this->rows[] = $row;
$len = strlen($row);
for($i = 0; $i < $len; ++$i){
$this->ingredients[$row{$i}] = null;
}
}
$this->output = clone $result;
}
/**
* @param string $key
* @param Item $item
*
* @return $this
* @throws \Exception
*/
public function setIngredient($key, Item $item){
if(!isset($this->ingredients[$key])){
throw new \Exception("Symbol does not appear in the shape: ". $key);
}
$this->ingredients[$key] = $item;
return $this;
}
/**
* @return Item[]
*/
public function getIngredientMap(){
$ingredients = [];
foreach($this->ingredients as $key => $ingredient){
if($ingredient instanceof Item){
$ingredients[$key] = clone $ingredient;
}else{
$ingredients[$key] = $ingredient;
}
}
return $ingredients;
}
/**
* @return string[]
*/
public function getShape(){
return $this->rows;
}
}

View File

@ -0,0 +1,92 @@
<?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\item\Item;
class ShapelessRecipe implements Recipe{
/** @var Item */
private $output;
/** @var Item[] */
private $ingredients = [];
public function __construct(Item $result){
$this->output = clone $result;
}
public function getResult(){
return clone $this->output;
}
/**
* @param Item $item
*
* @returns ShapelessRecipe
*
* @throws \Exception
*/
public function addIngredient(Item $item){
if(count($this->ingredients) >= 9){
throw new \Exception("Shapeless recipes cannot have more than 9 ingredients");
}
$it = clone $item;
$it->setCount(1);
while($item->getCount() > 0){
$this->ingredients[] = clone $it;
$item->setCount($item->getCount() - 1);
}
return $this;
}
/**
* @param Item $item
*
* @return $this
*/
public function removeIngredient(Item $item){
foreach($this->ingredients as $index => $ingredient){
if($item->getCount() <= 0){
break;
}
if($ingredient->equals($item, $item->getDamage() === null ? false : true)){
unset($this->ingredients[$index]);
$item->setCount($item->getCount() - 1);
}
}
return $this;
}
/**
* @return Item[]
*/
public function getIngredientList(){
$ingredients = [];
foreach($this->ingredients as $ingredient){
$ingredients[] = clone $ingredient;
}
return $ingredients;
}
}

View File

@ -0,0 +1,109 @@
<?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\item\Item;
/**
* This TransactionGroup only allows doing Transaction between one / two inventories
*/
class SimpleTransactionGroup implements TransactionGroup{
private $creationTime;
protected $hasExecuted = false;
/** @var Inventory[] */
protected $inventories = [];
/** @var Transaction[] */
protected $transactions = [];
public function __construct(){
$this->creationTime = microtime(true);
}
public function getCreationTime(){
return $this->creationTime;
}
public function getInventories(){
return $this->inventories;
}
public function getTransactions(){
return $this->transactions;
}
public function addTransaction(Transaction $transaction){
$this->transactions[spl_object_hash($transaction)] = $transaction;
$this->inventories[spl_object_hash($transaction->getInventory())] = $transaction->getInventory();
}
public function canExecute(){
/** @var Item[] $needItems */
$needItems = [];
/** @var Item[] $haveItems */
$haveItems = [];
foreach($this->transactions as $key => $ts){
$needItems[] = $ts->getTargetItem();
$checkSourceItem = $ts->getInventory()->getItem($ts->getSlot());
$sourceItem = $ts->getSourceItem();
if(!$checkSourceItem->equals($sourceItem, true) or $sourceItem->getCount() !== $checkSourceItem->getCount()){
return false;
}
$haveItems[] = $sourceItem;
}
foreach($needItems as $i => $needItem){
foreach($haveItems as $j => $haveItem){
if($needItem->equals($haveItem, true)){
$amount = min($needItem->getCount(), $haveItem->getCount());
$needItem->setCount($needItem->getCount() - $amount);
$haveItem->setCount($haveItem->getCount() - $amount);
if($haveItem->getCount() === 0){
unset($haveItems[$j]);
}
if($needItem->getCount() === 0){
unset($needItems[$i]);
break;
}
}
}
}
return count($haveItems) === 0 and count($needItems) === 0 and count($this->transactions) > 0;
}
public function execute(){
if($this->hasExecuted() or !$this->canExecute()){
return false;
}
foreach($this->transactions as $transaction){
$transaction->getInventory()->setItem($transaction->getSlot(), $transaction->getTargetItem());
}
return true;
}
public function hasExecuted(){
return $this->hasExecuted;
}
}

View File

@ -0,0 +1,47 @@
<?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\item\Item;
interface Transaction{
/**
* @return Inventory
*/
public function getInventory();
/**
* @return int
*/
public function getSlot();
/**
* @return Item
*/
public function getSourceItem();
/**
* @return Item
*/
public function getTargetItem();
}

View File

@ -0,0 +1,63 @@
<?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\item\Item;
interface TransactionGroup{
/**
* @return float
*/
function getCreationTime();
/**
* @return Transaction[]
*/
function getTransactions();
/**
* @return Inventory[]
*/
function getInventories();
/**
* @param Transaction $transaction
*/
function addTransaction(Transaction $transaction);
/**
* @return bool
*/
function canExecute();
/**
* @return bool
*/
function execute();
/**
* @return bool
*/
function hasExecuted();
}