Merge branch 'stable' into master

This commit is contained in:
Dylan K. Taylor 2020-08-03 20:14:46 +01:00
commit e1d80f05b1
5 changed files with 77 additions and 66 deletions

@ -1 +1 @@
Subproject commit 43edcfde6b9611b7c7d643be52332707cc10cd1b Subproject commit 767676e2b97843072220bad719c076b169c28fd3

View File

@ -24,50 +24,50 @@ declare(strict_types=1);
namespace pocketmine\crafting; namespace pocketmine\crafting;
use pocketmine\item\Item; use pocketmine\item\Item;
use pocketmine\utils\AssumptionFailedError;
use function array_map; use function array_map;
use function file_get_contents; use function file_get_contents;
use function is_array;
use function json_decode; use function json_decode;
final class CraftingManagerFromDataHelper{ final class CraftingManagerFromDataHelper{
public static function make(string $filePath) : CraftingManager{ public static function make(string $filePath) : CraftingManager{
$recipes = json_decode(file_get_contents($filePath), true); $recipes = json_decode(file_get_contents($filePath), true);
if(!is_array($recipes)){
throw new AssumptionFailedError("recipes.json root should contain a map of recipe types");
}
$result = new CraftingManager(); $result = new CraftingManager();
$itemDeserializerFunc = \Closure::fromCallable([Item::class, 'jsonDeserialize']); $itemDeserializerFunc = \Closure::fromCallable([Item::class, 'jsonDeserialize']);
foreach($recipes as $recipe){
switch($recipe["type"]){ foreach($recipes["shapeless"] as $recipe){
case "shapeless":
if($recipe["block"] !== "crafting_table"){ //TODO: filter others out for now to avoid breaking economics if($recipe["block"] !== "crafting_table"){ //TODO: filter others out for now to avoid breaking economics
break; continue;
} }
$result->registerShapelessRecipe(new ShapelessRecipe( $result->registerShapelessRecipe(new ShapelessRecipe(
array_map($itemDeserializerFunc, $recipe["input"]), array_map($itemDeserializerFunc, $recipe["input"]),
array_map($itemDeserializerFunc, $recipe["output"]) array_map($itemDeserializerFunc, $recipe["output"])
)); ));
break; }
case "shaped": foreach($recipes["shaped"] as $recipe){
if($recipe["block"] !== "crafting_table"){ //TODO: filter others out for now to avoid breaking economics if($recipe["block"] !== "crafting_table"){ //TODO: filter others out for now to avoid breaking economics
break; continue;
} }
$result->registerShapedRecipe(new ShapedRecipe( $result->registerShapedRecipe(new ShapedRecipe(
$recipe["shape"], $recipe["shape"],
array_map($itemDeserializerFunc, $recipe["input"]), array_map($itemDeserializerFunc, $recipe["input"]),
array_map($itemDeserializerFunc, $recipe["output"]) array_map($itemDeserializerFunc, $recipe["output"])
)); ));
break; }
case "smelting": foreach($recipes["smelting"] as $recipe){
if($recipe["block"] !== "furnace"){ //TODO: filter others out for now to avoid breaking economics if($recipe["block"] !== "furnace"){ //TODO: filter others out for now to avoid breaking economics
break; continue;
} }
$result->getFurnaceRecipeManager()->register(new FurnaceRecipe( $result->getFurnaceRecipeManager()->register(new FurnaceRecipe(
Item::jsonDeserialize($recipe["output"]), Item::jsonDeserialize($recipe["output"]),
Item::jsonDeserialize($recipe["input"])) Item::jsonDeserialize($recipe["input"]))
); );
break;
default:
break;
}
} }
return $result; return $result;

View File

@ -137,6 +137,8 @@ class InventoryTransaction{
* @throws TransactionValidationException * @throws TransactionValidationException
*/ */
protected function matchItems(array &$needItems, array &$haveItems) : void{ protected function matchItems(array &$needItems, array &$haveItems) : void{
$needItems = [];
$haveItems = [];
foreach($this->actions as $key => $action){ foreach($this->actions as $key => $action){
if(!$action->getTargetItem()->isNull()){ if(!$action->getTargetItem()->isNull()){
$needItems[] = $action->getTargetItem(); $needItems[] = $action->getTargetItem();

View File

@ -34,6 +34,7 @@ use pocketmine\inventory\transaction\action\InventoryAction;
use pocketmine\inventory\transaction\CraftingTransaction; use pocketmine\inventory\transaction\CraftingTransaction;
use pocketmine\inventory\transaction\InventoryTransaction; use pocketmine\inventory\transaction\InventoryTransaction;
use pocketmine\inventory\transaction\TransactionException; use pocketmine\inventory\transaction\TransactionException;
use pocketmine\inventory\transaction\TransactionValidationException;
use pocketmine\item\VanillaItems; use pocketmine\item\VanillaItems;
use pocketmine\item\WritableBook; use pocketmine\item\WritableBook;
use pocketmine\item\WrittenBook; use pocketmine\item\WrittenBook;
@ -82,10 +83,12 @@ use pocketmine\network\mcpe\protocol\ShowCreditsPacket;
use pocketmine\network\mcpe\protocol\SpawnExperienceOrbPacket; use pocketmine\network\mcpe\protocol\SpawnExperienceOrbPacket;
use pocketmine\network\mcpe\protocol\SubClientLoginPacket; use pocketmine\network\mcpe\protocol\SubClientLoginPacket;
use pocketmine\network\mcpe\protocol\TextPacket; use pocketmine\network\mcpe\protocol\TextPacket;
use pocketmine\network\mcpe\protocol\types\inventory\ContainerIds;
use pocketmine\network\mcpe\protocol\types\inventory\MismatchTransactionData; use pocketmine\network\mcpe\protocol\types\inventory\MismatchTransactionData;
use pocketmine\network\mcpe\protocol\types\inventory\NetworkInventoryAction; use pocketmine\network\mcpe\protocol\types\inventory\NetworkInventoryAction;
use pocketmine\network\mcpe\protocol\types\inventory\NormalTransactionData; use pocketmine\network\mcpe\protocol\types\inventory\NormalTransactionData;
use pocketmine\network\mcpe\protocol\types\inventory\ReleaseItemTransactionData; use pocketmine\network\mcpe\protocol\types\inventory\ReleaseItemTransactionData;
use pocketmine\network\mcpe\protocol\types\inventory\UIInventorySlotOffset;
use pocketmine\network\mcpe\protocol\types\inventory\UseItemOnEntityTransactionData; use pocketmine\network\mcpe\protocol\types\inventory\UseItemOnEntityTransactionData;
use pocketmine\network\mcpe\protocol\types\inventory\UseItemTransactionData; use pocketmine\network\mcpe\protocol\types\inventory\UseItemTransactionData;
use pocketmine\network\mcpe\protocol\types\inventory\WindowTypes; use pocketmine\network\mcpe\protocol\types\inventory\WindowTypes;
@ -215,19 +218,23 @@ class InGamePacketHandler extends PacketHandler{
$actions = []; $actions = [];
$isCraftingPart = false; $isCraftingPart = false;
$isFinalCraftingPart = false;
$converter = TypeConverter::getInstance(); $converter = TypeConverter::getInstance();
foreach($data->getActions() as $networkInventoryAction){ foreach($data->getActions() as $networkInventoryAction){
if( if(
(
$networkInventoryAction->sourceType === NetworkInventoryAction::SOURCE_TODO and ( $networkInventoryAction->sourceType === NetworkInventoryAction::SOURCE_TODO and (
$networkInventoryAction->windowId === NetworkInventoryAction::SOURCE_TYPE_CRAFTING_RESULT or $networkInventoryAction->windowId === NetworkInventoryAction::SOURCE_TYPE_CRAFTING_RESULT or
$networkInventoryAction->windowId === NetworkInventoryAction::SOURCE_TYPE_CRAFTING_USE_INGREDIENT $networkInventoryAction->windowId === NetworkInventoryAction::SOURCE_TYPE_CRAFTING_USE_INGREDIENT
) )
) or (
$this->craftingTransaction !== null &&
!$networkInventoryAction->oldItem->equals($networkInventoryAction->newItem) &&
$networkInventoryAction->sourceType === NetworkInventoryAction::SOURCE_CONTAINER &&
$networkInventoryAction->windowId === ContainerIds::UI &&
$networkInventoryAction->inventorySlot === UIInventorySlotOffset::CREATED_ITEM_OUTPUT
)
){ ){
$isCraftingPart = true; $isCraftingPart = true;
if($networkInventoryAction->windowId === NetworkInventoryAction::SOURCE_TYPE_CRAFTING_RESULT){
$isFinalCraftingPart = true;
}
} }
try{ try{
@ -242,9 +249,6 @@ class InGamePacketHandler extends PacketHandler{
} }
if($isCraftingPart){ if($isCraftingPart){
//we get the actions for this in several packets, so we need to wait until we have all the pieces before
//trying to execute it
if($this->craftingTransaction === null){ if($this->craftingTransaction === null){
$this->craftingTransaction = new CraftingTransaction($this->player, $this->player->getServer()->getCraftingManager(), $actions); $this->craftingTransaction = new CraftingTransaction($this->player, $this->player->getServer()->getCraftingManager(), $actions);
}else{ }else{
@ -253,7 +257,13 @@ class InGamePacketHandler extends PacketHandler{
} }
} }
if($isFinalCraftingPart){ try{
$this->craftingTransaction->validate();
}catch(TransactionValidationException $e){
//transaction is incomplete - crafting transaction comes in lots of little bits, so we have to collect
//all of the parts before we can execute it
return true;
}
try{ try{
$this->session->getInvManager()->onTransactionStart($this->craftingTransaction); $this->session->getInvManager()->onTransactionStart($this->craftingTransaction);
$this->craftingTransaction->execute(); $this->craftingTransaction->execute();
@ -276,7 +286,6 @@ class InGamePacketHandler extends PacketHandler{
}finally{ }finally{
$this->craftingTransaction = null; $this->craftingTransaction = null;
} }
}
}else{ }else{
//normal transaction fallthru //normal transaction fallthru
if($this->craftingTransaction !== null){ if($this->craftingTransaction !== null){

View File

@ -52,7 +52,7 @@ class VersionString{
$this->development = $isDevBuild; $this->development = $isDevBuild;
$this->build = $buildNumber; $this->build = $buildNumber;
preg_match('/(\d+)\.(\d+)\.(\d+)(?:-(.*))?$/', $this->baseVersion, $matches); preg_match('/^(\d+)\.(\d+)\.(\d+)(?:-(.*))?$/', $this->baseVersion, $matches);
if(count($matches) < 4){ if(count($matches) < 4){
throw new \InvalidArgumentException("Invalid base version \"$baseVersion\", should contain at least 3 version digits"); throw new \InvalidArgumentException("Invalid base version \"$baseVersion\", should contain at least 3 version digits");
} }