mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-05-27 15:52:46 +00:00
first look at anvil
This commit is contained in:
parent
c4a2b6494d
commit
e4f979dadf
@ -25,6 +25,7 @@ namespace pocketmine\block\inventory;
|
||||
|
||||
use pocketmine\inventory\SimpleInventory;
|
||||
use pocketmine\inventory\TemporaryInventory;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\world\Position;
|
||||
|
||||
class AnvilInventory extends SimpleInventory implements BlockInventory, TemporaryInventory{
|
||||
@ -37,4 +38,12 @@ class AnvilInventory extends SimpleInventory implements BlockInventory, Temporar
|
||||
$this->holder = $holder;
|
||||
parent::__construct(2);
|
||||
}
|
||||
|
||||
public function getInput() : Item {
|
||||
return $this->getItem(self::SLOT_INPUT);
|
||||
}
|
||||
|
||||
public function getMaterial() : Item {
|
||||
return $this->getItem(self::SLOT_MATERIAL);
|
||||
}
|
||||
}
|
||||
|
187
src/block/utils/AnvilHelper.php
Normal file
187
src/block/utils/AnvilHelper.php
Normal file
@ -0,0 +1,187 @@
|
||||
<?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/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block\utils;
|
||||
|
||||
use pocketmine\inventory\transaction\TransactionValidationException;
|
||||
use pocketmine\item\Durable;
|
||||
use pocketmine\item\EnchantedBook;
|
||||
use pocketmine\item\enchantment\AvailableEnchantmentRegistry;
|
||||
use pocketmine\item\enchantment\Enchantment;
|
||||
use pocketmine\item\enchantment\EnchantmentInstance;
|
||||
use pocketmine\item\enchantment\Rarity;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\player\Player;
|
||||
use function ceil;
|
||||
use function floor;
|
||||
use function max;
|
||||
use function min;
|
||||
use function strlen;
|
||||
|
||||
class AnvilHelper{
|
||||
private const COST_REPAIR_MATERIAL = 1;
|
||||
private const COST_REPAIR_SACRIFICE = 2;
|
||||
private const COST_RENAME = 1;
|
||||
private const COST_LIMIT = 39;
|
||||
|
||||
/**
|
||||
* Attempts to calculate the result of an anvil operation.
|
||||
*
|
||||
* Returns null if the operation can't do anything.
|
||||
*/
|
||||
public static function calculateResult(Player $player, Item $base, Item $material, ?string $customName = null) : ?AnvilResult {
|
||||
$resultCost = 0;
|
||||
$resultItem = clone $base;
|
||||
|
||||
if($resultItem instanceof Durable && $resultItem->isValidRepairMaterial($material) && $resultItem->getDamage() > 0){
|
||||
$resultCost += self::repairWithMaterial($resultItem, $material);
|
||||
}else{
|
||||
if($resultItem->getTypeId() === $material->getTypeId() && $resultItem instanceof Durable && $material instanceof Durable){
|
||||
$resultCost += self::repairWithSacrifice($resultItem, $material);
|
||||
}
|
||||
if($material->hasEnchantments()){
|
||||
$resultCost += self::combineEnchantments($resultItem, $material);
|
||||
}
|
||||
}
|
||||
|
||||
// Repair cost increment if the item has been processed, the rename is free of penalty
|
||||
$additionnalRepairCost = $resultCost > 0 ? 1 : 0;
|
||||
$resultCost += self::renameItem($resultItem, $customName);
|
||||
|
||||
$resultCost += 2 ** $resultItem->getRepairCost() - 1;
|
||||
$resultCost += 2 ** $material->getRepairCost() - 1;
|
||||
$resultItem->setRepairCost(
|
||||
max($resultItem->getRepairCost(), $material->getRepairCost()) + $additionnalRepairCost
|
||||
);
|
||||
|
||||
if($resultCost <= 0 || ($resultCost > self::COST_LIMIT && !$player->isCreative())){
|
||||
return null;
|
||||
}
|
||||
|
||||
return new AnvilResult($resultCost, $resultItem);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int The XP cost of repairing the item
|
||||
*/
|
||||
private static function repairWithMaterial(Durable $result, Item $material) : int {
|
||||
$damage = $result->getDamage();
|
||||
$quarter = min($damage, (int) floor($result->getMaxDurability() / 4));
|
||||
$numberRepair = min($material->getCount(), (int) ceil($damage / $quarter));
|
||||
if($numberRepair > 0){
|
||||
$material->pop($numberRepair);
|
||||
$damage -= $quarter * $numberRepair;
|
||||
}
|
||||
$result->setDamage(max(0, $damage));
|
||||
|
||||
return $numberRepair * self::COST_REPAIR_MATERIAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int The XP cost of repairing the item
|
||||
*/
|
||||
private static function repairWithSacrifice(Durable $result, Durable $sacrifice) : int{
|
||||
if($result->getDamage() === 0){
|
||||
return 0;
|
||||
}
|
||||
$baseDurability = $result->getMaxDurability() - $result->getDamage();
|
||||
$materialDurability = $sacrifice->getMaxDurability() - $sacrifice->getDamage();
|
||||
$addDurability = (int) ($result->getMaxDurability() * 12 / 100);
|
||||
|
||||
$newDurability = min($result->getMaxDurability(), $baseDurability + $materialDurability + $addDurability);
|
||||
|
||||
$result->setDamage($result->getMaxDurability() - $newDurability);
|
||||
|
||||
return self::COST_REPAIR_SACRIFICE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int The XP cost of combining the enchantments
|
||||
*/
|
||||
private static function combineEnchantments(Item $base, Item $sacrifice) : int{
|
||||
$cost = 0;
|
||||
foreach($sacrifice->getEnchantments() as $instance){
|
||||
$enchantment = $instance->getType();
|
||||
$level = $instance->getLevel();
|
||||
if(!AvailableEnchantmentRegistry::getInstance()->isAvailableForItem($enchantment, $base)){
|
||||
continue;
|
||||
}
|
||||
if(($targetEnchantment = $base->getEnchantment($enchantment)) !== null){
|
||||
// Enchant already present on the target item
|
||||
$targetLevel = $targetEnchantment->getLevel();
|
||||
$newLevel = ($targetLevel === $level ? $targetLevel + 1 : max($targetLevel, $level));
|
||||
$level = min($newLevel, $enchantment->getMaxLevel());
|
||||
$instance = new EnchantmentInstance($enchantment, $level);
|
||||
}else{
|
||||
// Check if the enchantment is compatible with the existing enchantments
|
||||
foreach($base->getEnchantments() as $testedInstance){
|
||||
$testedEnchantment = $testedInstance->getType();
|
||||
if(!$testedEnchantment->isCompatibleWith($enchantment)){
|
||||
$cost++;
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$costAddition = self::getCostAddition($enchantment);
|
||||
|
||||
if($sacrifice instanceof EnchantedBook){
|
||||
// Enchanted books are half as expensive to combine
|
||||
$costAddition = max(1, $costAddition / 2);
|
||||
}
|
||||
$levelDifference = $instance->getLevel() - $base->getEnchantmentLevel($instance->getType());
|
||||
$cost += $costAddition * $levelDifference;
|
||||
$base->addEnchantment($instance);
|
||||
}
|
||||
|
||||
return (int) $cost;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int The XP cost of renaming the item
|
||||
*/
|
||||
private static function renameItem(Item $item, ?string $customName) : int{
|
||||
$resultCost = 0;
|
||||
if($customName === null || strlen($customName) === 0){
|
||||
if($item->hasCustomName()){
|
||||
$resultCost += self::COST_RENAME;
|
||||
$item->clearCustomName();
|
||||
}
|
||||
}else{
|
||||
$resultCost += self::COST_RENAME;
|
||||
$item->setCustomName($customName);
|
||||
}
|
||||
|
||||
return $resultCost;
|
||||
}
|
||||
|
||||
private static function getCostAddition(Enchantment $enchantment) : int {
|
||||
return match($enchantment->getRarity()){
|
||||
Rarity::COMMON => 1,
|
||||
Rarity::UNCOMMON => 2,
|
||||
Rarity::RARE => 4,
|
||||
Rarity::MYTHIC => 8,
|
||||
default => throw new TransactionValidationException("Invalid rarity " . $enchantment->getRarity() . " found")
|
||||
};
|
||||
}
|
||||
}
|
41
src/block/utils/AnvilResult.php
Normal file
41
src/block/utils/AnvilResult.php
Normal file
@ -0,0 +1,41 @@
|
||||
<?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/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block\utils;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
|
||||
class AnvilResult{
|
||||
public function __construct(
|
||||
private int $repairCost,
|
||||
private ?Item $result,
|
||||
){}
|
||||
|
||||
public function getRepairCost() : int{
|
||||
return $this->repairCost;
|
||||
}
|
||||
|
||||
public function getResult() : ?Item{
|
||||
return $this->result;
|
||||
}
|
||||
}
|
60
src/inventory/transaction/AnvilTransaction.php
Normal file
60
src/inventory/transaction/AnvilTransaction.php
Normal 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/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\inventory\transaction;
|
||||
|
||||
use pocketmine\block\utils\AnvilResult;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\player\Player;
|
||||
use function count;
|
||||
|
||||
class AnvilTransaction extends InventoryTransaction{
|
||||
public function __construct(
|
||||
Player $source,
|
||||
private AnvilResult $anvilResult
|
||||
) {
|
||||
parent::__construct($source);
|
||||
}
|
||||
|
||||
public function validate() : void{
|
||||
if(count($this->actions) < 1){
|
||||
throw new TransactionValidationException("Transaction must have at least one action to be executable");
|
||||
}
|
||||
|
||||
/** @var Item[] $inputs */
|
||||
$inputs = [];
|
||||
/** @var Item[] $outputs */
|
||||
$outputs = [];
|
||||
$this->matchItems($outputs, $inputs);
|
||||
|
||||
//TODO
|
||||
}
|
||||
|
||||
public function execute() : void{
|
||||
parent::execute();
|
||||
|
||||
if($this->source->hasFiniteResources()){
|
||||
$this->source->getXpManager()->subtractXpLevels($this->anvilResult->getRepairCost());
|
||||
}
|
||||
}
|
||||
}
|
@ -33,6 +33,7 @@ use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\nbt\tag\IntTag;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\utils\Binary;
|
||||
use function in_array;
|
||||
use function lcg_value;
|
||||
use function mt_rand;
|
||||
|
||||
@ -172,4 +173,8 @@ class Armor extends Durable{
|
||||
$tag->setInt(self::TAG_CUSTOM_COLOR, Binary::signInt($this->customColor->toARGB())) :
|
||||
$tag->removeTag(self::TAG_CUSTOM_COLOR);
|
||||
}
|
||||
|
||||
public function isValidRepairMaterial(Item $material) : bool{
|
||||
return in_array($material->getTypeId(), $this->armorInfo->getMaterial()->getRepairMaterials(), true);
|
||||
}
|
||||
}
|
||||
|
@ -27,9 +27,13 @@ use pocketmine\world\sound\Sound;
|
||||
|
||||
class ArmorMaterial{
|
||||
|
||||
/**
|
||||
* @param int[] $repairMaterials
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly int $enchantability,
|
||||
private readonly ?Sound $equipSound = null
|
||||
private readonly ?Sound $equipSound = null,
|
||||
private readonly array $repairMaterials = []
|
||||
){
|
||||
}
|
||||
|
||||
@ -49,4 +53,11 @@ class ArmorMaterial{
|
||||
public function getEquipSound() : ?Sound{
|
||||
return $this->equipSound;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the items that can be used to repair the armor
|
||||
*/
|
||||
public function getRepairMaterials() : array{
|
||||
return $this->repairMaterials;
|
||||
}
|
||||
}
|
||||
|
@ -118,6 +118,10 @@ abstract class Durable extends Item{
|
||||
return $this->damage >= $this->getMaxDurability() || $this->isNull();
|
||||
}
|
||||
|
||||
public function isValidRepairMaterial(Item $material) : bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function deserializeCompoundTag(CompoundTag $tag) : void{
|
||||
parent::deserializeCompoundTag($tag);
|
||||
$this->unbreakable = $tag->getByte("Unbreakable", 0) !== 0;
|
||||
|
@ -69,6 +69,7 @@ class Item implements \JsonSerializable{
|
||||
|
||||
public const TAG_DISPLAY_NAME = "Name";
|
||||
public const TAG_DISPLAY_LORE = "Lore";
|
||||
public const TAG_REPAIR_COST = "RepairCost";
|
||||
|
||||
public const TAG_KEEP_ON_DEATH = "minecraft:keep_on_death";
|
||||
|
||||
@ -84,6 +85,7 @@ class Item implements \JsonSerializable{
|
||||
protected string $customName = "";
|
||||
/** @var string[] */
|
||||
protected array $lore = [];
|
||||
protected int $repairCost = 0;
|
||||
/** TODO: this needs to die in a fire */
|
||||
protected ?CompoundTag $blockEntityTag = null;
|
||||
|
||||
@ -282,6 +284,23 @@ class Item implements \JsonSerializable{
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the repair cost of the item.
|
||||
*/
|
||||
public function getRepairCost() : int{
|
||||
return $this->repairCost;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the repair cost of the item.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setRepairCost(int $cost) : self{
|
||||
$this->repairCost = $cost;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws NbtException
|
||||
*/
|
||||
@ -338,6 +357,7 @@ class Item implements \JsonSerializable{
|
||||
}
|
||||
|
||||
$this->keepOnDeath = $tag->getByte(self::TAG_KEEP_ON_DEATH, 0) !== 0;
|
||||
$this->repairCost = $tag->getInt(self::TAG_REPAIR_COST, 0);
|
||||
}
|
||||
|
||||
protected function serializeCompoundTag(CompoundTag $tag) : void{
|
||||
@ -406,6 +426,12 @@ class Item implements \JsonSerializable{
|
||||
}else{
|
||||
$tag->removeTag(self::TAG_KEEP_ON_DEATH);
|
||||
}
|
||||
|
||||
if($this->repairCost){
|
||||
$tag->setInt(self::TAG_REPAIR_COST, $this->repairCost);
|
||||
}else{
|
||||
$tag->removeTag(self::TAG_REPAIR_COST);
|
||||
}
|
||||
}
|
||||
|
||||
public function getCount() : int{
|
||||
|
@ -23,6 +23,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\item;
|
||||
|
||||
use function in_array;
|
||||
|
||||
abstract class TieredTool extends Tool{
|
||||
protected ToolTier $tier;
|
||||
|
||||
@ -61,4 +63,8 @@ abstract class TieredTool extends Tool{
|
||||
public function isFireProof() : bool{
|
||||
return $this->tier === ToolTier::NETHERITE;
|
||||
}
|
||||
|
||||
public function isValidRepairMaterial(Item $material) : bool{
|
||||
return in_array($material->getTypeId(), $this->tier->getRepairMaterials(), true);
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\item;
|
||||
|
||||
use pocketmine\block\BlockTypeIds;
|
||||
use pocketmine\utils\LegacyEnumShimTrait;
|
||||
|
||||
/**
|
||||
@ -36,7 +37,7 @@ use pocketmine\utils\LegacyEnumShimTrait;
|
||||
* @method static ToolTier STONE()
|
||||
* @method static ToolTier WOOD()
|
||||
*
|
||||
* @phpstan-type TMetadata array{0: int, 1: int, 2: int, 3: int, 4: int}
|
||||
* @phpstan-type TMetadata array{0: int, 1: int, 2: int, 3: int, 4: int, 5: int[]}
|
||||
*/
|
||||
enum ToolTier{
|
||||
use LegacyEnumShimTrait;
|
||||
@ -52,8 +53,8 @@ enum ToolTier{
|
||||
* This function exists only to permit the use of named arguments and to make the code easier to read in PhpStorm.
|
||||
* @phpstan-return TMetadata
|
||||
*/
|
||||
private static function meta(int $harvestLevel, int $maxDurability, int $baseAttackPoints, int $baseEfficiency, int $enchantability) : array{
|
||||
return [$harvestLevel, $maxDurability, $baseAttackPoints, $baseEfficiency, $enchantability];
|
||||
private static function meta(int $harvestLevel, int $maxDurability, int $baseAttackPoints, int $baseEfficiency, int $enchantability, array $repairMaterials = []) : array{
|
||||
return [$harvestLevel, $maxDurability, $baseAttackPoints, $baseEfficiency, $enchantability, $repairMaterials];
|
||||
}
|
||||
|
||||
/**
|
||||
@ -61,12 +62,26 @@ enum ToolTier{
|
||||
*/
|
||||
private function getMetadata() : array{
|
||||
return match($this){
|
||||
self::WOOD => self::meta(1, 60, 5, 2, 15),
|
||||
self::GOLD => self::meta(2, 33, 5, 12, 22),
|
||||
self::STONE => self::meta(3, 132, 6, 4, 5),
|
||||
self::IRON => self::meta(4, 251, 7, 6, 14),
|
||||
self::DIAMOND => self::meta(5, 1562, 8, 8, 10),
|
||||
self::NETHERITE => self::meta(6, 2032, 9, 9, 15)
|
||||
self::WOOD => self::meta(1, 60, 5, 2, 15, [
|
||||
ItemTypeIds::fromBlockTypeId(BlockTypeIds::OAK_PLANKS),
|
||||
ItemTypeIds::fromBlockTypeId(BlockTypeIds::SPRUCE_PLANKS),
|
||||
ItemTypeIds::fromBlockTypeId(BlockTypeIds::BIRCH_PLANKS),
|
||||
ItemTypeIds::fromBlockTypeId(BlockTypeIds::JUNGLE_PLANKS),
|
||||
ItemTypeIds::fromBlockTypeId(BlockTypeIds::ACACIA_PLANKS),
|
||||
ItemTypeIds::fromBlockTypeId(BlockTypeIds::DARK_OAK_PLANKS),
|
||||
ItemTypeIds::fromBlockTypeId(BlockTypeIds::CRIMSON_PLANKS),
|
||||
ItemTypeIds::fromBlockTypeId(BlockTypeIds::WARPED_PLANKS),
|
||||
ItemTypeIds::fromBlockTypeId(BlockTypeIds::CHERRY_PLANKS),
|
||||
ItemTypeIds::fromBlockTypeId(BlockTypeIds::MANGROVE_PLANKS)
|
||||
]),
|
||||
self::GOLD => self::meta(2, 33, 5, 12, 22, [ItemTypeIds::GOLD_INGOT]),
|
||||
self::STONE => self::meta(3, 132, 6, 4, 5, [
|
||||
ItemTypeIds::fromBlockTypeId(BlockTypeIds::COBBLESTONE),
|
||||
ItemTypeIds::fromBlockTypeId(BlockTypeIds::COBBLED_DEEPSLATE)
|
||||
]),
|
||||
self::IRON => self::meta(4, 251, 7, 6, 14, [ItemTypeIds::IRON_INGOT]),
|
||||
self::DIAMOND => self::meta(5, 1562, 8, 8, 10, [ItemTypeIds::DIAMOND]),
|
||||
self::NETHERITE => self::meta(6, 2032, 9, 9, 15, [ItemTypeIds::NETHERITE_INGOT])
|
||||
};
|
||||
}
|
||||
|
||||
@ -95,4 +110,13 @@ enum ToolTier{
|
||||
public function getEnchantability() : int{
|
||||
return $this->getMetadata()[4];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of items that can be used to repair this tool.
|
||||
*
|
||||
* @return int[]
|
||||
*/
|
||||
public function getRepairMaterials() : array{
|
||||
return $this->getMetadata()[5];
|
||||
}
|
||||
}
|
||||
|
@ -38,4 +38,8 @@ class TurtleHelmet extends Armor{
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function isValidRepairMaterial(Item $material) : bool{
|
||||
return $material->getTypeId() === ItemTypeIds::SCUTE;
|
||||
}
|
||||
}
|
||||
|
@ -69,12 +69,12 @@ final class VanillaArmorMaterials{
|
||||
}
|
||||
|
||||
protected static function setup() : void{
|
||||
self::register("leather", new ArmorMaterial(15, new ArmorEquipLeatherSound()));
|
||||
self::register("leather", new ArmorMaterial(15, new ArmorEquipLeatherSound(), [ItemTypeIds::LEATHER]));
|
||||
self::register("chainmail", new ArmorMaterial(12, new ArmorEquipChainSound()));
|
||||
self::register("iron", new ArmorMaterial(9, new ArmorEquipIronSound()));
|
||||
self::register("turtle", new ArmorMaterial(9, new ArmorEquipGenericSound()));
|
||||
self::register("gold", new ArmorMaterial(25, new ArmorEquipGoldSound()));
|
||||
self::register("diamond", new ArmorMaterial(10, new ArmorEquipDiamondSound()));
|
||||
self::register("netherite", new ArmorMaterial(15, new ArmorEquipNetheriteSound()));
|
||||
self::register("iron", new ArmorMaterial(9, new ArmorEquipIronSound(), [ItemTypeIds::IRON_INGOT]));
|
||||
self::register("turtle", new ArmorMaterial(9, new ArmorEquipGenericSound(), [ItemTypeIds::SCUTE]));
|
||||
self::register("gold", new ArmorMaterial(25, new ArmorEquipGoldSound(), [ItemTypeIds::GOLD_INGOT]));
|
||||
self::register("diamond", new ArmorMaterial(10, new ArmorEquipDiamondSound(), [ItemTypeIds::DIAMOND]));
|
||||
self::register("netherite", new ArmorMaterial(15, new ArmorEquipNetheriteSound(), [ItemTypeIds::NETHERITE_INGOT]));
|
||||
}
|
||||
}
|
||||
|
@ -23,11 +23,14 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\network\mcpe\handler;
|
||||
|
||||
use pocketmine\block\inventory\AnvilInventory;
|
||||
use pocketmine\block\inventory\EnchantInventory;
|
||||
use pocketmine\block\utils\AnvilHelper;
|
||||
use pocketmine\inventory\Inventory;
|
||||
use pocketmine\inventory\transaction\action\CreateItemAction;
|
||||
use pocketmine\inventory\transaction\action\DestroyItemAction;
|
||||
use pocketmine\inventory\transaction\action\DropItemAction;
|
||||
use pocketmine\inventory\transaction\AnvilTransaction;
|
||||
use pocketmine\inventory\transaction\CraftingTransaction;
|
||||
use pocketmine\inventory\transaction\EnchantingTransaction;
|
||||
use pocketmine\inventory\transaction\InventoryTransaction;
|
||||
@ -39,6 +42,7 @@ use pocketmine\network\mcpe\protocol\types\inventory\ContainerUIIds;
|
||||
use pocketmine\network\mcpe\protocol\types\inventory\stackrequest\CraftingConsumeInputStackRequestAction;
|
||||
use pocketmine\network\mcpe\protocol\types\inventory\stackrequest\CraftingCreateSpecificResultStackRequestAction;
|
||||
use pocketmine\network\mcpe\protocol\types\inventory\stackrequest\CraftRecipeAutoStackRequestAction;
|
||||
use pocketmine\network\mcpe\protocol\types\inventory\stackrequest\CraftRecipeOptionalStackRequestAction;
|
||||
use pocketmine\network\mcpe\protocol\types\inventory\stackrequest\CraftRecipeStackRequestAction;
|
||||
use pocketmine\network\mcpe\protocol\types\inventory\stackrequest\CreativeCreateStackRequestAction;
|
||||
use pocketmine\network\mcpe\protocol\types\inventory\stackrequest\DeprecatedCraftingResultsStackRequestAction;
|
||||
@ -289,7 +293,7 @@ class ItemStackRequestExecutor{
|
||||
* @throws ItemStackRequestProcessException
|
||||
*/
|
||||
private function assertDoingCrafting() : void{
|
||||
if(!$this->specialTransaction instanceof CraftingTransaction && !$this->specialTransaction instanceof EnchantingTransaction){
|
||||
if(!$this->specialTransaction instanceof CraftingTransaction && !$this->specialTransaction instanceof EnchantingTransaction && !$this->specialTransaction instanceof AnvilTransaction){
|
||||
if($this->specialTransaction === null){
|
||||
throw new ItemStackRequestProcessException("Expected CraftRecipe or CraftRecipeAuto action to precede this action");
|
||||
}else{
|
||||
@ -347,6 +351,15 @@ class ItemStackRequestExecutor{
|
||||
}
|
||||
}elseif($action instanceof CraftRecipeAutoStackRequestAction){
|
||||
$this->beginCrafting($action->getRecipeId(), $action->getRepetitions());
|
||||
}elseif($action instanceof CraftRecipeOptionalStackRequestAction){
|
||||
$window = $this->player->getCurrentWindow();
|
||||
if($window instanceof AnvilInventory){
|
||||
$result = AnvilHelper::calculateResult($this->player, $window->getInput(), $window->getMaterial(), $this->request->getFilterStrings()[0] ?? null);
|
||||
if($result !== null){
|
||||
$this->specialTransaction = new AnvilTransaction($this->player, $result);
|
||||
$this->setNextCreatedItem($result->getResult());
|
||||
}
|
||||
}
|
||||
}elseif($action instanceof CraftingConsumeInputStackRequestAction){
|
||||
$this->assertDoingCrafting();
|
||||
$this->removeItemFromSlot($action->getSource(), $action->getCount()); //output discarded - we allow CraftingTransaction to verify the balance
|
||||
|
Loading…
x
Reference in New Issue
Block a user